Aller au contenu

Webhooks (Endpoints)

Les webhooks permettent à Sangho de notifier votre serveur en temps réel lors d’événements importants — paiement réussi, remboursement effectué, abonnement annulé, etc. Plutôt que de poller l’API, votre serveur reçoit une requête HTTP POST dès que l’événement se produit.

Chaque endpoint webhook écoute une liste d’événements configurables et dispose de son propre secret de signature HMAC-SHA256. Consultez la Référence des événements pour la liste complète des types disponibles.

Toujours vérifier la signature

Chaque requête webhook inclut un header Sangho-Signature. Vérifiez systématiquement cette signature HMAC-SHA256 avant de traiter l’événement — cela garantit que la requête vient bien de Sangho et non d’un tiers malveillant. Consultez le guide de vérification de signature.

Événements disponibles

ÉvénementDéclencheur
payment_intent.succeededPaymentIntent passé en statut succeeded.
payment_intent.failedPaymentIntent passé en statut canceled après échec.
transaction.succeededTransaction créée et complétée.
refund.succeededRemboursement restitué à l'acheteur.
refund.failedRemboursement échoué côté opérateur.
invoice.paidFacture réglée.
invoice.payment_overdueDate d'échéance dépassée sans paiement.
checkout.session.completedCheckoutSession passée en statut complete.
subscription.createdNouvel abonnement créé.
subscription.canceledAbonnement annulé.
subscription.payment_failedTentative de renouvellement échouée.
customer.createdNouveau Customer créé.
customer.deletedCustomer supprimé.

Endpoints

MéthodeEndpointDescription
POST/webhooks/Créer un endpoint webhook
GET/webhooks/Lister les endpoints
GET/webhooks/{id}/Récupérer un endpoint
PATCH/webhooks/{id}/Modifier un endpoint
DELETE/webhooks/{id}/Supprimer un endpoint
POST/webhooks/{id}/disable/Désactiver (suspendre les envois)
POST/webhooks/{id}/enable/Réactiver un endpoint désactivé
POST/webhooks/{id}/roll-secret/Régénérer le secret de signature
POST/webhooks/{id}/test/Envoyer un événement de test
GET/webhooks/{id}/deliveries/Logs de livraison
POST/webhooks/{id}/deliveries/{did}/retry/Rejouer une livraison échouée

Schéma de l’objet

Response Objet Webhook
Structure complète retournée par tous les endpoints de cette ressource.
json
{
  "id": "wh_xxxxxxxxxxxx",
  "object": "webhook",
  "name": "Webhook production principal",
  "url": "https://monapp.com/webhooks/sangho",
  "status": "active",
  "events": [
    "payment_intent.succeeded",
    "transaction.succeeded",
    "refund.succeeded",
    "subscription.canceled"
  ],
  "security_profile": "HMAC_SHA256",
  "ssl_verification": true,
  "retry_policy": {
    "max_attempts": 5,
    "backoff_type": "exponential"
  },
  "last_delivery_at": "2026-03-01T10:05:00Z",
  "success_rate": 0.987,
  "livemode": true,
  "created_at": "2026-01-01T00:00:00Z"
}
Response Structure d'un événement reçu
Corps de la requête POST envoyée à votre endpoint à chaque événement.
json
{
  "id": "evt_xxxxxxxxxxxx",
  "object": "event",
  "type": "payment_intent.succeeded",
  "created_at": "2026-03-01T10:05:00Z",
  "livemode": true,
  "data": {
    "object": {
      "id": "pay_3Nx8mLKZ2eZvKYlo28m",
      "object": "payment_intent",
      "amount": 15000,
      "currency": "XAF",
      "status": "succeeded",
      "customer": "cust_xxxxxxxx",
      "metadata": { "order_id": "CMD-2026-042" }
    }
  }
}

Créer un endpoint webhook

Enregistre une nouvelle URL sur laquelle Sangho enverra les événements sélectionnés. Le secret de signature HMAC est retourné une seule fois à la création — stockez-le immédiatement dans votre gestionnaire de secrets.

POST Corps de la requête
name Requis
string ex : Production — commandes

Nom descriptif de l’endpoint. Affiché dans votre dashboard — utilisez un nom qui identifie clairement l’environnement ou l’usage.

Max 255 caractères. Un bon nom inclut l’environnement et la portée fonctionnelle, par exemple “Production — paiements & abonnements” ou “Staging — tous événements”.

url Requis
string URL HTTPS ex : https://monapp.com/webhooks/sangho

URL de votre endpoint webhook. Doit être accessible publiquement via HTTPS. Sangho effectue un ping de validation à la création.

L’URL doit répondre avec un code HTTP 2xx dans les 10 secondes pour être validée. Pour les tests en local, utilisez un tunnel comme ngrok ou localtunnel.

events Requis
array[string] ex : [“payment_intent.succeeded”, “refund.succeeded”]

Liste des types d’événements à écouter sur cet endpoint. Utilisez [”*”] pour recevoir tous les événements.

Préférez une liste explicite plutôt que ”*” pour réduire le volume de requêtes sur votre serveur et simplifier le débogage. Chaque endpoint peut écouter jusqu’à 50 types d’événements distincts. Consultez la référence des événements pour la liste complète.

security_profile Optionnel
string défaut : HMAC_SHA256

Méthode de signature des requêtes webhook.

En savoir plus

