Consultar Cash-Out por ID
Consulta los detalles y el estado de una transaccion PIX por el transaction_id.
Endpoint
GET /api/external/transactions/:idHeaders
| Header | Tipo | Obligatorio | Descripcion |
|---|---|---|---|
Authorization | String | Si | ApiKey {client_id}:{client_secret} |
Path Parameters
| Parametro | Tipo | Obligatorio | Descripcion |
|---|---|---|---|
id | String | Si | ID de la transaccion (transaction_id) |
Ejemplo
curl -X GET https://api.owem.com.br/api/external/transactions/PIXOUT20260309a1b2c3d4e5f6 \
-H "Authorization: ApiKey $CLIENT_ID:$CLIENT_SECRET"La respuesta varia de acuerdo al estado de la transaccion. Este endpoint busca en las siguientes fuentes, en el siguiente orden de prioridad:
- Transaccion liquidada (
transactionsportransaction_id, o por el UUID interno hex —Base.decode16) - PIX OUT en curso (
outbound_requestsstage 1 o 2) portransaction_id - QR Code (
qrcodesportx_id) — si haypaid_at+payment_end_to_end_id, resuelve la transaccion real linkeada entransactionsvia E2E; de lo contrario retorna el shape "QR Code No Pagado"
Si nada coincide en ninguna fuente, retorna 404.
Transaccion rechazada NO aparece aqui por transaction_id
Rechazos BACEN sincronicos (PACS.002 RJCT) y force-voids son persistidos en failed_transactions y no son encontrados por este endpoint cuando consulta por el transaction_id. Use los endpoints alternativos:
- GET /transactions/e2e/:e2e_id — busca en
failed_transactionsporend_to_end_id - GET /transactions/ref/:external_id — busca en
failed_transactionsporexternal_id - Webhook
pix.payout.rejected/pix.payout.failed— notificacion en tiempo real con payload completo
Rechazos de validacion de entrada (400/422 inmediato) no pasan por este flujo — ya retornaron el error sincronico en el POST.
Respuesta -- Transaccion Liquidada (200)
{
"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": "Pagamento fornecedor",
"counterparty_name": "Joao Silva",
"recipient_key": "12345678901",
"created_at": "2026-03-09T15:30:00Z",
"completed_at": "2026-03-09T15:30:02Z"
}
}| Campo | Tipo | Descripcion |
|---|---|---|
data.id | String | UUID interno de la transaccion en formato canonico con guiones, 36 caracteres (ej: "c7f3a8b1-2d4e-4f6a-9c1b-3e5f7a9b1d3e"). El controller pasa el binario de 16 bytes por Ecto.UUID.load/1 antes de serializar — el formato NO es hex lowercase de 32 chars sin guiones |
data.transaction_id | String | Identificador unico de la transaccion (prefijo comun PIXOUT para salidas y PIXIN para entradas, pero no es garantizado — siempre lea el campo, no derive del prefijo) |
data.end_to_end_id | String | Identificador End-to-End en el SPI/BACEN |
data.external_id | String | Identificador de su sistema. null si no informado |
data.type | String | Tipo de la transaccion. Valores comunes: pix, pix_return. El backend hace passthrough del campo t.type — rows legacy pueden retornar otros valores |
data.direction | String | outbound (cash-out), inbound (cash-in), credit, debit. Los dos ultimos aparecen cuando el campo t.direction no fue persistido y el backend infirio via Helpers.infer_direction/2 con base en account_id × to_account_id |
data.status | String | Status normalizado (ver tabla abajo) |
data.amount | Integer | Valor en unidades base (div 10.000 para reales). 300000 = R$ 30,00 |
data.fee_amount | Integer | Tarifa cobrada en unidades base |
data.net_amount | Integer | Valor neto en unidades base |
data.description | String | Descripcion informada en la creacion |
data.counterparty_name | String | Nombre de la contraparte (pagador o receptor) |
data.recipient_key | String | Clave PIX del destinatario (solo para salidas) |
data.created_at | String | Fecha de creacion (ISO 8601) |
data.completed_at | String | Fecha de conclusion (ISO 8601), null si pendiente |
Respuesta -- PIX OUT en Curso (200)
Retornado cuando la transaccion aun esta siendo procesada (antes de la confirmacion BACEN).
{
"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": "Pagamento fornecedor",
"type": "pix",
"direction": "outbound",
"payment_status": "processing",
"started_at": "2026-03-09T15:30:00Z",
"recipient": {
"name": "Joao Silva",
"key": "12345678901",
"key_type": "cpf"
}
}
}| Campo adicional | Tipo | Descripcion |
|---|---|---|
data.recipient | Object | Datos del destinatario resueltos via DICT |
data.recipient.name | String | Nombre del titular de la clave |
data.recipient.key | String | Clave PIX utilizada |
data.recipient.key_type | String | Tipo de la clave (cpf, cnpj, email, phone, evp) |
data.started_at | String | Fecha de inicio del procesamiento (ISO 8601) |
Respuesta -- Transaccion Rechazada (200)
Retornado por los endpoints /transactions/e2e/:e2e_id y GET /transactions/ref/:external_id cuando el PIX fue rechazado por el SPI o fallo durante el procesamiento. No retornado por GET /transactions/:id (vea aviso arriba sobre failed_transactions).
{
"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"
}
}
}| Campo adicional | Tipo | Descripcion |
|---|---|---|
data.failure_reason | String | Motivo bruto del rechazo (formato: "rejected: {CODE}" para codigos BACEN, o descripciones de integracion como "dict_key_not_found", "ambiguous key", "insufficient balance") |
data.reason_code | String | Codigo estructurado extraido de failure_reason. Para rechazos BACEN, sigue ISO 20022 (AC03, AB03, ED05, DUPL etc). null cuando failure_reason no contiene codigo estructurado |
data.reason_description | String | Descripcion humana del reason_code, en ingles (centralizada en Fluxiq.UseCases.Pix.ReasonCodes). Ejemplos: "Invalid creditor account number" (AC03), "Aborted by PSP of creditor" (AB03), "Settlement failed" (ED05). null cuando el codigo no es reconocido |
data.recipient | Object | Datos del destinatario (cuando disponibles). Puede ser omitido en fallas muy tempranas |
data.failed_at | String | Fecha/hora del rechazo (ISO 8601) |
Estructura de los codigos de rechazo
Los campos reason_code y reason_description son derivados del diccionario centralizado en Fluxiq.UseCases.Pix.ReasonCodes. Uselos para enrutamiento programatico de errores. Mantenga failure_reason solo para logs y diagnostico. Vea la tabla completa de codigos en PIX Cash-Out por Clave -- Codigos de Error.
Respuesta -- QR Code No Pagado (200)
Retornado cuando el ID corresponde a un QR Code que aun no fue pagado.
{
"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 QR | Descripcion |
|---|---|
pending | QR Code activo, aguardando pago |
settled | QR Code con paid_at llenado, pero el controller no logro resolver la transaccion real en transactions por payment_end_to_end_id. Ocurre en la ventana entre Phase 1 ACSP (ACK al BACEN) y Phase 2 ACCC (PG MERGE concluido), o cuando el link QR↔TX falla por otro motivo. Camino de codigo activo (show_transaction_controller.ex:83) — no trate como error; rehaga la consulta algunos segundos despues y el backend debe retornar el shape "Transaccion Liquidada" normalmente |
expired | QR Code expirado (TTL default 60 min — configurable por cuenta via account.qrcode_expiration_seconds) |
cancelled | QR Code cancelado manualmente (o cancelado en masa durante migracion estatico→dinamico en 2026-04) |
Nota: cuando el QR esta pagado y el backend logra hacer lookup de la transaccion real por E2E, la respuesta es la del shape "Transaccion Liquidada" arriba (con status: "settled" y el transaction_id real, no el tx_id del QR). Solo cuando ese lookup retorna nil es que se cae en el shape "QR Code No Pagado" con status: "settled".
Valores del campo status
Status del GET depende de la fuente
El GET /transactions/:id busca en 4 tablas distintas y retorna un status diferente segun la fuente donde la transaccion es encontrada. No existe un vocabulario unico entre todas las fuentes.
| Status | Fuente | Significado |
|---|---|---|
processing | outbound_requests (stage 1 o 2) | PACS.008 enviada, aguardando confirmacion del BACEN. Saldo en hold |
processing | outbound_requests (stage 4 — fila de retry) | Rate-limited por ClientLimiter / DictBucket.Guard, aguardando retry automatico (Oban PixOutRetryWorker, TTL 120min). El shape retornado es el mismo del stage 1/2 — diferencie por el webhook pix.payout.queued disparado en el encolamiento |
settled | transactions (status interno 1) | BACEN confirmo liquidacion y el saldo ya fue movido. Estado final de exito |
pending | transactions (status interno 2) | Caso raro — transaccion en estado intermedio antes de la promocion a settled |
failed | transactions (status interno 3) O failed_transactions | Estado final de falla. Rechazada por BACEN (PACS.002 RJCT), orfana force-voided (>30min en hold), expiracion de la fila de retry (DICT_QUEUE_TIMEOUT) o error interno |
Nota de compatibilidad: rows legacy (anteriores a la consolidacion del vocabulario) pueden presentar status: "completed" o status: "accepted". Tratelos como equivalentes a "settled".
Correspondencia con webhooks
pix.payout.queuedcorresponde astatus: "processing"en el GET mientras el request esta enoutbound_requests.stage=4pix.payout.confirmedsiempre corresponde astatus: "settled"en el GETpix.payout.failedypix.payout.rejectedsiempre corresponden astatus: "failed"en el GET
Para QR Codes (cash-in, fuera del alcance PIX OUT), la tabla qrcodes agrega 4 valores: pending, settled, expired, cancelled — descritos en la seccion "QR Code No Pagado" arriba.
Respuesta de Error -- 404
{
"worked": false,
"detail": "Transação não encontrada"
}