Payloads des Webhooks
Exemples de payloads envoyes pour chaque type d'evenement. Tous les webhooks sont envoyes en HTTP POST avec Content-Type: application/json.
En-tetes de securite
Chaque notification inclut les en-tetes X-Owem-Signature (HMAC-SHA256), X-Owem-Timestamp, X-Owem-Event-Id et X-Owem-Event-Type. Consultez Webhooks — Vue d'ensemble pour les details de validation.
Reference des Statuts
Tous les evenements ne signifient pas que la transaction est terminee. Utilisez le tableau ci-dessous pour savoir quand les fonds ont ete effectivement regles.
| Evenement | Statut | Signification | Fonds regles ? |
|---|---|---|---|
pix.charge.created | created | QR code généré ou cash-in initié. En attente de paiement. | Non — juste créé |
pix.charge.paid | paid | PIX reçu et réglé sur le compte. Solde mis à jour, frais débités. | Oui |
pix.charge.expired | expired | QR code expiré sans paiement. | N/A |
pix.charge.cancelled | cancelled | QR code annulé explicitement par le merchant avant le paiement. | N/A |
pix.payout.queued | queued | PIX envoyé mis en file par rate limit (ClientLimiter ou bucket DICT). Pas encore de débit. | Non — en attente de quota |
pix.payout.processing | processing | PIX envoyé, en attente de confirmation du destinataire. Solde réservé (hold). | Non — peut être annulé |
pix.payout.confirmed | settled | PIX envoyé confirmé par le destinataire. Débit définitif. | Oui |
pix.payout.failed | rejected | PIX envoyé rejeté par le destinataire. Hold libéré, solde restauré. | Non |
pix.payout.returned | returned | PIX envoyé remboursé après règlement. | Oui (inverse) |
pix.refund.requested | requested | Remboursement PIX demandé (MED). Blocage conservatoire créé. | Partiel |
pix.refund.completed | settled / completed | Remboursement PIX complété et réglé. Débit définitif. | Oui |
pix.return.received | settled | Retour PIX reçu et réglé sur le compte. | Oui |
pix.infraction.created | ACKNOWLEDGED | Infraction PIX signalée contre vous. Exige une action. | Partiel — blocage conservatoire si >R$1k |
pix.infraction.resolved | CLOSED / CANCELLED | Infraction résolue (remboursement exécuté ou refusé). | N/A — effet dans un autre événement |
pix.infraction.defense_submitted | defense_submitted | Défense soumise par le merchant. En attente BACEN. | N/A |
webhook.test | test | Événement de test déclenché manuellement via portail Admin/Merchant. | N/A |
Règles de réconciliation :
- Considérez les entrées de solde uniquement dans les status :
paid(crédit PIX IN) etreturned(inversion d'un PIX OUT envoyé précédemment). - Considérez les sorties de solde uniquement dans les status :
settled(débit PIX OUT confirmé) etcompleted(débit MED refund définitif), etsettleddanspix.return.received(inversion d'un PIX IN reçu précédemment). - Tous les autres status (
created,queued,processing,rejected,expired,requested,ACKNOWLEDGED,defense_submitted, etc.) sont intermédiaires — ils ne déclenchent pas de mouvement comptable de votre côté. - Ne traitez pas
pix.payout.processingcomme une confirmation ; attendez l'événement terminal (pix.payout.confirmedoupix.payout.failed).
Champs communs
Tous les payloads de webhook incluent ces champs :
| Champ | Type | Description |
|---|---|---|
event_type | string | Type d'evenement ayant declenche le webhook (ex : pix.charge.paid) |
status | string | Statut de l'operation — voir la Reference des Statuts |
account_id | integer | Numero de votre compte chez Owem |
entity_id | string (UUID) | Identifiant d'entite Owem |
Valeurs monetaires : Tous les montants sont en subcentavos (1 BRL = 10 000 subcentavos). Pour convertir en reais : montant / 10000. Exemple : 300000 / 10000 = R$ 30,00.
pix.charge.paid
Envoye quand un PIX est recu et regle sur le compte. C'est l'evenement qui confirme que l'argent est arrive.
Exemple — lie a un QR code
{
"event_type": "pix.charge.paid",
"status": "paid",
"account_id": 10014,
"amount": 300000,
"fee_amount": 400,
"end_to_end_id": "E9040088820260402095758709999671",
"entity_id": "26a48541-edce-4581-8c6e-564e7f2e6cd7",
"tx_id": "u5f26sfyrq4plkw7tjwa",
"qr_code_id": "f401d5e3-a2b1-4c8e-9f3d-1234567890ab",
"counterparty_name": "MARIA SANTOS",
"payer_document": "12345678901",
"payer_ispb": "60701190",
"payer_bank_name": "Itau Unibanco S.A.",
"external_id": "order-9876",
"paid_at": "2026-04-02T09:58:05Z"
}Exemple — transfert direct (sans QR)
{
"event_type": "pix.charge.paid",
"status": "paid",
"account_id": 10014,
"amount": 300000,
"fee_amount": 400,
"end_to_end_id": "E9040088820260402095758709999671",
"entity_id": "26a48541-edce-4581-8c6e-564e7f2e6cd7",
"tx_id": null,
"qr_code_id": null,
"counterparty_name": "JOAO SILVA",
"payer_document": "98765432100",
"payer_ispb": "00000000",
"payer_bank_name": "Banco do Brasil S.A.",
"external_id": null,
"paid_at": "2026-04-02T10:15:22Z"
}| Champ | Type | Description |
|---|---|---|
event_type | string | Toujours pix.charge.paid |
status | string | Toujours paid |
account_id | integer | Numero de compte ayant recu le PIX |
amount | integer | Montant recu en subcentavos. 300000 = R$ 30,00 |
fee_amount | integer | Frais debites en subcentavos. 400 = R$ 0,04 |
end_to_end_id | string | Identifiant E2E du BACEN (unique par transaction PIX) |
entity_id | string (UUID) | Identifiant d'entite Owem |
tx_id | string ou null | ID de transaction. Present quand lie a un QR code. null pour les transferts directs |
qr_code_id | string ou null | UUID du QR code associe. null pour les transferts directs |
counterparty_name | string ou null | Nom du payeur (expediteur) |
payer_document | string ou null | CPF/CNPJ du payeur (chiffres uniquement) |
payer_ispb | string ou null | ISPB (8 chiffres) de l'institution du payeur |
payer_bank_name | string ou null | Nom de l'institution du payeur, resolu via le cache BCB (896 banques) |
external_id | string ou null | Votre identifiant externe. Present lorsque le QR code a ete cree via l'API avec external_id. null pour les transferts directs ou QR sans external_id |
paid_at | string (ISO 8601) | Horodatage du reglement (UTC) |
pix.charge.created
Envoye quand un QR code est genere ou un cash-in est initie. Aucun mouvement financier n'a eu lieu.
{
"event_type": "pix.charge.created",
"status": "created",
"account_id": 10014,
"amount": 500000,
"entity_id": "26a48541-edce-4581-8c6e-564e7f2e6cd7",
"tx_id": "abc123def456ghi789"
}pix.payout.confirmed
Envoye quand un PIX envoye est confirme par l'institution destinataire. Debit definitif.
{
"event_type": "pix.payout.confirmed",
"status": "settled",
"account_id": 10014,
"amount": 500000,
"fee_amount": 200,
"end_to_end_id": "E3783905920260402101500000001",
"entity_id": "26a48541-edce-4581-8c6e-564e7f2e6cd7",
"transaction_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"external_id": "payment-456",
"pix_key": "destinataire@email.com",
"pix_key_type": "EMAIL",
"description": "Paiement fournisseur",
"initiated_at": "2026-04-02T10:14:59Z",
"recipient": {
"name": "EMPRESA DESTINO LTDA",
"document": "12345678000199",
"ispb": "60701190",
"account": "12345678",
"agency": "0001",
"institution_name": "Itau Unibanco S.A."
},
"sender": {
"name": "MINHA EMPRESA LTDA",
"document": "98765432000100",
"ispb": "37839059",
"account": "00001234",
"agency": "0001"
}
}| Champ | Type | Description |
|---|---|---|
event_type | string | Toujours pix.payout.confirmed |
status | string | Toujours settled -- debit definitif |
amount | integer | Montant envoye en subcentavos |
fee_amount | integer | Frais debites en subcentavos |
end_to_end_id | string | Identifiant E2E du BACEN |
transaction_id | string (UUID) | Identifiant unique de la transaction |
external_id | string ou null | Votre identifiant externe |
pix_key | string | Cle PIX du destinataire |
pix_key_type | string | Type de cle : CPF, CNPJ, EMAIL, PHONE, EVP |
description | string ou null | Description fournie par l'expediteur |
initiated_at | string (ISO 8601) | Horodatage du cash-out original (pas l'heure du settlement -- pour cela utilisez X-Owem-Timestamp du header) |
recipient | object | Donnees bancaires du destinataire (resolues via DICT) |
recipient.name | string ou null | Nom du titulaire du compte destination |
recipient.document | string ou null | CPF/CNPJ du destinataire (chiffres uniquement) |
recipient.ispb | string ou null | ISPB de l'institution destination |
recipient.account | string ou null | Numero du compte destination |
recipient.agency | string ou null | Agence du compte destination |
recipient.institution_name | string ou null | Nom de l'institution destination (resolu via le cache BCB) |
sender | object | Donnees bancaires du compte expediteur (votre compte Owem) |
sender.name | string ou null | Nom du titulaire du compte expediteur |
sender.document | string ou null | CPF/CNPJ de l'expediteur (chiffres uniquement) |
sender.ispb | string ou null | ISPB d'Owem Pay (37839059) |
sender.account | string ou null | Numero du compte expediteur |
sender.agency | string ou null | Agence du compte expediteur |
pix.payout.processing
Envoye quand un PIX envoye est en cours de traitement. Le solde est reserve (hold) mais pas definitif. Cet evenement est optionnel -- si vous ne souhaitez etre notifie que de l'etat terminal, ignorez-le et attendez pix.payout.confirmed ou pix.payout.failed.
{
"event_type": "pix.payout.processing",
"status": "processing",
"account_id": 10014,
"amount": 500000,
"fee_amount": 200,
"end_to_end_id": "E3783905920260402101500000001",
"entity_id": "26a48541-edce-4581-8c6e-564e7f2e6cd7",
"transaction_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"external_id": "payment-456",
"pix_key": "destinataire@email.com",
"pix_key_type": "EMAIL",
"description": "Paiement fournisseur",
"initiated_at": "2026-04-02T10:14:59Z",
"recipient": {
"name": "EMPRESA DESTINO LTDA",
"document": "12345678000199",
"ispb": "60701190",
"account": "12345678",
"agency": "0001",
"institution_name": "Itau Unibanco S.A."
},
"sender": {
"name": "MINHA EMPRESA LTDA",
"document": "98765432000100",
"ispb": "37839059",
"account": "00001234",
"agency": "0001"
}
}| Champ | Type | Description |
|---|---|---|
event_type | string | Toujours pix.payout.processing |
status | string | Toujours processing -- solde reserve, peut etre annule |
amount | integer | Montant en subcentavos |
fee_amount | integer | Frais en subcentavos (meme frais qui apparaitra dans confirmed/failed plus tard -- il est calcule a la creation du cash-out, pas apres) |
end_to_end_id | string | Identifiant E2E du BACEN |
transaction_id | string (UUID) | Identifiant unique de la transaction |
external_id | string ou null | Votre identifiant externe |
pix_key | string | Cle PIX du destinataire |
pix_key_type | string | Type de cle : CPF, CNPJ, EMAIL, PHONE, EVP |
description | string ou null | Description fournie par l'expediteur |
initiated_at | string (ISO 8601) | Horodatage du cash-out original |
recipient | object | Donnees bancaires du destinataire (resolues via DICT) |
recipient.name | string ou null | Nom du titulaire du compte destination |
recipient.document | string ou null | CPF/CNPJ du destinataire (chiffres uniquement) |
recipient.ispb | string ou null | ISPB de l'institution destination |
recipient.account | string ou null | Numero du compte destination |
recipient.agency | string ou null | Agence du compte destination |
recipient.institution_name | string ou null | Nom de l'institution destination |
sender | object | Donnees bancaires du compte expediteur (votre compte Owem) |
sender.name | string ou null | Nom du titulaire du compte expediteur |
sender.document | string ou null | CPF/CNPJ de l'expediteur (chiffres uniquement) |
sender.ispb | string ou null | ISPB d'Owem Pay (37839059) |
sender.account | string ou null | Numero du compte expediteur |
sender.agency | string ou null | Agence du compte expediteur |
Ordre des evenements
Un pix.payout.processing est toujours suivi (quelques secondes a quelques minutes plus tard) par un pix.payout.confirmed ou pix.payout.failed. Sur des transactions rapides (settlement immediat), le processing peut etre omis et vous recevez directement le terminal.
pix.payout.failed
Envoye quand un PIX envoye est rejete. Hold libere, solde restaure.
Mis a jour le 10/04/2026
Le payload inclut desormais les champs structures reason_code (code BACEN SPI) et reason_description (description en anglais). Les nouvelles integrations doivent utiliser ces champs pour le routage programmatique des echecs. Le champ legacy reason (texte libre) continue d'etre envoye pour assurer la compatibilite avec les integrations anciennes.
{
"event_type": "pix.payout.failed",
"status": "rejected",
"account_id": 10014,
"amount": 500000,
"fee_amount": 200,
"end_to_end_id": "E3783905920260402101500000001",
"entity_id": "26a48541-edce-4581-8c6e-564e7f2e6cd7",
"transaction_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"external_id": "payment-456",
"pix_key": "destinataire@email.com",
"pix_key_type": "EMAIL",
"description": "Paiement fournisseur",
"initiated_at": "2026-04-02T10:14:59Z",
"reason_code": "AC03",
"reason_description": "Invalid creditor account number",
"reason": "Compte destinataire introuvable",
"recipient": {
"name": "EMPRESA DESTINO LTDA",
"document": "12345678000199",
"ispb": "60701190",
"account": "12345678",
"agency": "0001",
"institution_name": "Itau Unibanco S.A."
},
"sender": {
"name": "MINHA EMPRESA LTDA",
"document": "98765432000100",
"ispb": "37839059",
"account": "00001234",
"agency": "0001"
}
}| Champ | Type | Description |
|---|---|---|
event_type | string | Toujours pix.payout.failed |
status | string | Toujours rejected -- hold libere, solde restaure |
amount | integer | Montant en subcentavos |
fee_amount | integer | Frais en subcentavos. Les frais affiches correspondent au montant qui aurait ete debite -- dans le ledger TB le pending transfer est automatiquement annule, donc en pratique aucun frais n'est debite pour les transactions rejetees |
end_to_end_id | string | Identifiant E2E du BACEN |
transaction_id | string (UUID) | Identifiant unique de la transaction |
external_id | string ou null | Votre identifiant externe |
pix_key | string | Cle PIX du destinataire |
pix_key_type | string | Type de cle : CPF, CNPJ, EMAIL, PHONE, EVP |
description | string ou null | Description fournie par l'expediteur |
initiated_at | string (ISO 8601) | Horodatage du cash-out original |
reason_code | string | Code BACEN SPI structure (2-6 caracteres). Exemples : AC03, ED05, AM02, BE01, MD06, FOCR. Utilisez ce champ pour le routage programmatique |
reason_description | string | Description en anglais du reason_code. Exemple : "Invalid creditor account number" |
reason | string | [Legacy] Description libre du motif. Conserve pour assurer la compatibilite ; les nouvelles integrations doivent utiliser reason_code + reason_description |
recipient | object | Donnees bancaires du destinataire (resolues via DICT) |
recipient.name | string ou null | Nom du titulaire du compte destination |
recipient.document | string ou null | CPF/CNPJ du destinataire (chiffres uniquement) |
recipient.ispb | string ou null | ISPB de l'institution destination |
recipient.account | string ou null | Numero du compte destination |
recipient.agency | string ou null | Agence du compte destination |
recipient.institution_name | string ou null | Nom de l'institution destination |
sender | object | Donnees bancaires du compte expediteur (votre compte Owem) |
sender.name | string ou null | Nom du titulaire du compte expediteur |
sender.document | string ou null | CPF/CNPJ de l'expediteur (chiffres uniquement) |
sender.ispb | string ou null | ISPB d'Owem Pay (37839059) |
sender.account | string ou null | Numero du compte expediteur |
sender.agency | string ou null | Agence du compte expediteur |
Codes reason_code les plus courants (BACEN SPI)
| Code | Signification en anglais | Action recommandee |
|---|---|---|
AC03 | Invalid creditor account number | Verifier les donnees bancaires du destinataire avec le client final |
AC06 | Creditor account blocked | Compte destination bloque -- ne pas retenter |
AM02 | Not allowed amount (limit exceeded) | Le montant depasse la limite PIX du destinataire ou de l'expediteur |
AM04 | Insufficient funds | Solde insuffisant a l'origine |
BE01 | End customer not in whitelist | Identifiant du destinataire non reconnu |
ED05 | Settlement failed | Echec du settlement -- retentative possible apres investigation |
MD06 | Refund requested by end customer | Remboursement demande par le client final |
FOCR | Forbidden credit return | Retour de credit interdit |
Liste complete : consultez le Catalogo de Mensagens do SPI du BACEN.
pix.payout.returned
Envoye quand un PIX que vous avez envoye est retourne par la banque destinataire apres settlement. Rare, mais peut survenir plusieurs jours plus tard. Le solde du merchant augmente (credit entrant).
Distinction de nomenclature
Trois flux differents peuvent etre confondus :
pix.return.received: un PIX que vous avez recu est retourne au payeur original. Solde DIMINUE.pix.payout.returned(celui-ci) : un PIX que vous avez envoye vous revient. Solde AUGMENTE.pix.refund.requested: blocage preventif MED sur un PIX que vous avez recu. Fonds geles.
{
"event_type": "pix.payout.returned",
"status": "settled",
"account_id": 10014,
"amount": 500000,
"entity_id": "26a48541-edce-4581-8c6e-564e7f2e6cd7",
"return_e2e_id": "D3783905920260410111500000001",
"end_to_end_id": "E3783905920260402101500000001",
"original_transaction_id": "PIXOUTa1b2c3d4e5f67890abcdef1234567890",
"external_id": "payment-456",
"return_reason": "MD06",
"return_reason_description": "Refund requested by end customer",
"counterparty_ispb": "60701190",
"counterparty_name": "EMPRESA DESTINO LTDA",
"paid_at": "2026-04-10T11:15:00Z"
}| Champ | Type | Description |
|---|---|---|
event_type | string | Toujours pix.payout.returned |
status | string | Toujours settled -- retour regle et credite sur votre compte |
amount | integer | Montant retourne en subcentavos (peut etre inferieur a l'original pour les retours partiels) |
return_e2e_id | string | E2E du retour (prefixe D) |
end_to_end_id | string | E2E de la transaction PIX OUT originale (prefixe E) |
original_transaction_id | string | transaction_id du PIX OUT original. Utilisez-le pour la correlation avec votre systeme |
external_id | string ou null | Votre identifiant externe de la transaction originale (si applicable) |
return_reason | string | Code BACEN du retour : MD06, BE08, FR01, SL02 |
return_reason_description | string | Description en anglais du return_reason |
counterparty_ispb | string | ISPB de l'institution ayant initie le retour |
counterparty_name | string | Nom de la contrepartie (institution destinataire du PIX original) |
paid_at | string (ISO 8601) | Horodatage du settlement du retour (UTC) |
Les frais ne sont pas rembourses
Les frais du cash-out original ne sont pas rembourses sur pix.payout.returned. Les frais ont ete debites pour l'envoi reussi, qui a bien eu lieu. Si la regle metier exige un remboursement des frais au client final, le merchant doit le gerer separement.
pix.refund.completed
Envoye quand un remboursement PIX est traite et complete.
{
"event_type": "pix.refund.completed",
"status": "settled",
"account_id": 10014,
"amount": 300000,
"entity_id": "26a48541-edce-4581-8c6e-564e7f2e6cd7",
"original_end_to_end_id": "E9040088820260402095758709999671",
"return_code": "MD06"
}pix.return.received
Envoye quand un retour PIX est recu. Cet evenement est genere quand un PIX que vous avez precedemment recu (cash-in) est retourne au payeur original. Le solde du merchant diminue.
Distinction de nomenclature
pix.return.received(celui-ci) : un PIX que vous avez recu est retourne au payeur original. Solde DIMINUE.pix.payout.returned: un PIX que vous avez envoye vous revient. Solde AUGMENTE.
Les noms sont inverses par rapport au sens commun -- faites attention.
{
"event_type": "pix.return.received",
"status": "settled",
"account_id": 10014,
"amount": 300000,
"entity_id": "26a48541-edce-4581-8c6e-564e7f2e6cd7",
"return_e2e_id": "D9040088820260402111500000001",
"end_to_end_id": "E9040088820260402095758709999671",
"original_transaction_id": "PIXINE9040088820260402095758709999671",
"external_id": null,
"return_reason": "MD06",
"return_reason_description": "Refund requested by end customer",
"counterparty_ispb": "60701190",
"counterparty_name": "EMPRESA X LTDA",
"paid_at": "2026-04-02T11:15:00Z"
}| Champ | Type | Description |
|---|---|---|
event_type | string | Toujours pix.return.received |
status | string | Toujours settled -- retour regle |
amount | integer | Montant retourne en subcentavos |
return_e2e_id | string | E2E du retour (prefixe D) |
end_to_end_id | string | E2E de la transaction PIX IN originale (prefixe E) |
original_transaction_id | string | transaction_id du PIX IN original. Utilisez-le pour la correlation avec votre systeme |
external_id | string ou null | Votre identifiant externe de la transaction originale (si applicable) |
return_reason | string | Code BACEN du retour : MD06, BE08, FR01, SL02 |
return_reason_description | string | Description en anglais du return_reason |
counterparty_ispb | string | ISPB de l'institution qui recoit le retour |
counterparty_name | string | Nom de la contrepartie (payeur original du PIX IN) |
paid_at | string (ISO 8601) | Horodatage du settlement du retour (UTC) |
Deduplication
Pour dedupliquer les retries de webhook, utilisez le header X-Owem-Event-Id OU la combinaison (return_e2e_id, end_to_end_id). Le return_e2e_id commence par D (retour) et le end_to_end_id commence par E (original).
webhook.test
Evenement de test declenche manuellement pour valider la configuration du webhook.
{
"event_type": "webhook.test",
"status": "test",
"account_id": 10014,
"entity_id": "26a48541-edce-4581-8c6e-564e7f2e6cd7",
"message": "Webhook test event"
}pix.payout.queued
Déclenché quand un PIX OUT est automatiquement placé en file de retry (feature du retry queue pix_out_retry_queue_enabled, disponible depuis la session 155). Motifs : rate limit du ClientLimiter par merchant ou épuisement du bucket DICT BACEN partagé.
Déclenché par pix.ex:315 (module Fluxiq.UseCases.Payments.OutboundPayment.Pix).
{
"event_type": "pix.payout.queued",
"status": "queued",
"account_id": 10011,
"merchant_id": "1b2db911-972f-4466-9be9-60a7c5450064",
"transaction_id": "PIXOUT0200806193e0984f830569",
"end_to_end_id": "E3783905920260421133012abcdef1234",
"amount": 200,
"external_id": "payment-456",
"reason": "dict_client_rate_limited",
"reason_code": "DICT_CLIENT_RATE_LIMITED",
"reason_description": "Merchant exceeded per-minute DICT lookup quota",
"queued_at": "2026-04-21T13:30:12Z",
"estimated_retry_seconds": 3,
"queue_ttl_seconds": 7200
}| Champ | Type | Description |
|---|---|---|
event_type | string | Toujours pix.payout.queued |
status | string | Toujours queued |
account_id | integer | Compte ayant initié le PIX OUT |
merchant_id | string (UUID) | Votre merchant_id |
transaction_id | string | Identifiant de la transaction Owem |
end_to_end_id | string | E2E BACEN généré pour le PIX OUT |
amount | integer | Valeur en subcentavos |
external_id | string ou null | Votre identifiant externe (si envoyé dans le request original) |
reason | string | Motif de la mise en file (snake_case). Valeurs connues : dict_client_rate_limited (limite par merchant), dict_bucket_exhausted (bucket DICT BACEN partagé épuisé), dict_rate_limited (fallback générique) |
reason_code | string | Code interne en UPPERCASE correspondant au reason. Valeurs : DICT_CLIENT_RATE_LIMITED, DICT_BUCKET_EXHAUSTED, DICT_RATE_LIMITED. Ce n'est pas un code BACEN SPI (comme AC03, AM02) — la mise en file se produit avant l'envoi au BACEN, donc les codes sont internes à Owem |
reason_description | string | Description en anglais du motif |
queued_at | string (ISO 8601) | Moment où la requête est entrée dans la file (UTC) |
estimated_retry_seconds | integer | Intervalle de retry du worker (3 s par défaut) ; la file ne garantit pas 3 s — peut prendre plus de temps si le bucket tarde à se libérer |
queue_ttl_seconds | integer | TTL maximum dans la file en secondes (7200 = 2 h). Après expiration, la requête passe en failed avec motif queue_ttl_expired |
reason_code ici n'est pas BACEN SPI
Notez que dans pix.payout.queued le reason_code est un code interne Owem en UPPERCASE (DICT_CLIENT_RATE_LIMITED, etc.). Dans pix.payout.failed le reason_code est un code BACEN SPI (ex. : AC03, AM02, ED05). Les deux champs ont le même nom mais des vocabulaires différents — traitez chaque événement séparément dans votre consommateur.
Drainage automatique
Les requêtes en file sont relancées automatiquement par le worker toutes les ~3s tant que le TTL reste valide. Dans des conditions normales, le traitement reprend dès que la limite par merchant ou le bucket DICT BACEN libère de la capacité, mais ce n'est pas un SLA de 3–10 min. Prochain événement : pix.payout.processing (quand elle sort de la file et est envoyée au BACEN). Si le TTL de 2 h expire sans succès, vous recevez pix.payout.failed avec reason="queue_ttl_expired".
pix.infraction.created
Déclenché quand une infraction PIX est signalée par la contrepartie (via BACEN DICT). Exige une défense avant defense_deadline OU blocage conservatoire automatique (MED).
Déclenché par pix_compliance.ex:463 (fonction upsert_infraction quand is_new=true).
{
"event_type": "pix.infraction.created",
"infraction_id": "e7f4d23a-6f2a-4d1e-a3e6-fe8b32bba95d",
"e2e_id": "E0416201020260404113012abcdef1234",
"status": "ACKNOWLEDGED",
"infraction_type": "REFUND_REQUEST",
"amount": 1500000,
"analysis_result": null,
"analysis_details": null,
"defense_deadline": "2026-04-21T23:59:59Z",
"counterpart_ispb": "60701190",
"account_id": 10011,
"merchant_id": "1b2db911-972f-4466-9be9-60a7c5450064",
"entity_id": "26a48541-edce-4581-8c6e-564e7f2e6cd7"
}| Champ | Type | Description |
|---|---|---|
event_type | string | Toujours pix.infraction.created |
infraction_id | string (UUID) | ID interne de l'infraction |
e2e_id | string | E2E de la transaction contestée |
status | string | Status BACEN : ACKNOWLEDGED, CLOSED, CANCELLED |
infraction_type | string | Type BACEN : REFUND_REQUEST, REFUND_CANCELLED, FRAUD |
amount | integer | Valeur en subcentavos |
defense_deadline | string (ISO 8601) | Délai pour soumission de défense |
counterpart_ispb | string (8 chiffres) | ISPB de l'institution contrepartie |
account_id | integer | Votre compte affecté |
merchant_id | string (UUID) | Votre merchant_id |
Action obligatoire
Les infractions avec status ACKNOWLEDGED et valeur > R$ 1 000 génèrent un blocage conservatoire automatique (MED). Vous devez répondre via POST /api/merchant/infractions/{id}/defense avant le defense_deadline sinon le remboursement sera exécuté.
pix.infraction.resolved
Déclenché quand une infraction est résolue (admin close ou auto-deny). Libère le blocage conservatoire s'il y en a un.
Déclenché par pix_compliance.ex:664 et admin/infractions/resolve_controller.ex:84.
{
"event_type": "pix.infraction.resolved",
"infraction_id": "e7f4d23a-6f2a-4d1e-a3e6-fe8b32bba95d",
"e2e_id": "E0416201020260404113012abcdef1234",
"status": "CLOSED",
"infraction_type": "REFUND_REQUEST",
"amount": 1500000,
"analysis_result": "DISAGREED",
"analysis_details": "Verificado pelo time de compliance e sem evidencias concretas nao temos como fazer devolucao",
"defense_deadline": "2026-04-21T23:59:59Z",
"counterpart_ispb": "60701190",
"account_id": 10011,
"merchant_id": "1b2db911-972f-4466-9be9-60a7c5450064",
"entity_id": "26a48541-edce-4581-8c6e-564e7f2e6cd7"
}| Champ | Type | Description |
|---|---|---|
analysis_result | string | AGREED (rembourse), DISAGREED (refuse) |
analysis_details | string | Justification de la décision |
| Autres champs | Identiques à pix.infraction.created |
pix.infraction.defense_submitted
Déclenché quand le merchant soumet une défense contre une infraction (via portail ou API).
Déclenché par admin/infractions/defense_controller.ex:67 et merchant/infractions/defense_controller.ex:178.
{
"event_type": "pix.infraction.defense_submitted",
"infraction_id": "e7f4d23a-6f2a-4d1e-a3e6-fe8b32bba95d",
"e2e_id": "E0416201020260404113012abcdef1234",
"status": "defense_submitted",
"account_id": 10011,
"merchant_id": "1b2db911-972f-4466-9be9-60a7c5450064",
"entity_id": "26a48541-edce-4581-8c6e-564e7f2e6cd7"
}| Champ | Type | Description |
|---|---|---|
event_type | string | Toujours pix.infraction.defense_submitted |
status | string | Toujours defense_submitted |
infraction_id | string (UUID) | ID de l'infraction en cours de défense |
Attend l'analyse BACEN
Après soumission, BACEN analyse la défense + preuves de la contrepartie. Résultat via pix.infraction.resolved.
Comment interpréter les webhooks
Pour confirmer que l'argent est arrivé : Attendez pix.charge.paid avec status: "paid". C'est le seul événement qui garantit que le montant a été crédité et les frais débités.
Pour confirmer que l'argent a été envoyé : Attendez pix.payout.confirmed avec status: "settled". Le statut processing est intermédiaire — le solde est réservé mais peut être annulé si rejeté.
Pour les retours : pix.return.received avec status: "settled" confirme le crédit réglé sur le compte.
Déduplication : Utilisez l'en-tête X-Owem-Event-Id ou le champ end_to_end_id comme clé d'idempotence.