惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

GbyAI
GbyAI
L
LINUX DO - 热门话题
月光博客
月光博客
B
Blog
博客园 - 叶小钗
美团技术团队
D
Docker
A
About on SuperTechFans
Stack Overflow Blog
Stack Overflow Blog
酷 壳 – CoolShell
酷 壳 – CoolShell
WordPress大学
WordPress大学
P
Proofpoint News Feed
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
Y
Y Combinator Blog
V
V2EX
Apple Machine Learning Research
Apple Machine Learning Research
博客园 - 三生石上(FineUI控件)
The Register - Security
The Register - Security
博客园_首页
The Cloudflare Blog
I
InfoQ
T
Tailwind CSS Blog
MongoDB | Blog
MongoDB | Blog
Engineering at Meta
Engineering at Meta
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
Microsoft Azure Blog
Microsoft Azure Blog
有赞技术团队
有赞技术团队
C
CERT Recently Published Vulnerability Notes
AWS News Blog
AWS News Blog
Spread Privacy
Spread Privacy
V
Visual Studio Blog
博客园 - Franky
Cloudbric
Cloudbric
Help Net Security
Help Net Security
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
N
News and Events Feed by Topic
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
K
KPMG report finds enterprise disconnect between AI and its ROI | CIO
Webroot Blog
Webroot Blog
博客园 - 【当耐特】
TaoSecurity Blog
TaoSecurity Blog
B
Blog RSS Feed
N
News | PayPal Newsroom
人人都是产品经理
人人都是产品经理
H
Heimdal Security Blog
L
LangChain Blog
PCI Perspectives
PCI Perspectives
Jina AI
Jina AI
Google DeepMind News
Google DeepMind News
Schneier on Security
Schneier on Security

DEV Community

