avatar

Elena Rodriguez

Updated: 2026-08-21

15 min read

Before a WhatsApp OTP verification API sends its first code, someone on your side has to settle an ownership question. Either you register your own WhatsApp Business Account and run the verification stack yourself , or you send through a provider that already holds the sender number and the template approval . Take the first route and Meta's account verification and template review move onto your critical path, usually costing days. Take the second and the sender identity in the thread belongs to your provider. Teams that skip the question tend to answer it by accident, then rediscover it during launch week.

What follows walks both routes: what the authentication template actually controls, how the send-and-verify flow gets wired, which delivery signals are worth handling, and the fallback logic that keeps signups moving when WhatsApp cannot reach someone. One assumption up front: WhatsApp already has a place in your verification mix. If that part is still open, our WhatsApp OTP overview covers the channel comparison and the use cases behind the decision.

Two Ways to Build WhatsApp OTP Verification

Both routes put a code in a WhatsApp thread. They differ in how much of the platform you operate yourself .

Decision point WhatsApp Business API direct OTP API with WhatsApp as a channel
Sender number Your own WABA, registered and verified with Meta Provider number pool, no separate business account registration
Template ownership You create and submit authentication templates Provider default template populated with your parameters
Code lifecycle You generate, store, expire, and compare the code Platform can generate and verify, or accept a code you generated
Fallback to SMS You build the channel orchestration Configured as a channel strategy and executed by the platform
Time to first code Days, gated by account and template review Hours, gated by your own integration
Best for Full control of sender identity, template copy, and conversation continuity Verification as infrastructure, especially with multi-channel needs
Two WhatsApp OTP implementation paths comparing WABA-direct ownership with a managed OTP API

The pooled-number path exists because WABA registration is the slowest part of a WhatsApp OTP rollout. According to EngageLab OTP documentation , the OTP service includes a built-in WhatsApp number pool so codes can be delivered without registering a separate business account, alongside SMS, email, and voice behind the same API.

Choose the direct path when the WhatsApp thread is part of your product experience and you want your own verified sender inside it. Choose the API path when verification is plumbing: a code goes out, comes back confirmed, and shows up in reporting, with nobody on your side owning template review as a recurring job. Teams already sending WhatsApp marketing usually hold the WABA anyway, which tilts the decision back toward direct; if that describes you, the sender registration and template mechanics are covered in our WhatsApp API send-message guide , and the solution provider comparison covers picking the BSP that fronts that account.

What the Authentication Template Decides (WABA-Direct Path)

WhatsApp has no generic send-a-code endpoint. Every business-initiated message runs on a pre-approved template, and one-time passcodes must use the authentication category, which locks the body to a security string with your code as the variable.

The button is where the template reaches into your app. Authentication templates support three button behaviors, documented by Meta for Developers , and each one asks for something different from your client.

Button type What the user does Platform support What your app must provide
Copy code Taps to copy, switches to your app, pastes Android and iOS Nothing beyond a code input field
One-tap autofill Taps once; WhatsApp opens your app with the code Android only App signature hash registered on the template
Zero-tap Nothing; the code is broadcast and verified silently Android only Signature hash plus a broadcast receiver

One-tap and zero-tap are Android-only. Send an authentication template to an iPhone and the client renders a copy code button no matter what you configured, so iOS users type the code by hand either way. The fallbacks are also mandatory in the payload: a zero-tap template still has to declare one-tap and copy code buttons for users who will never see them.

Which path does this section apply to?

Button selection is a template-level decision on the WABA-direct path, where you author and submit the authentication template yourself. On the managed OTP path the provider owns the template: EngageLab's OTP service currently sends through a default WhatsApp template, and its public OTP API documentation exposes no copy-code, one-tap, or zero-tap selection. If autofill behavior is a hard product requirement, confirm it with the provider before you build a broadcast receiver you cannot reach.

WhatsApp authentication template button compatibility for copy code, one-tap, and zero-tap on Android and iPhone

What Meta Requires Before Your First Call

Templates get approved or rejected on policy grounds, and consent is where launches stall. EngageLab's WhatsApp documentation lists three conditions that apply before any authentication message goes out.

Opt-in comes before verification. Every business-initiated WhatsApp message needs prior opt-in, and authentication messages get no exemption. Collect that permission at signup. Ask for it on the verification screen and your first API call is already out of compliance.

WhatsApp cannot be a silent default. Meta asks you to offer WhatsApp as one way to receive the code instead of forcing it. Your verification screen needs a channel selector, and a second channel has to stay reachable.

Users must know the code will autofill. With zero-tap, successful verification looks like nothing happened. Say so on screen. Confused users request another code, and every resend is a billable message.

Build the Send and Verify Flow

How many calls you make depends on who generates the code. Integration plans routinely get this fork wrong and only notice it during code review.

When the platform generates the code , the surface is two calls: POST /v1/messages to send, then POST /v1/verifications with the returned message_id and the code the user typed. Request and response details are in the Send OTP and Verify OTP references.

When your own system generates the code , you send it with POST /v1/codes instead, and per the Custom Send OTP documentation there is no verification call to make afterwards: comparison stays inside your application. Teams with an existing risk engine usually pick this so verification events land where the rest of their signals already are.

