# Consultar Transação por External ID

Consulta uma transação pelo `external_id`, o identificador definido pelo seu sistema no momento da criação (cash-in ou cash-out).

## Endpoint

```
GET /api/external/transactions/ref/:external_id
```

## Headers

| Header | Tipo | Obrigatório | Descrição |
|--------|------|-------------|-----------|
| `Authorization` | String | Sim | `ApiKey {client_id}:{client_secret}` |
| `X-Key-Case` | String | Não | Defina como `camelCase` para receber os campos da resposta em camelCase (padrão é snake_case) |

## Path Parameters

| Parâmetro | Tipo | Obrigatório | Descrição |
|-----------|------|-------------|-----------|
| `external_id` | String | Sim | Identificador externo definido na criação da transação |

::: tip Quando usar
Este endpoint é útil para conciliação entre o seu sistema e a Monetarie. Em vez de armazenar o `transaction_id` da Monetarie, consulte diretamente pelo ID do seu pedido, fatura ou referência interna.
:::

## Exemplo

```bash
curl -X GET https://api.monetarie.com/api/external/transactions/ref/order-9876 \
  -H "Authorization: ApiKey $CLIENT_ID:$CLIENT_SECRET"
```

## Shapes de Resposta

A resposta varia conforme o estado da transação. Veja abaixo os 4 shapes possíveis.

### Shape 1 -- Transação liquidada (`status: "settled"`)

Retornado quando a transação foi liquidada e persistida na tabela `transactions`.

```json
{
  "worked": true,
  "data": {
    "id": "c7f3a8b1-2d4e-4f6a-9c1b-3e5f7a9b1d3e",
    "transaction_id": "PIXOUT20260309a1b2c3d4e5f6",
    "end_to_end_id": "E46026562202603091530abcdef01",
    "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",
    "payer_document": null,
    "recipient_document": "12345678901",
    "payer_ispb": null,
    "payer_bank_name": null,
    "created_at": "2026-03-09T15:30:00Z",
    "completed_at": "2026-03-09T15:30:02Z"
  }
}
```

| Campo (top-level) | Tipo | Descrição |
|-------|------|-----------|
| `id` | String | UUID interno da transação |
| `transaction_id` | String | Identificador público da transação |
| `end_to_end_id` | String | E2E ID do BACEN |
| `external_id` | String | Identificador do seu sistema |
| `type` | String | `pix`, `ted`, `internal` |
| `direction` | String | `inbound` ou `outbound` |
| `status` | String | Status da transação (ver [pix-lifecycle](/pix-lifecycle)) |
| `amount` | Integer | Valor em unidades base (÷ 10.000 para reais) |
| `fee_amount` | Integer | Tarifa cobrada em unidades base |
| `net_amount` | Integer | Valor líquido em unidades base |
| `description` | String | Descrição da transação |
| `counterparty_name` | String | Nome da contraparte |
| `recipient_key` | String | Chave PIX do destinatário (apenas outbound) |
| `payer_document` | String | CPF/CNPJ do pagador (inbound). `null` para outbound |
| `recipient_document` | String | CPF/CNPJ do recebedor (outbound). `null` para inbound |
| `payer_ispb` | String | ISPB da instituição pagadora (inbound). `null` para outbound |
| `payer_bank_name` | String | Nome do banco pagador (inbound). `null` para outbound |
| `created_at` | String | Data de criação (ISO 8601) |
| `completed_at` | String | Data de conclusão (ISO 8601) |

### Shape 2 -- Transação em processamento (`status: "processing"`)

Retornado quando a transação está em `outbound_requests` aguardando resposta do BACEN (ainda não liquidada nem falhada).

```json
{
  "worked": true,
  "data": {
    "transaction_id": "PIXOUT20260309a1b2c3d4e5f6",
    "end_to_end_id": "E46026562202603091530abcdef01",
    "external_id": "order-9876",
    "amount": 300000,
    "fee_amount": 350,
    "net_amount": 300350,
    "status": "processing",
    "payment_status": "processing",
    "type": "pix",
    "direction": "outbound",
    "pix_key": "12345678901",
    "description": "Pagamento fornecedor",
    "started_at": "2026-03-09T15:30:00Z"
  }
}
```

| Campo | Tipo | Descrição |
|-------|------|-----------|
| `transaction_id` | String | Identificador público (prefixo `PIXOUT`) |
| `end_to_end_id` | String | E2E ID do BACEN |
| `external_id` | String | Identificador do seu sistema |
| `amount` | Integer | Valor em unidades base (÷ 10.000 para reais) |
| `fee_amount` | Integer | Tarifa em unidades base |
| `net_amount` | Integer | `amount + fee_amount` em unidades base |
| `status` | String | Sempre `"processing"` nesta shape |
| `payment_status` | String | Espelho de `status` para compatibilidade |
| `type` | String | `pix`, `ted`, `internal` |
| `direction` | String | `outbound` (shape exclusiva de PIX OUT em voo) |
| `pix_key` | String | Chave PIX do destinatário |
| `description` | String | Descrição informada no request |
| `started_at` | String | Instante em que a requisição entrou na fila (ISO 8601) |

::: warning Shape intermediária
Transações em `processing` estão em voo no BACEN. **Não confie neste estado como final** - aguarde o webhook `pix.payout.confirmed` ou `pix.payout.failed`. Operações em quarentena (stage=5, sem resposta do BACEN >30min) também retornam `"processing"` - ver [pix-lifecycle](/pix-lifecycle).
:::

### Shape 3 -- Transação falhada

