Comment envoyer des messages WhatsApp avec la Cloud API
21 mai 2026
·
20 min de lecture
Sections : Fondamentaux de l'API · Message texte · Modèle avec variables · Image et document · Boutons interactifs · Localisation · Envoi en masse avec rate limiting · Gestion d'erreurs et reprise · Wrappers de classe complets (Node / Python / PHP)
Fondamentaux de l'API : l'unique endpoint par lequel tout passe
Chaque message WhatsApp sortant — quel que soit le type — passe par un seul endpoint HTTP POST. Le type de message et le contenu sont dans le body JSON. C'est tout. Pas de WebSockets, pas de streaming, pas de long-polling.
API Endpoint
POST https://graph.facebook.com/v21.0/{PHONE_NUMBER_ID}/messages
Authorization: Bearer {ACCESS_TOKEN}
Content-Type: application/json
// PHONE_NUMBER_ID — ID numérique de votre numéro WhatsApp (PAS le numéro de téléphone lui-même)// Où le trouver : Meta Developer Dashboard → WhatsApp → Phone Numbers// ACCESS_TOKEN — token permanent System User// Où le trouver : Meta Business Settings → System Users → Generate Token
Trois valeurs dont vous avez besoin avant d'exécuter du code :
Phone Number ID — un ID numérique pour votre numéro WhatsApp Business (ressemble à 123456789012345). Différent de votre numéro de téléphone réel.
Access Token — un token permanent System User avec la permission whatsapp_business_messaging. N'utilisez jamais de token utilisateur temporaire en production.
Numéro de téléphone du destinataire — au format E.164 : code pays + numéro, sans espaces, sans tirets, sans le signe + dans la valeur JSON (par ex. 15550001234 pour un numéro américain, ou avec + également accepté : +15550001234).
Un envoi réussi renvoie HTTP 200 avec un body comme :
Success Response
{
"messaging_product": "whatsapp",
"contacts": [{ "input": "+15550001234", "wa_id": "15550001234" }],
"messages": [{ "id": "wamid.HBgL..." }] // conservez-le pour suivre le statut de livraison
}
Types de message : session vs modèle
Avant de choisir un type de message, vous devez savoir si vous êtes dans une fenêtre de service. La fenêtre de session (24 h après qu'un client vous a écrit, ou 72 h après un clic sur publicité Click-to-WhatsApp) détermine quels types de messages sont gratuits et sans restriction.
💬
text
Texte brut. Formatage WhatsApp de type markdown supporté. Jusqu'à 4 096 caractères.
Gratuit dans la fenêtre
📋
template
Format pré-approuvé avec emplacements de variables. Requis pour initier un contact hors fenêtre.
Approbation requise
🖼️
image
JPEG ou PNG. Max 5 Mo. URL ou media ID. Légende optionnelle.
Gratuit dans la fenêtre
📄
document
PDF, DOCX, XLSX. Max 100 Mo. URL ou media ID. Nom de fichier affiché.
Gratuit dans la fenêtre
🎬
video
MP4 ou 3GPP. Max 16 Mo. URL ou media ID. Légende optionnelle.
Gratuit dans la fenêtre
🔘
interactive
Réponses par boutons (max 3) ou messages liste (max 10 éléments). Le client tape pour répondre.
Gratuit dans la fenêtre
📍
location
Envoyez lat/lng avec nom et adresse optionnels. S'affiche sur une carte dans WhatsApp.
Gratuit dans la fenêtre
🎵
audio
MP3 ou AAC. Max 16 Mo. URL ou media ID. Légende non supportée.
Gratuit dans la fenêtre
Envoyer un message texte
L'envoi le plus simple. Fonctionne dans la fenêtre de service de 24 heures sans frais Meta (dans le quota mensuel de 1 000 conversations de service gratuites). Hors fenêtre, utilisez un modèle à la place.
Les modèles sont requis pour le premier message d'une nouvelle conversation, ou tout message envoyé en dehors de la fenêtre de service de 24 heures. Les modèles sont définis dans WhatsApp Manager, approuvés par Meta, et peuvent inclure des emplacements de variables {{1}}{{2}}. Votre appel API remplit ces variables au moment de l'envoi.
Délai d'approbation des modèles : Les modèles utility simples (confirmations de commande, mises à jour d'expédition) sont généralement approuvés en 1–24 heures. Les modèles marketing prennent 1–5 jours ouvrés. Vous pouvez vérifier le statut d'approbation via l'abonnement webhook message_template_status_update ou dans WhatsApp Manager. Les modèles au statut rejeté ne peuvent pas être envoyés — envoyer un modèle non-APPROVED renvoie une erreur 400.
Les messages média référencent un fichier soit par URL (le fichier doit être accessible publiquement via HTTPS) soit par Media ID (obtenu après avoir téléversé le fichier vers l'endpoint média de Meta). L'URL est plus simple pour la plupart des cas — la Cloud API la récupère et la met en cache. Les Media IDs sont meilleurs pour les actifs fréquemment réutilisés comme des images produit ou des PDF de marque.
Node.js
sendMedia.js
// Envoyer une image par URL publiqueasync functionsendImage(to, imageUrl, caption = '') {
returnsendMedia(to, 'image', { link: imageUrl, caption });
}
// Envoyer un document par URL publiqueasync functionsendDocument(to, docUrl, filename, caption = '') {
returnsendMedia(to, 'document', { link: docUrl, filename, caption });
}
// Sender média générique — fonctionne pour image, vidéo, audio, documentasync functionsendMedia(to, type, mediaObj) {
const res = awaitfetch(
`https://graph.facebook.com/v21.0/${process.env.WA_PHONE_ID}/messages`,
{
method: 'POST',
headers: {
'Authorization': `Bearer ${process.env.WA_TOKEN}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
messaging_product: 'whatsapp',
to,
type,
[type]: mediaObj, // { link, caption } OU { id, caption }
}),
}
);
if (!res.ok) throw newError(`Media send failed: ${await res.text()}`);
return (await res.json()).messages[0].id;
}
// UtilisationawaitsendImage('+15550001234', 'https://yourdomain.com/promo.jpg', 'Check out our new product! 🚀');
awaitsendDocument('+15550001234', 'https://yourdomain.com/invoice.pdf', 'invoice-2026.pdf');
Les messages interactifs à boutons permettent aux clients de répondre par un tap au lieu de taper. Maximum 3 boutons par message. Les titres de boutons sont limités à 20 caractères. Lorsqu'un client tape sur un bouton, votre webhook reçoit un message de type interactive avec l'id du bouton dans msg.interactive.button_reply.id.
Les messages de localisation s'affichent comme une épingle sur une carte dans WhatsApp avec un nom et une adresse optionnels en dessous. Les clients peuvent taper pour ouvrir dans leur app de cartes. Pas besoin d'URL ni de media ID — juste des coordonnées.
Request body (all languages)
{
"messaging_product": "whatsapp",
"to": "+15550001234",
"type": "location",
"location": {
"latitude": 40.712776,
"longitude": -74.005974,
"name": "SocialHook HQ", // optionnel — affiché au-dessus de l'adresse"address": "123 Main St, New York, NY"// optionnel
}
}
Envoi en masse : rate limits et le bon pattern
La WhatsApp Cloud API permet 80 messages par seconde par numéro de téléphone par défaut. À ce rythme, envoyer 10 000 messages prend environ 2 minutes. Sans rate limiting, une boucle naïve épuise la limite presque immédiatement et vous commencez à recevoir des erreurs 429 en pleine campagne. Le bon pattern : ajoutez un délai fixe entre les envois et implémentez un backoff exponentiel sur les 429.
Gestion des erreurs : ce que signifie chaque status code
HTTP Status
Cause courante
Correctif
200 OK
Message accepté par Meta — pas encore livré
Stockez le wamid renvoyé et écoutez les webhooks de statut de livraison
400 Bad Request
JSON invalide, champ obligatoire manquant, modèle non approuvé, nombre de variables de modèle ne correspond pas
Vérifiez le body de la réponse d'erreur — Meta renvoie un error.message détaillé expliquant le champ ou la contrainte exacte qui a échoué
401 Unauthorized
Access token invalide ou expiré ; header Authorization manquant
Régénérez un token permanent System User. N'utilisez jamais de token utilisateur temporaire en production — ils expirent après 60 jours
404 Not Found
Mauvais Phone Number ID dans l'URL ; numéro non enregistré sur Cloud API
Vérifiez le Phone Number ID dans Meta Developer Dashboard → WhatsApp → Phone Numbers. Confirmez que le numéro est enregistré et vérifié.
429 Too Many Requests
Limite de 80 msg/s dépassée, ou rate limit d'appels API
Implémentez un backoff exponentiel avec jitter. Ajoutez un délai de 15–20 ms entre envois lors d'opérations en masse. Ne réessayez pas immédiatement.
460 (interne Meta)
Le numéro du destinataire n'est pas enregistré sur WhatsApp
Le numéro n'est pas un utilisateur WhatsApp. Retirez-le de votre liste. Ce n'est pas un numéro livrable.
131026
Message non livrable — restrictions sur le compte WhatsApp du destinataire
Le destinataire a peut-être bloqué votre numéro ou son compte est restreint. Loguez et passez.
500 / 503
Panne d'infrastructure Meta ou erreur temporaire
Réessayez avec backoff exponentiel. Vérifiez metastatus.com pour les incidents en cours. Ne réessayez pas plus de 3 fois.
Classe de client WhatsApp complète (Node.js)
Les fonctions ci-dessus regroupées en classe réutilisable avec logique de retry intégrée, gestion d'erreurs cohérente et configuration basée sur les variables d'environnement :
L'autre moitié : recevoir les réponses avec SocialHook
Envoyer des messages n'est que la moitié du tableau. Quand votre client répond, la WhatsApp Cloud API déclenche un webhook vers votre serveur — mais vous avez besoin d'un endpoint HTTPS accessible publiquement pour le recevoir, plus de la vérification de signature HMAC-SHA256, de l'extraction de payload imbriqué et de la gestion des retry.
SocialHook prend en charge toute la couche entrante. Connectez votre numéro WhatsApp à SocialHook, collez l'URL de votre serveur comme destination, et chaque réponse client arrive comme un événement JSON normalisé — vérifié, extrait de l'enveloppe imbriquée de Meta et transféré à votre endpoint en moins de 50 ms. Le même format plat fonctionne aussi pour Facebook Messenger et Instagram DMs.
La configuration complète : votre serveur utilise le WhatsAppClient ci-dessus pour l'envoi, SocialHook livre les événements entrants à votre handler webhook. Deux directions, un seul forfait à 50 $/mois. Voir le guide complet de webhook entrant ou commencer avec le quickstart de 5 minutes.
FAQ
Questions fréquentes
Comment envoyer un message WhatsApp en utilisant la Cloud API ?
POST vers https://graph.facebook.com/v21.0/{PHONE_NUMBER_ID}/messages avec votre header Authorization: Bearer {ACCESS_TOKEN} et un body JSON avec messaging_product: "whatsapp", to: "+E.164_number", type: "text", et text: { body: "message" }. Le code complet pour Node.js, Python et PHP est dans la section message texte ci-dessus.
Qu'est-ce que le Phone Number ID WhatsApp et où le trouver ?
Le Phone Number ID est un identifiant numérique pour votre numéro spécifique WhatsApp Business sur la Cloud API — il est différent du numéro de téléphone réel. Trouvez-le dans Meta Developer Dashboard → WhatsApp → Phone Numbers. Il ressemble à un nombre à 15–16 chiffres. Utilisez-le dans l'URL : graph.facebook.com/v21.0/{PHONE_NUMBER_ID}/messages. Un numéro de téléphone a un ID qui ne change jamais.
Quelle est la différence entre un message de session et un message modèle ?
Un message de session (texte, image, boutons, localisation, document) ne peut être envoyé que dans la fenêtre de service de 24 heures qui s'ouvre quand un client vous écrit en premier. Ceux-ci sont gratuits dans le quota mensuel. Un message modèle est un format approuvé par Meta requis pour initier de nouvelles conversations ou envoyer hors de la fenêtre de service. Les modèles doivent être approuvés (1–24 h pour utility, jusqu'à 5 jours pour marketing) avant de pouvoir être envoyés.
Que se passe-t-il quand je reçois un 429 de la WhatsApp Cloud API ?
Vous avez atteint la rate limit (80 msg/s par défaut). Implémentez un backoff exponentiel : attendez 1000 * 2^attempt + random(500) ms avant de réessayer, plafonné à 60 secondes. Ajoutez du jitter (le composant aléatoire) pour empêcher les retries synchronisés de plusieurs workers. Pour les campagnes en masse, ajoutez un délai fixe de 15–20 ms entre envois pour rester en sécurité sous la limite plutôt que de l'atteindre puis réessayer.
Comment envoyer un modèle WhatsApp avec variables en Python ?
Mettez "type": "template" et incluez un tableau components avec un composant body contenant parameters — un objet par variable dans votre modèle. Chaque paramètre est {"type": "text", "text": "variable_value"}. Ils correspondent séquentiellement à {{1}}, {{2}}, {{3}} dans votre modèle. Le code Python complet est dans la section message modèle ci-dessus.
Comment recevoir les réponses des clients aux messages WhatsApp ?
Les réponses des clients arrivent via webhook — Meta déclenche un HTTP POST vers votre endpoint enregistré lorsqu'un événement de message se produit. Vous avez besoin d'une URL HTTPS accessible publiquement, de la vérification de signature HMAC-SHA256 et du parsing de payload imbriqué. SocialHook gère tout cela automatiquement et livre du JSON propre à votre endpoint en moins de 50 ms. Voir la configuration complète dans notre guide de webhook entrant.
Vous pouvez envoyer. Maintenant recevez aussi les réponses.
Votre code sortant est prêt. Connectez SocialHook pour l'entrant — chaque réponse client arrive comme JSON propre à votre endpoint webhook. Aucun boilerplate HMAC, aucun parsing de payload imbriqué, aucune infrastructure de retry à construire.
Arrêtez de gérer les API Meta. Commencez à construire.
Connectez votre premier compte Facebook, Instagram ou WhatsApp en moins de 2 minutes. Votre webhook reçoit son premier payload avant que votre café refroidisse.