WhatsApp OTP: native one-time codes for login, password reset, and transaction confirm
Native WhatsApp OTP for login, password reset, and transaction confirmation. One-tap "Copy Code" button. Pro+ Cloud-API only, included in your plan — you pay Meta directly.
What WhatsApp OTP is
If you run a SaaS, e-commerce store, or fintech app in MY, PK, ID, PH, BD, or anywhere SMS pricing is brutal, you already know the pain: every login, password reset, or high-value checkout fires an SMS OTP, and that SMS costs you anywhere from $0.03 to $0.10 per send depending on the corridor and the operator's mood that week. At even modest volume the SMS bill becomes a top-five line item, and the conversion rate is mediocre because half the OTPs land in the spam folder of an unfamiliar shortcode the user doesn't recognise.
WhatsApp OTP — built on Meta's native Authentication template category — is the answer. The customer receives a normal-looking WhatsApp message from your business name, with a one-tap Copy Code button right under the body. They tap it, the code copies to their clipboard, they paste it back into your app, and they're in. Total time: 2-4 seconds. Conversion: dramatically higher than SMS because the message arrived from a verified business profile they already trust.
Botline ships authentication templates as a first-class feature in the same place you author Marketing and Utility templates — so the same Pro+ tenant who sends a broadcast in the morning can be sending login OTPs from their own backend by lunch.
Plan gate: Pro+ on Cloud API, no upcharge
WhatsApp OTP rides on the Authentication conversation category, which is a Cloud API-only feature on Meta's side. That means you need a Cloud API line connected to your account — which means Pro or Enterprise plan and a Meta Business account in good standing. Free / Starter tenants on the Baileys QR connection cannot send authentication templates; the feature is gated by the same Cloud API plumbing as Flows, Catalog, and Marketing Templates.
If you're already on Pro+ with Cloud API connected, OTP templates are included in your plan at no upcharge from Botline. You pay Meta directly per Cloud API conversation rate — and authentication conversations are significantly cheaper than SMS in most SEA corridors. Pakistan and Malaysia are roughly an order of magnitude below SMS pricing as of writing; check the live Meta WhatsApp pricing schedule for your specific country. Botline takes nothing on top.
Three high-value use cases
Authentication templates are intentionally narrow — Meta locks down the body text, no marketing language allowed — but the volume use cases are enormous:
- Login OTP — user enters phone number, you fire
POST /tenant/otp/send, customer taps Copy Code, pastes into your login screen. Replaces every SMS gateway you currently pay for. The single biggest cost-saving switch most tenants make. - Password reset — "Forgot password?" flow. Same shape as login, but typically lower volume and higher per-event value because abandoned-reset users are users you've effectively lost. Better delivery rate than email + SMS combined.
- Transaction confirmation / 2FA — high-value checkout, withdrawal, money transfer, profile-change. Fire an OTP before authorising, log the response, complete the action. Many fintech tenants pair this with the optional 90-second expiration footer Meta auto-renders below the button.
Author an authentication template
Open Dashboard → WhatsApp → Templates and click + New template. Pick category Authentication. The editor will swap the standard header/body/footer/buttons fields for an auth-only sub-editor — this is intentional, because Meta locks the body text on auth templates and rejects anything else.
- Body is auto-filled with Meta's required boilerplate: {{1}} is your verification code. The {{1}} placeholder is where the OTP code itself slots in at send time. Don't edit this. Meta will reject the template at submission.
- Code expiration — pick how long the code stays valid (5-90 minutes; 0 = no expiration footer rendered). When set to anything non-zero, Meta auto-renders a short footer line on the customer's side reading something like "This code expires in 5 minutes" — you don't author that yourself.
- OTP button type — pick one of three:
- One-tap copy code (default, recommended) — renders a "Copy Code" button. Customer taps, code lands on clipboard.
- Autofill — for Android apps with the Meta SDK installed; the code autofills the OTP field in your app. Highest-conversion option but app-side integration required.
- Zero-tap copy code — same as one-tap but the code copies automatically when the message arrives. Higher friction-removal but slightly more privacy-aggressive; pick deliberately.
- Security recommendation — optional toggle that adds Meta's standard "For your security, do not share this code" line. Recommended for fintech / payments use cases.
- Click Submit to Meta. Botline forwards the template to Meta's template-management API and starts polling for status. Approval is the fastest of any template category — typically under 5 minutes because the body is auto-fixed and there's no marketing-content review required.
Once status flips to Approved, the template is callable from your backend. Use the dashboard's Test Send OTP button on the template detail page to verify end-to-end delivery to your own phone before wiring it into production.
Send an OTP from your backend
Once the template is approved, point your existing OTP backend at Botline's endpoint. Auth is your normal tenant JWT — the same bearer token your dashboard uses, generated in Settings → API access.
HTTP request:
POST https://api.botline.cc/tenant/otp/send
Authorization: Bearer <your-tenant-jwt>
Content-Type: application/json
{
"phone": "+923224031899",
"templateName": "login_otp",
"code": "847203"
}
cURL:
curl -X POST https://api.botline.cc/tenant/otp/send \
-H "Authorization: Bearer $BOTLINE_JWT" \
-H "Content-Type: application/json" \
-d '{
"phone": "+923224031899",
"templateName": "login_otp",
"code": "847203"
}'
Node.js / TypeScript:
const res = await fetch('https://api.botline.cc/tenant/otp/send', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.BOTLINE_JWT}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
phone: customer.phoneE164,
templateName: 'login_otp',
code: generateNumericCode(6),
}),
});
if (!res.ok) throw new Error(`OTP send failed: ${await res.text()}`);
Important contract notes:
- Phone must be E.164 (with leading + and country code). Validation is strict — an unformatted local number is rejected.
- Code must be numeric, 4-8 digits. Generate it on your side; Botline does not generate the code, just delivers it.
- You are responsible for storing and verifying the code. Botline is the delivery channel, not the OTP authority. Persist the code with a TTL (matching the template's expiration), check on submit, expire on use.
- Rate limit: 100 OTPs per tenant per minute via an in-memory token bucket. Plenty for sane volume; if you need higher, contact support.
- Cost logging: every successful send writes a row to wa_conversation_cost_log with origin='auth_otp' and category='authentication'. The /admin/ai → WA Spend tab gained a dedicated OTP 7d column so you can watch the spend live. Country is inferred from the phone prefix for per-corridor pricing.
What the customer sees
The end-user experience is a normal-looking WhatsApp message from your verified business name. The body reads “847203 is your verification code.”, and right below it is a single button labelled Copy Code. Tap it — the code is on the clipboard. Paste into your login screen. Done.
If you set an expiration, Meta auto-renders a small footer line: “This code expires in 5 minutes.” If you toggled the security recommendation, the body is preceded by “For your security, do not share this code.” Both are rendered by Meta on the receiving device — you don't author either.
Compared to SMS, the message lands faster (no carrier hop), is far less likely to be marked spam (verified sender, blue-tick if you have it), and is cheaper across most SEA corridors by a meaningful multiple.
Common pitfalls
Most issues during OTP setup fall into one of these buckets:
- Trying to use marketing language in the body — Meta auto-rejects anything other than the locked body. Botline's editor enforces this client-side, but if you bypass it via the API you'll get a rejection on submit. Don't fight Meta on this; the locked body is the whole point of the category.
- Forgetting {{1}} in the body — the placeholder is required for the code to slot in. Botline pre-fills this; only an issue if you've hand-edited the body.
- Authoring the expiration manually in a footer — don't. Meta auto-renders the expiration footer based on the codeExpirationMinutes field; a manual footer will be stripped or rejected.
- Using non-E.164 phones — e.g. 03224031899 for a Pakistani number. Strip the leading 0, prepend the country code, prepend +. The endpoint validates strictly.
- Re-using a template across categories — a template approved for Authentication can't be used for Marketing and vice versa. Author a separate template per category.
- Skipping Test Send — always run the Test Send OTP button against your own phone after approval, before pointing production traffic at the endpoint. Catches misconfigured Cloud API instances and missing tokens before they bite you at scale.
Cost angle: why this is the single biggest line-item swap most SEA SMBs make
If you currently spend $1,000/month on SMS OTPs in MY/PK, the equivalent WhatsApp authentication conversation cost is typically a fraction of that — check the Meta pricing schedule for your country pair as the exact number changes per corridor. The exact savings depend on your country mix and the SMS aggregator you currently use; the typical SEA SMB sees 50-80% reduction in OTP delivery costs after the cutover, plus the soft win of higher conversion (because the OTP arrived from a recognised business name and not an unfamiliar shortcode).
Two flips matter for the migration:
- Phone-number coverage — SMS reaches 100% of phones; WhatsApp reaches phones with WhatsApp installed. In MY/PK/ID/PH that's >90% of smartphone owners but not 100%. Most teams ship a fallback: try WhatsApp first, fall back to SMS only if the user opts out or fails delivery. Botline doesn't handle the fallback for you — that's your backend's job, but it's a 10-line if-statement.
- Conversation pricing tiers — Meta's authentication category is its own pricing tier separate from utility/marketing. The exact per-conversation price varies by country; check the live Meta pricing page for your corridor before estimating savings at scale.
What's next
OTP composes naturally with the rest of Botline:
- Pair OTP with a Flow for high-value KYC capture — OTP first, then a Flow form for the rest of the onboarding.
- Watch your spend live on the /admin/ai → WA Spend tab — the new OTP 7d column tracks authentication conversations separately from marketing/utility/catalog/flow.
- If you haven't connected Cloud API yet, follow the Cloud API connection guide first.
Open Templates, author your first authentication template, and your SMS bill will start dropping by tomorrow. Questions? Email support@botline.cc or WhatsApp +92 322 4031899 — we read every message.