Cliqtel
  • 产品 ▾
    基础设施
    虚拟号码覆盖 70 多个国家的本地、移动和免费号码 SIP 中继适用于任何 PBX 的运营商级 SIP
    通信
    消息双向 SMS 与 WhatsApp 模板 云电话系统可视化呼叫流程、IVR、队列、CRM 弹屏 联络中心高级路由与 AI——抢先体验
    合作伙伴
    Cliqtel Connect面向 MSP 的白标平台
  • 解决方案
  • 价格
  • 文档
  • 关于
🇬🇧 EN 🇳🇱 NL 🇩🇪 DE 🇫🇷 FR 🇪🇸 ES 🇧🇷 PT 🇸🇦 AR 🇨🇳 ZH 🇯🇵 JA 🇮🇳 HI
登录 立即开始
Cliqtel
产品 虚拟号码覆盖 70 多个国家的本地、移动和免费号码 SIP 中继适用于任何 PBX 的运营商级 SIP 消息双向 SMS 与 WhatsApp 模板 云电话系统可视化呼叫流程、IVR、队列、CRM 弹屏 联络中心高级路由与 AI——抢先体验 Cliqtel Connect面向 MSP 的白标平台
覆盖范围 集成 价格 文档与帮助 关于
语言
EN NL DE FR ES PT AR ZH JA HI
登录 免费开始
← Help Center
On this page
Overview Why WhatsApp for OTP Prerequisites 1 — Create Auth Template 2 — Send OTP 3 — Verify the Code Copy Code Button SMS Fallback Best Practices FAQ

OTP & 2FA via WhatsApp

Messaging · 10 min read OTP WhatsApp API
What this guide covers: How to send one-time passwords via WhatsApp using Meta's authentication template category. Includes template setup, API examples, copy-code buttons, SMS fallback logic, and rate limiting best practices.

Overview

WhatsApp authentication templates let you send OTP codes that arrive as rich messages with a one-tap copy button. Users don't need to manually read and type the code — they tap "Copy Code" and paste it into your app.

WhatsApp OTPs are delivered faster than SMS in most markets, cost less in many regions, and have near-100% open rates because users actively check WhatsApp throughout the day.

Why WhatsApp for OTP

FactorSMSWhatsApp
Open rate~95%~99%
Delivery speed1-5 seconds<1 second
Copy-code buttonNo (manual typing)Yes (one-tap copy)
Sender identityNumber or alphanumericVerified business profile
Cost (EU)~€0.008~€0.035 (auth template)
Cost (India)~€0.005~€0.003 (auth template)
Requires appNoYes (WhatsApp installed)
Best of both worlds: Send via WhatsApp first, fall back to SMS after 10 seconds if delivery isn't confirmed. This gives you WhatsApp's speed and UX where available, with SMS as a universal safety net.

Prerequisites

  • A WhatsApp Business Account connected to Cliqtel (setup guide)
  • An approved authentication template in your Meta WABA
  • A Cliqtel API key (Dashboard → API Keys)
  • An SMS-enabled number for fallback (optional but recommended)

Step 1 — Create an Authentication Template

1Create a template in Meta Business Manager

Go to Meta Business Suite → WhatsApp Manager → Message Templates → Create Template.

  • Category: Authentication
  • Template name: login_otp
  • Language: English (add more as needed)

Meta provides a standard authentication template format. The body is auto-generated:

TEMPLATE BODY (AUTO-GENERATED BY META)
1 is your verification code.

Security: Do not share this code.

Where 1 is replaced with your OTP code at send time. You can optionally add:

  • Copy code button — adds a "Copy Code" button that copies the OTP to clipboard
  • Code expiry — shows "This code expires in X minutes" below the message
Template approval: Authentication templates are usually approved within minutes. Do not include marketing content or links — Meta will reject the template.

Step 2 — Send OTP via WhatsApp

2Send the authentication template via API
NODE.JS — SEND WHATSAPP OTP
const code = crypto.randomInt(100000, 999999).toString();

// Store code with 5-minute expiry
await redis.setex(`otp:${phoneNumber}`, 300, code);

// Send via WhatsApp
const response = await fetch('https://cliqtel.com/api/v1/whatsapp/messages', {
  method: 'POST',
  headers: {
    'Authorization': 'Bearer YOUR_API_KEY',
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    account_id: 1,                    // Your WhatsApp account ID
    to: '+31611398058',
    type: 'template',
    template: {
      name: 'login_otp',
      language: { code: 'en' },
      components: [{
        type: 'body',
        parameters: [{ type: 'text', text: code }]
      }, {
        type: 'button',
        sub_type: 'url',
        index: 0,
        parameters: [{ type: 'text', text: code }]
      }]
    }
  }),
});

const data = await response.json();
console.log(data.id, data.status); // message ID, "accepted"
PYTHON
import secrets, requests

code = str(secrets.randbelow(900000) + 100000)
redis_client.setex(f"otp:{phone_number}", 300, code)

