Skip to main content
Use this guide when you want the user to start verification from WhatsApp instead of receiving a code. Send channel: "whatsapp_inbound" to POST /v3/request. OTP.ID returns a WhatsApp number, an exact message, and a deep link. The user sends that message to OTP.ID, and OTP.ID verifies the transaction automatically. This channel does not use POST /v3/send and does not use POST /v3/verify.

Flow overview

1

Create an inbound transaction

Call POST /v3/request with channel: "whatsapp_inbound". Include destination only when you want to bind the verification to one sender number.
2

Show the WhatsApp action

Render verification.wa_link as the primary action. You can also show verification.wa_number and verification.message for manual copy.
3

User sends the exact message

The user opens WhatsApp and sends the pre-filled message to the OTP.ID WhatsApp number.
4

OTP.ID verifies automatically

OTP.ID matches the inbound message to the transaction and marks it verified.
5

Update your UI

Use the otp.verified webhook for server-side automation, or poll GET /v3/otp/{otp_id} while the UI is waiting.

Create the inbound transaction

Request

Success response

If OTP.ID’s central WhatsApp number is temporarily not configured, this request fails with 503 CHANNEL_UNAVAILABLE instead of creating a transaction — you will never receive a broken wa_link. Treat it like any other channel outage: retry later or offer another channel. See the Error Codes reference.

Show the WhatsApp action

Use verification.wa_link as your primary button.
The user must send the exact message. If they change the text, OTP.ID cannot match it to the transaction.

Detect verification

WhatsApp Inbound is verified automatically. Do not ask the user for a code and do not call POST /v3/verify.

Option A: Listen for the webhook

OTP.ID sends the otp.verified webhook after the inbound message is matched.

Option B: Poll the status endpoint

If your UI is waiting in real time, poll GET /v3/otp/{otp_id} until the transaction becomes verified or expires.
While the transaction is still pending and has not expired, the response also includes the same verification block (wa_number, message, wa_link, expires_at) that POST /v3/request returned. Use it to re-render the WhatsApp button after a page reload instead of persisting the link yourself:
Once the user’s message is matched, the verification block disappears and status becomes verified:

UI states to handle