The request shape is the easy part. The policies wrapped around it are what an attacker probes and what a frustrated user runs into.

Set these before launch, not after an incident

  • Expiry window: short enough to limit replay, long enough to survive a slow delivery. On the managed path this lives in a template field instead of your application config, and when the strategy includes WhatsApp the supported values are 1, 5, or 10 minutes.
  • Single use: a verified code cannot be verified twice. After a success or an expiry, issue a fresh message; do not retry the same verification session.
  • Resend cap: rate-limit per user, per destination number, and per IP. An uncapped resend button is a paid abuse surface.
  • Attempt limit: end the verification session after a small number of wrong codes, before a script can walk the whole space.

Keep API keys server-side. A verification request that can be triggered from client-side JavaScript is an open endpoint, and OTP endpoints are a standing target for SMS pumping fraud that bills you for traffic no real user generated.

Handle the Delivery Signals That Matter for OTP

Verification is one of the few message types where delivery state should change what your product does next. A code that never reached the device is a different problem from a code that arrived and got ignored, and only callbacks tell you which one you have .

The managed OTP path reports one lifecycle across every channel, so the same handler covers a code that went out over WhatsApp and one that fell back to SMS. Per the OTP Lifecycle Status Callback documentation , the states are:

Status What it tells you What to do with it
sent Accepted by the channel for delivery Start the clock on your verification screen
sent_fail The channel rejected it outright Watch by destination country; a cluster here is a routing problem, not a user problem
delivered It reached the handset A stalled signup after this points at your input screen, not the channel
delivered_fail It was accepted but never landed The clearest signal that the number cannot be reached on that channel
verified The user submitted the correct code Your conversion event, and the denominator for everything above

Instrument the funnel as requested → sent → delivered → verified . Most teams track only the last number, which hides whether a falling verification rate is a delivery problem, a UX problem, or fraud inflating the top of the funnel. Split the failures by channel and destination country. That split is what tells you whether WhatsApp has earned its place as the primary route in a given market.

Design the Fallback Before You Need It

WhatsApp cannot reach every user. The app might never have been installed, the number might not be registered with WhatsApp, opt-in could be missing, or data connectivity is down while cellular still works. Each case ends the same way: a user stranded on a verification screen.

On the managed path, fallback is configuration, not application logic . You order the channels in the template, and the platform moves to the next one when the current channel fails. Build around that in two places. Your callback handler should not fire a second send when it sees a failure: the platform has already moved on, and a manual retry means two paid messages and two codes competing for the same input box. And the send_channel value returned by the send call is the channel used at that moment, not a promise about which channel finally delivered .

WhatsApp-first OTP fallback flow showing platform-managed SMS and voice failover with callback status events

What still belongs to you is the policy : which countries should start on SMS because WhatsApp penetration is low, and how many total attempts a single signup may consume. Cap that total across all channels, not per channel. Three WhatsApp tries followed by three SMS tries is six paid messages for one signup, and an abuse script will use every one of them. For how the channels compare on reliability and cost, see our multi-channel OTP comparison .

Configure WhatsApp OTP: Console Walkthrough

This walkthrough uses the managed OTP service and its built-in WhatsApp number pool . You do not need your own WhatsApp Business Account or the separate WhatsApp Business API product for this path. Each step names the screen, the action, and the signal that tells you it worked.

1 Enable the OTP Service and Create an Application

Create an account, enable the OTP service, and enter the OTP sub-console. Create an application for the product or environment that will send codes. Keep production and testing applications separate: API keys, templates, usage data, and callback events are all scoped to the application, and mixing them makes a failed send hard to trace later.

2 Create the OTP Template

Open Template Management and click Create Template . Beyond the name and signature, this screen is where the security parameters live: code type and length, code validity period, and the sending strategy. Use an operational template ID such as login_otp_whatsapp_primary so the purpose stays readable in API requests, callback payloads, and reporting without opening the template.

Watch out for the validity period. When the strategy includes WhatsApp, the supported values are 1, 5, or 10 minutes, so a 3-minute window designed on a whiteboard will not survive contact with this form.

EngageLab OTP console showing the Create Template form with code validity and channel strategy settings

3 Set WhatsApp as the Primary Channel

In the Phone number channel section, set WhatsApp as the primary sending channel. The managed path uses a default WhatsApp OTP template, so your control here stops at the message additions: whether to include a security reminder telling the user not to share the code, and whether to show how long the code stays valid. Button layout stays with the provider's template.

4 Add SMS or Voice Fallback

Add up to two fallback channels behind WhatsApp. A typical strategy is WhatsApp → SMS → Voice , and each channel can appear only once. This screen is where the fallback design from the previous section actually takes effect: if WhatsApp delivery fails, the platform attempts the next configured channel without another API call from you.

5 Submit the Template and Wait for Approval

Submit the template for review. It enters a pending state and cannot carry traffic until it is approved. Before moving on, confirm the status reads approved, WhatsApp is the intended primary channel, the fallback order is what you designed, and the code length and validity match your authentication flow.