Authentication Security Deep Dive: From Brute Force to Salted Hashing (With Java Examples) Why AI Systems Don’t Fail — They Drift Spilling beans for how i learn for exam😁"Reinforcement Learning Cheat Sheet" I Replaced Chrome with Safari for AI Browser Automation. Here's What Broke (and What Finally Worked) How Python Borrows Other People's Work The $40 Architecture: Processing 1 Billion API Requests with 99.99% Uptime Vibe Coding: A Workflow Guide (From Zero to SaaS) Most webhook security guides protect the wrong side. The scary part is delivery. Headless CMS for TanStack Start: Build a Blog with Cosmic EU Age Verification App "Hacked in 2 Minutes" — What Actually Happened Comfy Cloud’s delete function does not actually remove files Running AI Models on GPU Cloud Servers: A Beginner Guide Event-driven media intelligence with AWS Step Functions and Bedrock I scored 500 AI prompts across 8 quality dimensions — here's what broke How to Call Google Gemini API from Next.js (Free Tier, No Backend Needed) The Portal Protocol: Reclaiming Human Connection in the Age of AI How to Fix Your Team's Scattered Knowledge Problem With a Self-Hosted Forum Intro to tc Cloud Functors: A Graph-First Mental Model for the Modern Cloud Designing Multi-Tenant Backends With Both Ownership and Team Access I Built a Neumorphic CSS Library with 77+ Components — Here's What I Learned PostgreSQL Performance Optimization: Why Connection Pooling Is Critical at Scale Cómo construí un SaaS multi-rubro para gestionar expensas en Argentina con FastAPI + Vue 3 🚀 I Built an Ethical Hacking Scanner Tool – Open Source Project I Replaced /usage and /context in Claude Code With a Single Statusline A Pythonic Way to Handle Emails (IMAP/SMTP) with Auto-Discovery and AI-Ready Design I Collected 8.9 Million Polymarket Price Points — Here's What I Found About How Markets Really Move EcoTrack AI — Carbon Footprint Tracker & Dashboard Everyone's Using AI. No One Agrees How. 5 self-hosted ebook managers worth trying in 2026 Building Your First AI Agent with LangChain: From Chatbot to Autonomous Assistant Common SOC 2 Failures (Real World) Stop Vibe-Checking Your AI App: A Practical Guide to Evals How to Use SonarQube and SonarScanner Locally to Level Up Your Code Quality Your Next To-Do App Is Dead — I Replaced Mine with an OpenClaw AI Sign a Nostr event in 60 lines of Python using coincurve — no nostr-sdk, no nbxplorer, no rust toolchain ITGC Audit Explained Like You’re in Big 4 Patch Tuesday abril 2026: Microsoft parcha 163 vulnerabilidades y un zero-day en SharePoint Stop scraping everything: a better way to track competitor price changes Listing on MCPize + the Official MCP Registry while routing payments OUTSIDE the marketplace — how I kept 100% of my x402 revenue Building an AI-Powered Risk Intelligence System Using Serverless Architecture Why We Ripped Function Overloading Out of Our AI Toolchain Testing AI-Generated Code: How to Actually Know If It Works SaaS Churn Is Killing Your Business. Here Is What to Do About It (Without a Support Team) The Speed of AI Is No Longer Linear - And Self-Improving Models Are Why How to Implement RBAC for MCP Tools: A Practical Guide for Engineering Teams From Standard Quote to Persuasive Proposal: AI Automation for Arborists I built a CLI that scaffolds complete multi-tenant SaaS apps Axios CVE-2025–62718: The Silent SSRF Bug That Could Be Hiding in Your Node.js App Right Now The dashboard that ended our friendship Data Pipelines Explained Simply (and How to Build Them with Python) The Hidden Cost of AI Systems Nobody Talks About. undefined vs undeclared, and how typeof behaves Switching from file-based jobs to NATS/Kafka in Rust without changing code io_uring Adventures: Rust Servers That Love Syscalls Why Agentic AI is Killing the Traditional Database The POUR principles of web accessibility for developers and designers Quantum Neural Network 3D — A Deep Dive into Interactive WebGL Visualization How To Install Caveman In Codex On macOS And Windows Automation Pipeline Reliability: Why Your Workflow Breaks When Nobody Is Watching I Built an 'Open World' AI Coding Agent — It Works From ANY Folder From Freelancing to Product: A Tech Service Company's SaaS Transformation China's AI Giants: Adding Tencent Hunyuan & ByteDance Doubao to AI University (74 Providers) On the Vibe Coders and Their Lies clerk: Auto-Summarize Your Claude Code Sessions AI Weekly — 2026/04/10–04/17 | The Model Lockdown Is Here, but the Toolchain Is the Real Battleground AI 週報 — 2026/04/10–2026/04/17 模型封鎖潮來了,但工具鏈才是真戰場 Maybe this is how Open-Source apps are born... 🚀 Fine-Tune LLMs with LoRA and QLoRA: 2026 Guide tRPC v11 + Next.js App Router: End-to-End Type Safety Without the Boilerplate ShadCN UI in 2026: Why I Stopped Installing Component Libraries and Started Owning My Components SaaS Billing in React Server Components: Stripe + Supabase Without a Single `useEffect` Join our DEV Weekend Challenge — $1,000 in Prizes Across TEN winners! Submissions Due April 20 at 6:59 AM UTC. Implementing FSRS Spaced Repetition in Flutter + Supabase — Adding Memory Science to an AI Learning App "I Texted My Localhost From the Train — Claude Code Fixed the Bug Before I Got Home" I Built a Sales Prep AI and It Went Deeper Than Expected Design to Code #2: One JSON, Eleven Outputs Solving the 100M-Row Problem: A Summary Table Pattern for High-Volume Push Notification Logs Flutter Web With Wasm: What Actually Changes For Developers I Built 50 Royalty-Free Soundtracks for My Side Project in a Weekend Using AI Music Generation The Vibe Coding Security Checklist: 7 Things to Check Before You Ship Stop Letting Googlebot Guess Fix Your React App's SEO Right Desconstruindo o Streaming do LinkedIn: Como Criar um Engine de Extração de Vídeo de Alta Performance com HLS e FFmpeg (EDA Part-1) EDA (Exploratory Data Analysis) Explained With Real Life — Why Looking at Your Data Is the Most Important Step in Machine Learning Brand Relationship Management at Scale: Our 4-Touch Outreach System for 200+ Brands Why String.fromEnvironment() Might Return an Empty String in Dart JGuardrails 1.0.0 — Hardening Java LLM Apps Against Jailbreaks, Toxicity, and Prompt Injection Plan and Schedule a Full Week of Threads Content From One Claude Conversation Coding Cat Oran Ep3, Five Tables Changed Everything Updated: BFF Pattern I'm done watching freelancers get buried by 200 proposals. So I'm building the alternative. This is my first post BFS Algorithm in Java Step by Step Tutorial with Examples Tracking LLM Pricing Monthly: An Open Dataset for 22 AI Models How We Measure Content ROI on a Comparison Site: Revenue Attribution Without Perfect Data Introducing Nova AI Ops: The AI-Native Operating System for SRE Teams I built a free desktop video downloader for Windows — Grabbit How Talkie OCR Helps Vision-Impaired & Dyslexic Users Read the World Around Them VRCFaceTracking安装和iPhone面捕配置教程,有bug Even CrowdStrike Can't See Your Agents The Automation Gold Rush: What n8n Workflows and Claude Are Opening Up for Developers Right Now
How to Send Auth Codes via WhatsApp in Your App With Kinde
Shola Jegede · 2026-05-15 · via DEV Community

