W Waxion API

Guide d'installation et documentation

Waxion API est une passerelle WhatsApp livrée sous forme d'un fichier exécutable unique. Elle vous permet d'envoyer des messages texte, des pièces jointes et des campagnes en masse depuis votre propre numéro WhatsApp, via une interface web et une API HTTP.

Aucune dépendance

Un seul fichier à copier et à lancer. Ni base de données à installer, ni runtime.

5 messages offerts

Chaque compte démarre avec un essai gratuit, sans saisie de moyen de paiement.

Messages non stockés

Les messages reçus ne sont jamais écrits sur disque, uniquement relayés en direct.

Ce n'est pas un chatbot.

L'application ne répond jamais automatiquement aux messages. Elle sert à envoyer, et à consulter en direct les messages reçus — que vous pouvez relayer vers votre propre système grâce au webhook.

Installation

Vous avez besoin d'une machine Linux et du fichier waxion-api qui vous a été remis. Rien d'autre n'est à installer : ni Go, ni base de données, ni serveur web.

  1. 1

    Placer le fichier dans un dossier dédié

    Ce dossier accueillera aussi la session WhatsApp et, si vous en créez un, le fichier de configuration.

    mkdir -p /opt/waxion-api
    cd /opt/waxion-api
    # copiez ensuite le fichier waxion-api dans ce dossier
  2. 2

    Autoriser son exécution

    Un fichier fraîchement copié n'est pas exécutable par défaut sous Linux.

    chmod +x waxion-api
  3. 3

    Lancer l'application

    ./waxion-api

    L'interface est alors disponible sur http://localhost:3063 (port par défaut). Rendez-vous ensuite à la section Premiers pas.

Configuration

L'application démarre sans aucune configuration. Pour changer le port ou déclarer votre nom de domaine, créez un fichier nommé .env à côté de l'exécutable :

PORT=3700
PUBLIC_BASE_URL=https://votre-domaine.com
TRUSTED_ORIGIN=https://votre-domaine.com
Paramètre Défaut Rôle
PORT 3063 Port d'écoute HTTP de l'application.
PUBLIC_BASE_URL http://localhost:PORT Adresse publique de votre installation. Indispensable en production : c'est vers elle que le prestataire de paiement renvoie l'utilisateur après un abonnement.
TRUSTED_ORIGIN vide Seule origine autorisée à envoyer des requêtes modifiantes (protection contre les requêtes falsifiées). Renseignez votre domaine en production.
DATA_DIR ./data Dossier où est conservée la session WhatsApp de cette installation.
SESSION_TTL_HOURS 24 Durée de validité d'une session de connexion à l'interface.
MAX_LOGIN_ATTEMPTS 5 Nombre d'échecs de connexion avant verrouillage temporaire de l'adresse IP.
LOGIN_LOCKOUT_MINUTES 15 Durée de ce verrouillage.

Le dossier data/ est le seul à sauvegarder.

Il contient la liaison avec votre numéro WhatsApp. Votre compte, votre abonnement et vos paiements sont stockés côté serveur central, pas sur votre machine : ils vous suivent même si vous relancez l'exécutable ailleurs.

Garder l'application lancée en continu

Lancée simplement avec ./waxion-api, l'application s'arrête dès que vous fermez le terminal. Deux solutions selon vos besoins.

Solution rapide

Pour un test ou un usage ponctuel. L'application survit à la fermeture du terminal, mais pas à un redémarrage de la machine.

nohup ./waxion-api > waxion-api.log 2>&1 &

Pour l'arrêter :

pkill waxion-api

Solution recommandée

Un service systemd redémarre l'application automatiquement en cas d'erreur et après un redémarrage du serveur. Créez le fichier /etc/systemd/system/waxion-api.service :

[Unit]
Description=Waxion API
After=network.target

[Service]
Type=simple
WorkingDirectory=/opt/waxion-api
EnvironmentFile=/opt/waxion-api/.env
ExecStart=/opt/waxion-api/waxion-api
Restart=on-failure
User=waxion

