Référence API · v1

Documentation

Envoyez des messages WhatsApp depuis n'importe quel langage avec de simples requêtes HTTP. URL de base : https://api-wazo.tala-apps.tech/v1

Authentification

Créez une clé dans Console → Clés API, puis envoyez-la dans l'en-tête Authorization de chaque requête. Gardez-la côté serveur : ne l'intégrez jamais dans une application web ou mobile.

bash
Authorization: Bearer wag_xxxxxxxxxxxxxxxxxxxxxxxx

GET/v1/sessions

Lister les numéros

Renvoie vos numéros et leur id, à utiliser comme session_id pour choisir le numéro d'envoi (ou passez directement le numéro de téléphone dans from).

bash
curl https://api-wazo.tala-apps.tech/v1/sessions \
  -H "Authorization: Bearer $API_KEY"
json
{
  "sessions": [
    { "id": "c1f0e1a2-…", "name": "Service client", "phone": "242061234567", "status": "connected" }
  ]
}

POST/v1/messages

Envoyer un texte

Les messages sont mis en file puis envoyés un par un avec une cadence naturelle. La réponse arrive immédiatement avec le statut queued.

session_id

uuid · optionnel

Le numéro WhatsApp qui envoie, par son id (voir Lister les numéros).
from

string · optionnel

Le même choix par numéro de téléphone, ex. +242061234567. Si vous ne précisez ni session_id ni from, le message part de votre numéro connecté s'il n'y en a qu'un ; avec plusieurs numéros connectés, l'API renvoie une erreur 400 qui les liste.
to

string | string[]

Un ou plusieurs numéros au format international (50 max). Espaces et « + » acceptés.
text

string

Le texte du message (4096 caractères max). Mise en forme WhatsApp : *gras*, _italique_.
bash
curl -X POST https://api-wazo.tala-apps.tech/v1/messages \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "session_id": "c1f0e1a2-…",
    "to": ["+242 06 123 45 67", "+33612345678"],
    "text": "Bonjour ! Votre commande est prête 🎉"
  }'
json
{
  "messages": [
    { "id": "9b2d…", "to": "242061234567", "status": "queued" },
    { "id": "a71c…", "to": "33612345678", "status": "queued" }
  ]
}
javascript
await fetch("https://api-wazo.tala-apps.tech/v1/messages", {
  method: "POST",
  headers: { Authorization: `Bearer ${process.env.API_KEY}`, "Content-Type": "application/json" },
  body: JSON.stringify({ session_id: SESSION_ID, to: "+242061234567", text: "Bonjour !" }),
});

POST/v1/messages

Envoyer un média

Remplacez text par exactement un des objets ci-dessous. Le fichier est téléchargé depuis une URL publique (16 Mo max).

image

{ url, caption? }

Image JPEG, PNG ou WebP.
video

{ url, caption? }

Vidéo MP4.
audio

{ url, mimetype? }

Audio (MP3, OGG…).
document

{ url, filename?, caption?, mimetype? }

N'importe quel fichier : PDF, facture, billet…
bash
curl -X POST https://api-wazo.tala-apps.tech/v1/messages \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "session_id": "c1f0e1a2-…",
    "to": "+242061234567",
    "document": {
      "url": "https://exemple.com/factures/F-2026-104.pdf",
      "filename": "Facture F-2026-104.pdf",
      "caption": "Votre facture du mois"
    }
  }'

GET/v1/messages/{id}

Suivre un message

Le statut progresse au fil des accusés WhatsApp et ne revient jamais en arrière. Chaque étape est horodatée.

queued

en file

Accepté par l'API, en attente d'envoi.
sending

envoi

En cours d'envoi.
sent

sentAt

Accepté par les serveurs WhatsApp (une coche grise).
delivered

deliveredAt

Reçu sur le téléphone du destinataire (deux coches grises).
read

readAt

Lu par le destinataire (deux coches bleues). Non remonté si le destinataire a désactivé les confirmations de lecture : le message reste alors à delivered.
failed

