API externe

Documentation développeurs

Intégrez les paiements en ligne et TPE, consultez les opérations et recevez des webhooks via l'API externe Avirato Payments.

Webhooks

Les webhooks sont des notifications HTTP POST qu'Avirato Payments envoie automatiquement à votre système lorsqu'un événement pertinent se produit : un paiement est finalisé, un remboursement est traité, une capture est confirmée, etc.

Pourquoi ils sont importants

Les webhooks sont le moyen le plus fiable de savoir qu'une opération s'est terminée. Contrairement à la redirection (urlOk/urlKo), qui dépend du retour du client sur votre page :

  • Les webhooks arrivent toujours, même si le client ferme le navigateur
  • Ils arrivent quelques secondes après que le processeur confirme l'opération
  • Ils ne dépendent pas du comportement de l'utilisateur

Recommandation : utilisez les webhooks comme source principale de confirmation des opérations. Utilisez la redirection et le polling en complément.

Comment configurer votre URL de webhooks

Depuis Intégrations > Configuration Webhooks dans le tableau de bord, vous pouvez enregistrer une URL publique par environnement (Live et Test). Chaque URL peut être activée/désactivée séparément. Nous recommandons :

  • Une URL HTTPS avec certificat valide.
  • Un endpoint dédié à Avirato Payments (par exemple https://votre-domaine.com/avirato-payments/webhooks).
  • Vous devez avoir une clé API active pour l'environnement avant de configurer son URL. Sinon, le tableau de bord répond avec 422.

Important : seuls les webhooks générés à partir du moment où l'URL est configurée et active sont envoyés. Les événements antérieurs ne sont pas renvoyés rétroactivement.

Vérification d'authenticité (signature HMAC)

Tous les webhooks live arrivent signés avec HMAC-SHA256 en utilisant le même client_secret qui vous est affiché lors de la création (ou rotation) de la clé API de l'environnement. En-têtes :

En-têteValeur
X-Avirato-TimestampHorodatage Unix (secondes) du moment de l'envoi
X-Avirato-Signaturet={timestamp},v1={hmac} — où hmac = hash_hmac('sha256', timestamp + "." + body, client_secret)

Exemple de vérification en PHP :

$timestamp = $_SERVER['HTTP_X_AVIRATO_TIMESTAMP'] ?? '';
$signature = $_SERVER['HTTP_X_AVIRATO_SIGNATURE'] ?? '';
$body = file_get_contents('php://input');

if (!preg_match('/^t=(\d+),v1=([a-f0-9]+)$/', $signature, $m)) {
    http_response_code(400);
    exit;
}

$expected = hash_hmac('sha256', $timestamp . '.' . $body, $clientSecret);
if (!hash_equals($expected, $m[2])) {
    http_response_code(401);
    exit;
}

En Test, si vous avez créé une clé API test, les webhooks de test sont aussi signés avec son secret. Sinon, ils sont envoyés sans signature pour que vous puissiez explorer le format sans créer de clé API test pour l'instant.

Politique de nouvelles tentatives

En une ligne

Chaque fois qu'Avirato Payments vous envoie un webhook et que votre endpoint ne répond pas avec HTTP 200, il réessaie plus tard. L'attente entre chaque échec et la tentative suivante augmente : elle commence à 10 minutes et se termine à 48 heures. Après un total de 10 tentatives sans succès, Avirato Payments cesse de réessayer automatiquement.

Calendrier complet

Le tableau indique, pour un webhook qui échoue à chaque tentative, le moment exact où votre endpoint reçoit l'appel suivant, compté depuis le moment de l'événement d'origine (autorisation, remboursement, etc.).

TentativeQu'est-ce que c'estQuand vous le recevez (depuis l'événement)
1Envoi initialau moment de l'événement (≈ 0)
21re nouvelle tentative10 min après
32e nouvelle tentative30 min après
43e nouvelle tentative1 h 10 min après
54e nouvelle tentative2 h 40 min après
65e nouvelle tentative5 h 40 min après
76e nouvelle tentative11 h 40 min après
87e nouvelle tentative23 h 40 min après
98e nouvelle tentative1 jour 23 h 40 min après
109e (et dernière) nouvelle tentative≈ 4 jours après (95 h 40 min)
——à partir de là, plus de nouvelle tentative

Au total, 10 tentatives (1 envoi initial + 9 nouvelles tentatives) réparties sur environ 4 jours. L'horloge ne se réinitialise pas à chaque tentative : plus vous répondez correctement tard, plus les tentatives suivantes sont espacées.

Comment savoir à quelle tentative nous en sommes

Dans le tableau de bord, dans Intégrations > Live > Webhooks, chaque ligne de l'historique affiche :

  • Tentatives : nombre de tentatives consommées jusqu'à présent (1 à 10).
  • Dernière tentative : date et heure du dernier envoi.
  • HTTP : code HTTP renvoyé par votre endpoint lors de cette dernière tentative.
  • État : Livré (success), En attente (nouvelles tentatives encore possibles) ou Échoué (non applicable en flux live tant qu'il reste des tentatives).

Si l'endpoint continue d'échouer

Si après les 10 tentatives (≈ 4 jours) votre endpoint n'a répondu correctement aucune fois, Avirato Payments cesse de réessayer automatiquement même si vous réparez votre système ensuite. Dans ce cas :

  1. Réactivez votre endpoint et vérifiez qu'il répond correctement aux webhooks normaux.
  2. Pour les événements restés en attente, ouvrez Intégrations > Live > Webhooks, identifiez les webhooks à l'état En attente et forcez le renvoi manuel via le bouton « Renvoyer ». Chaque renvoi manuel effectue un nouvel appel HTTP vers votre endpoint avec le même payload.

Si vous désactivez ou supprimez temporairement votre URL

  • Tant que votre URL est désactivée (ou n'existe pas), Avirato Payments continue de mettre en file d'attente les webhooks des événements qui se produisent.
  • Le cron continue de compter les tentatives : si vous réactivez l'URL dans la fenêtre d'environ ≈ 4 jours, les éléments en attente seront livrés automatiquement au prochain tick (tant qu'il reste des tentatives pour ce webhook précis).
  • Passée cette fenêtre, les événements sont abandonnés et ne sont pas renvoyés même si vous réactivez l'URL. Vous devrez les demander manuellement depuis le tableau de bord si vous en avez besoin.

Comportement du renvoi manuel

  • Si vous renvoyez manuellement un webhook qui était en attente de nouvelles tentatives et que le renvoi réussit, les nouvelles tentatives automatiques s'arrêtent — le webhook est considéré comme livré.
  • Vous pouvez renvoyer un webhook déjà livré correctement. Le tableau de bord demandera une confirmation au préalable pour éviter les doublons accidentels, mais le renvoi s'exécute tout de même si vous le confirmez.

Source de vérité de l'état du paiement (Live)

En environnement Live, les notifications du processeur ont le dernier mot sur l'état réel du paiement. Un paiement peut donc changer d'état après que votre système l'ait traité comme finalisé.

Cas typiques où un webhook ultérieur peut inverser un succès antérieur :

  • Chargeback : le titulaire conteste le débit auprès de sa banque
  • Fraude détectée a posteriori : le processeur identifie une transaction frauduleuse des jours plus tard
  • Réversion bancaire : la banque émettrice annule l'opération
  • Correction du processeur : une notification antérieure contenait des données incomplètes ou incorrectes

Lorsque nous recevons l'un de ces événements en Live, nous mettons à jour l'état du paiement dans notre système (par exemple, de AUTHORISED à FAILED) et vous envoyons le webhook correspondant. Votre intégration doit :

  • Accepter des webhooks asynchrones qui modifient le résultat d'un paiement précédemment réussi
  • Traiter les webhooks (pas la réponse immédiate ni la redirection) comme référence pour le rapprochement et l'état final
  • Consulter à nouveau l'API (GET /payment/session/{sessionId}) lorsque vous avez besoin du dernier état connu

Test vs Live : en Test, les webhooks sont générés par notre propre simulateur et reflètent uniquement la simulation que vous avez lancée. Il n'y a pas de chargebacks ni de réversions en Test.

Format général

Tous les webhooks arrivent en POST sur votre URL avec ce format :

En-têtes

En-têteValeur
Content-Typeapplication/json
webcodeLe webcode associé au paiement (ex. : SHOP01)

Body

{
  "event_code": "AUTHORISATION",
  "data": {
    ...champs spécifiques à l'événement...
  }
}

Réponse attendue

Votre endpoint doit répondre avec HTTP 200. Le corps de la réponse n'est pas évalué — le code d'état suffit.

Si votre endpoint ne répond pas avec HTTP 200, le webhook sera réessayé automatiquement avec un backoff exponentiel.

---

Types d'événement

AUTHORISATION — Paiement finalisé (en ligne ou POS)

Envoyé lorsqu'un paiement (en ligne ou POS) est autorisé avec succès ou échoue.

{
  "event_code": "AUTHORISATION",
  "data": {
    "amount": 15000,
    "currency": "EUR",
    "paymentReference": "SHOP01-PXT-17195000005678",
    "paymentStatus": "AUTHORISED",
    "description": "Pedido #12345 - Servicio premium",
    "customReference": "ORD-2026-12345",
    "paymentSource": "external_api"
  }
}
ChampToujours présentDescription
amountOuiMontant en centimes
currencyOuiCode ISO 4217
paymentReferenceOuiRéférence du paiement
paymentStatusOuiAUTHORISED si succès, FAILED si échec
descriptionOuiDescription du paiement
customReferenceNonVotre référence interne (si fournie à la création de la session/paiement)
paymentSourceNonOrigine du paiement (ex. : external_api)
failedReasonNonMotif de l'échec (uniquement si le paiement a échoué)

Comment identifier le type de paiement par la référence :

Préfixe dans la référenceTypeEnvironnement
-PXT-Paiement en ligneLive
-PXTT-Paiement en ligneTest
-POSX-Paiement POSLive
-POSXT-Paiement POSTest

Exemple de paiement POS réussi :

{
  "event_code": "AUTHORISATION",
  "data": {
    "amount": 8500,
    "currency": "EUR",
    "paymentReference": "SHOP01-POSX-17195300001234",
    "paymentStatus": "AUTHORISED",
    "description": "Venta mostrador #205",
    "customReference": "VENTA-205-20260628",
    "paymentSource": "external_api"
  }
}

Exemple de paiement échoué (refusé) :

{
  "event_code": "AUTHORISATION",
  "data": {
    "amount": 15000,
    "currency": "EUR",
    "paymentReference": "SHOP01-PXT-17195000005678",
    "paymentStatus": "FAILED",
    "description": "Pedido #12345",
    "failedReason": "Refused",
    "paymentSource": "external_api"
  }
}

Important : les webhooks sont envoyés pour les paiements réussis et échoués. Vérifiez toujours le champ paymentStatus pour déterminer le résultat.

---

REFUND — Remboursement traité

Envoyé lorsqu'un remboursement est finalisé (succès ou échec) par le processeur.

{
  "event_code": "REFUND",
  "data": {
    "amount": 5000,
    "currency": "EUR",
    "paymentReference": "SHOP01-PXT-17195000005678",
    "refundReason": "CUSTOMER REQUEST",
    "refundReference": "SHOP01-RFX-17195234567890",
    "status": "success",
    "customReference": "ORD-2026-12345",
    "paymentSource": "external_api"
  }
}
ChampToujours présentDescription
amountOuiMontant remboursé en centimes
currencyOuiCode ISO 4217
paymentReferenceOuiRéférence du paiement d'origine
refundReasonOuiMotif du remboursement (CUSTOMER REQUEST, FRAUD, RETURN, DUPLICATE, OTHER)
refundReferenceOuiRéférence de cette opération de remboursement
statusOuisuccess ou failed
customReferenceNonVotre référence interne
paymentSourceNonOrigine du paiement
failedReasonNonMotif de l'échec (uniquement si status: "failed")

Exemple de remboursement échoué :

{
  "event_code": "REFUND",
  "data": {
    "amount": 5000,
    "currency": "EUR",
    "paymentReference": "SHOP01-PXT-17195000005678",
    "refundReason": "CUSTOMER REQUEST",
    "refundReference": "SHOP01-RFX-17195234567890",
    "status": "failed",
    "failedReason": "Insufficient balance"
  }
}

---

PREAUTHORISATION — Résultat de capture, annulation ou extension

Envoyé lorsqu'une opération sur une préautorisation est terminée. Le champ action indique le type d'opération.

Capture finalisée

{
  "event_code": "PREAUTHORISATION",
  "data": {
    "paymentReference": "SHOP01-PXT-17195123456789",
    "action": "capture",
    "result": "success",
    "amount": 45000,
    "currency": "EUR",
    "customReference": "ORD-2026-67890",
    "paymentSource": "external_api"
  }
}

Annulation finalisée

{
  "event_code": "PREAUTHORISATION",
  "data": {
    "paymentReference": "SHOP01-PXT-17195123456789",
    "action": "cancellation",
    "result": "success",
    "customReference": "ORD-2026-67890",
    "paymentSource": "external_api"
  }
}

Extension finalisée

{
  "event_code": "PREAUTHORISATION",
  "data": {
    "paymentReference": "SHOP01-PXT-17195123456789",
    "action": "extend",
    "result": "success",
    "expirationDate": "2026-08-15T00:00:00Z",
    "customReference": "ORD-2026-67890",
    "paymentSource": "external_api"
  }
}
ChampToujours présentDescription
paymentReferenceOuiRéférence du paiement préautorisé
actionOuicapture, cancellation ou extend
resultOuisuccess ou failure
amountUniquement captureMontant capturé en centimes
currencyUniquement captureCode ISO 4217
expirationDateUniquement extend réussiNouvelle date d'expiration
customReferenceNonVotre référence interne
paymentSourceNonOrigine du paiement
failedReasonNonMotif de l'échec (uniquement si result: "failure")

Exemple de capture échouée (montant dépasse l'autorisé) :

{
  "event_code": "PREAUTHORISATION",
  "data": {
    "paymentReference": "SHOP01-PXT-17195123456789",
    "action": "capture",
    "result": "failure",
    "failedReason": "Payment already captured, cannot capture again"
  }
}

Note sur le flux des modifications : toutes les modifications (remboursement, capture, annulation, extension) sont asynchrones. La réponse immédiate de l'API renvoie l'état received, indiquant que la requête a été acceptée pour traitement. Le résultat final (success ou failed) arrive ensuite via webhook. L'intégrateur ne doit pas considérer l'opération comme terminée avant de recevoir le webhook de confirmation.

---

CHARGEBACK — Rétrofacturation

Envoyé lorsqu'un titulaire de carte initie une rétrofacturation contre un paiement. Les rétrofacturations sont traitées par l'émetteur de la carte et peuvent prendre des jours ou des semaines à se résoudre.

{
  "event_code": "CHARGEBACK",
  "data": {
    "paymentReference": "SHOP01-PXT-17195123456789",
    "chargebackReference": "SHOP01-CHB-17195123456789",
    "action": "chargeback",
    "result": "success",
    "amount": 15000,
    "currency": "EUR",
    "reason": "Fraudulent transaction",
    "chargebackReasonCode": "10.4",
    "chargebackSchemeCode": "VISA_10_4",
    "defensePeriodEndsAt": "2026-06-15",
    "defendable": true,
    "disputeStatus": "Undefended",
    "paymentSource": "external_api"
  }
}
ChampToujours présentDescription
paymentReferenceOuiRéférence du paiement d'origine
chargebackReferenceOuiRéférence unique de la rétrofacturation
actionOuiToujours chargeback
resultOuisuccess ou failure
amountOuiMontant en centimes
currencyOuiDevise ISO 4217
reasonOuiMotif de la rétrofacturation
chargebackReasonCodeNonCode motif du schéma de carte
chargebackSchemeCodeNonCode du schéma (Visa, Mastercard, etc.)
defensePeriodEndsAtNonDate limite pour contester la rétrofacturation
defendableNontrue si vous pouvez contester la rétrofacturation
disputeStatusNonÉtat du litige (Undefended, Defended, etc.)
failedReasonNonMotif si result est failure
paymentSourceNonOrigine du paiement (external_api, etc.)

---

NOTIFICATION_OF_CHARGEBACK — Avis préalable de rétrofacturation

Avis anticipé qu'une rétrofacturation peut être en cours. Tous les processeurs ne l'envoient pas. Il vous permet de vous préparer avant le traitement formel de la rétrofacturation.

{
  "event_code": "NOTIFICATION_OF_CHARGEBACK",
  "data": {
    "paymentReference": "SHOP01-PXT-17195123456789",
    "chargebackReference": "SHOP01-CHB-17195123456789",
    "action": "notification_of_chargeback",
    "result": "success",
    "amount": 15000,
    "currency": "EUR",
    "reason": "Cardholder disputes transaction",
    "chargebackReasonCode": "10.4",
    "chargebackSchemeCode": "VISA_10_4",
    "defensePeriodEndsAt": "2026-06-15",
    "defendable": true,
    "disputeStatus": "Undefended",
    "autoDefended": false,
    "arn": "74027600000012345678901",
    "paymentSource": "external_api"
  }
}

Contient les mêmes champs que CHARGEBACK plus deux champs optionnels supplémentaires :

ChampDescription
autoDefendedtrue si le processeur a contesté automatiquement la rétrofacturation
arnAcquirer Reference Number — identifiant de la transaction de l'acquéreur

---

Webhooks en environnement Test

En environnement Test, les webhooks ne proviennent pas du processeur de paiement réel. Ils sont générés automatiquement par le backend d'Avirato Payments immédiatement après la finalisation de l'opération simulée.

Différences avec Live

AspectLiveTest
Qui envoieLe processeur de paiementLe backend d'Avirato Payments
Quand ça arriveSecondes à minutes après l'opération1 à 3 secondes après la réponse HTTP
FormatIdentiqueIdentique
ChampsIdentiquesIdentiques
Nouvelles tentatives automatiquesOui (backoff exponentiel, jusqu'à ~4 jours)Non : le simulateur effectue un seul envoi
Renvoi manuelOui, depuis le tableau de bordOui, depuis le tableau de bord (même bouton)
Critère de succès HTTPHTTP 200HTTP 200

Ce qu'il faut savoir

  • Le format est exactement le même : vous pouvez développer votre logique de traitement des webhooks en Test et elle fonctionnera en Live sans changement
  • Ils arrivent pour les paiements réussis ET échoués : en Live comme en Test, vous recevrez des webhooks lorsqu'un paiement est refusé ou qu'une opération échoue
  • URLs indépendantes par environnement : les webhooks Test sont envoyés à l'URL configurée pour l'environnement Test, et ceux Live à l'URL Live. Configurez les deux depuis le panneau webhooks du tableau de bord
  • Les références utilisent les suffixes Test : les paymentReference et operationReference contiendront les préfixes de test (-PXTT-, -POSXT-, -RFXT-, etc.)
  • Critère de succès simple : en Live comme en Test, il suffit que votre endpoint réponde HTTP 200 pour que le webhook soit marqué comme livré. Tout autre code d'état est considéré comme un échec et déclenche les nouvelles tentatives (en Live) ou reste en échec dans le tableau de bord (en Test).
  • Renvoi manuel disponible en Test et Live : depuis le panneau webhooks du tableau de bord, vous pouvez renvoyer manuellement un webhook précis. En Test comme en Live, le renvoi utilise l'URL actuellement configurée pour cet environnement, pas l'URL utilisée lors de l'envoi d'origine. Si vous renvoyez un webhook déjà livré, le tableau de bord demandera une confirmation explicite pour éviter les doublons accidentels.

Exemple de webhook de test (paiement en ligne réussi)

{
  "event_code": "AUTHORISATION",
  "data": {
    "amount": 15000,
    "currency": "EUR",
    "paymentReference": "SHOP01-PXTT-17195000005678",
    "paymentStatus": "AUTHORISED",
    "description": "Pedido test #12345",
    "customReference": "TEST-ORD-12345",
    "paymentSource": "external_api"
  }
}

Exemple de webhook de test (POS refusé)

{
  "event_code": "AUTHORISATION",
  "data": {
    "amount": 10077,
    "currency": "EUR",
    "paymentReference": "SHOP01-POSXT-17195300001234",
    "paymentStatus": "FAILED",
    "description": "Venta test #100",
    "failedReason": "Refused",
    "paymentSource": "external_api"
  }
}

---

Référence rapide

Opérationevent_codeaction (le cas échéant)Comment identifier l'API externe
Paiement en ligne finaliséAUTHORISATION—paymentReference contient -PXT- (Live) ou -PXTT- (Test)
Paiement POS finaliséAUTHORISATION—paymentReference contient -POSX- (Live) ou -POSXT- (Test)
Remboursement traitéREFUND—refundReference contient -RFX- (Live) ou -RFXT- (Test)
Capture traitéePREAUTHORISATIONcaptureOpération sur un paiement API externe
Annulation traitéePREAUTHORISATIONcancellationOpération sur un paiement API externe
Extension traitéePREAUTHORISATIONextendOpération sur un paiement API externe
Rétrofacturation reçueCHARGEBACK—Rétrofacturation initiée par le titulaire de la carte
Notification de rétrofacturationNOTIFICATION_OF_CHARGEBACK—Avis préalable d'une possible rétrofacturation

---

Bonnes pratiques

Idempotence sur votre endpoint

Votre endpoint de webhook peut recevoir la même notification plus d'une fois (nouvelles tentatives ou doublons du processeur). Assurez-vous que traiter le même webhook deux fois ne pose pas de problème : utilisez paymentReference ou refundReference comme clé de déduplication.

Réponse rapide

Répondez au webhook le plus tôt possible (idéalement en moins de 5 secondes). Si vous devez effectuer un traitement lourd, mettez le travail en file d'attente et répondez immédiatement avec HTTP 200.

Ne dépendez pas d'un seul canal

Utilisez les webhooks comme canal principal, mais implémentez aussi :

  1. Vérification post-redirection : lorsque le client revient sur urlOk, consultez GET /payment/session/{id} pour confirmer
  2. Polling de sécurité : un processus périodique qui consulte les sessions en état pending anciennes pour détecter les paiements finalisés que vous n'auriez pas traités