Cliqtel
  • Produtos
    Infraestrutura
    Números VirtuaisLocais, móveis e gratuitos em mais de 70 países Troncos SIPSIP de nível operadora para qualquer PBX Dados de viagem (eSIM)Dados móveis em 200+ países, sem roaming
    Comunicações
    MensagensSMS bidirecional e modelos de WhatsApp Sistema Telefônico em NuvemFluxos visuais de chamadas, IVR, filas, pop-up de CRM Contact CenterRoteamento avançado e IA — acesso antecipado
    Parceiros e IA
    Cliqtel ConnectPlataforma white-label para MSPs Acesso de IA (MCP)Telecom operável por IA para agentes e copilotos
  • Soluções
    Por equipe
    Equipes RemotasUm número comercial para uma equipe distribuída Equipes de SuporteFilas, IVR e caixas de entrada compartilhadas para suporte Equipes de VendasClick-to-call, pop-up de CRM e identificador de chamadas local
    Explorar
    CoberturaNúmeros e tarifas em mais de 70 países IntegraçõesConecte seu PBX, CRM e ferramentas
  • Preços
    Preços e planos
    PreçosPreços transparentes por número e por uso Cobertura e tarifasTarifas de chamadas e de números por país PacotesPacotes pré-pagos de números + minutos
  • Documentação
    Primeiros passos
    IntroduçãoConfigure sua conta e seu primeiro número Referência da APIAPI REST para números, chamadas e mensagens Fluxos de ChamadasCrie IVRs e roteamento visualmente Central de AjudaFAQs, guias e resolução de problemas
    Guias
    Configuração de PBX e SIPConecte 3CX, FreePBX, Asterisk e Teams Guias de MensagensGuias de integração de SMS e WhatsApp RegulatórioRegras de registro de números por país
  • Sobre
    Empresa
    Sobre a CliqtelQuem somos e o que construímos ContatoFale com nossa equipe de vendas ou suporte ParceirosTorne-se parceiro ou revendedor Cliqtel
    Recursos
    BlogNovidades de produto e guias de telecom StatusStatus ao vivo da plataforma e da rede IntegraçõesMarketplace de PBX, CRM e ferramentas
English EN Nederlands NL Deutsch DE Français FR Español ES Português PT العربية AR 中文 ZH 日本語 JA हिन्दी HI
Entrar Solicitar um número
Cliqtel
Produtos Números VirtuaisLocais, móveis e gratuitos em mais de 70 países Troncos SIPSIP de nível operadora para qualquer PBX Dados de viagem (eSIM)Dados móveis em 200+ países, sem roaming MensagensSMS bidirecional e modelos de WhatsApp Sistema Telefônico em NuvemFluxos visuais de chamadas, IVR, filas, pop-up de CRM Contact CenterRoteamento avançado e IA — acesso antecipado Cliqtel ConnectPlataforma white-label para MSPs Acesso de IA (MCP)Telecom operável por IA para agentes e copilotos
Soluções Equipes RemotasUm número comercial para uma equipe distribuída Equipes de SuporteFilas, IVR e caixas de entrada compartilhadas para suporte Equipes de VendasClick-to-call, pop-up de CRM e identificador de chamadas local CoberturaNúmeros e tarifas em mais de 70 países IntegraçõesConecte seu PBX, CRM e ferramentas
Preços PreçosPreços transparentes por número e por uso Cobertura e tarifasTarifas de chamadas e de números por país PacotesPacotes pré-pagos de números + minutos
Documentação IntroduçãoConfigure sua conta e seu primeiro número Referência da APIAPI REST para números, chamadas e mensagens Fluxos de ChamadasCrie IVRs e roteamento visualmente Central de AjudaFAQs, guias e resolução de problemas Configuração de PBX e SIPConecte 3CX, FreePBX, Asterisk e Teams Guias de MensagensGuias de integração de SMS e WhatsApp RegulatórioRegras de registro de números por país
Sobre Sobre a CliqtelQuem somos e o que construímos ContatoFale com nossa equipe de vendas ou suporte ParceirosTorne-se parceiro ou revendedor Cliqtel BlogNovidades de produto e guias de telecom StatusStatus ao vivo da plataforma e da rede IntegraçõesMarketplace de PBX, CRM e ferramentas

Idioma
EN NL DE FR ES PT AR ZH JA HI
Entrar Começar — grátis
← 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
Sobre Blog Parceiros Cobertura Documentação da API Status Privacidade Termos Cookies Ajuda Pesquisar
cliqtel.com é operado pela Cliqtel B.V., registrada em Zeist, Países Baixos · KVK 42033793 · IVA NL869402468B01 · SBI 62.09

Usamos cookies essenciais para que a Cliqtel funcione. Com o seu consentimento, também usamos cookies de análise para melhorar nosso serviço. Política de Cookies