Skip to main content
The whatsapp_inbound channel flips the normal OTP flow: instead of OTP.ID sending a code to the user, the user sends a pre-filled message to OTP.ID. This approach is popular in mobile apps because a single tap on a deep-link opens WhatsApp with the verification message already composed — no typing required. OTP.ID matches the token in the incoming message, marks the transaction as verified, and fires the otp.verified webhook to your server.

How it works

1

Request a WhatsApp Inbound OTP

Call POST /v3/request with "channel": "whatsapp_inbound". You do not need to supply number (see Binding vs. Unbound below).
2

Receive the verification block

The API response includes a verification object containing OTP.ID’s central WhatsApp number, the exact message text the user must send, and a deep-link that pre-fills the message in WhatsApp.
3

Display the deep-link or message to the user

Show a “Verify via WhatsApp” button powered by wa_link, or display the message text so the user can copy and send it manually.
4

User sends the message

The user taps your button (or manually sends the message) to OTP.ID’s WhatsApp number. The message text must be sent verbatim — any modification breaks the token match.
5

OTP.ID matches the token and verifies

OTP.ID receives the message, matches the embedded token against the pending transaction, marks it as verified, and fires the otp.verified webhook to your server.

Sending the request

Request body:

Response with the verification block

A successful request returns a verification object in addition to the standard transaction fields. The status is "pending" — it transitions to "verified" when the user sends the correct message.

verification field reference

In mobile apps, render wa_link as a prominent button — for example, “Verify via WhatsApp”. On Android and iOS, tapping this link opens WhatsApp directly with the correct message pre-filled in the compose field. The user only needs to tap Send. This dramatically improves completion rates compared to asking the user to copy and paste a code.

Binding vs. unbound

You can optionally include a number in your request to restrict verification to a specific phone number. Bound request example:

Handling completion

Because the user acts in a separate app, your server learns about verification via the otp.verified webhook rather than a synchronous API response. In your UI, you can:
  1. Poll GET /v3/otp/{otp_id} every few seconds and check status === "verified".
  2. Listen for the webhook (recommended) and push a notification to your frontend via WebSocket or SSE when the event arrives.
See the Webhooks guide for payload details and how to verify the webhook signature.

Limitations

whatsapp_inbound is not supported by POST /v3/send. You must use POST /v3/request for this channel. Additionally, POST /v3/verify is not called by your server for this flow — verification happens automatically when OTP.ID receives the user’s WhatsApp message.