OTP Transaction ID Format
Every OTP transaction is assigned a unique ID at creation time. The format is:OTP20260807ABCD000001
Store the
otp_id returned in the API response — you need it to poll the transaction status and to verify the OTP.
Transaction Statuses
Thestatus field of a transaction takes one of the following values.
A
failed delivery still creates a transaction record and still returns HTTP 200 OK. Check the status field in the response body to distinguish a failed delivery from a network or authentication error.Expiry and attempt exhaustion are not status values. When the TTL elapses or the channel-specific attempt limit is reached, the stored
status does not change (it stays sent/success) — instead, POST /v3/verify rejects the attempt with error code OTP_EXPIRED, TOO_MANY_ATTEMPTS, or ALREADY_USED (HTTP 422). The failed-attempt limit is 5 for standard channels and 2 for misscall. Use expires_at and attempts from GET /v3/otp/{otp_id} to detect these conditions when polling.Lifecycle Flow
The diagram below describes the full journey of an OTP transaction in plain text.1
Create the transaction
Call
POST /v3/request (with automatic OTP generation or request-only flows) or POST /v3/send (supplying your own OTP value for whatsapp, sms, or email). Delivery happens synchronously — the API response already carries the delivery outcome (status: sent/success/failed) together with the otp_id. Only whatsapp_inbound starts at status: pending.For whatsapp_inbound, the response also includes a verification block containing wa_number, message, wa_link, and expires_at. Display this information to your user right away.2
OTP.ID attempts delivery
OTP.ID contacts the channel vendor (WhatsApp provider, SMS gateway, email relay, or telephony provider). If the vendor accepts the message, the status advances to
sent or success and credits are deducted. If the vendor rejects or cannot reach the destination, the status is set to failed and no charge is applied.3
User receives the code
Your user reads the OTP from their WhatsApp message, SMS, email, missed-call log, or (for
whatsapp_inbound) sends the pre-filled WhatsApp message. The OTP is valid until the TTL expires.4
Your app submits the code for verification
When the user enters the code in your interface, call
POST /v3/verify with the otp_id and the otp value the user provided.5
OTP.ID returns the verification result
OTP.ID checks the submitted code and returns one of the following outcomes:
- Correct code — HTTP
200,verified: true. Status advances toverified. - Wrong code (attempts remaining) — HTTP
200,verified: false,reason: "mismatch". The transaction remains active; the user can try again. - Attempt limit reached — the failed submission that reaches the limit returns HTTP
200withverified: false; the transaction is then permanently locked. The next verification call returns HTTP422withTOO_MANY_ATTEMPTS. The limit is 5 failed attempts for standard channels and 2 formisscall. - Expired — HTTP
422, error codeOTP_EXPIRED. - Already used — HTTP
422, error codeALREADY_USED.
Polling Transaction Status
If you need to check the state of a transaction outside of the verification flow (for example, to confirm delivery or to build a status dashboard), use the status endpoint:whatsapp_inbound transactions to detect when the user has sent their reply and the status advances to verified.
TTL Clamping
Thettl field controls how many seconds the OTP remains valid after creation. OTP.ID applies the following clamping rules silently — values outside the valid range are adjusted rather than rejected.
OTP.ID never returns a validation error for an out-of-range
ttl. The value is silently clamped. Always read the expires_at field in the response to know the exact expiry time.OTP Length Clamping
Theotp_length field controls how many digits the generated OTP contains. The same silent clamping logic applies.