Your users are in San Francisco, Jakarta, São Paulo, and Sydney. They have WhatsApp open all day. They check it before they check their SMS inbox. When your app sends an OTP to their phone number, it lands in a carrier SMS thread they barely look at. When it lands in WhatsApp, they see it instantly.

In this article, you will learn:

  • Why WhatsApp OTP delivers better completion rates than SMS in high-penetration markets
  • How Kinde delivers phone OTPs via WhatsApp when configured, with automatic SMS fallback
  • What you need before you start: Twilio account, WhatsApp Sender, Kinde Pro
  • How to configure Twilio Verify with a WhatsApp Sender
  • How to connect your Twilio account to Kinde
  • How to enable phone authentication in your Next.js app
  • How to enable WhatsApp as the delivery channel in Kinde
  • How to configure SMS as the automatic fallback
  • How to test the full flow before going live
  • What to watch for in Africa, South Asia, and Southeast Asia specifically

Let's dive in!

Why WhatsApp OTP Is the Right Choice for Your Market

If your users are in Europe or North America, SMS OTP is a reasonable default. Delivery is reliable, carrier infrastructure is solid, and most users check texts promptly.

If your users are in Nigeria, Kenya, Indonesia, Brazil, India, or the Philippines, the calculation is different. WhatsApp penetration in these markets is near-universal. Users across sub-Saharan Africa and Southeast Asia treat WhatsApp as their primary communication channel. SMS sits behind it, sometimes significantly behind.

The data on this is clear. Twilio has documented that in heavy WhatsApp countries, 20 to 40 percent of users pick the WhatsApp channel when given the option for OTP delivery. More importantly, WhatsApp OTPs arrive over Wi-Fi connections. A user whose cellular data signal is weak but who is on Wi-Fi still receives the WhatsApp message instantly. SMS requires telephony connectivity. In markets where cellular data coverage is more reliable than SMS delivery, WhatsApp is not just more convenient. It is more reliable.

There is also a cost argument. WhatsApp authentication messages cost 50 to 99 percent less than SMS in most markets globally. In developing markets where SMS costs are highest, the savings are largest. At any meaningful scale, the economics strongly favor WhatsApp.

The correct production setup is WhatsApp first with automatic SMS fallback for the minority of users who do not have WhatsApp. That is exactly what Kinde gives you.

Two-column comparison. LEFT: SMS OTP delivery flow showing Phone number → Carrier network → SMS inbox (variable delivery time, carrier dependent, fails on weak signal). RIGHT: WhatsApp OTP delivery flow showing Phone number → WhatsApp Business API → WhatsApp inbox (instant, Wi-Fi compatible, end-to-end encrypted, automatic SMS fallback if WhatsApp unavailable)

How Kinde Handles WhatsApp OTP

