Intégrations

L'API OTP WhatsApp pour les développeurs en 2026 — envoyer et vérifier un code, avec des exemples PHP, Laravel, Node.js et Python

Le contrat complet de l'API des codes de vérification WhatsApp : envoi, vérification, renvoi et statut, la clé publique et la signature HMAC, chaque code d'erreur et chaque limite, et le rappel de vérification vers votre serveur — avec du code prêt en PHP, Laravel, Node.js, Python et curl.

9 min de lecture Mis à jour le1 octobre 2026 L'équipe ArabyBot
L'équipe ArabyBotPartenaire officiel de Meta · rédigé à partir des données de notre propre plateforme
Sur cette page 11
  1. Avant la première ligne de code : une application OTP et deux clés
  2. Cinq points d'accès — tout le contrat
  3. L'essai le plus rapide : curl
  4. PHP — une seule fonction pour chaque appel
  5. Laravel — via Http
  6. Node.js — fetch, sans bibliothèque
  7. Python — requests
  8. Erreurs et limites — et que faire pour chacune
  9. Le rappel de vérification vers votre serveur
  10. Ce que vous payez
  11. Questions des développeurs

La réponse courte

Avec deux appels : POST /wa_otp_api/send avec le numéro de l'utilisateur renvoie un request_id, puis POST /wa_otp_api/verify avec ce request_id et le code qu'il a saisi. L'authentification se fait par une clé publique dans l'en-tête X-Public-Key, avec une signature HMAC-SHA256 facultative à l'aide du secret. Le code part de votre numéro connecté au tarif de Meta pour le pays du destinataire, ou du numéro partagé à un prix fixe par code, sans compte Meta. C'est la seule API publique pour développeurs ouverte aujourd'hui.

Aussi demandé sous la forme : «WhatsApp OTP PHP» · «WhatsApp OTP Laravel» · «WhatsApp OTP Node.js» · «OTP API» · «كيف ارسل كود تحقق على الواتساب من الموقع» · «كود OTP لا يصل» · «خدمة OTP للشركات» · «كيف أرسل OTP من API؟» · «WhatsApp OTP integration» · «WhatsApp API example» · «WhatsApp API error» · «OTP واتساب لا يصل»

Avant la première ligne de code : une application OTP et deux clés

  1. Créez une application OTP dans le tableau de bord

    Depuis OTP dans le tableau de bord d'ArabyBot : le nom de l'application, le nom affiché dans le message, puis l'expéditeur — le numéro partagé prêt à l'emploi, ou un numéro WhatsApp connecté à votre compte. Vous fixez aussi la longueur du code, sa durée de validité et le nombre de tentatives de vérification autorisées.

  2. Récupérez la clé publique et le secret

    La clé publique commence par ab_otp_ et voyage dans l'en-tête X-Public-Key à chaque appel. Le secret commence par sk_otp_ et n'est affiché qu'une fois à la création : gardez-le dans les variables d'environnement de votre serveur — c'est avec lui que vous signez les requêtes et que vous vérifiez notre signature sur les rappels.

  3. Choisissez ce que vous verrouillez

    Trois réglages facultatifs sur l'application : la signature des requêtes (tout appel sans X-Signature valide est refusé), les domaines autorisés pour les appels du navigateur, et les adresses IP de vos serveurs. Activez le premier et le troisième si l'appel passe par votre serveur.

Cinq points d'accès — tout le contrat

Serveur : https://app.arabybot.com · spécification complète sur /openapi.json
Point d'accèsCorpsRetours
POST /wa_otp_api/sendphone, facultatif lang, length (4–8), expiry_seconds (60–900), metadatarequest_id, expires_in, expires_at
POST /wa_otp_api/verifyrequest_id, coderequest_id, phone, verified_at
POST /wa_otp_api/resendrequest_idUn nouveau code, même forme que l'envoi
GET /wa_otp_api/status/{request_id}—status, attempts, expires_at, verified_at
GET /wa_otp_api/ping—Le nom et les réglages de l'application — pour vérifier que la clé fonctionne