Valeurs : HMAC_SHA256 (recommandé — header Sangho-Signature), JWT (token JWT signé dans le header Authorization), BASIC (Basic Auth — déconseillé en production). Consultez le guide de signature pour les détails d’implémentation.

ssl_verification Optionnel
boolean défaut : true

Active la vérification du certificat SSL de votre endpoint.

En savoir plus

Ne désactivez ssl_verification qu’en environnement de développement avec un certificat auto-signé. En production, maintenez toujours cette option à true.

retry_policy Optionnel
object

Politique de retry en cas d’échec de livraison (timeout, erreur 5xx).

En savoir plus

Objet avec deux champs : max_attempts (défaut : 5, max : 10) et backoff_type (exponential ou linear, défaut : exponential). Avec le backoff exponentiel, les retries se font à 1 min, 5 min, 30 min, 2 h, 8 h. Avec linear : toutes les 30 minutes.

metadata Optionnel
object

Données libres associées à l’endpoint — environnement, équipe responsable, etc.

Secret affiché une seule fois

Le champ secret retourné à la création ne sera plus jamais affiché. Stockez-le immédiatement dans votre gestionnaire de secrets (variable d’environnement, Vault, AWS Secrets Manager…). Si vous le perdez, régénérez-en un nouveau via POST /webhooks/{id}/roll-secret/.

Créer un endpoint

bash
curl -X POST https://api.sangho.com/v1/webhooks/ \
  -H "Authorization: Bearer sk_live_xxxx" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Webhook production — commandes",
    "url": "https://monapp.com/webhooks/sangho",
    "events": [
      "payment_intent.succeeded",
      "transaction.succeeded",
      "refund.succeeded",
      "subscription.canceled"
    ],
    "security_profile": "HMAC_SHA256",
    "retry_policy": {
      "max_attempts": 5,
      "backoff_type": "exponential"
    }
  }'
Response 201 Created — Secret visible une seule fois
L'endpoint est créé et actif. Le champ secret est affiché ici et uniquement ici — stockez-le immédiatement.
Après cette réponse, le secret n'est plus accessible via l'API. Toute perte nécessite un roll-secret.
json
{
  "id": "wh_xxxxxxxxxxxx",
  "object": "webhook",
  "name": "Webhook production — commandes",
  "url": "https://monapp.com/webhooks/sangho",
  "status": "active",
  "events": [
    "payment_intent.succeeded",
    "transaction.succeeded"
  ],
  "secret": "whsec_xxxxxxxxxxxxxxxxxxxxxxxxxxx",
  "security_profile": "HMAC_SHA256",
  "livemode": true,
  "created_at": "2026-01-01T00:00:00Z"
}

Vérifier la signature

À chaque envoi, Sangho calcule une signature HMAC-SHA256 du corps de la requête avec votre secret et l’inclut dans le header Sangho-Signature. Vous devez recalculer cette signature côté serveur et comparer avec une méthode résistante aux timing attacks.

Utilisez le corps brut (raw body)

La signature est calculée sur le corps brut de la requête, avant tout parsing JSON. En Express.js, configurez express.raw({ type: 'application/json' }) sur la route webhook — ne passez pas par express.json() qui transformerait le body.

Gestion des livraisons

L’endpoint GET /webhooks/{id}/deliveries/ retourne l’historique des tentatives de livraison pour un endpoint donné. En cas d’échec, vous pouvez rejouer une livraison via POST /webhooks/{id}/deliveries/{did}/retry/.

Répondez rapidement, traitez en async

Votre endpoint doit retourner un 200 dans les 10 secondes. Pour les traitements longs (envoi d’email, appel à un service tiers), enfilez la tâche dans une queue (Celery, Bull, Sidekiq…) et répondez immédiatement. Passé ce délai, Sangho considère la livraison comme échouée et déclenche la politique de retry.

Vérification de signature

python
# Vérification côté réception (Python / Django)
import hmac, hashlib, os


def verify_webhook(payload: bytes, signature: str, secret: str) -> bool:
    expected = hmac.new(
        secret.encode(),
        payload,
        hashlib.sha256
    ).hexdigest()
    return hmac.compare_digest(f"sha256={expected}", signature)


@app.route('/webhooks/sangho', methods=['POST'])
def handle_webhook():
    payload = request.get_data()
    sig = request.headers.get('Sangho-Signature', '')


    if not verify_webhook(payload, sig, os.environ['SANGHO_WEBHOOK_SECRET']):
        return '', 403


    event = request.json
    if event['type'] == 'payment_intent.succeeded':
        order_id = event['data']['object']['metadata']['order_id']
        fulfill_order(order_id)


    return '', 200

Logs de livraison

Response GET /webhooks/{id}/deliveries/
Retourne les tentatives de livraison avec statut HTTP et réponse de votre serveur.
json
{
  "object": "list",
  "data": [
    {
      "id": "del_xxxxxxxxxx",
      "event_type": "payment_intent.succeeded",
      "status": "succeeded",
      "http_status": 200,
      "attempts": 1,
      "duration_ms": 145,
      "delivered_at": "2026-03-01T10:05:01Z"
    },
    {
      "id": "del_yyyyyyyyyy",
      "event_type": "refund.succeeded",
      "status": "failed",
      "http_status": 500,
      "attempts": 3,
      "next_retry_at": "2026-03-01T12:05:00Z",
      "error": "Connection timeout"
    }
  ]
}