[Install]
WantedBy=multi-user.target

Puis activez-le :

sudo systemctl daemon-reload
sudo systemctl enable --now waxion-api
sudo systemctl status waxion-api

Mettre à jour l'application

Remplacez le fichier waxion-api par la nouvelle version reçue, puis redémarrez le service (sudo systemctl restart waxion-api). Le dossier data/ n'est jamais affecté : vous n'aurez pas à rescanner de code QR.

Option : lancer avec Docker

Docker n'est pas nécessaire — l'exécutable fonctionne seul. Cette option intéresse ceux dont l'infrastructure est déjà conteneurisée. Le principe reste le même : on se contente d'emballer l'exécutable que vous avez reçu.

1

Créer un fichier Dockerfile

À placer dans le même dossier que l'exécutable, sans extension.

FROM alpine:3.20

# Certificats requis pour les appels sécurisés sortants
RUN apk add --no-cache ca-certificates tzdata

WORKDIR /app
COPY waxion-api .
RUN chmod +x waxion-api

VOLUME ["/app/data"]
ENTRYPOINT ["./waxion-api"]
2

Construire l'image

docker build -t waxion-api:latest .
3

Démarrer le conteneur

Le dossier data est monté depuis l'hôte : la session WhatsApp survit ainsi aux redémarrages et aux reconstructions de l'image.

docker run -d \
  --name waxion-api \
  --restart unless-stopped \
  --env-file .env \
  -p 3700:3700 \
  -v "$(pwd)/data:/app/data" \
  waxion-api:latest

Adaptez le port à celui déclaré dans votre fichier .env. Si vous n'en avez pas, utilisez -p 3063:3063 et retirez l'option --env-file.

Variante avec Docker Compose

Plus commode si vous relancez souvent. Créez docker-compose.yml, puis lancez docker compose up -d.

services:
  waxion-api:
    build: .
    image: waxion-api:latest
    restart: unless-stopped
    env_file:
      - .env
    ports:
      - "3700:3700"
    volumes:
      - ./data:/app/data

Exposer l'application en HTTPS avec Nginx

Cette étape ne concerne que les installations accessibles depuis Internet. Nginx place votre application derrière un nom de domaine et un certificat TLS.

Deux réglages sont indispensables et souvent oubliés.

  • client_max_body_size — sans lui, Nginx refuse tout envoi de fichier dépassant 1 Mo, avant même que l'application ne le reçoive. C'est la cause la plus fréquente des erreurs à l'envoi de pièces jointes.
  • proxy_buffering off — sans lui, le code QR de connexion et l'affichage en direct des messages reçus n'apparaissent pas.
server {
  server_name votre-domaine.com;

  client_max_body_size 140m;

  location / {
    proxy_pass http://127.0.0.1:3700;
    proxy_http_version 1.1;
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Proto $scheme;
    proxy_buffering off;
    proxy_read_timeout 3600s;
  }

  listen 443 ssl;
  ssl_certificate     /etc/letsencrypt/live/votre-domaine.com/fullchain.pem;
  ssl_certificate_key /etc/letsencrypt/live/votre-domaine.com/privkey.pem;
}

Vérifiez la syntaxe puis rechargez Nginx :

sudo nginx -t && sudo systemctl reload nginx

Pensez enfin à renseigner PUBLIC_BASE_URL et TRUSTED_ORIGIN avec votre adresse HTTPS dans le fichier .env, puis à redémarrer l'application.

Premiers pas dans l'application

1

Créer votre compte

Depuis l'écran de connexion, choisissez « Créer un compte ». Votre identifiant doit faire au moins 3 caractères, et votre mot de passe au moins 8. L'essai gratuit de 5 messages est activé immédiatement.

2

Lier votre numéro WhatsApp

Un code QR s'affiche. Depuis WhatsApp sur votre téléphone, ouvrez Appareils connectés puis scannez-le. La liaison reste valable tant que vous ne la révoquez pas.

3

Envoyer un premier message

Utilisez l'onglet d'envoi de l'interface pour vérifier que tout fonctionne, avant de brancher votre propre système sur l'API.

