Skip to content

Consulter Cash-Out par ID

Consultez les détails et le status d'une transaction PIX par son transaction_id.

Endpoint

GET /api/external/transactions/:id

Headers

HeaderTypeObligatoireDescription
AuthorizationStringOuiApiKey {client_id}:{client_secret}

Path Parameters

ParamètreTypeObligatoireDescription
idStringOuiID de la transaction (transaction_id)

Exemple

bash
curl -X GET https://api.owem.com.br/api/external/transactions/PIXOUT20260309a1b2c3d4e5f6 \
  -H "Authorization: ApiKey $CLIENT_ID:$CLIENT_SECRET"

La réponse varie selon l'état de la transaction. Cet endpoint cherche dans les sources suivantes, dans l'ordre de priorité :

  1. Transaction liquidée (transactions par transaction_id, ou par l'UUID interne hex — Base.decode16)
  2. PIX OUT en cours (outbound_requests stage 1 ou 2) par transaction_id
  3. QR Code (qrcodes par tx_id) — s'il y a paid_at + payment_end_to_end_id, résout la transaction réelle liée dans transactions via E2E ; sinon retourne le shape « QR Code Non Payé »

Si rien ne correspond dans aucune source, retourne 404.

Une transaction rejetée N'apparaît PAS ici par transaction_id

Les rejets BACEN synchrones (PACS.002 RJCT) et les force-voids sont persistés dans failed_transactions et ne sont pas trouvés par cet endpoint quand vous consultez par le transaction_id. Utilisez les endpoints alternatifs :

Les rejets de validation d'entrée (400/422 immédiat) ne passent pas par ce flux — ils ont déjà retourné l'erreur synchrone au POST.


Réponse -- Transaction liquidée (200)

json
{
  "worked": true,
  "data": {
    "id": "c7f3a8b12d4e4f6a9c1b3e5f7a9b1d3e",
    "transaction_id": "PIXOUT20260309a1b2c3d4e5f6",
    "end_to_end_id": "E37839059202603091530abcdef01",
    "external_id": "order-9876",
    "type": "pix",
    "direction": "outbound",
    "status": "settled",
    "amount": 300000,
    "fee_amount": 350,
    "net_amount": 300350,
    "description": "Paiement fournisseur",
    "counterparty_name": "Joao Silva",
    "recipient_key": "12345678901",
    "created_at": "2026-03-09T15:30:00Z",
    "completed_at": "2026-03-09T15:30:02Z"
  }
}
ChampTypeDescription
data.idStringUUID interne de la transaction en format canonique avec tirets, 36 caractères (ex. : "c7f3a8b1-2d4e-4f6a-9c1b-3e5f7a9b1d3e"). Le controller passe le binaire de 16 octets par Ecto.UUID.load/1 avant de sérialiser — le format N'est PAS hex lowercase de 32 caractères sans tirets
data.transaction_idStringIdentifiant unique de la transaction (préfixe courant PIXOUT pour les sorties et PIXIN pour les entrées, mais non garanti — lisez toujours le champ, ne dérivez pas du préfixe)
data.end_to_end_idStringIdentifiant End-to-End dans le SPI/BACEN
data.external_idStringIdentifiant de votre système. null s'il n'a pas été renseigné
data.typeStringType de la transaction. Valeurs courantes : pix, pix_return. Le backend fait passthrough du champ t.type — les rows legacy peuvent retourner d'autres valeurs
data.directionStringoutbound (cash-out), inbound (cash-in), credit, debit. Les deux derniers apparaissent quand le champ t.direction n'a pas été persisté et le backend a inféré via Helpers.infer_direction/2 à partir de account_id × to_account_id
data.statusStringStatus normalisé (voir tableau ci-dessous)
data.amountIntegerValeur en unités de base (÷ 10 000 pour reais). 300000 = R$ 30,00
data.fee_amountIntegerFrais prélevés en unités de base
data.net_amountIntegerValeur nette en unités de base
data.descriptionStringDescription renseignée à la création
data.counterparty_nameStringNom de la contrepartie (payeur ou bénéficiaire)
data.recipient_keyStringClé PIX du destinataire (uniquement pour les sorties)
data.created_atStringDate de création (ISO 8601)
data.completed_atStringDate de conclusion (ISO 8601), null si en attente

Réponse -- PIX OUT en cours (200)

Retourné quand la transaction est encore en cours de traitement (avant confirmation BACEN).

json
{
  "worked": true,
  "data": {
    "status": "processing",
    "transaction_id": "PIXOUT20260309a1b2c3d4e5f6",
    "end_to_end_id": "E37839059202603091530abcdef01",
    "amount": 300000,
    "fee_amount": 350,
    "net_amount": 300350,
    "external_id": "order-9876",
    "pix_key": "12345678901",
    "description": "Paiement fournisseur",
    "type": "pix",
    "direction": "outbound",
    "payment_status": "processing",
    "started_at": "2026-03-09T15:30:00Z",
    "recipient": {
      "name": "Joao Silva",
      "key": "12345678901",
      "key_type": "cpf"
    }
  }
}
Champ additionnelTypeDescription
data.recipientObjectDonnées du destinataire résolues via DICT
data.recipient.nameStringNom du titulaire de la clé
data.recipient.keyStringClé PIX utilisée
data.recipient.key_typeStringType de la clé (cpf, cnpj, email, phone, evp)
data.started_atStringDate de début du traitement (ISO 8601)

Réponse -- Transaction rejetée (200)

Retournée par les endpoints /transactions/e2e/:e2e_id et GET /transactions/ref/:external_id quand le PIX a été rejeté par le SPI ou a échoué pendant le traitement. Non retournée par GET /transactions/:id (voir avertissement ci-dessus sur failed_transactions).

json
{
  "worked": true,
  "data": {
    "status": "failed",
    "transaction_id": "PIXOUT20260309a1b2c3d4e5f6",
    "end_to_end_id": "E37839059202603091530abcdef01",
    "amount": 300000,
    "fee_amount": 350,
    "external_id": "order-9876",
    "type": "pix",
    "direction": "outbound",
    "payment_status": "failed",
    "failure_reason": "rejected: AB03",
    "reason_code": "AB03",
    "reason_description": "Aborted by PSP of creditor",
    "started_at": "2026-03-09T15:30:00Z",
    "failed_at": "2026-03-09T15:30:05Z",
    "recipient": {
      "name": "Joao Silva",
      "key": "12345678901"
    }
  }
}
Champ additionnelTypeDescription
data.failure_reasonStringMotif brut du rejet (format : "rejected: {CODE}" pour les codes BACEN, ou descriptions d'intégration comme "dict_key_not_found", "ambiguous key", "insufficient balance")
data.reason_codeStringCode structuré extrait de failure_reason. Pour les rejets BACEN, suit ISO 20022 (AC03, AB03, ED05, DUPL etc.). null quand failure_reason ne contient pas de code structuré
data.reason_descriptionStringDescription humaine du reason_code, en anglais (centralisée dans Fluxiq.UseCases.Pix.ReasonCodes). Exemples : "Invalid creditor account number" (AC03), "Aborted by PSP of creditor" (AB03), "Settlement failed" (ED05). null quand le code n'est pas reconnu
data.recipientObjectDonnées du destinataire (quand disponibles). Peut être omis dans les échecs très précoces
data.failed_atStringDate/heure du rejet (ISO 8601)

Structure des codes de rejet

Les champs reason_code et reason_description sont dérivés du dictionnaire centralisé dans Fluxiq.UseCases.Pix.ReasonCodes. Utilisez-les pour le routage programmatique des erreurs. Gardez failure_reason uniquement pour les logs et le diagnostic. Voir le tableau complet des codes dans PIX Cash-Out par clé -- Codes d'erreur.


Réponse -- QR Code non payé (200)

Retournée quand l'ID correspond à un QR Code qui n'a pas encore été payé.

json
{
  "worked": true,
  "data": {
    "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
    "transaction_id": "7popu57v6us7p6pcicgq12345",
    "end_to_end_id": null,
    "external_id": "order-9876",
    "type": "pix_qrcode",
    "status": "pending",
    "amount": 300000,
    "fee_amount": 0,
    "net_amount": 300000,
    "description": "Cobrança PIX",
    "direction": "credit",
    "counterparty_name": null,
    "recipient_key": "12345678901",
    "created_at": "2026-03-09T15:30:00Z",
    "completed_at": null
  }
}
Status QRDescription
pendingQR Code actif, en attente de paiement
settledQR Code avec paid_at renseigné, mais le controller n'a pas pu résoudre la transaction réelle dans transactions par payment_end_to_end_id. Se produit dans la fenêtre entre Phase 1 ACSP (ACK au BACEN) et Phase 2 ACCC (PG MERGE terminé), ou quand le lien QR↔TX échoue pour une autre raison. Chemin de code actif (show_transaction_controller.ex:83) — ne traitez pas comme une erreur ; refaites la consultation quelques secondes plus tard et le backend devrait retourner le shape « Transaction liquidée » normalement
expiredQR Code expiré (TTL default 60 min — configurable par compte via account.qrcode_expiration_seconds)
cancelledQR Code annulé manuellement (ou annulé en masse pendant la migration statique→dynamique en 2026-04)

Note : quand le QR est payé et que le backend réussit à faire le lookup de la transaction réelle par E2E, la réponse est celle du shape « Transaction liquidée » ci-dessus (avec status: "settled" et le transaction_id réel, pas le tx_id du QR). Ce n'est que quand ce lookup retourne nil que l'on retombe sur le shape « QR Code Non Payé » avec status: "settled".


Valeurs du champ status

Le status du GET dépend de la source

Le GET /transactions/:id cherche dans 4 tables distinctes et retourne un status différent selon la source où la transaction est trouvée. Il n'existe pas de vocabulaire unique entre toutes les sources.

StatusSourceSignification
processingoutbound_requests (stage 1 ou 2)PACS.008 envoyée, en attente de confirmation du BACEN. Solde en hold
processingoutbound_requests (stage 4 — file de retry)Rate-limited par ClientLimiter / DictBucket.Guard, en attente de retry automatique (Oban PixOutRetryWorker, TTL 120min). Le shape retourné est le même que celui du stage 1/2 — différenciez par le webhook pix.payout.queued déclenché à la mise en file
settledtransactions (status interne 1)BACEN a confirmé la liquidation et le solde a déjà été mouvementé. État final de succès
pendingtransactions (status interne 2)Cas rare — transaction dans un état intermédiaire avant promotion à settled
failedtransactions (status interne 3) OU failed_transactionsÉtat final d'échec. Rejetée par BACEN (PACS.002 RJCT), orpheline force-voided (>30min en hold), expiration de la file de retry (DICT_QUEUE_TIMEOUT) ou erreur interne

Note de compatibilité : les rows legacy (antérieures à la consolidation du vocabulaire) peuvent présenter status: "completed" ou status: "accepted". Traitez-les comme équivalents à "settled".

Correspondance avec les webhooks

  • pix.payout.queued correspond à status: "processing" dans le GET tant que la requête est dans outbound_requests.stage=4
  • pix.payout.confirmed correspond toujours à status: "settled" dans le GET
  • pix.payout.failed et pix.payout.rejected correspondent toujours à status: "failed" dans le GET

Pour les QR Codes (cash-in, hors du scope PIX OUT), la table qrcodes ajoute 4 valeurs : pending, settled, expired, cancelled — décrites dans la section « QR Code non payé » ci-dessus.

Réponse d'erreur -- 404

json
{
  "worked": false,
  "detail": "Transação não encontrada"
}

Owem Pay Instituição de Pagamento — ISPB 37839059