Kinde supports phone number as both a primary authentication method and a secondary MFA factor. When phone authentication is configured, Kinde uses Twilio to deliver OTP codes. When you configure a WhatsApp Sender in your Twilio account and connect it to Kinde, Kinde automatically prefers WhatsApp for delivery and falls back to SMS when WhatsApp is unavailable.

This is Twilio's Verify WhatsApp feature working through Kinde's phone authentication layer. You do not write any message-routing logic. Kinde and Twilio handle it. When a user enters their phone number on your sign-in screen, the OTP arrives in their WhatsApp. If they do not have WhatsApp or the delivery fails, Twilio's Verify API automatically retries via SMS.

There are a few important constraints to know before you start:

Kinde Pro is required for production phone authentication. Kinde gives you 10 free SMS test sends per month on any plan to experiment with the feature, but production phone authentication (including WhatsApp) requires upgrading to the Pro plan or above.

The OTP message format is not editable. Kinde uses a standardized SMS/WhatsApp template that complies with OTP best practices. The message arrives as: 123456 is your verification code. followed by For your security, do not share this code. No app name, no URL, no hash. The sender name shown at the top of the WhatsApp chat comes from your registered Twilio business display name, not the message body. You cannot customize the message text or format.

A Twilio business account is required. You cannot use a personal or trial Twilio account for production A2P (Application-to-Person) messaging. You need a Twilio business account with a configured phone number or Messaging Service.

10DLC registration may be required in the US. If your users are in the United States, Twilio requires 10DLC registration for SMS. Check Twilio's guidelines and A2P messaging requirements for your target countries before setting up.

What You Need Before You Start

Before touching the Kinde dashboard, have the following ready:

A Twilio business account with your Account SID and Auth Token from the Twilio Console.

A Twilio phone number or Messaging Service SID. Twilio gives you two options for identifying the sender: a specific phone number or a Messaging Service (a pool of numbers Twilio manages for deliverability). The Messaging Service is recommended for production because Twilio handles number rotation and deliverability automatically.

A WhatsApp Sender configured in Twilio. This is a WhatsApp Business Account (WABA) phone number registered with Meta and approved for authentication message templates. Twilio's Verify WhatsApp documentation walks through this process. You need Meta Business verification and an approved authentication template before WhatsApp delivery works.

A Kinde account on the Pro plan or above.

A Next.js app with the Kinde SDK installed. If you are starting fresh, the Kinde Next.js quickstart at docs.kinde.com gets you to a working auth setup in under ten minutes.

Note: You can complete the Kinde configuration and test with the 10 free SMS sends before completing the WhatsApp Sender setup in Twilio. This lets you verify the Kinde connection is working before adding WhatsApp to the mix.

Step #1: Configure Twilio for Phone and WhatsApp Delivery

Log in to your Twilio Console at console.twilio.com.

Get your credentials. From the Console Dashboard, copy your Account SID and Auth Token. Keep the Auth Token private.

Set up a Messaging Service (recommended) or phone number. If using a Messaging Service, navigate to Messaging → Services → Create Messaging Service. Give it a name, add your sender number to it, and copy the Messaging Service SID.

If using a specific Twilio phone number instead, navigate to Phone Numbers → Manage → Active numbers and copy the phone number in E.164 format (e.g. +12025551234).

Configure the WhatsApp Sender for Verify. This is the step that enables WhatsApp delivery. Navigate to Messaging → Senders → WhatsApp senders in the Twilio Console.

Twilio Console showing the Verify section in the left sidebar, with WhatsApp Senders highlighted

Select Add Sender. You will be prompted to connect a WhatsApp Business Account. This requires:

  • A Meta Business Account (verified)
  • A phone number registered as a WhatsApp Business number
  • An approved WhatsApp authentication message template

Twilio auto-creates the authentication template in supported languages once you complete the WhatsApp Sender setup. The template uses the Copy Code format, which displays the OTP with a button users tap to copy it to their clipboard.

Note: WhatsApp Sender approval from Meta typically takes one to three business days. Plan your timeline accordingly. You can continue with the Kinde setup and test using SMS while waiting for WhatsApp approval.

Step #2: Connect Twilio to Kinde

