Consultar Cash-Out por ID
Consulta os detalhes e o status de uma transação PIX pelo transaction_id.
Endpoint
GET /api/external/transactions/:idHeaders
| Header | Tipo | Obrigatório | Descrição |
|---|---|---|---|
Authorization | String | Sim | ApiKey {client_id}:{client_secret} |
Path Parameters
| Parâmetro | Tipo | Obrigatório | Descrição |
|---|---|---|---|
id | String | Sim | ID da transação (transaction_id) |
Exemplo
curl -X GET https://api.owem.com.br/api/external/transactions/PIXOUT20260309a1b2c3d4e5f6 \
-H "Authorization: ApiKey $CLIENT_ID:$CLIENT_SECRET"A resposta varia de acordo com o estado da transação. Este endpoint busca nas seguintes fontes, na seguinte ordem de prioridade:
- Transação liquidada (
transactionsportransaction_id, ou pelo UUID interno hex —Base.decode16) - PIX OUT em andamento (
outbound_requestsstage 1 ou 2) portransaction_id - QR Code (
qrcodesportx_id) — se houverpaid_at+payment_end_to_end_id, resolve a transação real linkada emtransactionsvia E2E; caso contrário retorna o shape "QR Code Não Pago"
Se nada casar em nenhuma fonte, retorna 404.
Transação rejeitada NÃO aparece aqui por transaction_id
Rejeições BACEN síncronas (PACS.002 RJCT) e force-voids são persistidos em failed_transactions e não são encontrados por este endpoint quando você consulta pelo transaction_id. Use os endpoints alternativos:
- GET /transactions/e2e/:e2e_id — busca em
failed_transactionsporend_to_end_id - GET /transactions/ref/:external_id — busca em
failed_transactionsporexternal_id - Webhook
pix.payout.rejected/pix.payout.failed— notificação em tempo real com payload completo
Rejeições de validação de entrada (400/422 imediato) não passam por este fluxo — já retornaram o erro síncrono no POST.
Resposta -- Transação 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 | Descrição |
|---|---|---|
data.id | String | UUID interno da transação em formato canônico com hifens, 36 caracteres (ex: "c7f3a8b1-2d4e-4f6a-9c1b-3e5f7a9b1d3e"). O controller passa o binário de 16 bytes por Ecto.UUID.load/1 antes de serializar — o formato NÃO é hex lowercase de 32 chars sem hifens |
data.transaction_id | String | Identificador único da transação (prefixo comum PIXOUT para saídas e PIXIN para entradas, mas não é garantido — sempre leia o campo, não derive do prefixo) |
data.end_to_end_id | String | Identificador End-to-End no SPI/BACEN |
data.external_id | String | Identificador do seu sistema. null se não informado |
data.type | String | Tipo da transação. Valores comuns: pix, pix_return. O backend faz passthrough do campo t.type — rows legadas podem retornar outros valores |
data.direction | String | outbound (cash-out), inbound (cash-in), credit, debit. Os dois últimos aparecem quando o campo t.direction não foi persistido e o backend inferiu via Helpers.infer_direction/2 com base em account_id × to_account_id |
data.status | String | Status normalizado (ver tabela abaixo) |
data.amount | Integer | Valor em unidades base (div 10.000 para reais). 300000 = R$ 30,00 |
data.fee_amount | Integer | Tarifa cobrada em unidades base |
data.net_amount | Integer | Valor líquido em unidades base |
data.description | String | Descrição informada na criação |
data.counterparty_name | String | Nome da contraparte (pagador ou recebedor) |
data.recipient_key | String | Chave PIX do destinatário (apenas para saídas) |
data.created_at | String | Data de criação (ISO 8601) |
data.completed_at | String | Data de conclusão (ISO 8601), null se pendente |
Resposta -- PIX OUT em Andamento (200)
Retornado quando a transação ainda está sendo processada (antes da confirmação 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 | Descrição |
|---|---|---|
data.recipient | Object | Dados do destinatário resolvidos via DICT |
data.recipient.name | String | Nome do titular da chave |
data.recipient.key | String | Chave PIX utilizada |
data.recipient.key_type | String | Tipo da chave (cpf, cnpj, email, phone, evp) |
data.started_at | String | Data de início do processamento (ISO 8601) |
Resposta -- Transação Rejeitada (200)
Retornado pelos endpoints /transactions/e2e/:e2e_id e GET /transactions/ref/:external_id quando o PIX foi rejeitado pelo SPI ou falhou durante o processamento. Não retornado por GET /transactions/:id (veja aviso acima 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 | Descrição |
|---|---|---|
data.failure_reason | String | Motivo bruto da rejeição (formato: "rejected: {CODE}" para códigos BACEN, ou descrições de integração como "dict_key_not_found", "ambiguous key", "insufficient balance") |
data.reason_code | String | Código estruturado extraído de failure_reason. Para rejeições BACEN, segue ISO 20022 (AC03, AB03, ED05, DUPL etc). null quando failure_reason não contém código estruturado |
data.reason_description | String | Descrição humana do reason_code, em inglês (centralizada em Fluxiq.UseCases.Pix.ReasonCodes). Exemplos: "Invalid creditor account number" (AC03), "Aborted by PSP of creditor" (AB03), "Settlement failed" (ED05). null quando o código não é reconhecido |
data.recipient | Object | Dados do destinatário (quando disponíveis). Pode ser omitido em falhas muito precoces |
data.failed_at | String | Data/hora da rejeição (ISO 8601) |
Estrutura dos códigos de rejeição
O campo reason_code e reason_description são derivados do dicionário centralizado em Fluxiq.UseCases.Pix.ReasonCodes. Use-os para roteamento programático de erros. Mantenha failure_reason apenas para logs e diagnóstico. Veja a tabela completa de códigos em PIX Cash-Out por Chave -- Códigos de Erro.
Resposta -- QR Code Não Pago (200)
Retornado quando o ID corresponde a um QR Code que ainda não foi pago.
{
"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 | Descrição |
|---|---|
pending | QR Code ativo, aguardando pagamento |
settled | QR Code com paid_at preenchido, mas o controller não conseguiu resolver a transação real em transactions por payment_end_to_end_id. Ocorre na janela entre Phase 1 ACSP (ACK ao BACEN) e Phase 2 ACCC (PG MERGE concluído), ou quando o link QR↔TX falha por outro motivo. Caminho de código ativo (show_transaction_controller.ex:83) — não trate como erro; refaça a consulta alguns segundos depois e o backend deve retornar o shape "Transação Liquidada" normalmente |
expired | QR Code expirado (TTL default 60 min — configurável por conta via account.qrcode_expiration_seconds) |
cancelled | QR Code cancelado manualmente (ou cancelado em massa durante migração estático→dinâmico em 2026-04) |
Nota: quando o QR está pago e o backend consegue fazer lookup da transação real por E2E, a resposta é a do shape "Transação Liquidada" acima (com status: "settled" e o transaction_id real, não o tx_id do QR). Apenas quando esse lookup retorna nil é que se cai no shape "QR Code Não Pago" com status: "settled".
Valores do campo status
Status do GET depende da fonte
O GET /transactions/:id busca em 4 tabelas distintas e retorna um status diferente conforme a fonte onde a transação é encontrada. Não existe um vocabulário único entre todas as fontes.
| Status | Fonte | Significado |
|---|---|---|
processing | outbound_requests (stage 1 ou 2) | PACS.008 enviada, aguardando confirmação do BACEN. Saldo em hold |
processing | outbound_requests (stage 4 — fila de retry) | Rate-limited por ClientLimiter / DictBucket.Guard, aguardando retry automático (Oban PixOutRetryWorker, TTL 120min). O shape retornado é o mesmo do stage 1/2 — diferencie pelo webhook pix.payout.queued disparado no enfileiramento |
settled | transactions (status interno 1) | BACEN confirmou liquidação e o saldo já foi movimentado. Estado final de sucesso |
pending | transactions (status interno 2) | Caso raro — transação em estado intermediário antes da promoção a settled |
failed | transactions (status interno 3) OU failed_transactions | Estado final de falha. Rejeitada por BACEN (PACS.002 RJCT), orfã force-voided (>30min em hold), expiração da fila de retry (DICT_QUEUE_TIMEOUT) ou erro interno |
Nota de compatibilidade: rows legadas (anteriores à consolidação do vocabulário) podem apresentar status: "completed" ou status: "accepted". Trate-os como equivalentes a "settled".
Correspondência com webhooks
pix.payout.queuedcorresponde astatus: "processing"no GET enquanto o request está emoutbound_requests.stage=4pix.payout.confirmedsempre corresponde astatus: "settled"no GETpix.payout.failedepix.payout.rejectedsempre correspondem astatus: "failed"no GET
Para QR Codes (cash-in, fora do escopo PIX OUT), a tabela qrcodes adiciona 4 valores: pending, settled, expired, cancelled — descritos na seção "QR Code Não Pago" acima.
Resposta de Erro -- 404
{
"worked": false,
"detail": "Transação não encontrada"
}