Genuka WA docs

Envoyer une campagne WhatsApp par API

Envoyer une campagne WhatsApp par API : template marketing, destinataires, lancement, quotas par forfait, limites marketing de Meta et suivi des envois.

Pour envoyer une campagne WhatsApp par API avec Genuka WA, vous faites approuver un template MARKETING par Meta, vous créez la campagne avec POST /api/v1/campaigns et sa liste de destinataires, puis vous la lancez avec POST /api/v1/campaigns/{id}/launch. Chaque destinataire est suivi jusqu'à la lecture, et Meta facture les messages délivrés directement à votre propre compte WhatsApp Business.

Mis à jour le 8 octobre 2026

Ce qu'il faut avant d'envoyer une campagne

  • Un numéro connecté et son connectionId — voir Connecter un numéro.
  • Une clé API, utilisée uniquement côté serveur — voir Authentification.
  • Un moyen de paiement sur votre compte Meta. Genuka est Meta Tech Provider, pas BSP : Meta facture votre compte WhatsApp Business (WABA) directement, et un client onboardé par un Tech Provider doit y ajouter son propre moyen de paiement (Meta, Partners). Sans lui, le template est approuvé mais chaque envoi revient en erreur 131042.
  • Des destinataires qui ont accepté de recevoir vos messages. C'est une règle de WhatsApp, pas une bonne pratique — la section sur l'opt-in, plus bas, la détaille.

Comment créer le template marketing ?

Hors de la fenêtre de service de 24 heures, seul un template approuvé est délivré. Une campagne en utilise toujours un. Soumettez-le avec la catégorie MARKETING :

POST /api/v1/templates
curl -X POST https://wa.genuka.com/api/v1/templates \
  -H "Authorization: Bearer $GENUKA_WA_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "connectionId": "con_1",
    "name": "promo_octobre",
    "language": "fr",
    "category": "MARKETING",
    "components": [
      { "type": "BODY",
        "text": "Bonjour {{1}}, -20 % sur toute la boutique jusqu’à dimanche.",
        "example": { "body_text": [["Awa"]] } },
      { "type": "BUTTONS", "buttons": [
        { "type": "URL", "text": "Voir les offres", "url": "https://example.com/promo" }
      ] }
    ]
  }'

La réponse est un 201 qui porte l'id du template et son statut. Meta l'examine — l'examen peut prendre jusqu'à 24 heures (Meta, Template fundamentals). Le verdict arrive sur vos webhooks (template.status_changed) et sur GET /api/v1/templates/{id}. Une campagne ne part qu'avec un template approved.

Chaque variable du corps ({{1}}, {{2}}…) exige un exemple, sinon le template est refusé. La référence API couvre les en-têtes média, les paramètres nommés et les boutons.

Comment créer et lancer la campagne ?

Créez la campagne

POST /api/v1/campaigns prend quatre champs, tous obligatoires : connectionId, templateId, name et recipients. Chaque destinataire porte son numéro au format international (+ et indicatif pays) et ses propres variables. La campagne est créée en statut draft : rien n'est encore envoyé.

Lancez-la

POST /api/v1/campaigns/{id}/launch envoie chaque destinataire encore pending et répond avec le décompte : sent, failed, skipped. Un sent veut dire que Meta a accepté le message, pas qu'il est arrivé — la livraison et la lecture arrivent ensuite, par webhook.

Suivez les statuts

Lisez les compteurs sur GET /api/v1/campaigns/{id} et le détail par destinataire sur GET /api/v1/campaigns/{id}/recipients. La section sur le suivi, plus bas, détaille les deux.

# 1. Créer la campagne (statut draft)
curl -X POST https://wa.genuka.com/api/v1/campaigns \
  -H "Authorization: Bearer $GENUKA_WA_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "connectionId": "con_1",
    "templateId": "tpl_123",
    "name": "Promo octobre",
    "recipients": [
      { "to": "+237690000001", "variables": ["Awa"] },
      { "to": "+237690000002", "variables": ["Paul"] }
    ]
  }'