With Twilio credentials ready, connect them to Kinde.

In your Kinde dashboard, navigate to Settings → Environment → Phone providers.

Kinde Settings showing the Phone providers section with a form to enter Twilio credentials. Fields visible: Account SID, Auth Token, and the choice between Messaging Service SID or Twilio Phone Number. Show the fields partially filled

Enter your Twilio credentials:

  • Account SID: from your Twilio Console dashboard
  • Auth Token: from your Twilio Console dashboard
  • Messaging service SID or Twilio phone number: enter whichever you set up in Step #1

If you want to use a fallback in case the primary Twilio service is interrupted, enable the fallback service option and configure a secondary provider.

Select Save.

Terrific! Kinde can now route phone OTP delivery through Twilio. The WhatsApp channel activates automatically once your WhatsApp Sender is approved in Twilio.

Step #3: Enable Phone Authentication in Kinde

With Twilio connected, turn on phone as an authentication method for your application.

Navigate to Settings → Environment → Authentication. In the Passwordless section, find the Phone tile and select Configure.

Kinde Settings > Environment > Authentication page showing the Passwordless section with Email + code, Phone, and Username + code tiles. The Phone tile has a

In the configuration window, toggle phone authentication on for the applications you want it active for. If you have multiple applications in your Kinde environment, you can enable it selectively per application.

Select Save.

Your sign-in screen now includes a phone number input option alongside the existing email input. Users can choose to sign in with their phone number and receive an OTP instead of entering a password or email code.

Step #4: Enable WhatsApp as the Delivery Channel

With phone authentication active and Twilio connected, the final step is confirming that WhatsApp is set as the preferred delivery channel.

In your Kinde dashboard, navigate to Settings → Environment → Phone providers. In your Twilio configuration, you will see the WhatsApp delivery option.

Kinde Settings > Phone providers showing the Twilio configuration with a WhatsApp section. Show the toggle or setting that enables WhatsApp as the preferred delivery channel, with SMS shown as the fallback

Enable the WhatsApp delivery option. Once enabled:

  • Kinde sends the OTP via WhatsApp when the user's phone number is registered with WhatsApp
  • If WhatsApp delivery fails (user does not have WhatsApp, or the delivery fails for any reason), Twilio's Verify API automatically falls back to SMS
  • No code changes are needed in your application

The fallback happens silently. Your users do not see an error or need to request a retry. Twilio detects the WhatsApp delivery failure and retries via SMS automatically.

Step #5: Configure Phone Auth as MFA (Optional)

If you want to use WhatsApp OTP as a second factor rather than (or in addition to) a primary authentication method, configure it at the MFA level.

Navigate to Settings → Environment → Multi-factor auth.

Kinde Settings > Multi-factor auth page showing the

In the Additional authentication methods section, toggle on SMS. Per the Kinde docs, the SMS MFA option delivers via WhatsApp when configured, with automatic fallback to SMS. The WhatsApp preference follows from your Twilio configuration in Step #4 automatically.

Set MFA to Yes (mandatory) or Optional depending on your product's security requirements:

  • Yes: every user is required to set up MFA on first sign-in. For products targeting enterprise customers or handling sensitive data, this is the right default.
  • Optional: users are prompted to set up MFA but can skip it. They can enable it later from their profile settings.

Note: if your primary authentication method is already phone OTP (email OTP), do not set phone SMS as the secondary MFA factor. Kinde recommends against using the same channel for both primary and secondary factors. If your primary auth is email OTP, use phone SMS or authenticator app for MFA. If your primary auth is phone OTP, use email or authenticator app for MFA.

Select Save.

Step #6: Wire Phone Authentication Into Your Next.js App

Kinde's hosted sign-in screen already includes the phone number input once you enable phone authentication. Your Next.js app does not need code changes to show the phone sign-in option. It appears automatically on the Kinde-hosted auth pages.

However, if you want to pre-fill the phone number for users coming from a known context (for example, users you have invited via phone number), use the login_hint parameter to reduce friction:

// app/api/auth/[kindeAuth]/route.ts
// Standard Kinde auth setup — no changes needed for basic WhatsApp OTP