Retornado quando a transação está em `failed_transactions` (rejeitada pelo BACEN ou falha interna).

```json
{
  "worked": true,
  "data": {
    "transaction_id": "PIXOUT20260309a1b2c3d4e5f6",
    "end_to_end_id": "E46026562202603091530abcdef01",
    "external_id": "order-9876",
    "amount": 300000,
    "status": "failed",
    "type": "pix",
    "direction": "outbound",
    "reason_code": "AC03",
    "reason_description": "Invalid creditor account number",
    "recipient": {
      "name": "Joao Silva",
      "key": "12345678901"
    },
    "failed_at": "2026-03-09T15:30:02Z"
  }
}
```

| Campo extra | Tipo | Descrição |
|-------|------|-----------|
| `reason_code` | String | Código BACEN/provider (ex: `AC03`, `ED05`, `AM02`) |
| `reason_description` | String | Descrição em inglês |
| `recipient` | Object | `{name, key}` do destinatário |
| `failed_at` | String | Data da falha (ISO 8601) |

### Shape 4 -- QR code (cash-in)

Retornado quando o `external_id` foi registrado em um QR code de cobrança (pago ou não pago). Usado como fallback quando não há row em `transactions` nem em `outbound_requests`.

```json
{
  "worked": true,
  "data": {
    "id": "e9f3df72-031f-49bf-abc3-a9ce1d540726",
    "tx_id": "smyoka2zd5xowvqq2hea",
    "pix_key": "evp-xxxx-xxxx-xxxx",
    "amount": 100000,
    "fee_amount": 0,
    "status": "paid",
    "external_id": "order-9876",
    "description": "Pedido #1234",
    "end_to_end_id": "E46026562202604101607b2fc9d8b4c6b",
    "direction": "inbound",
    "type": "pix_qrcode",
    "created_at": "2026-04-10T16:00:00Z",
    "paid_at": "2026-04-10T16:07:08Z"
  }
}
```

| Campo | Tipo | Descrição |
|-------|------|-----------|
| `id` | String | UUID do QR code |
| `tx_id` | String | `txId` BACEN (identificador do QR no SPI) |
| `pix_key` | String | Chave PIX do recebedor no QR |
| `amount` | Integer | Valor do QR em unidades base (`0` se QR sem valor definido) |
| `fee_amount` | Integer | Sempre `0` no QR code (tarifa é cobrada na liquidação) |
| `status` | String | `paid`, `pending`, `expired`, `cancelled` |
| `external_id` | String | Identificador do seu sistema |
| `description` | String | Descrição informada na criação do QR |
| `end_to_end_id` | String | E2E do PIX que liquidou o QR (apenas se `status=paid`). `null` caso contrário. |
| `direction` | String | Sempre `"inbound"` para QR code |
| `type` | String | Sempre `"pix_qrcode"` |
| `created_at` | String | Instante de criação do QR (ISO 8601) |
| `paid_at` | String | Instante do pagamento (ISO 8601). `null` se ainda não pago. |

Todos os valores monetários estão em **unidades base** (÷ 10.000 para reais).

::: tip Prioridade de busca
O backend procura o `external_id` nesta ordem: (1) `transactions` → shape 1, (2) `outbound_requests` em voo → shape 2, (3) `failed_transactions` → shape 3, (4) `qrcodes` → shape 4. A primeira tabela que contém o ID vence.
:::

::: warning Diferenças entre shapes (importante para o parser do cliente)
As 4 shapes compartilham alguns campos (ex: `transaction_id`, `end_to_end_id`, `external_id`, `amount`, `status`, `type`, `direction`) mas **não têm o mesmo conjunto de campos**:

- **Shape 1 (`settled`)**: 18 campos incluindo `fee_amount`, `net_amount`, `payer_document`, `payer_ispb`, `payer_bank_name`, `recipient_document`, `recipient_key`, `counterparty_name`
- **Shape 2 (`processing`)**: 13 campos - **não traz** dados da contraparte (`payer_document`, `payer_ispb`, `recipient_document` ausentes), só o que está em `outbound_requests`
- **Shape 3 (`failed`)**: traz `reason_code` + `reason_description` + objeto `recipient.{name, key}` aninhado (observe: não é `recipient_document` flat)
- **Shape 4 (QR code)**: esquema diferente - tem `tx_id`, `paid_at`, `pix_key`, sempre `direction="inbound"` e `type="pix_qrcode"`

**Recomendação**: inspecione `data.status` primeiro; use switch/case para dispatch a 4 parsers distintos. Não assuma presença de campos cross-shape.
:::

::: tip Comprovante oficial
Para gerar um comprovante formatado (PDF-ready, com dados de instituição e valores em BRL formatados), use [`GET /api/external/transactions/:id/receipt`](/pix-cashout-receipt) após a liquidação - o endpoint `/transactions/ref/:external_id` traz dados brutos para conciliação programática, não formatação visual.
:::

## Resposta de Erro -- 404

```json
{
  "worked": false,
  "errors": {
    "not_found": "Transação não encontrada para o external_id informado"
  }
}
```

## Resposta de Erro -- 401

```json
{
  "worked": false,
  "errors": {
    "unauthorized": "Missing API key credentials. Use Authorization: ApiKey <client_id>:<client_secret>"
  }
}
```

::: warning Unicidade
O `external_id` não é único por conta. Se múltiplas transações possuem o mesmo `external_id`, o endpoint retorna a mais recente. Recomendamos usar valores únicos para facilitar a conciliação.
:::