4

Récupérer votre clé API

Dans l'onglet Paramètres. Cette clé permet à vos propres applications d'envoyer des messages sans passer par l'interface.

Deuxième partie

Documentation de l'API

Tout ce que l'interface web sait faire est également accessible en HTTP. Vous pouvez donc brancher votre logiciel de gestion, votre site ou vos automatisations directement sur Waxion API.

Principes généraux

Adresse de base

C'est l'adresse de votre installation. En local : http://localhost:3063. Derrière un domaine : https://votre-domaine.com.

Format des réponses

Toutes les réponses suivent la même structure. Vérifiez toujours le champ success avant d'exploiter data.

{
  "success": true,
  "message": "Message envoyé",
  "data": { },
  "error": ""
}

Deux modes d'authentification

Clé APIRecommandé

Pour tout système externe. Récupérez votre clé dans l'onglet Paramètres, puis transmettez-la à chaque requête via l'en-tête :

X-API-Key: votre_cle_api

L'en-tête Authorization: Bearer votre_cle_api est également accepté, si votre outil le pose automatiquement.

Session par cookie

C'est le mode utilisé par l'interface web elle-même, après connexion. Certaines opérations sensibles y sont réservées : la connexion WhatsApp, l'abonnement, et la gestion de la clé API — une clé API ne peut donc pas servir à en obtenir une nouvelle.

Votre clé API vaut un mot de passe.

Conservez-la côté serveur uniquement, jamais dans le code d'une page web ou d'une application mobile. En cas de doute, régénérez-la depuis l'onglet Paramètres : l'ancienne cesse instantanément de fonctionner.

Envoi de messages

Ce sont les deux routes que vous utiliserez le plus. Elles acceptent la clé API et consomment votre essai gratuit ou votre abonnement.

POST /api/messages/send-text Clé API acceptée

Envoie un message texte à un destinataire.

Corps de la requête

{
  "phone": "24177000000",
  "message": "Bonjour, votre réservation est confirmée."
}

Le numéro s'écrit au format international, sans + ni espaces : indicatif pays suivi du numéro.

Exemple complet

curl -X POST https://votre-domaine.com/api/messages/send-text \
  -H "Content-Type: application/json" \
  -H "X-API-Key: votre_cle_api" \
  -d '{"phone":"24177000000","message":"Bonjour !"}'

Réponse

{
  "success": true,
  "message": "Message envoyé",
  "data": { "message_id": "3EB0...", "phone": "24177000000" }
}
POST /api/messages/send-file Clé API acceptée

Envoie une pièce jointe de n'importe quel type — PDF, image, vidéo, audio, tableur, archive — accompagnée d'une légende facultative. Le fichier est transmis encodé en base64.

Corps de la requête

{
  "phone": "24177000000",
  "caption": "Voici votre billet",
  "filename": "billet.pdf",
  "mimetype": "application/pdf",
  "file_base64": "data:application/pdf;base64,JVBERi0x..."
}
Champ Obligatoire Détail
phone Numéro international du destinataire.
file_base64 Contenu du fichier en base64. Le préfixe data:...;base64, est accepté mais facultatif.
filename Conseillé Nom affiché au destinataire.
mimetype Facultatif Déduit du nom de fichier s'il est absent.
caption Facultatif Texte accompagnant la pièce jointe.
Taille maximale : 100 Mo — c'est la limite officielle de WhatsApp pour les documents. Si vous passez par Nginx, vérifiez également le réglage client_max_body_size décrit plus haut.

Comment l'essai et l'abonnement sont décomptés

  • Abonnement actif — envois illimités, aucun compteur n'est décompté.
  • Essai en cours — l'envoi est autorisé, et le compteur n'est incrémenté qu'après un envoi réussi. Un échec ne vous coûte rien.
  • Essai épuisé, sans abonnement — la requête est refusée avec le code 402. Le détail de vos droits est renvoyé dans data.entitlement.

Campagnes en masse

