# Balance

Queries the bank account balance associated with the API Key.

## Endpoint

```
GET /api/external/balance
```

## Headers

| Header | Type | Required | Description |
|--------|------|----------|-------------|
| `Authorization` | String | Yes | `ApiKey {client_id}:{client_secret}` |
| `X-Key-Case` | String | No | Set to `camelCase` to receive response fields in camelCase (default is snake_case) |

## Example

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

## Success Response (200)

```json
{
  "worked": true,
  "balance": 3000000,
  "available": 2700000,
  "pending": 300000,
  "currency": "BRL"
}
```

| Field | Type | Description |
|-------|------|-------------|
| `worked` | Boolean | `true` indicates operation success |
| `balance` | Integer | Safe balance in **base units** (÷ 10,000 for BRL). `3000000` = R$ 300.00 |
| `available` | Integer | Available balance for operations in base units. `2700000` = R$ 270.00 |
| `pending` | Integer | Amount held in pending transactions in base units. `300000` = R$ 30.00 |
| `currency` | String | Currency code (always `BRL`) |

::: danger Response values in base units
All response values are integers in **base units**. To convert to BRL, divide by 10,000.
Example: `3000000` ÷ 10,000 = **R$ 300.00**. Never use floating point.
:::

## Balance calculation

| Field | Definition |
|---|---|
| `balance` | **Safe balance** = `min(tigerbeetle_balance, postgres_balance)`. If there is a TB↔PG divergence, the smaller value is used |
| `available` | `balance - pending` - balance effectively available for new operations |
| `pending` | Sum of **pending debits** in TigerBeetle (`account.debits_pending`) |

The `balance` field protects against inflated balance in scenarios of temporary divergence between TigerBeetle and PostgreSQL (e.g., MED block, post-deploy reconciliation). You will **never** see here a value higher than what is actually available in the ledger system - always the smaller of the two systems.

### What composes `pending` (pending debits in TigerBeetle)

Each item below is a **pending transfer** in TigerBeetle that reduces `available` until it is posted or voided:

| Origin | When it appears | When it is released |
|---|---|---|
| **PIX OUT in flight** (TB pending from wallet → in-transit COSIF) | During sending, while awaiting BACEN confirmation (~1.6s typical) | Posted on `pix.payout.confirmed` (settled); voided on `pix.payout.failed` |
| **MED disputed amount** | When a MED case requires a temporary reserve of the disputed amount | Released or settled according to the final decision. Track `pix.infraction.resolved` and see [Infractions](/en/infractions). |
| **Quarantine (stage=5)** | PIX OUT without BACEN response >30min - balance stays in limbo | Posted/voided only after manual decision by the Monetarie reserve team (may take hours or D+1). See [pix-lifecycle](/en/pix-lifecycle#quarantine-operations-without-bacen-response). |
| **Other internal holds** | Rare - usually related to fees or specific adjustments | Depends on the type |

::: info Situations where `balance < raw TB balance`
- **TB↔PG divergence**: in rare cases (e.g., post-deploy remediation window, session 142 TB-PG equalization incident), `balance` reflects the **smaller** of the two systems until convergence. We never see an inflated balance; at most, it is underreported for a few minutes.
:::

::: warning `available` may appear "stuck" even with growing PIX IN
If you see `balance` rising (inflows) but `available` not growing proportionally, **an active MED block is very likely**. Query [`GET /api/external/med`](/en/med-list) to list the preventive blocks. Every block originates from an infraction - see [Infractions](/en/infractions) for the complete flow.
:::

::: warning Cache and consistency
The balance is computed in real time (typical latency <10ms) - there is no cache. However, in post-settlement windows (<200ms after the `pix.charge.paid` webhook), PostgreSQL may not yet be updated. For critical reconciliation, wait for the webhook before querying the balance.
:::

## Error Response (401)

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