Skip to content
Akedly
LegacyDEPRECATED

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.

Request Parameters

  • Name
    APIKey
    Type
    string
    Description

    Your API key, from Account & Billing → API Keys in the dashboard

  • 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/or email. For country codes, reference https://countrycode.org/

  • Name
    otp
    Type
    string
    Requirement
    Optional
    Description

    Bring your own 4, 5 or 6 digit OTP code (numbers only). When provided, billing switches to pay-per-message upon activation instead of pay-per-successful-authentication. Step 3 stays required: send every code your user enters to the verify call, even when your own server also checks it.

  • Name
    otpLanguage
    Type
    string
    Requirement
    Optional
    Description

    OTP message language for WhatsApp and SMS. Overrides the pipeline's OTP Language for this request. See accepted values and defaults.

  • Name
    digits
    Type
    number
    Requirement
    Optional
    Description

    Specifies the length of the OTP to be generated. Accepts 4, 5 or 6. Defaults to 6 if not provided.

  • Name
    template
    Type
    object
    Requirement
    Optional
    Description

    { id, variables } for your own approved OTP template. Checked here; activate sends with it. An invalid selection fails with a 400 before anything is sent.

  • Name
    waitForChannels
    Type
    boolean
    Requirement
    Optional
    Description

    When set to true, the API waits up to 5 seconds for channel outcomes before responding, then returns a bounded activation snapshot. A channel can still be pending when the wait ends, and a later signed otp.channels.updated event can report a late WhatsApp failure or fallback. When omitted or false, the response reports the channels attempted at dispatch time and does not wait for confirmations. This typically adds about 1 second to response time; 5 seconds is the maximum wait.

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
    data.otpLanguage
    Type
    string
    Description

    Always present: en or ar. The language the OTP is requested in, not a delivery receipt.

  • Name
    data.template
    Type
    object
    Description

    Present when a custom template was selected: { id, language } as resolved at creation. It does not confirm which channel or template delivered the code.

  • Name
    message
    Type
    string
    Description

    Human-readable description of the transaction status

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

POSThttps://api.akedly.io/api/v1/transactions/activate/{transactionID}
{
  //empty body
}

Activation dispatch responses

StatusErrorCause & Solution
409OTP_DISPATCH_IN_PROGRESSAnother call holds this send: it is still in flight, or it finished but its result is not readable yet. retryable is true; read retryAfterSeconds (3) from the body; the response also sets Retry-After: 3, which browsers may not expose cross-origin. Retry the same call after that many seconds. Expect 409 while in flight or while the result is not readable yet. Once the first send is accepted, a retry may use the one resend described in the note above, and only within the 2-minute activation window. To get a fresh code, create a new transaction.
409OTP_DISPATCH_OUTCOME_UNKNOWNThe first send's outcome could not be confirmed. retryable is false; do not retry the same transaction. Create a new transaction in Step 1, then activate it.

Activation errors

JSON409 Status
{
  "status": "error",
  "message": "Your verification code is still being sent. Please wait a few seconds and try again.",
  "code": "OTP_DISPATCH_IN_PROGRESS",
  "reason": "dispatch_in_progress",
  "retryable": true,
  "retryAfterSeconds": 3
}

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)
    • Telegram (if available and WhatsApp is not)
    • Local SMS (for Egyptian numbers without WhatsApp/Telegram)
    • International SMS (for international numbers without WhatsApp/Telegram)

Key Benefits:

  • Guaranteed delivery through multiple channels increases success rates
  • Flexible billing options based on your OTP preference

A real send's response includes dispatched: true; dev-mode test activations omit dispatched.

Next Steps:

  • Extract the _id from the response data 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

Channel Delivery Confirmation

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 and transactionReq 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

Failed Authentication Response

  • 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.


Error Reference

Common errors you may encounter when using the V1.0 REST API, grouped by category.

Authentication Errors

StatusErrorCause & Solution
500User not found — Invalid API keyAPIKey is missing, or the key is not currently usable because it is unknown, revoked, expired (past its grace period), or replaced. Verify that you are using a current API key from the Akedly dashboard. The response does not identify which condition applies.
500Account not activeYour Akedly account is inactive. Contact support to reactivate.
500Account not verifiedComplete email verification for your Akedly account.
403Activation window exceededStep 2 (activate) must be called within 2 minutes of Step 1 (create). That window is shorter than the 3-minute OTP validity which starts once the OTP is sent — do not queue activation for later. Create a new transaction instead.

Configuration Errors

StatusErrorCause & Solution
400INVALID_OTP_LANGUAGEInvalid otpLanguage; see accepted values. V1 returns status, code and message.
500No billing planSubscribe to a billing plan in your dashboard before creating transactions.
500Subscription expiredYour billing subscription has expired. Renew in the dashboard.
500Pipeline not foundThe pipelineID does not exist. Verify the ID in your dashboard.
500Pipeline inactiveThe pipeline is disabled. Activate it in Dashboard > Pipelines.
500Pipeline misconfiguredThe pipeline is missing required settings (e.g., no verification methods enabled). Check pipeline configuration.

Rate Limiting & Abuse Prevention

StatusErrorCause & Solution
429Phone number bannedThe phone number has been temporarily banned due to excessive failed attempts. Wait for the ban to expire.
429Cooldown periodA 60-second cooldown is enforced between OTP requests to the same number. Wait and retry.
429Throttle exceededToo many requests in a short period. Implement exponential backoff in your retry logic.

Billing Errors

StatusErrorCause & Solution
402Insufficient quotaYour message quota is exhausted. Top up your balance or upgrade your plan.

Verification Errors

StatusErrorCause & Solution
403Invalid OTPThe OTP entered by the user does not match. Prompt them to re-enter.
403Transaction expiredThe transaction has expired (3-minute TTL). Create a new transaction and resend the OTP. The body is {"message": "Transaction expired, please re-try from the beginning and request a new one"}.
429MAX_ATTEMPTS_EXCEEDEDThe 10th wrong OTP force-expires the transaction. Create a new one; further attempts return the 403 expired response above.
403Transaction already verifiedThis transaction was already completed successfully. Each transaction can be verified once — create a new one for a new authentication.
404Missing OTP or transaction request IDThe request omitted the otp field or the transaction request ID in the path. Both are required.

OTP Template Errors

Returned when the request or the pipeline default selects an OTP template that cannot be used. Nothing is sent or billed. Unlike the message-only errors above, these carry status and code. Remedies are in the OTP templates guide.

StatusCodeCause
400TEMPLATE_UNKNOWNThe template id is malformed, not found, or not owned by the account.
400TEMPLATE_ARCHIVEDThe template was archived.
400TEMPLATE_WABA_REQUIREDThe account has no active own WABA, or its token cannot be read.
400TEMPLATE_WABA_CHANGEDThe template belongs to a previous WABA.
400TEMPLATE_NOT_APPROVEDThe OTP language has no approved variant.
400TEMPLATE_REJECTEDMeta rejected the OTP language variant.
400TEMPLATE_VARIABLE_MISSINGA required variable has no request value or stored default.
400TEMPLATE_VARIABLE_INVALIDA variable name or value is invalid, or the template object contains an unsupported key.

Server Errors

StatusErrorCause & Solution
500Failed to send OTPInternal error during OTP delivery. Retry the request. If persistent, contact support.