Une campagne envoie un message personnalisé à une liste de destinataires, en espaçant automatiquement chaque envoi pour préserver votre compte WhatsApp.

POST /api/bulk Clé API acceptée

Démarre une campagne. La réponse est immédiate : l'envoi se poursuit en arrière-plan et vous suivez sa progression grâce à l'identifiant renvoyé.

{
  "contacts": [
    { "phone": "24177000001", "message": "Bonjour Jean" },
    {
      "phone": "24177000002",
      "message": "Bonjour Awa",
      "file_base64": "data:application/pdf;base64,...",
      "file_name": "billet.pdf",
      "mimetype": "application/pdf"
    }
  ],
  "delay_min_seconds": 8,
  "delay_max_seconds": 20
}

300

contacts maximum par campagne

3 s

délai minimum imposé entre deux envois

8–20 s

délai recommandé en usage réel

Le délai réel est tiré au hasard entre vos deux bornes avant chaque envoi : cette irrégularité rend le comportement plus naturel aux yeux de WhatsApp.

Vos droits sont revérifiés avant chaque destinataire, et non seulement au lancement. Si l'essai s'épuise en cours de campagne, celle-ci s'arrête d'elle-même et les destinataires restants sont marqués en échec avec un motif explicite.
GET /api/bulk/{id} Suivre une campagne : statut, nombre d'envois réussis, échecs et détail par destinataire.
GET /api/bulk Lister les campagnes de cette installation depuis son démarrage.
POST /api/bulk/{id}/cancel Interrompre une campagne en cours ; les envois déjà effectués ne sont pas annulés.

Le suivi des campagnes est conservé en mémoire : il est remis à zéro au redémarrage de l'application. Si vous devez archiver les résultats, récupérez-les depuis votre propre système.

Recevoir les messages entrants

Waxion API ne conserve jamais le contenu des messages reçus. Pour les exploiter, déclarez une adresse de webhook : chaque message entrant y sera transmis en temps réel, à charge pour votre système de le traiter et de le conserver.

GET /api/settings/webhook Consulter l'adresse actuellement configurée.
POST /api/settings/webhook Clé API acceptée
{ "webhook_url": "https://votre-systeme.com/webhook/whatsapp" }

Le changement prend effet immédiatement, sans redémarrage. Envoyez une chaîne vide pour désactiver le relais.

Ce que votre serveur recevra

Pour chaque message reçu, Waxion API envoie une requête POST à votre adresse, avec ce contenu :

{
  "from": "24177000000",
  "push_name": "Jean D.",
  "text": "Bonjour",
  "message_id": "3EB0...",
  "timestamp": "2026-07-02T10:00:00Z"
}
  • L'envoi est abandonné au bout de 8 secondes sans réponse de votre part.
  • Un webhook lent ou indisponible ne perturbe jamais la réception WhatsApp. En contrepartie, il n'y a ni file d'attente ni nouvelle tentative : un message non reçu par votre serveur est définitivement perdu.
  • Seuls les messages textuels sont relayés à ce jour.

Compte, abonnement et connexion WhatsApp

Ces routes sont réservées à l'interface web : elles exigent une session, et n'acceptent pas la clé API. Elles sont documentées ici à titre de référence.

Compte

POST /api/auth/signup Créer un compte : username (3 caractères minimum), password (8 minimum), phone_number facultatif.
POST /api/auth/login Ouvrir une session.
POST /api/auth/logout Fermer la session courante.
GET /api/auth/me Identifier le compte connecté.
POST /api/auth/change-password Changer le mot de passe. Toutes les sessions ouvertes sont invalidées.
GET /api/settings/api-token Obtenir sa clé API (créée à la volée au premier appel).
POST /api/settings/api-token/regenerate Générer une nouvelle clé et révoquer l'ancienne immédiatement.

Abonnement

GET /api/billing/status Consulter l'état de l'essai et de l'abonnement : messages restants, date de fin, tarif.
POST /api/billing/subscribe Ouvrir un paiement Mobile Money et récupérer l'adresse vers laquelle rediriger l'utilisateur.

