> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://en.docs.api.corpx.com/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://en.docs.api.corpx.com/_mcp/server.

# Cashout limits

The cashout ceiling is per account, per operation and per window. It is not a
[policy](/baas/guias/autenticacao/politicas) rule: `pixOut.maxAmount` is no
longer evaluated. Exceeding the ceiling returns
`422 limit_exceeded_transaction`.

## Read what is available

`GET /v1/accounts/{accountId}/limits/available` returns PIX, TED, boleto and
internal transfer, each with four windows, used and remaining.

| Field on `GET /limits/available` | Meaning          | Hours (America/Sao\_Paulo) |
| -------------------------------- | ---------------- | -------------------------- |
| `singleTransfer`                 | One operation    | —                          |
| `daytime`                        | Daytime window   | 06:00–20:00                |
| `nighttime`                      | Nighttime window | 20:00–06:00                |
| `monthly`                        | Calendar month   | —                          |

`operation` is `pix_out`, `ted_out`, `boleto` or `internal_out`.

With no effective ceiling the window is fail-open: the payment is not blocked
by a local limit. Precedence is the account's own cell, then the tenant
default, then the global default. `source` on the window says which one
applied. A local PIX ceiling does not replace the settlement bank's cap.

`GET /v1/accounts/{accountId}/pix/limits` is **deprecated**. It returns only
the settlement bank's PIX ceilings, with no used amount, and sends `Link`
pointing at `/limits/available`.

## Ask for an increase

`POST /v1/accounts/{accountId}/limit-requests` opens a request. **It does not
change the ceiling.** CorpX reviews it and, on approval, applies the amount
immediately. `effectiveAt` stays `null` until a waiting period exists.

```bash
curl -X POST "https://tenant.api.corpx.com/v1/accounts/$ACCOUNT_ID/limit-requests" \
  -H "Authorization: Bearer $TOKEN" \
  -H "X-Tenant-Id: $TENANT_ID" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: 3f1c0b6e-9a2d-4c71-8e55-1b7a0d4c9e21" \
  -H "X-Acting-Document: 39053344705" \
  -H "X-Acting-Ip: 200.10.20.30" \
  -d '{
    "operation": "pix_out",
    "window": "daytime",
    "requestedLimitBrl": 50000,
    "justification": "Payroll for the month.",
    "identifier": "3f1c0b6e-9a2d-4c71-8e55-1b7a0d4c9e21",
    "risk": {
      "provider": "castle",
      "action": "allow",
      "score": 0.12,
      "policyName": "ib-limit-increase",
      "evaluatedAt": "2026-10-02T18:00:00Z"
    }
  }'
```

`201`:

```json
{
  "id": "lr_01J9XQ8K2M3N4P5Q6R7S8T9U0V",
  "status": "pending_review",
  "operation": "pix_out",
  "window": "daytime",
  "currentLimitBrl": 20000,
  "requestedLimitBrl": 50000,
  "approvedLimitBrl": null,
  "justification": "Payroll for the month.",
  "identifier": "3f1c0b6e-9a2d-4c71-8e55-1b7a0d4c9e21",
  "decisionMessage": null,
  "effectiveAt": null,
  "createdAt": "2026-10-02T18:00:01Z"
}
```

### Window names

On this route the window is snake\_case. On `GET /limits/available` the same
concept is camelCase. Do not mix the two.

| Request (`window`) | Read (`GET /limits/available`) |
| ------------------ | ------------------------------ |
| `single_transfer`  | `singleTransfer`               |
| `daytime`          | `daytime`                      |
| `nighttime`        | `nighttime`                    |
| `monthly`          | `monthly`                      |

`requestedLimitBrl` must be **above** the effective ceiling of that window.
With no ceiling, `currentLimitBrl` is `0` and any positive amount passes this
check. An equal or lower amount is `422 limit_request_not_above_current`.

### Idempotency

`Idempotency-Key` is required (up to 128 characters) and `identifier` must be
**identical** to the header. The same key returns the original request with
`201`, even if the body changes. A different key, while a `pending_review`
request exists for the same operation and window, is
`409 limit_request_pending`.

### Who asked, and risk

`X-Acting-Document` is required: a CPF (11 digits) or CNPJ (14). It is the
document the webhook carries so you can notify the right person.
`X-Acting-Ip` is the operator's IP, not your server's.

`risk` is optional. `action` is `allow`, `challenge` or `deny`; `score`, when
sent, is between 0 and 1. The block is only stored and shown to the reviewer.
**`deny` does not reject the request.**

`justification` is required, up to 500 characters.

## Follow and cancel

`GET /v1/accounts/{accountId}/limit-requests?status=` returns
`{ "items": [...] }`. `status` filters `pending_review`, `approved`,
`refused` or `cancelled`. With no filter, every status is returned.

`GET .../limit-requests/{id}` adds `decisionMessage`, `effectiveAt` and
`events`: `[{ "at", "status", "message" }]`. Only public events are included.
The reviewer's internal note never leaves this API.

`POST .../limit-requests/{id}/cancel` cancels only `pending_review`. Any
other status is `409 limit_request_closed`. Cancellation also sends the
webhook.

## Status

| Status           | Meaning                                                                                                     |
| ---------------- | ----------------------------------------------------------------------------------------------------------- |
| `pending_review` | In the queue. The ceiling is still the old one.                                                             |
| `approved`       | Approved **and applied**. `approvedLimitBrl` is the ceiling now in force and may be lower than the request. |
| `refused`        | Refused. The ceiling did not change. `decisionMessage` explains.                                            |
| `cancelled`      | Cancelled by the requester, while still in review.                                                          |

There is no "approved but not yet applied" state.

## Webhook `limit_request.updated`

Sent on approval, refusal and cancellation. Not sent on creation: the `201`
is the acknowledgement. A per-account subscription receives the event because
`accountId` is on the envelope.

`data`: `id`, `accountId`, `status`, `operation`, `window`,
`requestedLimitBrl`, `approvedLimitBrl`, `decisionMessage`, `effectiveAt`,
`actingDocument`, `identifier`.

The full example is in [Webhooks](/baas/guias/conta/webhooks).

## Errors

| Code                                  | HTTP | When                                                                |
| ------------------------------------- | ---- | ------------------------------------------------------------------- |
| `missing_idempotency_key`             | 400  | No `Idempotency-Key`, or a key longer than 128 characters           |
| `invalid_identifier`                  | 400  | `identifier` differs from the key                                   |
| `invalid_justification`               | 400  | Empty or longer than 500 characters                                 |
| `invalid_risk`                        | 400  | `action` or `score` outside the contract                            |
| `acting_document_required`            | 400  | No `X-Acting-Document`                                              |
| `invalid_acting_document`             | 400  | Document is neither a CPF nor a CNPJ                                |
| `limit_request_operation_unavailable` | 422  | `operation` or `window` outside the table above                     |
| `limit_request_not_above_current`     | 422  | Requested (or approved) amount does not beat the effective ceiling  |
| `limit_request_pending`               | 409  | A review is already open for the same operation and window          |
| `limit_request_closed`                | 409  | Cancelling or deciding a request that is no longer `pending_review` |
| `limit_request_not_found`             | 404  | `id` does not exist on this account                                 |