Skip to content
Documentation menu

Documentation

POST /verifications/exchange

Exchange the verification_token a mobile SDK produced for the recipient it proves. This is the only trustworthy answer to whether a user controls a number.

Exchange the verification_token a mobile SDK handed your app for the recipient it proves. Call it from your own backend with a server key: a publishable key is refused here, which is the whole point of the split.

This is the only trustworthy answer to “did this user prove they control this number”. The matched field the device saw is a hint for its own UI, read off a device you do not control, and an app can claim anything. Until you make this call, your backend knows nothing.

curl -X POST https://api.otp.com/api/v1/verifications/exchange \
  -H "Authorization: Bearer otp_live_•••" \
  -H "Content-Type: application/json" \
  -d '{"verification_token":"otp_vt_•••"}'

Request body

FieldTypeRequiredDescription
verification_tokenstringyesThe token your app received when the verification succeeded on the device. Starts with otp_vt_, at most 128 characters.

Tokens are short-lived and single-purpose, so exchange one as soon as your app hands it over rather than storing it.

Idempotency

Exchanging is idempotent for the same API key within the token lifetime: a retry after a network failure returns the same result instead of losing the verification. There is no idempotency-key header to send, because the token is already the key. A different key of your own is not the same key, so route the retry through the same one.

Response

{
  "otp_id": "6f0d2c5e-…",
  "recipient": "+14155552671",
  "recipient_type": "phone",
  "channel": "sms",
  "verified_at": "2026-09-08T19:33:21Z"
}
FieldDescription
otp_idThe verification this token belongs to.
recipientThe recipient that was verified, in full. This is the answer the device could not be trusted to give you.
recipient_typephone or email.
channelThe channel the verified code was delivered on: sms, whatsapp, telegram, or email.
verified_atWhen the end user entered the correct code, in UTC.

Common errors

StatusTypeWhen
401HTTPExceptionMissing, invalid, or revoked key, or a publishable key used here. This endpoint takes a server key only.
404HTTPExceptionThe token is unknown, expired, already exchanged, or not yours.
422ValidationErrorMissing or malformed request body.

Those four cases share one 404 on purpose: told apart, they would let anyone with an API key probe which tokens exist. Treat a 404 as “there is no verification here”, not as something to retry, and start a new verification instead.

See Error codes for the full list.