L'abonnement mensuel coûte 15 000 FCFA. Il est activé pour un mois dès le paiement confirmé, et prolongé si un abonnement était déjà en cours. Il expire automatiquement à échéance : aucun prélèvement récurrent n'est effectué.

Connexion WhatsApp

GET /api/whatsapp/status État de la liaison et numéro connecté.
POST /api/whatsapp/connect Démarrer la liaison et la génération du code QR.
GET /api/whatsapp/qr Dernier code QR généré, en image.
FLUX /api/whatsapp/qr/stream Flux continu des codes QR successifs jusqu'au scan.
FLUX /api/whatsapp/incoming/stream Flux continu des messages entrants, affichés en direct sans être stockés.
POST /api/whatsapp/disconnect Rompre la liaison avec le numéro.

Les entrées marquées FLUX sont des flux Server-Sent Events : la connexion reste ouverte et le serveur pousse les nouveautés au fil de l'eau. Aucune de ces routes ne consomme votre essai gratuit.

Codes d'erreur

Code Signification et marche à suivre
400 Requête mal formée : numéro invalide, champ obligatoire manquant, ou fichier dépassant la taille autorisée.
401 Non authentifié : session expirée, ou clé API absente ou invalide.
402 Essai gratuit épuisé et aucun abonnement actif. Un abonnement est nécessaire pour continuer à envoyer.
403 Origine refusée. Vérifiez que TRUSTED_ORIGIN correspond bien à l'adresse depuis laquelle vous appelez l'API.
404 Ressource introuvable, par exemple un identifiant de campagne inconnu.
429 Trop de tentatives de connexion échouées. Votre adresse IP est temporairement verrouillée.
502 WhatsApp ou le prestataire de paiement est injoignable. Vérifiez l'état de la liaison WhatsApp.
500 Erreur interne inattendue. Consultez les journaux de l'application.

Préserver votre compte WhatsApp

WhatsApp surveille les comportements d'envoi automatisés. Ces précautions réduisent nettement le risque de suspension de votre numéro.

Espacez vos envois

Un délai de 8 à 20 secondes entre chaque message reste le meilleur compromis entre prudence et rapidité.

Variez le contenu

Un texte strictement identique envoyé des centaines de fois est le signal le plus facilement détecté. Personnalisez au moins le nom du destinataire.

Répartissez les grosses campagnes

Mieux vaut plusieurs campagnes modestes étalées sur plusieurs jours qu'un envoi massif en une seule fois.

Surveillez la liaison

Une déconnexion inattendue signale souvent que WhatsApp a jugé votre activité suspecte. Réduisez alors immédiatement le volume et la fréquence.

Dépannage

L'envoi d'un fichier échoue dès qu'il dépasse environ 1 Mo
C'est presque toujours Nginx, et non l'application : il refuse par défaut les requêtes de plus de 1 Mo, avant même qu'elles n'atteignent Waxion API. Ajoutez client_max_body_size 140m; dans votre configuration, puis rechargez Nginx. Voir la section dédiée.
Le code QR ne s'affiche pas, ou les messages reçus n'apparaissent pas en direct
Ces deux fonctions reposent sur des flux maintenus ouverts. Si vous passez par Nginx, ajoutez proxy_buffering off; et proxy_read_timeout 3600s; dans le bloc location.
L'API renvoie une erreur d'origine non autorisée (403)
Votre TRUSTED_ORIGIN ne correspond pas à l'adresse utilisée par le navigateur. Elle doit être identique au caractère près, protocole compris — par exemple https://votre-domaine.com, sans barre oblique finale.
L'envoi échoue avec « WhatsApp non connecté »
La liaison a été rompue, souvent parce que l'appareil a été retiré depuis le téléphone, ou après une longue inactivité. Rendez-vous dans l'interface et scannez à nouveau le code QR.
Consulter les journaux de l'application
Avec systemd : journalctl -u waxion-api -f. Avec Docker : docker logs -f waxion-api. Avec nohup : le fichier waxion-api.log.