// For login with pre-filled phone number hint:
// Pass login_hint in the authorization URL when you know the user's phone number
// This skips the phone number entry step

import { handleAuth } from "@kinde-oss/kinde-auth-nextjs/server";
export const GET = handleAuth();

Enter fullscreen mode Exit fullscreen mode

For inviting users with a known phone number and pre-filling the sign-in form:

// components/PhoneInviteButton.tsx
// Pre-fills the phone number on the Kinde sign-in screen
// Useful when you know the user's phone number before they authenticate

import { LoginLink } from "@kinde-oss/kinde-auth-nextjs/components";

interface PhoneInviteButtonProps {
  phoneNumber: string; // E.164 format e.g. "+2348012345678"
}

export function PhoneInviteButton({ phoneNumber }: PhoneInviteButtonProps) {
  return (
    <LoginLink
      authUrlParams={{
        // login_hint pre-fills the identity field on the Kinde sign-in screen
        // The user sees their phone number already entered and just confirms it
        login_hint: phoneNumber,
        // connection_id routes directly to phone authentication
        // Skips the method selection screen
        connection_id: "phone",
      }}
    >
      Sign in with phone
    </LoginLink>
  );
}

Enter fullscreen mode Exit fullscreen mode

For protecting API routes on the server, the existing getKindeServerSession approach works identically regardless of whether the user authenticated via email or phone:

// app/api/example/route.ts
// Phone-authenticated users produce the same session as email-authenticated users
// No changes needed to protected route logic

import { getKindeServerSession } from "@kinde-oss/kinde-auth-nextjs/server";
import { NextResponse } from "next/server";

export async function GET() {
  const { isAuthenticated, getUser } = getKindeServerSession();

  if (!(await isAuthenticated())) {
    return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
  }

  const user = await getUser();

  // user.phone is populated when the user authenticated via phone number
  // user.email is populated when the user authenticated via email
  // Both may be present if the user has linked both identities

  return NextResponse.json({
    userId: user?.id,
    phone: user?.phone,
    email: user?.email,
  });
}

Enter fullscreen mode Exit fullscreen mode

Amazing!

Step #7: Test the Full WhatsApp OTP Flow

Before going live, test three scenarios in your Kinde non-production environment.

Test 1: WhatsApp delivery to a WhatsApp-registered number

Enter a phone number that is registered with WhatsApp. Kinde should route the OTP through Twilio Verify to WhatsApp. The code arrives in your WhatsApp with your Twilio-registered business name as the sender.

Note: Kinde provides 10 free SMS sends per month for testing. These 10 free sends apply to SMS delivery. WhatsApp delivery tests use your Twilio Verify credits.

Test 2: Automatic SMS fallback

To test the fallback, enter a valid phone number that is not registered with WhatsApp, or temporarily disable WhatsApp in your Twilio account. Twilio Verify should detect the WhatsApp delivery failure and automatically send via SMS. The OTP code is the same in both channels.

Test 3: MFA flow (if configured)

If you have set phone SMS as an MFA factor, sign in with email OTP first. On the second factor screen, Kinde prompts for the phone-based code. Enter your phone number if not already registered, and confirm the WhatsApp delivery.

Kinde-hosted sign-in screen showing the phone number input field. Show a clean phone number entry UI with the country code dropdown and the number field. This is what users see when they choose phone authentication

A WhatsApp message on a phone showing a Kinde OTP delivery. The message shows the standard format

Country-Specific Notes for African and Southeast Asian Markets

Nigeria and Ghana: WhatsApp penetration is extremely high, above 90 percent of smartphone users. SMS delivery is inconsistent in some areas. WhatsApp OTP is strongly recommended as the primary channel. Twilio's A2P messaging in Nigeria requires pre-registered sender IDs. Check Twilio's Nigeria SMS guidelines before launch.

Kenya, Tanzania, Uganda: WhatsApp is widely used but M-Pesa and other mobile money services mean users are accustomed to SMS-based verification from financial services. WhatsApp OTP delivers a better experience but SMS fallback is particularly important in rural areas.

