Skip to main content
This guide walks you through the complete OTP flow — from obtaining your API key to sending a code and verifying it — using nothing but curl. By the end, you’ll have made real API calls and understand the shape of every response you’ll encounter in production.
The OTP code itself is never returned in API responses — it’s delivered directly to the user through the chosen channel.
1

Get your API key

Every request to the OTP.ID API must include a Bearer API key. To obtain yours:
  1. Log in to your dashboard at https://app.otp.id.
  2. Open the Akun (Account) page and find the API Key card.
  3. Click Tampilkan (Show), confirm with your account password, then copy the key — you’ll pass it in the Authorization header of every request.
Your API key is a UUID string, like this: 550e8400-e29b-41d4-a716-446655440000Keep it secret. Never commit it to source control or expose it in client-side code.
2

Send an OTP via WhatsApp

Call POST /v3/request to have OTP.ID generate a code and deliver it to your user over WhatsApp. Pass destination as the user’s phone number in E.164 format (digits only, no + prefix) and a brand name that will appear in the message.
A successful response looks like this:
Save the otp_id — you’ll need it in the next two steps. The expires_at field tells you when the code stops being valid. price is the number of credits deducted for this send, and last_balance is your remaining credits after this send.
3

Verify the OTP

Once your user submits the code they received, call POST /v3/verify with the otp_id from the previous step and the code the user entered.
Successful verification — the code matches:
Code mismatch — the user entered the wrong code:
A mismatch returns HTTP 200 with verified: false — it is a valid, expected outcome, not an API error. Only check data.verified to decide whether to grant access.
reason is only ever "" (success) or "mismatch" (wrong code). Other outcomes — expired OTP, attempt limit reached, or an already-verified OTP — come back as HTTP 422 error responses with codes OTP_EXPIRED, TOO_MANY_ATTEMPTS, and ALREADY_USED. See the verify reference.
4

Check transaction status

For polling-based flows — or when you want to inspect a past OTP record — call GET /v3/otp/{otp_id} with the OTP’s ID.
The response includes the full OTP record with its current status:
The status values are pending, sent, success, failed, and verified. For real-time notifications without polling, set up the otp.verified webhook instead.

Next Steps

You’ve completed the full OTP flow. Here’s where to go deeper:
  • Authentication — understand API key scoping and how to handle auth errors.
  • Channels — learn when to use SMS, Email, Missed Call, or WhatsApp Inbound instead of WhatsApp outbound.
  • Webhooks — set up the otp.verified event to receive async verification results.
  • API Reference — see the full schema for every request and response field.