resp = requests.post(
    'https://cliqtel.com/api/v1/whatsapp/messages',
    headers={'Authorization': 'Bearer YOUR_API_KEY'},
    json={
        'account_id': 1,
        'to': '+31611398058',
        'type': 'template',
        'template': {
            'name': 'login_otp',
            'language': {'code': 'en'},
            'components': [{
                'type': 'body',
                'parameters': [{'type': 'text', 'text': code}]
            }, {
                'type': 'button',
                'sub_type': 'url',
                'index': 0,
                'parameters': [{'type': 'text', 'text': code}]
            }]
        }
    },
)

print(resp.json()['id'], resp.json()['status'])

Step 3 — Verify the Code

3Compare user input with stored code

The verification logic is identical to SMS OTP — compare the user's input against the stored code in Redis or your database.

NODE.JS — VERIFY OTP
async function verifyOTP(phoneNumber, userInput) {
  const stored = await redis.get(`otp:${phoneNumber}`);

  if (!stored) return { valid: false, error: 'Code expired' };

  if (stored !== userInput) {
    const attempts = await redis.incr(`otp_attempts:${phoneNumber}`);
    await redis.expire(`otp_attempts:${phoneNumber}`, 300);
    if (attempts >= 5) {
      await redis.del(`otp:${phoneNumber}`);
      return { valid: false, error: 'Too many attempts' };
    }
    return { valid: false, error: 'Invalid code' };
  }

  await redis.del(`otp:${phoneNumber}`);
  await redis.del(`otp_attempts:${phoneNumber}`);
  return { valid: true };
}

Copy Code Button

When you configure the authentication template with a copy code button, the user sees a "Copy Code" button below the message. Tapping it copies the OTP to their clipboard so they can paste it into your app without typing.

This significantly improves conversion rates — users don't mistype digits or switch between apps to manually copy.

Pro tip: On Android, if your app uses the SMS Retriever API equivalent for WhatsApp, the code can be auto-filled without any user interaction at all.

SMS Fallback

Not all users have WhatsApp installed. Implement a fallback to SMS if WhatsApp delivery isn't confirmed within 10 seconds.

NODE.JS — WHATSAPP-FIRST, SMS FALLBACK
async function sendOTP(phoneNumber, code) {
  // 1. Try WhatsApp first
  const waResponse = await sendWhatsAppOTP(phoneNumber, code);

  // 2. Wait for delivery confirmation (max 10 seconds)
  const delivered = await pollDeliveryStatus(waResponse.id, {
    timeout: 10000,
    interval: 2000,
  });

  if (delivered) {
    return { channel: 'whatsapp', messageId: waResponse.id };
  }

  // 3. Fall back to SMS
  const smsResponse = await fetch('https://cliqtel.com/api/v1/sms/messages', {
    method: 'POST',
    headers: {
      'Authorization': 'Bearer YOUR_API_KEY',
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
      from_number_id: 42,
      to: phoneNumber,
      body: `Your code is ${code}. Expires in 5 minutes.`,
    }),
  });

  return { channel: 'sms', messageId: (await smsResponse.json()).id };
}

Best Practices

  • Use 6-digit codes — matches industry standard and works with copy-code button
  • Set 5-minute expiry — long enough to switch apps, short enough to be secure
  • Rate limit to 1 OTP per 60 seconds per number, 5 per hour
  • Always implement SMS fallback for users without WhatsApp
  • Track which channel delivered successfully to optimize future sends per user
  • Use a dedicated number for OTPs — don't mix authentication and marketing on the same number
  • Log the channel, delivery time, and verification result for fraud detection

FAQ

Is WhatsApp OTP cheaper than SMS?

It depends on the country. In India and Brazil, WhatsApp authentication templates are significantly cheaper than SMS. In the EU, SMS is often cheaper. Use the fallback pattern to optimize cost: try WhatsApp first in low-cost markets, SMS first in high-cost WhatsApp markets.

What happens if the user hasn't opted in?

Authentication templates are exempt from the usual marketing opt-in requirement. You can send OTP codes to any WhatsApp number without prior consent. However, the user must have WhatsApp installed and the number must be registered.

Can I customize the OTP message?

Authentication templates have a fixed format set by Meta. You can only customize the security disclaimer text and whether to include a copy-code button and expiry timer. The body format (1 is your verification code) cannot be changed.

How do I track delivery?

Cliqtel sends delivery status webhooks for WhatsApp messages: sent, delivered, read, and failed. Set up a webhook endpoint in your WhatsApp account settings to receive these updates.

Ready to integrate WhatsApp OTP?

Check the full WhatsApp setup guide for account connection and template management.

WhatsApp Guide →
© 2026 Cliqtel · cliqtel.com
关于我们 博客 合作伙伴 覆盖范围 API 文档 运行状态 隐私 条款 Cookie 帮助 搜索
cliqtel.com 由 Cliqtel B.V. 运营,注册地为荷兰泽斯特 · KVK 42033793 · VAT NL869402468B01 · SBI 62.09

我们使用必要的 Cookie 以确保 Cliqtel 正常运行。在您同意的情况下,我们也会使用分析类 Cookie 以改进我们的服务。Cookie 政策