EngageLab OTP Template Management showing an approved template ready for API traffic

6 Create a Server-Side API Key

Open API Keys and create a key for the application. Set an expiration date, an IP allowlist, and the minimum permissions the flow needs. Store the credentials on your backend only: an OTP key reachable from browser JavaScript or shipped inside a mobile binary is an open send endpoint, which is the fraud surface described earlier.

EngageLab OTP console showing API key permissions, IP allowlist, and expiration settings

7 Wire Send, Verify, and the Callback

Call POST /v1/messages with the destination number and the approved template ID when a user requests a code, and keep the returned message_id : it is what ties the later check back to this send. When the user submits the code, call POST /v1/verifications with that ID and the value they typed, and let the protected action proceed only when the response confirms verification.

1. Send the code from your backend. Replace the placeholders with the destination, template ID, and a Base64-encoded dev_key:dev_secret credential. Never expose that credential in browser or mobile code.

curl --request POST 'https://otp.api.engagelab.cc/v1/messages' \
  --header 'Content-Type: application/json' \
  --header "Authorization: Basic $OTP_BASIC_AUTH" \
  --data '{
    "to": "+6591234567",
    "template": {
      "id": "login_otp_whatsapp_primary",
      "language": "default",
      "params": {}
    }
  }'

A successful response returns the identifier you must retain. send_channel is the channel used at this stage, not proof of the channel that ultimately delivered after fallback.

{
  "message_id": "1725407449772531712",
  "send_channel": "whatsapp"
}

2. Verify the code server-side. Pair the user-entered value with the message_id from the send response.

curl --request POST 'https://otp.api.engagelab.cc/v1/verifications' \
  --header 'Content-Type: application/json' \
  --header "Authorization: Basic $OTP_BASIC_AUTH" \
  --data '{
    "message_id": "1725407449772531712",
    "verify_code": "667090"
  }'

Continue the login, signup, or protected action only when verified is true . A successfully verified message cannot be verified a second time.

{
  "message_id": "1725407449772531712",
  "verify_code": "667090",
  "verified": true
}

Then register an HTTPS callback endpoint so the lifecycle states land somewhere you can query. Treat that feed as monitoring and reconciliation, not as a retry trigger; the channel strategy is already handling failover.

8 Test the Failure Paths, Not the Happy Path

Send a real code to your own number first, then spend the rest of the time on what breaks: a number with no WhatsApp account , an unreachable number, an expired code, a code submitted twice, a WhatsApp failure that should roll to SMS, and a callback endpoint that returns an error . These are the paths a happy-path demo never exercises and real traffic finds within hours. Top up the account balance before production traffic starts , because an empty balance stops sends regardless of how well the template is configured.

WhatsApp OTP Verification API FAQ

Do I need a WhatsApp Business Account to send OTPs?

Not always. Sending through the WhatsApp Business API directly requires your own registered and verified business account. Sending through an OTP API that maintains a WhatsApp number pool does not, which takes account registration and template review off your critical path. The trade-off is that the sender identity in the thread belongs to the provider, not your brand.

Should my backend generate the code, or the platform?

Either works, and the difference is what you maintain. When the platform generates it, the flow is send then verify, two calls, and expiry and single-use enforcement come with the template. When you generate it, you send the pre-generated value through the custom send endpoint and do the comparison yourself, with no verification call to the provider. Teams with an existing risk engine often keep generation in-house so verification events feed it directly.

Does WhatsApp OTP autofill work on iPhone?

No. One-tap autofill and zero-tap are Android-only capabilities of WhatsApp authentication templates. On iOS the WhatsApp client renders a copy code button instead, and the user pastes the code manually. This is a template-level behavior on the WABA-direct path; if you are on a managed OTP path, ask the provider which button types its template actually uses before sizing the work.

What should happen when the WhatsApp message fails?

On a managed OTP path the channel strategy handles it: the platform moves to the next configured channel on its own, so your callback handler should log the failure instead of issuing a second send. What you still own is the total attempt cap across all channels and the country-level decision about which channel should be primary. Uncapped retries multiply cost on exactly the traffic most likely to be automated abuse.

How do I compare WhatsApp OTP API providers?

Look past per-message price at the operational details: whether a number pool removes WABA registration, which authentication button types the template supports, how fallback is configured and who executes it, what delivery callbacks you receive, and per-country coverage for your actual user base. Our OTP API provider guide works through those criteria in detail.

Ship Verification That Holds Under Real Traffic

A WhatsApp OTP verification API takes an afternoon to call and considerably longer to run well. Pick the integration path by how much of the platform you genuinely want to operate. Settle early whether you or the platform generates the code, since that decides your call count. Set expiry, single-use, resend, and attempt policies before launch, not after the first abuse spike. And let the channel strategy own fallback instead of scripting retries into your callback handler.

Test the failure paths on both platforms before real users find them. Create a template, put an SMS failover behind WhatsApp, and send one code to your own number on an Android device and an iPhone.

Ready to build WhatsApp-first OTP with fallback already planned?

Use EngageLab OTP to generate, send, verify, and monitor codes across WhatsApp, SMS, voice, and email from one managed flow.

EngageLab OTP verification service