Réconciliation
Retrouver l'issue d'un paiement quand la notification n'est pas arrivée.
az54 rejoue la notification sortante, journalise chaque tentative, et vous laisse relire l'état à la demande. Tout ce qui suit est accessible avec une clé d'API seule — aucun jeton de session n'est nécessaire.
Le rejeu automatique
Une notification qui n'aboutit pas est rejouée jusqu'à 6 fois :
| Tentative | Émise à | Écart avec la précédente |
|---|---|---|
| 1 | immédiatement | — |
| 2 | T+30 s | 30 s |
| 3 | T+2 min 30 s | 2 min |
| 4 | T+12 min 30 s | 10 min |
| 5 | T+1 h 12 min 30 s | 1 h |
| 6 | T+7 h 12 min 30 s | 6 h |
Chaque tentative a son propre timeout de 30 secondes et ne suit aucune
redirection : un 301 ou un 302 sur votre URL est un échec. La chaîne
s'arrête au premier 2xx.
Trois causes d'échec ne sont pas rejouées, parce qu'aucune tentative de plus ne les résoudrait ; le catalogue plus bas les marque comme telles. L'absence de secret de signature, elle, est rejouée : c'est la fenêtre transitoire d'une rotation menée à l'envers (révoquer avant de créer), et la tentative suivante trouvera le nouveau secret.
Une notification non terminale peut aussi être abandonnée en cours de chaîne : si
la transaction est devenue terminale entre-temps, livrer un pending six heures
plus tard vous ferait régresser. Les
transitions étant monotones, seule la notification terminale
compte.
Lire l'état à la demande
Deux lectures, selon l'identifiant que vous avez en main.
Par identifiant az54 — GET /v1/transactions/by-id/{transactionId}
(référence). C'est le
champ id renvoyé par POST /v1/pay-in et POST /v1/pay-out, et le champ
transactionId du corps du webhook. La réponse porte la
transaction complète — fee, netAmount, cause d'échec, failedAt — et le
journal des notifications (section suivante).
Par votre identifiant — GET /v1/transactions?orderId=votre-order-id
(référence). Correspondance exacte, qui
vous évite de conserver l'identifiant az54. La réponse est une page de liste :
elle ne porte pas le journal. Les autres filtres — status, type,
failureCategory, dateFrom/dateTo, page, limit — sont dans la
référence ; ce sont eux qui servent à balayer un lot en une requête.
Les deux lectures sont scopées à votre organisation. Un id appartenant à une
autre organisation répond 404 NOT_FOUND, exactement comme un id inexistant.
Elles consomment le quota général, 1000 requêtes par 15 minutes, compté par seau dérivé de votre clé (Erreurs et limites). De quoi relire sans compter, pas de quoi interroger chaque commande en boucle : une requête filtrée qui ramène un lot vaut mieux que N appels unitaires.
Le journal des tentatives
GET /v1/transactions/by-id/{transactionId} renvoie un tableau
notifications[], une entrée par tentative d'émission, de la plus ancienne à
la plus récente.
{
"attemptNo": 2,
"url": "https://exemple.test/webhooks/az54",
"httpStatus": 500,
"errorKind": "HTTP_ERROR",
"errorDetail": "Request failed with status code 500",
"durationMs": 214,
"createdAt": "2026-09-02T18:04:31.882Z"
}errorKind vaut null sur un envoi réussi, et sinon l'une de ces six valeurs :
errorKind | Ce qui s'est passé | Rejoué |
|---|---|---|
HTTP_ERROR | Votre serveur a répondu hors 2xx. httpStatus porte son code. | oui |
NETWORK_ERROR | Rien n'est arrivé : timeout, DNS injoignable, connexion refusée. | oui |
SKIPPED_NO_SECRET | Aucun secret de signature actif sur l'organisation. Rien n'a été posté. | oui |
SKIPPED_NO_URL | Ni webhookUrl sur la transaction, ni repli d'organisation. url est null. | non |
BLOCKED_UNSAFE_URL | L'URL résout vers une IP non publique, ou son schéma n'est pas https. | non |
MISSING_CURRENCY | Anomalie côté az54 : la devise de la transaction n'a pas pu être résolue. | non |
errorDetail est un indice de debug, tronqué à 500 caractères et non
contractuel. durationMs ne mesure que la requête HTTP : il est null quand
aucune n'a été tentée.
Trois propriétés du journal :
attemptNorepart à 1 à chaque notification. Une transaction en émet plusieurs (une par changement de statut, plus la mise à disposition d'uneauthorizationUrl), et chacune a sa propre chaîne de rejeu. Compter les lignes ne donne donc pas le nombre de notifications émises.- Une chaîne plus courte que les 6 tentatives est normale : elle s'est
arrêtée sur un
2xx, sur une cause non rejouable, ou parce qu'un statut terminal l'a périmée. - Le journal est borné aux 50 tentatives les plus récentes, et les lignes sont conservées 30 jours. Archivez ce dont vous avez besoin au-delà.
Renvoyer une notification
POST /v1/transactions/by-id/{transactionId}/resend-callbackPas de corps
(référence).
La réponse 200 signifie « renvoi programmé » : l'appel enfile une nouvelle
notification, avec sa propre chaîne de 6 tentatives. Ce n'est pas un envoi
synchrone — relisez notifications[] pour en connaître l'issue.
Trois contraintes :
- Réservé aux transactions terminales (
completed,failed,cancelled). Surcreated,initiated,pendingouprocessing, la réponse est un409 CONFLICT: il n'y a rien de définitif à renvoyer, et le rejeu automatique est de toute façon encore en cours. - 3 requêtes par minute et par transaction. Le renvoi déclenche une chaîne entière côté az54 : ce n'est pas un bouton sur lequel s'appuyer en boucle.
- Le corps renvoyé porte l'état courant, pas l'événement historique : le
statut terminal de la transaction, avec sa cause d'échec si elle a échoué.
nextAction.authorizationUrly figure si une URL d'autorisation avait été émise, mais elle est alors probablement expirée côté prestataire — et une transaction encore en cours de redirection n'est pas renvoyable, puisqu'elle n'est pas terminale.
La procédure
- Répondez
2xxd'abord, traitez ensuite, et gardez votre handler de webhook idempotent. - Sur un
502ou un timeout, rejouez la même requête avec le mêmeorderId(Idempotence). - Balayez périodiquement, par lot. Une requête sur la période concernée
(
dateFrom/dateTo,limit=100) ramène tout ce qu'il faut rapprocher chez vous. C'est ce qui remplace l'attente indéfinie d'une notification — et ça coûte une requête, pas une par commande. - Quand une transaction est terminale mais que vous n'avez rien reçu, lisez
notifications[]par identifiant az54 :errorKindvous dit si le problème est chez vous (HTTP_ERROR,NETWORK_ERROR), dans votre configuration (SKIPPED_NO_URL,SKIPPED_NO_SECRET,BLOCKED_UNSAFE_URL) ou chez nous (MISSING_CURRENCY). - Corrigez, puis renvoyez. Un renvoi avant correction rejoue les mêmes six échecs.
Ce que la réconciliation ne couvre pas encore
- Pas de relevé comptable par API. Ni export CSV, ni endpoint de relevé
asynchrone :
GET /v1/transactionspaginé est le seul chemin. L'export CSV du tableau de bord ne fait rien d'autre que parcourir ces pages. - Pas de soldes par clé d'API.
GET /v1/balancesexige un jeton de session. - Une
authorizationUrlmanquée n'est pas récupérable. Elle n'est portée par aucune lecture, et le renvoi étant réservé aux transactions terminales, un pay-in en redirection dont la notification s'est perdue se relance avec un nouvelorderId(Workflows de pay-in). - Pas de repli d'URL réglable par clé d'API. Un repli d'organisation
existe côté az54 —
SKIPPED_NO_URLen tient compte — mais s'y régler est un réglage de compte, pas une surface d'intégration : session seule, non exposé par le tableau de bord aujourd'hui. Détail dans Webhook sortant.
