# Extracto

Lista las transacciones de la cuenta con paginacion y filtros.

## Endpoint

```
GET /api/external/statement
```

## 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) |

## Query Parameters

| Parametro | Tipo | Obligatorio | Descripcion | Default |
|-----------|------|-------------|-------------|---------|
| `page` | Integer | No | Numero de pagina | `1` |
| `per_page` | Integer | No | Items por pagina (max 100) | `20` |
| `status` | String | No | Filtrar por la columna `payment_status`. Valores: `settled`, `rejected`, `failed`, `processing` | -- |
| `type` | String | No | Filtrar por tipo (`pix`, `ted`, `internal`) | -- |
| `date_from` | String | No | Fecha inicial (formato `YYYY-MM-DD`) | -- |
| `date_to` | String | No | Fecha final (formato `YYYY-MM-DD`) | -- |

**Valores aceptados en `status`**:
- `settled`: Transacciones liquidadas (default de exito)
- `rejected`: Rechazadas por el BACEN
- `failed`: Fallas internas o pos-rechazo
- `processing`: En procesamiento

::: warning Display vs Filter
El valor exhibido en el campo `status` de la respuesta puede diferir del valor aceptado por el filtro:

- Row con `status=2` exhibe `"pending"` pero es filtrada por `status=processing`
- Row con `payment_status=nil` y `status=1` exhibe `"completed"` pero es filtrada por `status=settled`

Use los valores del filtro arriba; el display es normalizado para consumo cliente.
:::

## Ejemplo

```bash
curl -X GET "https://api.monetarie.com/api/external/statement?page=1&per_page=20&status=settled&date_from=2026-03-01&date_to=2026-03-07" \
  -H "Authorization: ApiKey $CLIENT_ID:$CLIENT_SECRET"
```

## Respuesta de Exito (200)

```json
{
  "worked": true,
  "data": [
    {
      "id": "a1b2c3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d",
      "transaction_id": "7popu57v6us7p6pcicgq12345",
      "end_to_end_id": "E46026562202603071530000001",
      "external_id": "order-9876",
      "type": "pix",
      "status": "settled",
      "amount": 300000,
      "fee_amount": 0,
      "net_amount": 300000,
      "description": "Pedido #1234",
      "direction": "inbound",
      "counterparty_name": "Maria Santos",
      "created_at": "2026-03-07T15:30:00Z",
      "completed_at": "2026-03-07T15:30:02Z"
    },
    {
      "id": "f7e8d9c0-b1a2-4c3d-9e8f-7a6b5c4d3e2f",
      "transaction_id": "PIXOUT20260306x9y8z7w6v5u4",
      "end_to_end_id": "E46026562202603061200000005",
      "external_id": "invoice-4521",
      "type": "pix",
      "status": "settled",
      "amount": 500000,
      "fee_amount": 350,
      "net_amount": 500350,
      "description": "Pagamento fornecedor",
      "direction": "outbound",
      "counterparty_name": "Joao Silva",
      "recipient_key": "12345678901",
      "created_at": "2026-03-06T12:00:00Z",
      "completed_at": "2026-03-06T12:00:03Z"
    }
  ],
  "page": 1,
  "per_page": 20
}
```

| Campo | Tipo | Descripcion |
|-------|------|-------------|
| `worked` | Boolean | `true` indica exito en la operacion |
| `data` | Array | Lista de transacciones |
| `page` | Integer | Pagina actual |
| `per_page` | Integer | Items por pagina |

### Campos de cada transaccion

| Campo | 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. `null` si no informado |
| `type` | String | Tipo (`pix`, `ted`, `internal`) |
| `status` | String | Status de la transaccion (normalizado para display). Ver bloque "Display vs Filter" en [Query Parameters](#query-parameters). |
| `amount` | Integer | Valor en **unidades base** (÷ 10.000 para reales). `300000` = R$ 30,00 |
| `fee_amount` | Integer | Tarifa cobrada en unidades base |
| `net_amount` | Integer | Valor neto en unidades base |
| `description` | String | Descripcion de la transaccion |
| `direction` | String | `inbound` (entrada) o `outbound` (salida) |
| `counterparty_name` | String | Nombre de la contraparte |
| `recipient_key` | String | Clave PIX del destinatario (solo salidas) |
| `payer_document` | String | CPF/CNPJ del pagador (solo inbound). `null` para outbound. |
| `recipient_document` | String | CPF/CNPJ del receptor (solo outbound). `null` para inbound. |
| `payer_ispb` | String | ISPB de la institucion pagadora (solo inbound). `null` para outbound. |
| `payer_bank_name` | String | Nombre del banco pagador resuelto por el ISPB (solo inbound). `null` para outbound. |
| `created_at` | String | Fecha de creacion (ISO 8601 UTC) |
| `completed_at` | String | Fecha de conclusion (ISO 8601 UTC). `null` si aun no liquidada. |

::: info Fecha en UTC
Todos los campos de fecha/hora son retornados en **ISO 8601 UTC** (sufijo `Z`). Para convertir a horario de Brasilia (BRT), substraiga 3 horas. El filtro `date_from`/`date_to` tambien es interpretado como UTC - un dia filtrado (`date_from=2026-03-07`) cubre de `2026-03-07T00:00:00Z` hasta `2026-03-07T23:59:59Z`.
:::

::: tip In-flight transactions
La pagina 1 del listado incluye PIX OUT aun en vuelo (tabla `outbound_requests`, stage < 3) cuando no hay filtro `status` aplicado o `status=processing`. Esto permite conciliacion en tiempo real - usted ve la transaccion mientras esta siendo procesada por el BACEN, con `status="pending"`, `payment_status="processing"` y `completed_at=null`.

Cuando usted aplica `status=settled` o `status=rejected`, el merge con `outbound_requests` **no es hecho** - solo la tabla `transactions`/`failed_transactions` es consultada. Esto evita duplicidad cuando usted solo quiere transacciones terminales.
:::

::: warning net_amount en outbound es la suma (no substraccion)
En transacciones **outbound** (`direction="outbound"`), el `net_amount` es calculado como `amount + fee_amount` (debito total en la cuenta, incluyendo la tarifa). En transacciones **inbound**, `net_amount = amount - fee_amount` (credito neto ya con la tarifa descontada).

Ejemplo outbound: `amount=500000`, `fee_amount=350`, `net_amount=500350` - R$ 50,035 debitados de su cuenta. **No** R$ 49,965.
:::

::: info Rate limit y polling
`GET /statement` pasa por el rate limiter global de `/api/external/*` (90.000 req/min por IP autenticado). Solo `GET /balance` esta exento de ese limiter. Aun asi, evite polling alto en este endpoint - prefiera suscribir webhooks (`pix.charge.paid`, `pix.payout.confirmed`, `pix.payout.failed`) para notificacion en tiempo real y use `/statement` para conciliacion periodica (ej: intervalos de 5-15 min o end-of-day batch).
:::

::: tip Permiso
Este endpoint requiere `statement:read` en la API Key. El endpoint hermano `GET /api/external/transactions` (misma query base, shape casi identica) requiere `transfer:read` - caso su integracion use solo un conjunto de permisos, confirme cual endpoint acepta sus alcances.
:::

## Respuesta de Error (401)

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

::: tip Paginacion
El limite maximo de `per_page` es 100. Para extraer grandes volumenes, itere por las paginas incrementando el parametro `page` hasta que la respuesta retorne un array `data` vacio o con menos items que `per_page`.
:::