Indonesia, Philippines, Vietnam: Near-universal WhatsApp (and Line, in some markets) penetration. International SMS is expensive from most providers. WhatsApp OTP delivers significant cost savings at scale here.

India: WhatsApp has over 500 million users. However, Meta has implemented messaging limits for WhatsApp Business in India. Review the current Meta Business Platform limits for Indian traffic before projecting volume. Twilio's documentation covers the current limits.

Brazil: One of the highest WhatsApp penetration rates globally. WhatsApp OTP is effectively the standard for authentication flows built for Brazilian users.

For all markets: always test with real numbers in the target country before launch. Carrier behavior, number formatting requirements (always use E.164 format), and delivery timing vary by region.

Troubleshooting Common Issues

OTP not received via WhatsApp

Check that your WhatsApp Sender is approved in Twilio and that the authentication template is active. An unapproved or suspended sender silently fails delivery. Check Twilio's delivery logs for error codes. Error code 63024 from Twilio means the phone number is not associated with a WhatsApp account and the fallback to SMS should have triggered.

OTP received via SMS instead of WhatsApp

This is the expected behavior when WhatsApp delivery is not available. If you expected WhatsApp delivery but got SMS, check: Is the destination phone number registered with WhatsApp? Is the WhatsApp Sender active and approved in Twilio? Has the user blocked your business sender in WhatsApp?

"You need to enter your Twilio account details" message in Kinde

This appears when Kinde's phone authentication is configured but Twilio credentials have not been saved, or the credentials are invalid. Navigate to Settings → Environment → Phone providers and re-enter your Twilio Account SID and Auth Token.

Users in the United States not receiving SMS

US carriers require 10DLC registration for A2P SMS. If your Twilio account is not 10DLC registered for US traffic, messages to US numbers will fail. Complete 10DLC registration in Twilio before enabling phone authentication for US users.

Phone number formatting errors

Kinde and Twilio both require phone numbers in E.164 format (e.g. +2348012345678 for a Nigerian number). If users enter numbers without country codes, the OTP send will fail. Kinde's hosted sign-in screen includes a country code dropdown to help users format numbers correctly. If you are pre-filling numbers via login_hint, always format them in E.164.

Putting It All Together

Here is a summary of the full setup:

Step What you do Where
Twilio business account Get Account SID, Auth Token, Messaging Service Twilio Console
WhatsApp Sender Register WhatsApp Business number with Meta via Twilio Twilio Console > Verify > WhatsApp Senders
Connect Twilio to Kinde Enter Twilio credentials Kinde > Settings > Phone providers
Enable phone auth Toggle on Phone in Passwordless section Kinde > Settings > Authentication
Enable WhatsApp delivery Configure WhatsApp as preferred channel Kinde > Settings > Phone providers
Configure MFA (optional) Enable SMS as second factor Kinde > Settings > Multi-factor auth
Test 3-scenario flow test before going live Non-production environment

Full delivery flow showing Your App (user enters phone number) → Kinde (routes to Twilio) → Twilio Verify (checks WhatsApp availability) → two paths: WhatsApp path (user has WhatsApp, message delivered via WhatsApp Business API, end-to-end encrypted) and SMS fallback path (user does not have WhatsApp or delivery fails, Twilio retries via SMS carrier network). Both paths return to user entering OTP in your app → Kinde verifies → user authenticatedn

Conclusion

In this article, you connected Twilio Verify to Kinde, registered a WhatsApp Business Sender, enabled phone authentication, and configured WhatsApp as the preferred OTP delivery channel with automatic SMS fallback. Users in markets where WhatsApp dominates now receive their authentication codes in the app they check first, over Wi-Fi when needed, at a fraction of the SMS cost.

The setup is the same for phone as primary auth and as MFA. Once your Twilio credentials are in Kinde and your WhatsApp Sender is approved, the routing is handled entirely by Twilio Verify. Your application code does not change. Kinde issues the same JWT regardless of whether the OTP arrived via WhatsApp or SMS.

Kinde is free for up to 10,500 monthly active users. Phone authentication and WhatsApp OTP require the Pro plan. Create your account at kinde.com and meet your users where they already are.