# { "data": { "id": "cmp_9", "name": "Promo octobre", "status": "draft", "_count": { "recipients": 2 } } }

# 2. La lancer
curl -X POST https://wa.genuka.com/api/v1/campaigns/cmp_9/launch \
  -H "Authorization: Bearer $GENUKA_WA_API_KEY"
# { "data": { "sent": 2, "failed": 0, "skipped": 0 } }

variables est un tableau positionnel pour les paramètres du corps. Pour un en-tête média, un bouton dynamique ou des paramètres nommés, passez un objet à la place — { "body": [...], "bodyNamed": { "first_name": "Awa" }, "header": {...}, "buttons": [...] } — la même forme que l'envoi d'un template. Les paramètres d'un template à paramètres nommés vont dans bodyNamed : placés dans body, ils partiraient comme des paramètres positionnels.

Pourquoi le lancement est-il refusé ?

Ces contrôles ont lieu avant le premier envoi : un lancement refusé n'a rien envoyé. Les refus les plus courants :

StatutCodeCause
402plan_limit_messagesLa liste ne tient pas dans le quota restant de la période. Tous les destinataires pending comptent, y compris ceux qui seront ensuite écartés comme désinscrits
402subscription_past_dueL'essai ou la période payée est échu
400send_templateLe template n'est pas approved (en examen, refusé, en pause) — le message dit lequel
409send_configLe numéro a été déconnecté de l'API depuis l'application WhatsApp Business (coexistence) : reconnectez-le
409number_releasedLe numéro a été libéré de votre forfait : reconnectez-le par l'Embedded Signup
403account_deactivatedLe client propriétaire du numéro est suspendu
404campaign_not_foundL'id n'existe pas ou n'est pas à la portée de votre clé

À la création, un templateId et un connectionId qui appartiennent à deux clients différents répondent 400 template_connection_mismatch, et une liste sans aucun to exploitable 400 no_valid_recipients. Les autres codes sont dans la référence des erreurs.

Combien de messages une campagne peut-elle envoyer ?

Genuka ne facture jamais le message. Votre forfait inclut en revanche un quota de messages sortants par numéro payé et par période de facturation, partagé entre les envois API et les destinataires de campagne. Le quota de la période vaut : numéros payés × quota unitaire du palier. Le compteur repart de zéro à chaque nouvelle période : chaque mois sur un abonnement mensuel, au renouvellement sur un abonnement annuel.

PalierNuméros maxMessages inclus par numéro et par période
Starter5500
Growth155 000
Scale10030 000
Enterprisesur mesuresur mesure

Exemple : 3 numéros en Growth donnent 15 000 messages pour la période. L'essai gratuit de 7 jours tourne sur le palier Growth avec un numéro, soit 5 000 messages. Seuls les messages acceptés par Meta sont décomptés : un envoi que Meta refuse à l'appel ne consomme rien, mais un message accepté puis signalé failed par webhook reste décompté. Les tarifs sont sur la page de prix et en Markdown sur /pricing.md.

Quelles limites Meta impose-t-il aux campagnes marketing ?

Le quota Genuka n'est pas la seule limite. Meta en applique quatre, indépendantes de votre forfait :

Limite MetaCe qu'elle ditCe que vous voyez
Plafond d'envoiNombre de destinataires uniques joignables hors fenêtre de service, par 24 heures glissantes, au niveau du portefeuille Business : 250 pour un portefeuille neuf, puis 2 000, 10 000, 100 000, illimité (doc)WhatsApp Manager, Account tools > Messaging limits (même page). Le messagingLimitTier de GET /api/v1/numbers?refresh=true n'est qu'indicatif : il vient d'un champ que Meta a déprécié et peut être vide
Plafond marketing par utilisateurWhatsApp peut ne pas délivrer un template marketing à quelqu'un qui en reçoit beaucoup et en lit peu. Attendez au moins 24 heures avant de réessayer (doc)Erreur 131049 sur le webhook de statut, destinataire failed
Numéros des États-UnisWhatsApp ne délivre pas actuellement de templates marketing aux numéros américains (même page)Échec du destinataire
Débit80 messages par seconde par numéro par défaut, 20 pour un numéro en coexistence (débit, coexistence)Le lancement est cadencé dessus

