Documentation
Overview
otp.com is one API for OTP verification over SMS, WhatsApp, Telegram, and Email. Here is what it does and how the pieces fit together.
otp.com is a single API for verifying users with one-time passcodes. You send a code to a phone number or email address, the user types it back, and you confirm it in one more call. Delivery across SMS, WhatsApp, Telegram, and Email is handled for you, with fallback between channels when one does not get through. WhatsApp differs only in delivery: the send returns a link the user opens to receive the code over chat, then verifies it the same way as every other channel.
What it is
- One endpoint, every channel. You call
POST /otp/sendwith a recipient. Your account routing decides whether that goes over SMS, WhatsApp, Telegram, or Email, and falls back automatically if the first channel does not get through. On WhatsApp the response returns anaction_urlthe user opens to receive the code over chat. - Pay per verification sent. One charge per code at the published per-country rate; verifying is free, and a resend is a new verification. Test keys run in the sandbox, where nothing is delivered and nothing is charged.
- Self-serve. Create a key, send your first code in minutes. No sales call, no setup fee.
- Meet your stack. Call the REST API directly, use an official SDK (Node.js, Python, Go, PHP), or let an AI agent drive it through the MCP server.
What it is not
You do not pick a channel per request, you do not template the message, and you never receive the code itself in an API response. Those are deliberate: routing, message copy, and code generation are handled server-side so your integration stays a two-call flow.
The flow
Verification is two steps, with two optional helpers:
- Send a code with
POST /otp/send. You get back anotp_id. - Verify what the user typed with
POST /otp/verify, using thatotp_id. - Optionally resend (
POST /otp/resend) to advance to the next channel, or check status (GET /otp/{otp_id}) at any time.
WhatsApp follows the same two steps; the only difference is that the user opens the
send’s action_url to receive the code over chat before entering it. See
WhatsApp verification.
# 1. send
curl -X POST https://api.otp.com/api/v1/otp/send \
-H "Authorization: Bearer otp_live_•••" \
-H "Content-Type: application/json" \
-d '{"recipient":"+14155552671","locale":"en"}'
# -> { "otp_id": "9f3c1b2a-…", "status": "pending", "channel": "sms" }
# 2. verify
curl -X POST https://api.otp.com/api/v1/otp/verify \
-H "Authorization: Bearer otp_live_•••" \
-H "Content-Type: application/json" \
-d '{"otp_id":"9f3c1b2a-…","code":"123456"}'
# -> { "otp_id": "9f3c1b2a-…", "status": "approved", "matched": true }
Where to go next
- New here? Start with the Quickstart.
- Setting up keys? See Authentication.
- Want the mental model? Read How verification works.
- Just need the calls? Jump to the API reference or copy a code example.
- Prefer a library? See the official SDKs. Building with AI? Use the MCP server.