Skip to content
Documentation menu

Documentation

Quickstart

Send and verify your first one-time passcode in a few minutes, using a sandbox test key so nothing is charged and no real message is sent.

The flow is two steps: send a code, then verify what the user enters. This guide runs both in the sandbox, so no real message goes out and nothing is charged. When you are ready for production, swap the test key for a live one.

1. Get an API key

Create a key on the API Keys screen in your dashboard.

  • A test key (otp_test_…) runs in the sandbox: no real message, no charge.
  • A live key (otp_live_…) sends for real.

Send the key as a Bearer token on every request. See Authentication for details.

2. Send a code

Call POST /otp/send with the recipient (a phone number in E.164 form, or an email address) and the end user’s IP as client_ip. You do not pass a channel: your app routing chooses it. The response returns an otp_id you use to track and verify the code. client_ip is optional on the wire but worth passing from day one: requests without it share a much tighter rate limit, and it feeds the abuse protection that guards your own traffic (see send).

curl -X POST https://api.otp.com/api/v1/otp/send \
  -H "Authorization: Bearer otp_test_•••" \
  -H "Content-Type: application/json" \
  -d '{"recipient":"+14155552671","locale":"en","client_ip":"81.2.69.142"}'
{
  "otp_id": "9f3c1b2a-…",
  "status": "pending",
  "channel": "sms",
  "masked_recipient": "+1****71",
  "action_url": null,
  "completion": "code"
}

If routing picks WhatsApp, the response may also carry an action_url (a wa.me link) the user opens to finish on chat. completion tells you what happens after that: "code" means they receive a code and you verify exactly as below. The three WhatsApp shapes are covered in WhatsApp verification.

3. Verify what the user entered

When the user types the code, call POST /otp/verify with the otp_id and the code. matched: true means the code was correct and the OTP is approved. This is the same on every channel, WhatsApp included, except when the send came back with completion: "inbound": that OTP approves without a code (see WhatsApp verification).

In the sandbox, the accepted code is always 123456.

curl -X POST https://api.otp.com/api/v1/otp/verify \
  -H "Authorization: Bearer otp_test_•••" \
  -H "Content-Type: application/json" \
  -d '{"otp_id":"9f3c1b2a-…","code":"123456"}'
{
  "otp_id": "9f3c1b2a-…",
  "status": "approved",
  "matched": true
}

4. If it did not arrive

Call POST /otp/resend to advance to the next channel in your order (for example SMS to WhatsApp), or force one with {"channel":"sms"}. GET /otp/{otp_id} reads the status at any time.

Next steps