---
title: Webhooks
description: Webhooks Coinetic : configuration, vérification de la signature HMAC, déduplication, relances, ordre de livraison, types d'événements et rotation du secret.
url: https://coinetic.money/fr/docs/webhooks/
lang: fr
---

# Webhooks

Coinetic informe votre serveur de chaque changement d'une facture par une requête POST. Un webhook est un signal « allez consulter la facture », pas une preuve de paiement.

## Configuration

- Tableau de bord → « Clés et webhooks » → « Ajouter ». L'URL doit être en `https://`, vers une adresse publique sur le port 443 (en sandbox, `http://localhost` est aussi accepté).
- Le secret de l'endpoint n'est affiché qu'une seule fois. Jusqu'à 5 endpoints actifs : chaque événement est envoyé à tous.

## Requête

```http
POST /webhooks/coinetic HTTP/1.1
Content-Type: application/json
User-Agent: cryptopay-webhooks/1
X-Webhook-Id: evt_3f9c…
X-Webhook-Timestamp: 1760000000
X-Webhook-Signature: v1=5d1e…

{"id":"evt_3f9c…","type":"invoice.paid","created_at":"2026-10-12T15:04:05Z","livemode":true,"data":{"invoice_id":"inv_x7k2…","order_id":"ORDER-1001","status":"paid","paid_amount":"49990000"}}
```

`X-Webhook-Id` reste identique d'une relance à l'autre. Pendant une rotation du secret, `X-Webhook-Signature` contient deux signatures séparées par une virgule. Les noms techniques (`cryptopay-webhooks/1`) sont historiques : inutile de les modifier de votre côté.

## Vérification de la signature

```
expected = "v1=" + hex(HMAC-SHA256(webhook_secret, X-Webhook-Timestamp + "." + raw_body))
```

- Prenez le **corps brut**, c'est-à-dire les octets avant tout parsing JSON.
- Vérifiez que `X-Webhook-Timestamp` ne s'écarte pas de l'heure actuelle de plus de 5 minutes.
- Découpez `X-Webhook-Signature` sur la virgule. La signature est valide si **l'une quelconque** des parties correspond à la valeur attendue (comparaison en temps constant).
- Aucune correspondance ? Répondez `401` et ne faites rien.

Valeurs de référence : secret `whsec-0123456789abcdef0123456789abcdef`, timestamp `1760000000`, corps `{"id":"evt_1","type":"invoice.paid"}` → `v1=aceeb56215ba09e7a2923d48f89afb8331f422f2d0a8cf60f76fef69fe06a6a4`.

## Traitement

```
vérifier la signature → dédupliquer par X-Webhook-Id → GET /v1/invoices/{invoice_id}
→ mettre à jour la commande selon le statut de l'API (livraison une seule fois) → répondre 2xx
```

- **Déduplication.** Un même événement peut arriver plusieurs fois. Conservez les `X-Webhook-Id` déjà traités ; positionnez l'indicateur « livré » dans la même transaction que la livraison.
- **Répondez vite** : en moins de 10 secondes. Placez les traitements longs dans une file d'attente.
- **Codes de réponse :** `2xx` = reçu ; `410 Gone` = ne pas relancer cette livraison ; tout autre code (y compris `3xx` : les redirections ne sont pas suivies) ou un délai dépassé = relance.
- Ignorez les champs et types d'événements inconnus : la liste va s'allonger.

Des handlers prêts à l'emploi en quatre langages sont disponibles dans le [démarrage rapide](https://coinetic.money/fr/docs/quickstart/#webhook).

## Relances

10 s → 30 s → 2 min → 10 min → 30 min → 1 h → 3 h ×7 → 1 h, avec une légère variation aléatoire. La dernière tentative a lieu environ 24 heures plus tard. Une livraison échouée peut être renvoyée manuellement : tableau de bord → « Webhooks » → « Renvoyer ».

## Ordre de livraison

Les événements **d'une même facture** sont livrés à un endpoint dans l'ordre : le suivant ne part pas tant que la livraison précédente attend une relance. Qu'elle aboutisse ou échoue, les suivants partent ensuite. Fiez-vous donc au statut renvoyé par `GET /v1/invoices/{id}`, et non à l'enchaînement des événements. Les événements de factures différentes sont indépendants.

## Types d'événements

| Événement | Quand |
| --- | --- |
| `invoice.detected` | Le paiement est visible sur le réseau |
| `invoice.confirming` | Le paiement est inclus dans un bloc, les confirmations sont en cours |
| `invoice.paid` | Payé et confirmé : vous pouvez livrer (après revérification). `data.late: true` : un stablecoin est arrivé après expiration et a été crédité automatiquement |
| `invoice.overpaid` | Payé avec un excédent |
| `invoice.underpaid` | Montant confirmé inférieur au montant dû |
| `invoice.awaiting_payment` | La facture attend de nouveau un paiement (par exemple après le réorg de son unique paiement) |
| `invoice.expired` | Délai écoulé sans paiement |
| `invoice.late_payment` | Paiement en actif volatil reçu après expiration |
| `invoice.manual_review` | Paiement en cours de contrôle AML |
| `invoice.payment_held` | Paiement bloqué par le contrôle AML (quarantaine) |
| `invoice.reorged` | Le bloc contenant le paiement a été annulé, le statut a été recalculé (par exemple `paid` → `confirming`) |
| `invoice.payment_after_close` | Paiement reçu sur une facture déjà clôturée : il ne règle pas la commande et peut être remboursé |
| `invoice.cancelled` | Facture clôturée sans paiement, par exécution d'un remboursement |
| `refund.sent` | Remboursement exécuté ; `data.refund` contient le montant, l'adresse et le `tx_hash` |

Les événements de facturation (`billing.*`) concernent les factures de commission de la plateforme : émission, paiement, retard, suspension et levée de la suspension.

> **Biens numériques et `invoice.reorged`.** Un réorg après `paid` est rare, mais il arrive. Si vous livrez instantanément, abonnez-vous à cet événement et transmettez ces cas à votre support.

## Rotation du secret

Tableau de bord → « Changer le secret » : Coinetic se met à signer avec **les deux** secrets.

- Ajoutez le nouveau secret sur votre serveur (acceptez les deux).
- Cliquez sur « Terminer la rotation » : l'ancien est supprimé.
- Retirez l'ancien secret de votre serveur.
