Skip to main content
Toutes les routes nécessitent votre clé API secrète (Authorization: Bearer sk_...) ou une session dashboard. Un point de réception (webhook) appartient à votre marchand ; un abonnement (subscription) rattache ce point de réception à un type d’événement précis — un même webhook peut avoir plusieurs abonnements.
Créer, modifier ou supprimer un webhook (ou un abonnement), ainsi que renvoyer manuellement une livraison, se fait exclusivement depuis le tableau de bord. Seule la consultation (points de réception, abonnements, historique de livraison) reste accessible par clé API — voir Accès dashboard vs. clé API.

Catalogue d’events

Les events settlement.* sont en cours de fiabilisation côté plateforme — le contenu de data n’est pas garanti pour ces events précis pour le moment. Le catalogue reste correct, mais évitez de dépendre de la forme exacte de leur payload tant que ce point n’est pas stabilisé.

Format de l’enveloppe

Chaque event envoyé à votre URL partage la même structure :

data selon l’event

Comprendre les montants

amount n’est pas ce que le payeur débourse : cela dépend de fee_charge_mode. Pour rapprocher votre comptabilité, utilisez charged (ce qui a quitté le compte du client) et net_amount (ce qui vous revient) — jamais amount seul.
msisdn est vide sur les transactions antérieures au 17 août 2026 : le numéro n’était alors pas conservé. country, network et les montants sont toujours présents.

Consulter vos webhooks

Le secret de signature (signing_secret) n’est jamais renvoyé en lecture — ni par Lister, ni par Récupérer. Il n’apparaît qu’une seule fois, dans la réponse de création et dans celle d’une rotation de secret, y compris quand AlphaPay l’a généré pour vous. Copiez-le à ce moment-là : il n’est plus jamais réaffichable. Si vous l’avez perdu, définissez-en un nouveau depuis votre dashboard (Webhooks → Changer le secret) — les webhooks suivants seront signés avec celui-ci.

Sécurité — vérifier la signature

Chaque requête envoyée à votre URL inclut trois headers, en plus du corps JSON de l’event :
La signature couvre l’horodatage et le corps, séparés par un point :
L’horodatage est régénéré à chaque tentative de livraison : une nouvelle tentative 2 h plus tard porte le sien.

Deux contrôles, pas un seul

  1. L’âge — rejetez si X-Webhook-Timestamp s’écarte de plus de 5 minutes de votre horloge. Sans ce contrôle, un webhook légitime intercepté reste rejouable indéfiniment : sa signature ne périme jamais.
  2. La signature — recalculez-la sur le corps brut reçu, jamais sur une re-sérialisation de payload que vous reconstruiriez : l’ordre des clés ou le formatage des nombres peuvent différer et casser la comparaison bit à bit.
L’horodatage étant inclus dans la signature, un attaquant ne peut pas le rajeunir pour contourner le contrôle d’âge — la signature ne correspondrait plus.
Comparez toujours en temps constant (hash_equals, timingSafeEqual, hmac.compare_digest) et jamais avec == : une comparaison classique s’arrête au premier caractère différent, ce qui laisse fuiter la signature attendue par mesure du temps de réponse.

Historique de livraison

Chaque tentative de livraison (réussie, échouée, en cours de retry) est journalisée.
Pas de filtre disponible sur cette vue marchand — récupérez la liste et filtrez côté client. Un renvoi manuel se fait depuis le tableau de bord.

Fiabilité

  • 5 tentatives par event : immédiat, puis +30s, +5min, +30min, +2h.
  • Timeout de 15s par tentative.
  • Après épuisement des 5 tentatives, la livraison passe en statut FAILED définitif — seul un renvoi manuel depuis le tableau de bord peut la relancer, elle n’est plus retentée automatiquement.
Un abonnement ne peut être créé qu’une seule fois par couple (webhook, event_type). Retenter d’abonner le même webhook au même event_type renvoie aujourd’hui une erreur serveur générique plutôt qu’un message dédié.