Le téléphone est au format international, chiffres uniquement ou précédés d'un + : 966501234567. Chaque erreur revient sous une seule forme : {"success":false,"error_code":"…","message":"…"} : construisez donc votre logique sur error_code, pas sur le texte du message.

L'essai le plus rapide : curl

# 1) send the code
curl -X POST https://app.arabybot.com/wa_otp_api/send \
  -H "Content-Type: application/json" \
  -H "X-Public-Key: ab_otp_…" \
  -d '{"phone":"966501234567","lang":"ar"}'

{"success":true,"request_id":"3f6c2a9e-41b7-4c0d-9a51-7e2b8d4f1c60",
 "expires_in":300,"expires_at":"2026-10-01 14:05:00"}

# 2) verify what the user typed
curl -X POST https://app.arabybot.com/wa_otp_api/verify \
  -H "Content-Type: application/json" \
  -H "X-Public-Key: ab_otp_…" \
  -d '{"request_id":"3f6c2a9e-41b7-4c0d-9a51-7e2b8d4f1c60","code":"482913"}'

{"success":true,"request_id":"3f6c2a9e-…","phone":"966501234567",
 "verified_at":"2026-10-01 14:01:12"}

PHP — une seule fonction pour chaque appel

Le cURL intégré de PHP suffit, sans bibliothèque. Gardez le request_id dans la session de l'utilisateur côté serveur, pas dans la page.

<?php
// One helper for every call. Keys come from the environment, never from the page.
function arabybot_otp(string $action, array $body): array
{
    $raw     = json_encode($body);
    $headers = [
        'Content-Type: application/json',
        'X-Public-Key: ' . getenv('ARABYBOT_OTP_PUBLIC_KEY'),
    ];
    if ($secret = getenv('ARABYBOT_OTP_SECRET')) {   // only if request signing is on
        $headers[] = 'X-Signature: sha256=' . hash_hmac('sha256', $raw, $secret);
    }
    $ch = curl_init('https://app.arabybot.com/wa_otp_api/' . $action);
    curl_setopt_array($ch, [
        CURLOPT_POST => true, CURLOPT_POSTFIELDS => $raw, CURLOPT_HTTPHEADER => $headers,
        CURLOPT_RETURNTRANSFER => true, CURLOPT_TIMEOUT => 15,
    ]);
    $res = json_decode((string) curl_exec($ch), true);
    curl_close($ch);

    return is_array($res) ? $res : ['success' => false, 'error_code' => 'network'];
}

session_start();
$sent = arabybot_otp('send', ['phone' => '201001234567', 'lang' => 'ar']);
$_SESSION['otp_request'] = $sent['request_id'] ?? null;

// …later, when the user submits the code
$check = arabybot_otp('verify', ['request_id' => $_SESSION['otp_request'], 'code' => $_POST['code']]);
if (! empty($check['success'])) {
    // the number is verified
}

Laravel — via Http

Le client Http de Laravel écrit la requête en quelques lignes. Si vous activez la signature des requêtes, signez exactement les octets que vous envoyez : construisez le JSON vous-même et envoyez-le avec withBody, car ->post() réencode le tableau.

use Illuminate\Support\Facades\Http;

// config/services.php → 'arabybot' => ['otp_key' => env('ARABYBOT_OTP_PUBLIC_KEY')]
$otp = Http::withHeaders(['X-Public-Key' => config('services.arabybot.otp_key')])
    ->baseUrl('https://app.arabybot.com/wa_otp_api')
    ->timeout(15);

$sent = $otp->post('/send', ['phone' => $request->phone, 'lang' => 'ar'])->json();
session(['otp_request' => $sent['request_id'] ?? null]);

$check = $otp->post('/verify', [
    'request_id' => session('otp_request'),
    'code'       => $request->code,
])->json();

if ($check['success'] ?? false) {
    // verified
}

