V1.0 Sunset Extended to December 30, 2026
The V1.0 REST API sunset has been extended to December 30, 2026 based on community feedback. Existing integrations will continue to work until then. New integrations should use V2.0 Widgets or wait for V1.2.
V1.2 REST API Coming Soon
V1.2 wraps V1 with ~80% of V2's security features (fingerprinting, rate limiting, circuit breaking, captcha) -- no iframe required. Same REST API simplicity, built-in protection. Learn more
V1.0 REST API Authentication
Step 1: Create an Authentication Transaction
After setting up your pipeline, initiate an authentication transaction when a user needs to be authenticated. This generates a unique transaction ID that will be used throughout the authentication process.
Looking for a simpler integration? Check out our official SDKs for Node.js and Flutter that handle this entire flow with just a few method calls.
Request Parameters
If you include the email field in verificationAddress, ensure you've enabled email as a verification method in your pipeline settings at https://app.akedly.io/pipeline/${pipelineID}
- Name
APIKey- Type
- string
- Description
Your API key from the Akedly dashboard API section
- Name
pipelineID- Type
- string
- Description
The unique identifier of your pipeline, found in the pipeline's basic details
- Name
verificationAddress- Type
- JSON
- Description
JSON object containing the user's contact information for OTP delivery. Include
phoneNumberwith country code and/oremail. For country codes, reference https://countrycode.org/
- Name
otp- Type
- string
- Description
Optional: Bring your own 4 or 6 digit OTP code (numbers only). When provided, billing switches to pay-per-message upon activation instead of pay-per-successful-authentication.
- Name
digits- Type
- number
- Description
Optional: Specifies the length of the OTP to be generated. Accepts either
4or6. Defaults to6if not provided.
- Name
waitForChannels- Type
- boolean
- Description
Optional: When set to
true, the API polls up to 5 seconds for webhook confirmations from delivery channels before responding. Channels are reported as "confirmed" or "failed" instead of just "attempted". Adds ~1 second overhead. Useful when you need accurate delivery status for analytics or user display.
Response Format
- Name
status- Type
- string
- Description
The status of your transaction request ("success" or "error")
- Name
data- Type
- JSON
- Description
Contains the critical
transactionID- your authorization token to proceed with OTP delivery. Save this transactionID as you'll need it for the next step.
- Name
message- Type
- string
- Description
Human-readable description of the transaction status
Best Practice: Store the transactionID in your database alongside the user's current session or operation. This allows you to track which user corresponds to which authentication attempt when they return to your application after verification.
For example, if you're implementing user registration with email verification, save the transactionID with the new user's record to mark them as verified once authentication completes.
Request Body & URL
{
"APIKey": "6e1d6585bbe17f6abc80cf10a1********ad3fe197775b19fde2ebb5464d",
"pipelineID": "6748*******f948b29ef",
"verificationAddress": {
"phoneNumber": "+20155****2491",
"email": "testmail@akedly.io"
},
"digits": 6
}
Response
{
"status": "success",
"data": {
"transactionID": "a77549536888557729a0e4cd454d28371f658426135af11ce6cba7f6123aafff"
},
"message": "Main transaction created successfully"
}
Step 2: Activate Transaction and Send OTP
With your transactionID from Step 1, activate the transaction to trigger OTP delivery to the user's specified contact information.
Request Body & URL
{
//empty body
}
How OTP Delivery Works
Upon successful activation, Akedly delivers the OTP using our smart multi-channel approach:
Multi-Channel Delivery:
- Email: Always sent when email address is provided
- Phone: Delivered through the most reliable available channel:
- WhatsApp (if available on the number)
- Local SMS (for Egyptian numbers without WhatsApp)
- International SMS (for international numbers without WhatsApp)
Key Benefits:
- Guaranteed delivery through multiple channels increases success rates
- Flexible billing options based on your OTP preference
Billing Model Differences:
Standard Authentication (Akedly-generated OTP):
- Pay-per-successful-authentication - Only charged when user completes Step 3 verification
- No charge if user fails to verify or abandons the process
- Traditional pay-per-success pricing model
Custom OTP Authentication (Bring Your Own):
- Pay-per-message - Charged immediately upon Step 2 activation
- Billing occurs regardless of verification outcome
- Since the OTP is predetermined, Step 3 verification becomes optional for authentication integrity
Important: When using custom OTP, we strongly recommend completing Step 3 verification to maintain accurate dashboard analytics, usage tracking, and cost analysis in your Akedly app dashboard.
Next Steps:
- Extract the
_idfrom the responsedata.transactionReqobject - Save this
_id- you'll need it for verification in Step 3 - Display your OTP input interface to the user
- Prepare to collect and verify the user's OTP input
Response
{
"status": "success",
"message": "OTP sent successfully",
"email": true, //email sending status
"WhatsApp": true, //whatsapp sending status
"sms": true, //sms sending status
"data": {
"_id": "66726b726cdd6713",
"status": "Pending",
"mainTransactionID": "a77549536888557729a0e4cd454d28371f658426135af11ce6cba7f6123aafff",
"sentVerification": true,
"uid": "0aefbca6-0ef9-490f-a68b-f5f334ad35e5",
"creationDate": "2025-08-31T19:26:32.300Z",
"expirationDate": "2025-08-31T19:29:32.300Z",
"__v": 0,
"sentVerificationDate": "2025-08-31T19:26:33.582Z",
"sentVerificationMethod": "674dff8ae3444b3662d33026"
}
}
Response
{
"message": "Rate limit exceeded. Try again in 47 seconds"
}
Channel Delivery Confirmation
Error Handling: - 403 status codes: Indicate OTP delivery failures - 429 status codes: Rate limit exceeded - Akedly enforces a 60-second rate limit per user to prevent abuse. Wait for the specified time before allowing retry attempts. Handle these error cases gracefully in your application flow.
Step 3: Verify User's OTP Input
Submit the user's OTP input for verification using the _id from Step 2:
- Name
otp- Type
- string
- Description
The OTP code entered by the user (must be sent as a string)
Successful Authentication Response
- Name
status- Type
- string
- Description
Authentication result status ("success")
- Name
data- Type
- JSON
- Description
Complete transaction data including
mainTransactionandtransactionReqobjects
- Name
message- Type
- string
- Description
Human-readable success message
- Name
mainTransaction- Type
- JSON
- Description
The original transaction object from Step 1, containing pipeline and user details
- Name
transactionReq- Type
- JSON
- Description
Verification attempt details including timestamps for OTP sending, user input, and verification completion
Note: The response data is provided for logging and analytics purposes. You can also view all verification attempts in your Akedly dashboard at https://app.akedly.io/admin/verifications.
Failed Authentication Response
- Name
status- Type
- number
- Description
HTTP error status code (typically 403 for invalid OTP)
- Name
data- Type
- JSON
- Description
Contains
frontendCallbackURLfor redirect handling (only relevant when using Akedly's hosted authentication interface)
- Name
message- Type
- string
- Description
Error description explaining why authentication failed
All error responses follow this format, with the message field providing specific details about what went wrong.
Request Body & URL
{
"otp": "123456"
}
Response
{
"message": "OTP verified successfully",
"status": "success",
"data": {
"frontendCallbackURL": "https://yourapp.com/auth/callback?transactionID=ae2eacaebe3ed78b105498d5d0cfe54f11b4130a0847d67b36927752148679e5&status=Successful",
"mainTransaction": {
"verificationAddress": {
"phoneNumber": "+201556452491"
},
"_id": "68b4a1e2d686446a498008b0",
"userID": "6821bb199f9cfd6b2754e6ef",
"pipelineID": "6821bba09f9cfd6b2754e752",
"status": "Successful",
"optinActivated": false,
"payPerMessage": true,
"billedInActivation": true,
"OTP": "123456",
"creationDate": "2025-08-31T19:26:26.689Z",
"expirationDate": "2025-08-31T19:29:26.689Z",
"updateDate": "2025-08-31T19:27:27.440Z",
"transactionID": "ae2eacaebe3ed78b105498d5d0cfe54f11b4130a0847d67b36927752148679e5",
"__v": 0
},
"transactionReq": {
"_id": "68b4a1e8d686446a498008bd",
"status": "Successful",
"mainTransactionID": "ae2eacaebe3ed78b105498d5d0cfe54f11b4130a0847d67b36927752148679e5",
"sentVerification": true,
"uid": "0aefbca6-0ef9-490f-a68b-f5f334ad35e5",
"creationDate": "2025-08-31T19:26:32.300Z",
"expirationDate": "2025-08-31T19:29:32.300Z",
"__v": 0,
"sentVerificationDate": "2025-08-31T19:26:33.582Z",
"sentVerificationMethod": "674dff8ae3444b3662d33026",
"inputOTP": "123456",
"verificationDate": "2025-08-31T19:27:27.440Z"
}
}
}
Response
{
"message": "Invalid OTP",
"status": 403,
"data": {
"frontendCallbackURL"
}
}
Error Reference
Common errors you may encounter when using the V1.0 REST API, grouped by category.
Authentication Errors
| Status | Error | Cause & Solution |
|---|---|---|
| 401 | Account not active | Your Akedly account is inactive. Contact support to reactivate. |
| 401 | Account not verified | Complete email verification for your Akedly account. |
Configuration Errors
| Status | Error | Cause & Solution |
|---|---|---|
| 400 | No billing plan | Subscribe to a billing plan in your dashboard before creating transactions. |
| 400 | Subscription expired | Your billing subscription has expired. Renew in the dashboard. |
| 400 | Pipeline not found | The pipelineID does not exist. Verify the ID in your dashboard. |
| 400 | Pipeline inactive | The pipeline is disabled. Activate it in Dashboard > Pipelines. |
| 400 | Pipeline misconfigured | The pipeline is missing required settings (e.g., no verification methods enabled). Check pipeline configuration. |
Rate Limiting & Abuse Prevention
| Status | Error | Cause & Solution |
|---|---|---|
| 429 | Phone number banned | The phone number has been temporarily banned due to excessive failed attempts. Wait for the ban to expire. |
| 429 | Cooldown period | A 60-second cooldown is enforced between OTP requests to the same number. Wait and retry. |
| 429 | Throttle exceeded | Too many requests in a short period. Implement exponential backoff in your retry logic. |
Billing Errors
| Status | Error | Cause & Solution |
|---|---|---|
| 402 | Insufficient quota | Your message quota is exhausted. Top up your balance or upgrade your plan. |
Verification Errors
| Status | Error | Cause & Solution |
|---|---|---|
| 403 | Invalid OTP | The OTP entered by the user does not match. Prompt them to re-enter. |
| 410 | Transaction expired | The transaction has expired (3-minute TTL). Create a new transaction and resend the OTP. |
Server Errors
| Status | Error | Cause & Solution |
|---|---|---|
| 500 | Failed to send OTP | Internal error during OTP delivery. Retry the request. If persistent, contact support. |