Envoyez des messages WhatsApp depuis votre application via une API REST simple. Authentification par clé, réponses JSON, codes HTTP standards.
Chaque requête doit inclure votre clé API dans l'en-tête Authorization, selon le schéma Bearer :
Authorization: Bearer wch_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
En alternative, l'en-tête X-API-Key est accepté.
Vos clés se gèrent depuis votre espace : Tenant → Clés API. Une clé n'est affichée en clair qu'une seule fois, à sa création.
POST/api/v1/messages
| Champ | Type | Requis | Description |
|---|---|---|---|
to | string | oui | Numéro du destinataire. Format local (0600000000) ou international (212600000000). |
body | string | oui | Contenu texte du message. |
type | string | non | Type de message. Défaut : text. |
reference | string | non | Référence libre côté client, renvoyée telle quelle. |
curl -X POST https://winochat.ma/api/v1/messages \ -H "Authorization: Bearer wch_VOTRE_CLE_API" \ -H "Content-Type: application/json" \ -d '{"to":"0600000000","body":"Bonjour !","type":"text"}'
// 201 Created — message accepté et mis en file { "data": { "id": 8, "status": "queued", "to": "212600000110", "type": "text", "price": 0.08, "balance_after": 285.36, "reference": "votre-reference", "queued_at": "2026-05-30T20:33:58+01:00" } }
queued signifie « accepté et en file ». L'envoi réel suit immédiatement.
Suivez la remise via le statut du message ou les webhooks.
GET/api/v1/messages/{id}/status
curl https://winochat.ma/api/v1/messages/8/status \
-H "Authorization: Bearer wch_VOTRE_CLE_API"
{
"data": {
"id": 8,
"status": "sent",
"sent_at": "2026-05-30T20:34:02+01:00",
"error_message": null
}
}
Statuts : queued, sent, failed (voir error_message).
GET/api/v1/balance
curl https://winochat.ma/api/v1/balance \
-H "Authorization: Bearer wch_VOTRE_CLE_API"
{
"data": {
"balance": 285.36,
"currency": "MAD",
"price_per_message": 0.08
}
}
GET/api/v1/stats
Renvoie les statistiques agrégées du compte sur une période : volumes, taux de livraison et de lecture, détail par jour, et solde courant.
period — today, 7days, 30days ou month (défaut : 30days).from et to — dates au format YYYY-MM-DD (prioritaires sur period).curl https://winochat.ma/api/v1/stats?period=7days \
-H "Authorization: Bearer wch_VOTRE_CLE_API"
{
"data": {
"period": { "from": "2026-06-01", "to": "2026-06-07" },
"totals": {
"sent": 131,
"delivered": 120,
"read": 95,
"failed": 6,
"received": 33,
"delivery_rate": 91.6,
"read_rate": 72.5,
"failure_rate": 4.6
},
"by_day": [
{ "date": "2026-06-07", "sent": 57, "delivered": 52, "read": 40, "failed": 1 }
],
"balance": { "amount": 272.28, "currency": "MAD" }
}
}
Ces endpoints permettent d\'afficher le QR code de connexion WhatsApp directement dans votre application, et de surveiller l\'état de la ligne. La session WhatsApp reste gérée par WinoChat ; votre application ne fait qu\'afficher le QR et lire l\'état.
GET/api/v1/wa/status
curl https://winochat.ma/api/v1/wa/status \
-H "Authorization: Bearer wch_VOTRE_CLE_API"
{
"data": {
"connected": false,
"phone": null,
"qr_available": true,
"state": "qr_pending"
}
}
state vaut connected, qr_pending ou disconnected.
POST/api/v1/wa/qr
Déclenche la génération d\'un nouveau QR. La génération prend environ 5 secondes (le temps que le service WhatsApp démarre la session).
curl -X POST https://winochat.ma/api/v1/wa/qr \
-H "Authorization: Bearer wch_VOTRE_CLE_API"
GET/api/v1/wa/qr
{
"data": {
"connected": false,
"qr_available": true,
"qr": "data:image/png;base64,iVBORw0K...",
"expires_in": 52
}
}
Le champ qr est une data-URL directement affichable dans une balise <img src="...">. Le QR expire après ~60s (expires_in en secondes).
GET /wa/status. Si connected vaut true, la ligne est prête : aucune action.POST /wa/qr pour demander un QR.GET /wa/qr toutes les 2 secondes. Le QR apparaît après ~5s (qr_available: true). N\'appelez pas une seule fois : sondez en boucle.qr dans une balise <img>. L\'utilisateur la scanne depuis WhatsApp.GET /wa/status toutes les 3s. Dès que connected: true, la ligne est connectée.POST /wa/qr, laissez ~5 secondes et sondez GET /wa/qr en boucle. Un seul appel immédiat renverra qr_available: false.
Les erreurs renvoient un code HTTP approprié et un corps JSON :
{
"error": {
"code": "unauthorized",
"message": "Clé API manquante ou invalide."
}
}
| HTTP | code | Signification |
|---|---|---|
| 401 | unauthorized | Clé API manquante, invalide ou révoquée. |
| 400 | invalid_phone | Numéro de destinataire invalide. |
| 400 | invalid_request | Corps JSON malformé ou paramètre requis manquant. |
| 422 | wa_not_connected | La ligne WhatsApp du compte n'est pas connectée. |
| 422 | insufficient_funds | Solde insuffisant pour envoyer. |
| 429 | rate_limited | Trop de requêtes : limite par minute ou quota dépassé. |
| 500 | server_error | Erreur interne. Réessayez ou contactez le support. |
Chaque clé a une limite de requêtes par minute (60 par défaut) et, le cas échéant, un quota quotidien. En cas de dépassement, l'API renvoie 429 rate_limited. Espacez vos envois ou contactez le support pour relever vos limites.
Configurez une URL de webhook (Tenant → Clés API → Webhook) pour recevoir les événements en temps réel par POST.
| Événement | Déclenché quand… |
|---|---|
message.sent | Le message a été remis à WhatsApp. |
message.delivered | Le message a été délivré au destinataire. |
message.read | Le message a été lu. |
message.failed | L'envoi a échoué. |
Chaque requête inclut un en-tête X-Wino-Signature = HMAC-SHA256(secret, corps_brut).
$payload = file_get_contents('php://input'); $signature = $_SERVER['HTTP_X_WINO_SIGNATURE'] ?? ''; $expected = hash_hmac('sha256', $payload, $secretWebhook); if (!hash_equals($expected, $signature)) { http_response_code(401); exit('Signature invalide'); }
<?php function winochat_send($to, $body) { $ch = curl_init('https://winochat.ma/api/v1/messages'); curl_setopt_array($ch, [ CURLOPT_RETURNTRANSFER => true, CURLOPT_POST => true, CURLOPT_HTTPHEADER => [ 'Authorization: Bearer wch_VOTRE_CLE_API', 'Content-Type: application/json', ], CURLOPT_POSTFIELDS => json_encode([ 'to' => $to, 'body' => $body, 'type' => 'text', ]), ]); $res = curl_exec($ch); curl_close($ch); return json_decode($res, true); }
async function winochatSend(to, body) { const res = await fetch('https://winochat.ma/api/v1/messages', { method: 'POST', headers: { 'Authorization': 'Bearer wch_VOTRE_CLE_API', 'Content-Type': 'application/json', }, body: JSON.stringify({ to, body, type: 'text' }), }); return res.json(); }
# pip install requests import requests def winochat_send(to, body): r = requests.post( 'https://winochat.ma/api/v1/messages', headers={ 'Authorization': 'Bearer wch_VOTRE_CLE_API', 'Content-Type': 'application/json', }, json={'to': to, 'body': body, 'type': 'text'}, timeout=15, ) return r.json()