Le plafond marketing par utilisateur n'est pas actif pour les envois depuis ou vers l'Espace économique européen, le Royaume-Uni, le Japon et la Corée du Sud (même page Meta).

Les templates MARKETING d'une campagne sont d'abord proposés à la Marketing Messages API de Meta ; si votre compte n'y a pas accès, l'envoi repasse sur l'endpoint classique sans interrompre la campagne.

Combien coûte une campagne chez Meta ?

Meta facture par message délivré, au tarif de la catégorie du template et de l'indicatif du pays du destinataire, sur votre portefeuille Business (Meta, Pricing). Genuka n'y ajoute aucune marge et ne voit jamais passer ce paiement.

Faut-il un opt-in pour une campagne WhatsApp ?

Oui. La politique WhatsApp Business n'autorise à contacter quelqu'un que s'il vous a donné son numéro et a confirmé vouloir recevoir vos messages (WhatsApp Business Messaging Policy). Meta précise que la demande doit nommer votre entreprise et dire clairement à quoi la personne s'abonne, par le canal de votre choix — site, SMS, formulaire papier (Meta, Get opt-in). Une qualité durablement basse fait limiter le numéro par Meta (même page).

Genuka applique la désinscription pour vous sur les campagnes marketing :

  • Quand un utilisateur arrête les messages marketing depuis WhatsApp, Meta l'annonce par webhook ; Genuka l'enregistre. Un envoi refusé avec 131050 (« ce destinataire a choisi de ne plus recevoir de messages marketing ») l'enregistre aussi.
  • Au lancement d'une campagne MARKETING, ces contacts sont écartés avant tout envoi et passent en statut skipped, avec le motif. Ils ne consomment ni quota ni facturation Meta.
  • Les campagnes UTILITY et AUTHENTICATION ne sont pas filtrées : ce ne sont pas des messages marketing.

Un mot-clé maison (« répondez STOP ») n'est pas interprété automatiquement : les réponses vous arrivent sur message.received, et c'est à vous de retirer ces contacts de vos listes.

Comment suivre les résultats d'une campagne ?

GET /api/v1/campaigns/{id} renvoie la campagne, son template, son numéro et un objet stats qui compte les destinataires par statut :

GET /api/v1/campaigns/cmp_9
{
  "data": {
    "id": "cmp_9",
    "name": "Promo octobre",
    "status": "completed",
    "template": { "id": "tpl_123", "name": "promo_octobre", "language": "fr", "status": "approved" },
    "_count": { "recipients": 1200 },
    "stats": { "read": 640, "delivered": 410, "sent": 95, "failed": 41, "skipped": 14 }
  }
}

Chaque destinataire n'est compté qu'une fois, sous son statut le plus avancé : un message lu figure dans read, pas dans delivered. Le taux de livraison se lit donc (delivered + read) / (total − skipped).

StatutSignification
pendingPas encore envoyé
sentAccepté par Meta
deliveredArrivé sur le téléphone
readLu — seulement si le destinataire a activé les confirmations de lecture
failedRefusé, avec le motif de Meta dans errorMessage
skippedÉcarté au lancement : désinscrit du marketing

Pour les échecs, GET /api/v1/campaigns/{id}/recipients?status=failed&limit=1000 liste chaque destinataire avec errorMessage, sentAt, deliveredAt, readAt et failedAt (200 lignes par défaut, 1 000 au maximum). En temps réel, abonnez un endpoint à message.delivered, message.read, message.failed et user_preference.stopped — voir Webhooks.

Comment renvoyer aux destinataires bloqués par le plafond marketing ?

Le plafond marketing par utilisateur se signale après l'envoi : Meta accepte le message, puis le webhook de statut revient failed avec l'erreur 131049 (Meta, Per-user limits). Le destinataire passe en failed, avec le texte de Meta dans errorMessage (Meta décrit cette erreur ainsi : « This message was not delivered to maintain healthy ecosystem engagement »). Un nouvel appel à launch ne le renverra pas : il ne reprend que les destinataires pending.