// With request signing on, sign the exact bytes you send:
// $raw = json_encode($body);
// Http::withHeaders([... 'X-Signature' => 'sha256='.hash_hmac('sha256', $raw, $secret)])
//     ->withBody($raw, 'application/json')->post('https://app.arabybot.com/wa_otp_api/send');

Node.js — fetch, sans bibliothèque

import crypto from 'node:crypto';

// Node 18+ (built-in fetch). Keys from the environment.
async function otp(action, body) {
  const raw = JSON.stringify(body);
  const headers = {
    'Content-Type': 'application/json',
    'X-Public-Key': process.env.ARABYBOT_OTP_PUBLIC_KEY,
  };
  if (process.env.ARABYBOT_OTP_SECRET) {            // only if request signing is on
    headers['X-Signature'] = 'sha256=' + crypto
      .createHmac('sha256', process.env.ARABYBOT_OTP_SECRET).update(raw).digest('hex');
  }
  const res = await fetch(`https://app.arabybot.com/wa_otp_api/${action}`,
    { method: 'POST', headers, body: raw });
  return res.json();
}

const sent  = await otp('send', { phone: '971501234567', lang: 'ar' });
const check = await otp('verify', { request_id: sent.request_id, code: '482913' });
console.log(check.success ? 'verified' : check.error_code);

Python — requests

import hashlib, hmac, json, os
import requests

def otp(action, body):
    raw = json.dumps(body)
    headers = {"Content-Type": "application/json",
               "X-Public-Key": os.environ["ARABYBOT_OTP_PUBLIC_KEY"]}
    secret = os.environ.get("ARABYBOT_OTP_SECRET")
    if secret:  # only if request signing is on
        headers["X-Signature"] = "sha256=" + hmac.new(
            secret.encode(), raw.encode(), hashlib.sha256).hexdigest()
    return requests.post(f"https://app.arabybot.com/wa_otp_api/{action}",
                         data=raw, headers=headers, timeout=15).json()

sent = otp("send", {"phone": "9647701234567", "lang": "ar"})
check = otp("verify", {"request_id": sent["request_id"], "code": "482913"})
print("verified" if check.get("success") else check.get("error_code"))

Erreurs et limites — et que faire pour chacune

Exactement tels que le serveur les renvoie
error_codeHTTPSignification et que faire
missing_key · invalid_key401La clé publique est absente, erronée, ou l'application est en pause.
missing_signature · bad_signature401La signature est activée et la requête n'est pas signée, ou la signature porte sur un corps différent de celui envoyé.
origin_blocked · ip_blocked403L'appel vient d'un domaine ou d'une IP non autorisés dans les réglages de l'application.
invalid_phone · missing_phone422Corrigez le numéro au format international avant l'envoi.
cooldown · rate_limit_phone429Trop de requêtes pour un même numéro. Lisez retry_after en secondes et affichez un compte à rebours.
rate_limit_app · rate_limit_app_day429La limite de l'application : 60 envois par minute et 20 000 par jour par défaut.
invalid_code401Code erroné ; attempts_remaining l'accompagne.
too_many_attempts429Tentatives épuisées ; demandez un nouveau code.
expired · already_resolved410Le code a expiré, ou a déjà été utilisé.
quota_exceeded · insufficient_balance · package_expired402Votre forfait ou votre portefeuille ne couvre pas l'envoi.
wa_send_failed502WhatsApp a refusé l'envoi ; un prélèvement sur le numéro partagé est remboursé.

Le rappel de vérification vers votre serveur

Si vous définissez une URL de rappel sur l'application, un événement otp.verified vous parvient dès qu'un code est vérifié, signé avec votre secret. Calculez le HMAC-SHA256 du corps tel que reçu et comparez-le à l'en-tête avant de lui faire confiance.

// The callback your server receives when a code is verified (if you set a callback URL)
POST https://your-site.example/otp-callback
X-ArabyBot-Event: otp.verified
X-ArabyBot-Signature: sha256=<HMAC-SHA256 of the raw body, keyed with your sk_otp_ secret>

