# Consultar Transaccion por External ID

Consulta una transaccion por `external_id`, el identificador definido por su sistema en el momento de la creacion (cash-in o cash-out).

## Endpoint

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

## Headers

| Header | Tipo | Obligatorio | Descripcion |
|--------|------|-------------|-------------|
| `Authorization` | String | Si | `ApiKey {client_id}:{client_secret}` |
| `X-Key-Case` | String | No | Defina como `camelCase` para recibir los campos de la respuesta en camelCase (default es snake_case) |

## Path Parameters

| Parametro | Tipo | Obligatorio | Descripcion |
|-----------|------|-------------|-------------|
| `external_id` | String | Si | Identificador externo definido en la creacion de la transaccion |

::: tip Cuando usar
Este endpoint es util para conciliacion entre su sistema y Monetarie. En lugar de almacenar el `transaction_id` de Monetarie, consulte directamente por el ID de su pedido, factura o referencia interna.
:::

## Ejemplo

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

## Shapes de Respuesta

La respuesta varia conforme al estado de la transaccion. Vea abajo los 4 shapes posibles.

### Shape 1 -- Transaccion liquidada (`status: "settled"`)

Retornado cuando la transaccion fue liquidada y persistida en la tabla `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 | Descripcion |
|-------|------|-------------|
| `id` | String | UUID interno de la transaccion |
| `transaction_id` | String | Identificador publico de la transaccion |
| `end_to_end_id` | String | E2E ID del BACEN |
| `external_id` | String | Identificador de su sistema |
| `type` | String | `pix`, `ted`, `internal` |
| `direction` | String | `inbound` o `outbound` |
| `status` | String | Status de la transaccion (ver [pix-lifecycle](/es/pix-lifecycle)) |
| `amount` | Integer | Valor en unidades base (÷ 10.000 para reales) |
| `fee_amount` | Integer | Tarifa cobrada en unidades base |
| `net_amount` | Integer | Valor neto en unidades base |
| `description` | String | Descripcion de la transaccion |
| `counterparty_name` | String | Nombre de la contraparte |
| `recipient_key` | String | Clave PIX del destinatario (solo outbound) |
| `payer_document` | String | CPF/CNPJ del pagador (inbound). `null` para outbound |
| `recipient_document` | String | CPF/CNPJ del receptor (outbound). `null` para inbound |
| `payer_ispb` | String | ISPB de la institucion pagadora (inbound). `null` para outbound |
| `payer_bank_name` | String | Nombre del banco pagador (inbound). `null` para outbound |
| `created_at` | String | Fecha de creacion (ISO 8601) |
| `completed_at` | String | Fecha de conclusion (ISO 8601) |

### Shape 2 -- Transaccion en procesamiento (`status: "processing"`)

Retornado cuando la transaccion esta en `outbound_requests` aguardando respuesta del BACEN (aun no liquidada ni fallada).

```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 | Descripcion |
|-------|------|-------------|
| `transaction_id` | String | Identificador publico (prefijo `PIXOUT`) |
| `end_to_end_id` | String | E2E ID del BACEN |
| `external_id` | String | Identificador de su sistema |
| `amount` | Integer | Valor en unidades base (÷ 10.000 para reales) |
| `fee_amount` | Integer | Tarifa en unidades base |
| `net_amount` | Integer | `amount + fee_amount` en unidades base |
| `status` | String | Siempre `"processing"` en este shape |
| `payment_status` | String | Espejo de `status` para compatibilidad |
| `type` | String | `pix`, `ted`, `internal` |
| `direction` | String | `outbound` (shape exclusivo de PIX OUT en vuelo) |
| `pix_key` | String | Clave PIX del destinatario |
| `description` | String | Descripcion informada en el request |
| `started_at` | String | Instante en que la solicitud entro en la fila (ISO 8601) |

::: warning Shape intermedio
Transacciones en `processing` estan en vuelo en el BACEN. **No confie en este estado como final** - aguarde el webhook `pix.payout.confirmed` o `pix.payout.failed`. Operaciones en cuarentena (stage=5, sin respuesta del BACEN >30min) tambien retornan `"processing"` - ver [pix-lifecycle](/es/pix-lifecycle).
:::