Pour retenter ces personnes, attendez au moins 24 heures, listez GET /api/v1/campaigns/{id}/recipients?status=failed, gardez ceux qui portent ce motif (ou le code 131049 reçu sur message.failed) et créez une nouvelle campagne avec eux. Dans le cas plus rare où Meta refuse l'envoi lui-même avec 131049, le destinataire reste pending, et un nouvel appel à launch 24 heures plus tard le reprend.

Limites de la version actuelle

  • Le lancement est synchrone et borné dans le temps. L'appel parcourt la liste un destinataire après l'autre : chaque envoi attend la réponse de Meta puis l'enregistrement de son statut, si bien que le débit réel reste bien en dessous du plafond du numéro. Au-delà de 2 minutes environ, le CDN qui protège l'API répond 524 — une page d'erreur, pas du JSON — alors que l'envoi continue côté serveur (Cloudflare, erreur 524). Gardez des campagnes de quelques centaines de destinataires et découpez une grosse audience en plusieurs campagnes.
  • Après un 524, suivez la campagne au lieu de la relancer. Interrogez GET /api/v1/campaigns/{id} jusqu'à ce que status ne soit plus running. N'appelez jamais launch sur une campagne running : rien ne l'en empêche aujourd'hui, et deux exécutions en parallèle enverraient deux fois le message aux destinataires que la première n'a pas encore atteints.
  • Une exécution trop longue est interrompue. Le serveur ne laisse pas un appel tourner indéfiniment. Si la campagne est encore running 15 minutes après l'appel, l'exécution a été coupée : les destinataires restés pending n'ont pas été envoyés, et un nouvel appel à launch les reprend.
  • Pas de planification. Aucun champ de date : appelez launch au moment voulu, depuis votre propre tâche planifiée.

Et si je préfère une interface plutôt qu'une API ?

Genuka WA n'a pas de console de campagnes : /api/v1/campaigns est une brique d'intégration (template + destinataires + statuts). Si vous voulez segmenter une clientèle et lancer des campagnes sans écrire de code, Genuka Core, la plateforme de gestion commerciale de Genuka, le fait : elle catégorise vos clients, analyse leur comportement d'achat et lance des campagnes WhatsApp, SMS et email ciblées.

FAQ

Puis-je envoyer une campagne à des contacts qui ne m'ont jamais écrit ?

Oui, avec un template approuvé et leur opt-in. C'est précisément le rôle du template : il est le seul message délivré hors de la fenêtre de 24 heures. Le plafond d'envoi de Meta (250 destinataires uniques par 24 heures pour un portefeuille neuf) s'applique à ces envois.

Combien coûte une campagne WhatsApp avec Genuka WA ?

Deux lignes séparées. Meta facture chaque template délivré à votre portefeuille Business, selon la catégorie et le pays du destinataire. Genuka facture un abonnement par numéro WhatsApp, avec un quota de messages inclus, et ne prend aucune marge sur les tarifs de Meta.

Que se passe-t-il si un destinataire s'est désinscrit ?

Sur une campagne MARKETING, il est écarté avant l'envoi et marqué skipped. Il ne consomme pas votre quota et Meta ne vous facture rien pour lui.

Pourquoi sent est-il élevé mais delivered faible ?

sent signifie seulement que Meta a accepté le message. Les accusés de livraison arrivent ensuite par webhook ; s'ils ne viennent pas, regardez failed et les erreurs 131049 (plafond marketing) ou 131026 (destinataire injoignable).

Puis-je relancer la même campagne ?

Oui, une fois qu'elle n'est plus running (completed ou failed) : launch n'envoie alors que les destinataires encore pending, jamais un message déjà parti. Ne la relancez pas pendant qu'elle est running, même après un 524 : attendez qu'elle en sorte, ou 15 minutes si elle y reste (voir les limites ci-dessus).

Sources

Sur cette page