{"event":"otp.verified","app_id":"12","request_id":"3f6c2a9e-…",
 "phone":"966501234567","verified_at":"2026-10-01T14:01:12+00:00"}

Ce que vous payez

Sur votre propre numéro, le code part sous forme de modèle d'authentification approuvé et Meta facture le tarif du pays du destinataire : 0,0036 $ vers un numéro égyptien et 0,0107 $ vers un numéro saoudien, mesuré sur 1 147 codes. Sur le numéro partagé, c'est un prix fixe par code prélevé sur votre portefeuille (0,0300 $), sans compte Meta. Le tableau pour chaque pays arabe se trouve dans le prix du code de vérification dans chaque pays arabe.

Questions des développeurs

1

Ai-je besoin de mon propre numéro sur l'API WhatsApp pour envoyer le code ?

Non. Quand vous créez une application OTP, vous choisissez l'expéditeur : le numéro partagé que gère la plateforme, opérationnel en quelques minutes sans compte Meta, à prix fixe par code prélevé sur votre portefeuille, ou votre propre numéro connecté à la plateforme, qui envoie via un modèle d'authentification approuvé sur votre numéro, Meta vous facturant directement le tarif du pays du destinataire.

2

Je vérifie par numéro de téléphone ou par request_id ?

Par request_id, toujours. L'appel d'envoi le renvoie ; gardez-le dans la session de l'utilisateur sur votre serveur, puis envoyez-le avec le code qu'il a tapé à l'appel de vérification. Un code n'est accepté qu'une seule fois, et il est refusé après son expiration ou après la limite de tentatives que vous avez fixée pour l'application.

3

Combien coûte un code ?

Sur votre propre numéro : le tarif d'authentification de Meta pour le pays du destinataire — 0,0036 $ vers un numéro égyptien et 0,0107 $ vers un numéro saoudien ; le tableau complet se trouve dans le prix du code dans chaque pays arabe. Sur le numéro partagé : un prix fixe de 0,0300 $ par code. Chaque renvoi est un nouveau message facturé.

4

Et si l'envoi échoue ?

L'appel renvoie wa_send_failed avec le code HTTP 502 et la raison de WhatsApp, et sur le numéro partagé vous n'êtes pas facturé, car le prélèvement est remboursé automatiquement. Montrez à l'utilisateur un bouton « réessayer » après une pause ; ne renvoyez pas en boucle.

5

Puis-je l'appeler directement depuis le navigateur ?

Techniquement oui — l'API accepte les appels du navigateur depuis les domaines que vous autorisez dans les réglages de l'application. Mais la bonne conception fait passer l'appel par votre serveur : c'est là que vous gardez le request_id hors de portée de l'utilisateur, activez la signature des requêtes avec le secret, et limitez les appels aux adresses IP de vos serveurs.

6

Existe-t-il une API pour envoyer des messages WhatsApp autres que le code ?

Pas encore ouverte. L'API OTP est la seule API publique pour développeurs disponible aujourd'hui, avec les webhooks de réception des commandes et d'événements de panier et les outils de l'agent IA — détaillés dans le guide du développeur.

L'équipe ArabyBotPartenaire commercial officiel de Meta au Moyen-Orient 191 guides Des chiffres de notre plateforme Tous les guides

Comment nous rédigeons ces guides Les chiffres proviennent de notre plateforme et des factures réelles de Meta, datés avec leur échantillon ; nous décrivons ce qui fonctionne aujourd'hui, pas ce que nous prévoyons, et disons ce que nous ne faisons pas et quand quelqu'un d'autre est le meilleur choix. Relu par l'équipe ArabyBot le1 octobre 2026.

Partager ce guide
Et vous gérez tout cela depuis votre téléphoneTout ce qui est sur cette page se gère aussi depuis l'application mobile ArabyBot — réponses, commandes, campagnes et rapports de l'IA. Pas seulement un tableau de bord web.

Créez une application OTP et envoyez le premier code

Sur le numéro partagé, le premier code arrive quelques minutes après l'inscription, sans compte Meta.