# Extrato

Lista as transações da conta com paginação e filtros.

## Endpoint

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

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

## Query Parameters

| Parâmetro | Tipo | Obrigatório | Descrição | Default |
|-----------|------|-------------|-----------|---------|
| `page` | Integer | Não | Número da página | `1` |
| `per_page` | Integer | Não | Itens por página (max 100) | `20` |
| `status` | String | Não | Filtrar pela coluna `payment_status`. Valores: `settled`, `rejected`, `failed`, `processing` | -- |
| `type` | String | Não | Filtrar por tipo (`pix`, `ted`, `internal`) | -- |
| `date_from` | String | Não | Data inicial (formato `YYYY-MM-DD`) | -- |
| `date_to` | String | Não | Data final (formato `YYYY-MM-DD`) | -- |

**Valores aceitos em `status`**:
- `settled`: Transações liquidadas (padrão de sucesso)
- `rejected`: Rejeitadas pelo BACEN
- `failed`: Falhas internas ou pós-rejeição
- `processing`: Em processamento

::: warning Display vs Filter
O valor exibido no campo `status` da resposta pode diferir do valor aceito pelo filtro:

- Row com `status=2` exibe `"pending"` mas é filtrada por `status=processing`
- Row com `payment_status=nil` e `status=1` exibe `"completed"` mas é filtrada por `status=settled`

Use os valores do filtro acima; o display é normalizado para consumo cliente.
:::

## Exemplo

```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"
```

## Resposta de Sucesso (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 | Descrição |
|-------|------|-----------|
| `worked` | Boolean | `true` indica sucesso na operação |
| `data` | Array | Lista de transações |
| `page` | Integer | Página atual |
| `per_page` | Integer | Itens por página |

### Campos de cada transação

| Campo | 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. `null` se não informado |
| `type` | String | Tipo (`pix`, `ted`, `internal`) |
| `status` | String | Status da transação (normalizado para display). Ver bloco "Display vs Filter" em [Query Parameters](#query-parameters). |
| `amount` | Integer | Valor em **unidades base** (÷ 10.000 para reais). `300000` = R$ 30,00 |
| `fee_amount` | Integer | Tarifa cobrada em unidades base |
| `net_amount` | Integer | Valor líquido em unidades base |
| `description` | String | Descrição da transação |
| `direction` | String | `inbound` (entrada) ou `outbound` (saída) |
| `counterparty_name` | String | Nome da contraparte |
| `recipient_key` | String | Chave PIX do destinatário (apenas saídas) |
| `payer_document` | String | CPF/CNPJ do pagador (apenas inbound). `null` para outbound. |
| `recipient_document` | String | CPF/CNPJ do recebedor (apenas outbound). `null` para inbound. |
| `payer_ispb` | String | ISPB da instituição pagadora (apenas inbound). `null` para outbound. |
| `payer_bank_name` | String | Nome do banco pagador resolvido pelo ISPB (apenas inbound). `null` para outbound. |
| `created_at` | String | Data de criação (ISO 8601 UTC) |
| `completed_at` | String | Data de conclusão (ISO 8601 UTC). `null` se ainda não liquidada. |

::: info Data em UTC
Todos os campos de data/hora são retornados em **ISO 8601 UTC** (sufixo `Z`). Para converter para horário de Brasília (BRT), subtraia 3 horas. O filtro `date_from`/`date_to` também é interpretado como UTC - um dia filtrado (`date_from=2026-03-07`) cobre de `2026-03-07T00:00:00Z` até `2026-03-07T23:59:59Z`.
:::

::: tip In-flight transactions
A página 1 da listagem inclui PIX OUT ainda em voo (tabela `outbound_requests`, stage < 3) quando não há filtro `status` aplicado ou `status=processing`. Isso permite conciliação em tempo real - você vê a transação enquanto ela está sendo processada pelo BACEN, com `status="pending"`, `payment_status="processing"` e `completed_at=null`.

Quando você aplica `status=settled` ou `status=rejected`, o merge com `outbound_requests` **não é feito** - apenas a tabela `transactions`/`failed_transactions` é consultada. Isso evita duplicidade quando você só quer transações terminais.
:::

::: warning net_amount em outbound é a soma (não subtração)
Em transações **outbound** (`direction="outbound"`), o `net_amount` é calculado como `amount + fee_amount` (débito total na conta, incluindo a tarifa). Em transações **inbound**, `net_amount = amount - fee_amount` (crédito líquido já com a tarifa descontada).

Exemplo outbound: `amount=500000`, `fee_amount=350`, `net_amount=500350` - R$ 50,035 debitados da sua conta. **Não** R$ 49,965.
:::

::: info Rate limit e polling
`GET /statement` passa pelo rate limiter global de `/api/external/*` (90.000 req/min por IP autenticado). Apenas `GET /balance` é exceção e não passa pelo limiter. Mesmo assim, evite polling alto neste endpoint - prefira assinar webhooks (`pix.charge.paid`, `pix.payout.confirmed`, `pix.payout.failed`) para notificação em tempo real e use `/statement` para conciliação periódica (ex: intervalos de 5-15 min ou end-of-day batch).
:::

::: tip Permissão
Este endpoint requer `statement:read` na API Key. O endpoint irmão `GET /api/external/transactions` (mesma query base, shape quase idêntica) requer `transfer:read` - caso sua integração use apenas um conjunto de permissões, confirme qual endpoint aceita seus escopos.
:::

## Resposta de Erro (401)

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

::: tip Paginação
O limite máximo de `per_page` é 100. Para extrair grandes volumes, itere pelas páginas incrementando o parâmetro `page` até que a resposta retorne um array `data` vazio ou com menos itens que `per_page`.
:::
