WhatsApp Multi-Device API
API REST complète pour gérer plusieurs instances WhatsApp avec support des médias, webhooks et reconnexion automatique.
Getting Started
Cette API vous permet de connecter et gérer plusieurs comptes WhatsApp simultanément. Elle supporte l'envoi de messages texte, médias, audio (y compris notes vocales), localisations et contacts.
Authentication
L'API utilise deux niveaux d'authentification :
1. Bearer Token (Admin)
Pour générer l'API Key. Défini dans .env :
Authorization: Bearer your-super-secret-bearer-token
2. API Key (Standard)
Pour toutes les autres opérations. Peut être envoyée via header ou body :
X-API-Key: votre_api_key_generee
Rate Limits
| Endpoint | Limite | Fenêtre |
|---|---|---|
| Général (toutes routes API) | 100 requêtes | 1 minute |
| Messaging (envoi messages) | 30 messages par device | 1 minute |
| Génération API Key | 5 requêtes | 1 heure |
API Key Management
Génère une nouvelle API Key. Nécessite le Bearer Token.
Request
curl -X POST https://w.whapply.com/api/key/generate \ -H "Authorization: Bearer your-bearer-token"
Response
{
"success": true,
"api_key": "abc123def456...",
"message": "API Key générée"
}
Obtenir les informations sur l'API Key.
Response
{
"success": true,
"generated_at": "2026-02-15T10:30:00.000Z",
"devices_count": 3
}
Device Management
Liste tous les devices avec leurs statuts.
Response
{
"success": true,
"count": 2,
"devices": [
{
"device_key": "abc123...",
"name": "WhatsApp Principal",
"phone": "212600000000@c.us",
"status": "connected",
"has_qr": false,
"stats": {
"sent": 145,
"received": 89,
"failed": 2
}
}
]
}
Créer un nouveau device WhatsApp.
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| name | string | Required | Nom du device |
| webhook | string | Optional | URL webhook pour recevoir les messages |
Request
{
"name": "WhatsApp Support",
"webhook": "https://example.com/webhook"
}
Obtenir le QR Code pour connecter un device.
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| device_key | string | Required | Clé du device |
Response
{
"success": true,
"qr": "2@abc123...",
"qrImage": "data:image/png;base64,...",
"device": "WhatsApp Support"
}
Redémarrer un device.
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| device_key | string | Required | Clé du device |
Supprimer définitivement un device.
Messaging
Envoyer un message texte.
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| device_key | string | Required | Clé du device |
| to | string | Required | Numéro destinataire (format: 212600000000) |
| message | string | Required | Texte du message |
Request
{
"device_key": "abc123...",
"to": "212600000000",
"message": "Bonjour, comment allez-vous ?"
}
Response
{
"success": true,
"message": "Message envoyé",
"data": {
"id": "3EB0C8F7D3C2A1B5E6...",
"to": "212600000000@c.us",
"timestamp": 1708000000
}
}
Envoyer une image, vidéo ou document.
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| device_key | string | Required | Clé du device |
| to | string | Required | Numéro destinataire |
| media | string | Required | Fichier en base64 |
| mimetype | string | Required | Type MIME (ex: image/jpeg) |
| filename | string | Optional | Nom du fichier |
| caption | string | Optional | Légende du média |
Supported MIME Types
| Category | MIME Types |
|---|---|
| Images | image/jpeg, image/png, image/gif, image/webp |
| Videos | video/mp4, video/3gpp, video/quicktime |
| Documents | application/pdf, application/msword, application/vnd.ms-excel, text/plain, etc. |
Request
{
"device_key": "abc123...",
"to": "212600000000",
"media": "/9j/4AAQSkZJRgABAQEA...",
"mimetype": "image/jpeg",
"filename": "photo.jpg",
"caption": "Regardez cette photo !"
}
Envoyer un fichier audio ou une note vocale (PTT).
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| device_key | string | Required | Clé du device |
| to | string | Required | Numéro destinataire |
| audio | string | Required | Audio en base64 |
| mimetype | string | Required | Type MIME audio (ex: audio/ogg) |
| ptt | boolean | Optional | true = note vocale, false = fichier audio (default: false) |
Request
{
"device_key": "abc123...",
"to": "212600000000",
"audio": "T2dnUwACAAAAAAAAAAA...",
"mimetype": "audio/ogg",
"ptt": true
}
Envoyer une localisation GPS.
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| device_key | string | Required | Clé du device |
| to | string | Required | Numéro destinataire |
| latitude | number | Required | Latitude GPS |
| longitude | number | Required | Longitude GPS |
| description | string | Optional | Description du lieu |
Request
{
"device_key": "abc123...",
"to": "212600000000",
"latitude": 33.5731,
"longitude": -7.5898,
"description": "Casablanca, Morocco"
}
Partager un contact (vCard).
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| device_key | string | Required | Clé du device |
| to | string | Required | Numéro destinataire |
| contact_id | string | Required | ID du contact à partager (format: 212611111111@c.us) |
Request
{
"device_key": "abc123...",
"to": "212600000000",
"contact_id": "212611111111@c.us"
}
Monitoring
Statistiques globales du serveur et des devices.
Response
{
"success": true,
"stats": {
"devices": {
"total": 5,
"connected": 3,
"reconnecting": 1,
"disconnected": 1
},
"messages": {
"sent": 1523,
"received": 892,
"failed": 12,
"reconnections": 5
},
"webhooks": {
"pending": 2
},
"server": {
"uptime": 3600,
"uptime_formatted": "0d 1h 0m",
"memory": {
"rss": "156.23 MB",
"heapUsed": "89.45 MB"
}
}
}
}
Historique des événements système.
Query Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
| limit | number | 100 | Nombre de logs à retourner |
| type | string | - | Filtrer par type d'événement |
| device_key | string | - | Filtrer par device |
Example
curl "https://w.whapply.com/api/logs?limit=50&type=message_sent" \ -H "X-API-Key: your-api-key"
Vérifier l'état du serveur (pas d'authentification requise).
Response
{
"success": true,
"status": "running",
"uptime": 3600,
"timestamp": "2026-02-15T14:30:00.000Z"
}
Webhooks
Lorsqu'un webhook est configuré sur un device, tous les messages entrants seront envoyés à l'URL configurée, incluant automatiquement les médias en base64.
Format du Payload - Message Texte
{
"device_key": "abc123...",
"from": "212600000000@c.us",
"to": "212611111111@c.us",
"body": "Hello!",
"type": "chat",
"timestamp": 1708000000,
"hasMedia": false,
"isForwarded": false,
"isGroup": false
}
Format du Payload - Message avec Média
{
"device_key": "abc123...",
"from": "212600000000@c.us",
"to": "212611111111@c.us",
"body": "Check this photo!",
"type": "image",
"timestamp": 1708000000,
"hasMedia": true,
"isForwarded": false,
"isGroup": false,
"media": {
"mimetype": "image/jpeg",
"data": "base64_encoded_data...",
"filename": "IMG-20260215-WA0001.jpg"
}
}
Types de Messages
| Type | Description | Media |
|---|---|---|
| chat | Message texte standard | Non |
| image | Photo ou image | Oui |
| video | Fichier vidéo | Oui |
| audio | Fichier audio | Oui |
| ptt | Note vocale (Push-to-Talk) | Oui |
| document | Document (PDF, Word, etc.) | Oui |
| sticker | Sticker WhatsApp | Oui |
| location | Partage de localisation | Non |
Exemple Complet : Traitement Webhook
// Endpoint webhook qui reçoit les messages app.post('/webhook', async (req, res) => { const message = req.body; // Répondre rapidement au webhook (< 10s) res.status(200).send('OK'); // Traiter le message en arrière-plan if (message.hasMedia && message.media) { // Le média est déjà en base64, il suffit de le sauvegarder const buffer = Buffer.from(message.media.data, 'base64'); const filename = message.media.filename || `media_${Date.now()}`; fs.writeFileSync(`./media/${filename}`, buffer); console.log('Média sauvegardé:', { filename: filename, type: message.media.mimetype, from: message.from, size: buffer.length }); } else { // Message texte simple console.log('Message texte:', message.body); } });
import base64
from pathlib import Path
from fastapi import FastAPI
app = FastAPI()
@app.post("/webhook")
async def handle_webhook(message: dict):
# Répondre rapidement
if message.get("hasMedia") and message.get("media"):
# Décoder le base64 et sauvegarder
media_data = base64.b64decode(message["media"]["data"])
filename = message["media"].get("filename", f"media_{int(time.time())}")
Path(f"./media/{filename}").write_bytes(media_data)
print(f"Média sauvegardé: {filename}")
print(f"Type: {message['media']['mimetype']}")
print(f"De: {message['from']}")
else:
# Message texte
print(f"Message: {message['body']}")
return {"status": "ok"}
<?php // webhook.php $message = json_decode(file_get_contents('php://input'), true); // Répondre rapidement http_response_code(200); echo 'OK'; // Traiter le message if ($message['hasMedia'] && isset($message['media'])) { // Décoder et sauvegarder le média $mediaData = base64_decode($message['media']['data']); $filename = $message['media']['filename'] ?? 'media_' . time(); file_put_contents("./media/$filename", $mediaData); error_log("Média sauvegardé: $filename"); error_log("Type: " . $message['media']['mimetype']); } else { // Message texte error_log("Message: " . $message['body']); } ?>
Gestion des Erreurs Média
Si le téléchargement du média échoue, le webhook recevra un champ media_error :
{
"device_key": "abc123...",
"type": "image",
"hasMedia": true,
"media_error": "Download failed: timeout"
}
Retry Policy
Les webhooks sont automatiquement retentés en cas d'échec :
- Tentative 1 : Immédiate
- Tentative 2 : Après 1 seconde
- Tentative 3 : Après 5 secondes
- Tentative 4 : Après 15 secondes (dernière)
Error Codes
| Code | Message | Description |
|---|---|---|
| 400 | Bad Request | Paramètres manquants ou invalides |
| 401 | Unauthorized | API Key ou Bearer Token invalide |
| 404 | Not Found | Device ou ressource introuvable |
| 429 | Too Many Requests | Rate limit dépassé |
| 500 | Internal Server Error | Erreur serveur |
| 503 | Service Unavailable | Device non connecté ou API Key non configurée |
Error Response Format
{
"success": false,
"error": "Device non connecté",
"details": "Additional error information"
}