
Une intégration WhatsApp API qui fonctionne parfaitement en conditions idéales n'est pas une intégration robuste. Les erreurs sont inévitables : réseau instable, token expiré, numéro invalide, limite de débit dépassée. En Afrique, ces problèmes sont encore plus fréquents : la connectivité mobile peut être intermittente, les numéros changent souvent, et les pics de trafic lors de promotions peuvent surcharger momentanément les API. Savoir gérer ces erreurs proprement, c'est la différence entre un système qui se dégrade gracieusement et un système qui perd silencieusement des messages critiques.
Anatomie d'une erreur WhatsApp API
Quand l'API retourne une erreur, le corps de la réponse JSON suit toujours cette structure :
{
"error": {
"message": "Invalid phone number",
"type": "OAuthException",
"code": 100,
"error_data": {
"messaging_product": "whatsapp",
"details": "The phone number +221700000000 is not valid"
},
"error_subcode": 2494010,
"fbtrace_id": "AbcDef123456"
}
}
Les champs essentiels sont code (code d'erreur principal), error_subcode (détail précis de l'erreur), message (description lisible) et fbtrace_id (identifiant unique pour le support Meta). Gardez toujours le fbtrace_id dans vos logs : c'est indispensable si vous ouvrez un ticket de support.
Les codes d'erreur les plus courants
Voici les erreurs que vous rencontrerez fréquemment :
Erreurs d'authentification et d'autorisation :
190— Token d'accès expiré ou invalide. Solution : renouveler le token.200— Permission manquante. Vérifiez les scopes de votre application.10— Permission refusée. Votre compte n'a pas accès à cette fonctionnalité.
Erreurs de destinataire :
131030— Numéro de téléphone non valide ou non enregistré sur WhatsApp.131031— Le destinataire a bloqué votre numéro.131047— Message non autorisé : plus de 24h sans réponse client, utilisez un template.131026— Le message n'a pas pu être livré (numéro injoignable, stockage plein).
Erreurs de rate limiting :
130429— Rate limit atteint. Réduisez la fréquence d'envoi.131048— Limite de spam atteinte. Votre numéro a été temporairement restreint.
Erreurs de template :
132000— Template introuvable ou non approuvé.132001— Template rejeté ou désactivé par Meta.132007— Paramètres du template incorrects (mauvais nombre ou type).
Erreurs de média :
131053— URL du média inaccessible ou invalide.131054— Taille du fichier dépassée.
Implémentation du retry logic
La stratégie de retry doit être différente selon le type d'erreur. Certaines erreurs sont définitives (numéro invalide) et ne méritent pas de retry. D'autres sont temporaires (rate limit, erreur serveur) et nécessitent une attente avant relance.
// Node.js - Retry avec backoff exponentiel
class WhatsAppAPIError extends Error {
constructor(code, message, subcode, fbtrace) {
super(message);
this.code = code;
this.subcode = subcode;
this.fbtrace = fbtrace;
this.retryable = this.isRetryable(code);
}
isRetryable(code) {
// Erreurs temporaires : à retenter
const retryableCodes = [
429, // HTTP Too Many Requests
500, // Internal Server Error
502, // Bad Gateway
503, // Service Unavailable
130429, // WhatsApp rate limit
];
return retryableCodes.includes(code);
}
}
async function sendWithRetry(payload, maxAttempts = 5) {
let attempt = 0;
while (attempt < maxAttempts) {
try {
const response = await axios.post(API_URL, payload, { headers: HEADERS });
return response.data;
} catch (error) {
attempt++;
const apiError = parseApiError(error);
// Ne pas retenter les erreurs définitives
if (!apiError.retryable) {
console.error(`Erreur définitive [${apiError.code}]: ${apiError.message}`);
throw apiError;
}
if (attempt >= maxAttempts) {
console.error(`Échec après ${maxAttempts} tentatives`);
throw apiError;
}
// Backoff exponentiel avec jitter
const baseDelay = 1000; // 1 seconde
const delay = Math.min(baseDelay * Math.pow(2, attempt) + Math.random() * 1000, 60000);
console.log(`Tentative ${attempt}/${maxAttempts}, attente ${delay}ms...`);
await sleep(delay);
}
}
}
function parseApiError(axiosError) {
const data = axiosError.response?.data?.error || {};
const httpCode = axiosError.response?.status || 0;
const code = data.code || httpCode;
return new WhatsAppAPIError(
code,
data.message || axiosError.message,
data.error_subcode,
data.fbtrace_id
);
}
const sleep = (ms) => new Promise(resolve => setTimeout(resolve, ms));
Pour les erreurs de rate limit (code 130429), respectez le header Retry-After si présent dans la réponse HTTP :
async function handleRateLimitError(error) {
const retryAfter = parseInt(error.response?.headers['retry-after'] || '60');
console.log(`Rate limit atteint. Attente de ${retryAfter} secondes...`);
await sleep(retryAfter * 1000);
}
Gestion avancée des erreurs en production
En production, une bonne gestion des erreurs implique plusieurs niveaux :
Classification des erreurs :
function classifyError(code) {
const classifications = {
// Erreurs d'entrée - corriger les données
'invalid_input': [131030, 132007, 100],
// Erreurs de permission - vérifier configuration
'permission': [190, 200, 10],
// Erreurs temporaires - retenter
'transient': [130429, 500, 502, 503],
// Erreurs de logique métier - changer l'approche
'business_logic': [131047, 131031, 131048]
};
for (const [category, codes] of Object.entries(classifications)) {
if (codes.includes(code)) return category;
}
return 'unknown';
}
async function handleMessageError(messageId, recipientPhone, error) {
const category = classifyError(error.code);
switch(category) {
case 'invalid_input':
// Marquer le numéro comme invalide en base de données
await markPhoneAsInvalid(recipientPhone);
await logError(messageId, error, 'PHONE_INVALID');
break;
case 'business_logic':
if (error.code === 131047) {
// Fenêtre 24h fermée : envoyer un template à la place
await sendTemplateMessage(recipientPhone, 'relance_contact');
} else if (error.code === 131031) {
// Client a bloqué : ne plus contacter
await markAsOptOut(recipientPhone);
}
break;
case 'transient':
// Remettre dans la queue pour retry
await requeueMessage(messageId, Date.now() + 60000);
break;
default:
await alertTeam(`Erreur inconnue [${error.code}] pour ${recipientPhone}`);
}
}
Alertes et monitoring : mettez en place des alertes lorsque le taux d'erreur dépasse un seuil (ex : plus de 5% d'erreurs sur 1000 messages). Des outils comme Sentry, Datadog ou même un simple cron qui surveille vos logs peuvent faire la différence entre une panne détectée en 5 minutes et une panne découverte le lendemain matin.
Consultez le guide complet WhatsApp Business API et l'article sur l'automatisation des flux WhatsApp pour comprendre le contexte global dans lequel s'inscrit cette gestion d'erreurs.
FAQ
Q: Comment distinguer une erreur temporaire d'une erreur définitive dans la réponse API ?
R: En règle générale, les codes HTTP 4xx (sauf 429) indiquent des erreurs côté client (définitives) : numéro invalide, token expiré, permission manquante. Les codes 5xx et le 429 indiquent des erreurs temporaires du serveur ou de rate limit. Pour les erreurs WhatsApp spécifiques, référez-vous à la liste des codes dans la documentation officielle Meta.
Q: Combien de tentatives de retry faut-il implémenter ?
R: Entre 3 et 5 tentatives avec un backoff exponentiel est une bonne pratique générale. Pour les erreurs de rate limit, respectez le délai indiqué par l'API. Au-delà de 5 tentatives sans succès, il vaut mieux déplacer le message dans une "dead letter queue" pour investigation manuelle plutôt que de continuer à retenter indéfiniment.
Q: Que faire si mon token d'accès expire en cours d'opération ?
R: Mettez en place un mécanisme de refresh automatique du token. Détectez le code 190, rafraîchissez le token via l'API Meta, puis relancez la requête. Pour les tokens système (System User Tokens), configurez une alerte avant expiration et renouvelez-les proactivement. Les tokens permanents (non-expiring) sont recommandés pour les applications en production.
Q: Comment gérer les erreurs de webhook (quand mon serveur ne peut pas traiter un événement) ?
R: Toujours retourner un HTTP 200 à Meta dès réception, même si votre traitement échoue ensuite. Stockez le payload dans une queue persistante avant de traiter. Si le traitement échoue, rejouez depuis la queue. Ne dépendez jamais des retries automatiques de Meta comme seul mécanisme de fiabilité.
Q: L'erreur 131047 ("Message non autorisé hors fenêtre 24h") est-elle contournable ?
R: Non, et vous ne devez pas chercher à la contourner. C'est une règle de Meta pour protéger les utilisateurs contre le spam. La bonne pratique est d'avoir des templates HSM approuvés pour ré-engager les clients inactifs. Ces templates sont les seuls messages autorisés pour initier une conversation après 24h sans interaction.
Gérez vos intégrations WhatsApp avec sérénité. Whakup absorbe la complexité de la gestion des erreurs, des retries et des rate limits pour vous permettre de vous concentrer sur votre business.

Co-fondateur et Chief Product Officer de Whakup, Pablo conçoit les fonctionnalités qui permettent aux marques africaines de maximiser leur impact sur WhatsApp.
Prêt à passer à l'action ?
Essayez Whakup gratuitement pendant 15 jours. Aucune carte bancaire requise.
Démarrer l'essai gratuitArticles similaires
Authentification et tokens WhatsApp API : gestion sécurisée des accès
Comprendre et gérer les tokens d'accès WhatsApp Business API. Types de tokens, renouvellement, bonnes pratiques de sécurité et gestion des droits pour vos intégrations.
Intégrer WhatsApp API avec Node.js : tutoriel complet avec exemples de code
Apprenez à intégrer l'API WhatsApp Business Cloud avec Node.js. Exemples de code complets, envoi de messages, gestion des webhooks et bonnes pratiques pour développeurs africains.
Logs et monitoring WhatsApp API : tracer les échanges et détecter les anomalies
Mettez en place une stratégie de logs et monitoring pour votre intégration WhatsApp API. Tracez chaque échange, détectez les anomalies et assurez la continuité de service.