error

Échec, avec la raison dans error. Les messages restés en file plus de 24 h (numéro hors ligne) ou dont le numéro a été déconnecté passent en échec.
bash
curl https://api-wazo.tala-apps.tech/v1/messages/9b2d… \
  -H "Authorization: Bearer $API_KEY"
json
{
  "message": {
    "id": "9b2d…", "to": "242061234567", "status": "read",
    "error": null, "waMessageId": "3EB0C4…",
    "createdAt": "2026-10-15T09:12:03.000Z",
    "sentAt": "2026-10-15T09:12:05.000Z",
    "deliveredAt": "2026-10-15T09:12:06.000Z",
    "readAt": "2026-10-15T09:14:41.000Z"
  }
}

Webhooks

Configurez une URL dans Console → Webhooks pour recevoir les messages entrants et les changements de statut. Chaque événement est un POST JSON. Répondez par un code 2xx en moins de 10 s ; sinon, nous réessayons après 5 s, 30 s et 2 min.

message.received

entrant

Un contact vous a écrit. Répondez avec POST /v1/messages.
message.sent

statut

Message accepté par WhatsApp.
message.delivered

statut

Reçu sur le téléphone du contact.
message.read

statut

Lu par le contact.
message.failed

statut

Échec, avec la raison dans error.
conversation.handoff

agent IA

L'agent IA a passé la main à un humain.
json
{
  "event": "message.received",
  "timestamp": "2026-10-15T09:20:11.000Z",
  "data": {
    "id": "5c1e…",
    "conversationId": "e0a4…",
    "sessionId": "c1f0e1a2-…",
    "from": "242061234567",
    "name": "Grâce M.",
    "content": { "type": "text", "text": "Bonjour, vous livrez à Pointe-Noire ?" },
    "waMessageId": "3EB0…",
    "timestamp": "2026-10-15T09:20:10.000Z"
  }
}

Vérifiez la signature avec votre secret : l'en-tête X-Signature vaut t=<timestamp>,v1=<signature>, où la signature est un HMAC-SHA256 de <timestamp>.<corps brut>.

javascript
import crypto from "node:crypto";

function verify(rawBody, header, secret) {
  const { t, v1 } = Object.fromEntries(header.split(",").map((p) => p.split("=")));
  if (Math.abs(Date.now() / 1000 - Number(t)) > 300) return false; // 5 min max
  const expected = crypto.createHmac("sha256", secret).update(`${t}.${rawBody}`).digest("hex");
  return crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(v1));
}

Agent IA

Chaque numéro peut avoir un agent IA qui répond automatiquement aux messages reçus. Configurez-le dans Numéros → Agent IA : instructions (rôle, ton, règles) et base de connaissances (PDF, TXT, MD, CSV ou texte collé). L'agent retrouve les passages pertinents de vos documents avant chaque réponse.

  • Il attend quelques secondes après le dernier message pour répondre en une seule fois.
  • Si vous répondez vous-même (téléphone ou boîte de réception), il se met en pause sur cette conversation.
  • Si le contact demande un humain, il envoie votre message de transfert et déclenche l'événement conversation.handoff.
  • Il ne lit pas encore les messages vocaux ni le contenu des images.

Limites & erreurs

400

Requête invalide

Le champ details liste les erreurs de validation.
401

Non authentifié

Clé API absente, invalide ou révoquée.
404

Introuvable

Numéro ou message inexistant (ou appartenant à un autre compte).
409

Conflit

Le numéro n'est pas connecté à WhatsApp.
402

Abonnement expiré

Essai ou offre terminé : envois et agent IA suspendus jusqu'au renouvellement.
429

Trop de requêtes

120 requêtes par minute, et quota quotidien de messages selon votre offre.

Pour protéger vos numéros contre le bannissement, n'envoyez des messages qu'à des personnes qui ont accepté de vous lire : pas de prospection de masse ni de listes achetées.