### Shape 3 -- Transaccion fallada

Retornado cuando la transaccion esta en `failed_transactions` (rechazada por el BACEN o falla 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 | Descripcion |
|-------|------|-------------|
| `reason_code` | String | Codigo BACEN/provider (ej: `AC03`, `ED05`, `AM02`) |
| `reason_description` | String | Descripcion en ingles |
| `recipient` | Object | `{name, key}` del destinatario |
| `failed_at` | String | Fecha de la falla (ISO 8601) |

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

Retornado cuando el `external_id` fue registrado en un QR code de cobro (pagado o no pagado). Usado como fallback cuando no hay row en `transactions` ni en `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 | Descripcion |
|-------|------|-------------|
| `id` | String | UUID del QR code |
| `tx_id` | String | `txId` BACEN (identificador del QR en el SPI) |
| `pix_key` | String | Clave PIX del receptor en el QR |
| `amount` | Integer | Valor del QR en unidades base (`0` si QR sin valor definido) |
| `fee_amount` | Integer | Siempre `0` en el QR code (tarifa es cobrada en la liquidacion) |
| `status` | String | `paid`, `pending`, `expired`, `cancelled` |
| `external_id` | String | Identificador de su sistema |
| `description` | String | Descripcion informada en la creacion del QR |
| `end_to_end_id` | String | E2E del PIX que liquido el QR (solo si `status=paid`). `null` caso contrario. |
| `direction` | String | Siempre `"inbound"` para QR code |
| `type` | String | Siempre `"pix_qrcode"` |
| `created_at` | String | Instante de creacion del QR (ISO 8601) |
| `paid_at` | String | Instante del pago (ISO 8601). `null` si aun no pagado. |

Todos los valores monetarios estan en **unidades base** (÷ 10.000 para reales).

::: tip Prioridad de busqueda
El backend busca el `external_id` en este orden: (1) `transactions` → shape 1, (2) `outbound_requests` en vuelo → shape 2, (3) `failed_transactions` → shape 3, (4) `qrcodes` → shape 4. La primera tabla que contiene el ID gana.
:::

::: warning Diferencias entre shapes (importante para el parser del cliente)
Los 4 shapes comparten algunos campos (ej: `transaction_id`, `end_to_end_id`, `external_id`, `amount`, `status`, `type`, `direction`) pero **no tienen el mismo conjunto de campos**:

- **Shape 1 (`settled`)**: 18 campos incluyendo `fee_amount`, `net_amount`, `payer_document`, `payer_ispb`, `payer_bank_name`, `recipient_document`, `recipient_key`, `counterparty_name`
- **Shape 2 (`processing`)**: 13 campos - **no trae** datos de la contraparte (`payer_document`, `payer_ispb`, `recipient_document` ausentes), solo lo que esta en `outbound_requests`
- **Shape 3 (`failed`)**: trae `reason_code` + `reason_description` + objeto `recipient.{name, key}` anidado (observe: no es `recipient_document` flat)
- **Shape 4 (QR code)**: esquema diferente - tiene `tx_id`, `paid_at`, `pix_key`, siempre `direction="inbound"` y `type="pix_qrcode"`

**Recomendacion**: inspeccione `data.status` primero; use switch/case para dispatch a 4 parsers distintos. No asuma presencia de campos cross-shape.
:::

::: tip Comprobante oficial
Para generar un comprobante formateado (PDF-ready, con datos de institucion y valores en BRL formateados), use [`GET /api/external/transactions/:id/receipt`](/es/pix-cashout-receipt) despues de la liquidacion - el endpoint `/transactions/ref/:external_id` trae datos brutos para conciliacion programatica, no formato visual.
:::

## Respuesta de Error -- 404

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

## Respuesta de Error -- 401

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

::: warning Unicidad
El `external_id` no es unico por cuenta. Si multiples transacciones tienen el mismo `external_id`, el endpoint retorna la mas reciente. Recomendamos usar valores unicos para facilitar la conciliacion.
:::
