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
phoneNumber
with 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.
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"
}
}
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
_id
from the responsedata.transactionReq
object - 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"
}
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
mainTransaction
andtransactionReq
objects
- 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
frontendCallbackURL
for 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"
}
}