> 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.

# Changelog

## v2.88.0 — Batch PIX via API (M2M)

* **New: batch PIX** at `/v1/accounts/{accountId}/pix/batches` ([guide](/baas/guias/pagar/pix-em-lote)). Five steps: `GET .../template` downloads the CSV template; `POST .../batches` creates the `DRAFT` batch (`Idempotency-Key` required); `POST .../items/csv` (raw file, up to 5 MiB) or `PUT .../items` (1–50 JSON items) add rows **atomically**; `POST .../review` runs the asynchronous pre-flight; `POST .../dispatch` with `{"acknowledged": true}` fires. Each row pays a **PIX key** or a **bank account** and becomes a regular PIX out (same limits, policies, statement and `pix.out.*`).
* **Review before any debit.** `review` resolves keys in DICT (24-hour cache; counts toward the lookup window), detects `identifier` already used on the account and amounts above the per-operation limit, and returns a summary with `totalAmount`/`validAmount`, **available balance** and daily/nightly/monthly **limits** with `sufficient` flags. `INVALID` items block dispatch until fixed or removed.
* **Correction and receipts.** `GET .../items/export?status=failed` returns only failed/invalid rows in the template format plus `errorCode`/`errorMessage` — the file uploads as is to a new batch. `GET .../items/{itemId}/receipt` renders one PDF; `POST .../receipts` creates an export job (`pix_batch_receipts`, ZIP with one PDF per item and `resumo.csv`). File names: `{YYYY-MM-DD}_{HHMM}_PIX_{amount}_{receiver}_{identifier}_{endToEnd}.pdf`.
* **New webhook `pix.batch.completed`** with `status` (`COMPLETED`, `PARTIAL_FAILED`, `FAILED`) and `statistics` (`total`, `completed`, `failed`, `totalAmount`, `completedAmount`, `failedAmount`). Per-item events keep being emitted.
* **Enablement and limits.** M2M-only surface with scope `pix_out.create`; user tokens get 403. The tenant feature `pix_batch` **and** `pixBatch.enabled=true` in the account policy are set by CorpX (`403 feature_disabled` / `403 pix_batch_account_disabled`). `pixBatch.maxItems` caps rows per batch (default 50, hard cap 5,000), returned as `limits.maxItems`. Dispatch honours cashout locks and the transaction PIN like `POST /pix/out`.
* New codes in the [error catalog](/baas/guias/referencia/erros): `pix_batch_not_found`, `pix_batch_item_not_found`, `pix_batch_account_disabled`, `pix_batch_chunk_invalid`, `pix_batch_csv_invalid`, `pix_batch_too_large`, `pix_batch_item_conflict`, `pix_batch_not_editable`, `pix_batch_empty`, `pix_batch_not_reviewed`, `pix_batch_has_invalid_items`, `pix_batch_acknowledgement_required`, `pix_batch_insufficient_balance`, `pix_batch_no_receipts`, `pix_batch_receipt_unavailable`, `receipt_render_failed`, `invalid_pix_batch_policy`.

## v2.87.0 — Close an account in the tenant

* **`POST /v1/accounts/{accountId}/close`** removes this tenant's access to the account. The 200 body is the same on both internal paths — the caller cannot tell whether another tenant still operates it. Humans need `tenant_manager` or `admin`; credentials need `accounts.close` (legacy `api2/write` still passes). A viewer cannot close.
* An exclusive account with a non-zero raw settlement-bank balance returns **422** `account_has_balance` and leaves the row `active`. A zero balance emails MT support and then writes `status=closed` / `status_source=tenant_close`. Already closed in this tenant returns the same 200, without a second email.
* Binding to another account, a missing account, or a `suspended` row is always **404** `account_not_found` on this route. `closed` cuts the API, webhook fanout, and the tenant catalog.
* `GET /v1/accounts/{accountId}/bank-account` no longer returns 422 when the live lookup fails and the account number is already stored on the tenant — the overview uses that number (branch 0001).

## v2.86.4 — PIN reset on the CorpX page

* When PIN reset on the CorpX page is enabled for the tenant, replacing an existing PIN with `PUT /v1/accounts/{accountId}/security/pin` returns **403** `pin_change_disabled`, and `DELETE .../security/pin/{document}` returns **403** `pin_invalidate_disabled`. The first enrollment still uses PUT. Verify and status are unchanged.
* **`POST /v1/accounts/{accountId}/security/pin/reset-request`** returns the page link (`resetUrl`). The operator opens it, completes the facial check and, if it is approved, chooses the new PIN on that same page. The body does not accept the PIN. With no PIN on file, the response is **409** `pin_reset_not_enrolled`. The optional `displayMessage` is shown on the page. The link lasts 30 minutes; the fifth request in the same hour returns **429** `pin_reset_rate_limited`.

## v2.86.0 — GET /pix/limits deprecated

* **`GET /v1/accounts/{accountId}/pix/limits` is deprecated.** The route still returns the partner PIX ceilings and now sends `Deprecation: true` and `Link` with `rel="successor-version"`.
* **The canonical read is `GET /v1/accounts/{accountId}/limits/available` (Get limits).** The four windows, with used and remaining, for PIX, TED, boleto, and internal transfers.

## v2.86.0 — GET /pix/limits deprecated

* **`GET /v1/accounts/{accountId}/pix/limits` is deprecated.** The route still returns the partner PIX ceilings and now sends `Deprecation: true` and `Link` with `rel="successor-version"`.
* **The canonical read is `GET /v1/accounts/{accountId}/limits/available` (Get limits).** The four windows, with used and remaining, for PIX, TED, boleto, and internal transfers.

## v2.86.0 — GET /pix/limits deprecated

* **`GET /v1/accounts/{accountId}/pix/limits` is deprecated.** The route still returns the partner PIX ceilings and now sends `Deprecation: true` and `Link` with `rel="successor-version"`.
* **The canonical read is `GET /v1/accounts/{accountId}/limits/available` (Get limits).** The four windows, with used and remaining, for PIX, TED, boleto, and internal transfers.

## v2.84.0 — Standalone identity verification

* New `POST/GET /v1/identity-verifications` surface to prove control of a CPF before `password_reset`, `second_factor_reset`, `high_value_transaction`, or `sensitive_action`, independently of onboarding or a bank account. Creation returns `verificationLink` and starts at `PENDING`; terminal states are `APPROVED`, `FAILED`, and `EXPIRED`.
* The API requires a **master M2M** credential, `X-Tenant-Id`, the `identity_verification.manage` scope, the tenant feature, and an exactly registered `callbackUri`. `displayMessage` is optional plain text up to 240 characters; link lifetime defaults to 30 minutes (maximum 60).
* Approvals are single-use through `POST /v1/identity-verifications/{id}/consume`: `purpose` and `referenceId` must match creation. An exact retry is idempotent; a competing or different binding returns `409`. The consumption window defaults to 10 minutes (maximum 60).
* Fixed quota of **10 `201` creations per tenant per BRT calendar month**. Every `201` counts and is never refunded, including later failure or expiry. A closed quota returns HTTP `429` with `identity_verification_monthly_limit_exceeded`; `rate_limited` remains a separate traffic control.
* The `identity.verification.completed` event, signed in `X-Signature`, reports `APPROVED`, `FAILED`, and `EXPIRED`. Evidence is available from `GET /v1/identity-verifications/{id}/artifacts`, protected by the dedicated `kyc.read` scope.

## v2.84.0 — Standalone identity verification

* New `POST/GET /v1/identity-verifications` surface to prove control of a CPF before `password_reset`, `second_factor_reset`, `high_value_transaction`, or `sensitive_action`, independently of onboarding or a bank account. Creation returns `verificationLink` and starts at `PENDING`; terminal states are `APPROVED`, `FAILED`, and `EXPIRED`.
* The API requires a **master M2M** credential, `X-Tenant-Id`, the `identity_verification.manage` scope, the tenant feature, and an exactly registered `callbackUri`. `displayMessage` is optional plain text up to 240 characters; link lifetime defaults to 30 minutes (maximum 60).
* Approvals are single-use through `POST /v1/identity-verifications/{id}/consume`: `purpose` and `referenceId` must match creation. An exact retry is idempotent; a competing or different binding returns `409`. The consumption window defaults to 10 minutes (maximum 60).
* Fixed quota of **10 `201` creations per tenant per BRT calendar month**. Every `201` counts and is never refunded, including later failure or expiry. A closed quota returns HTTP `429` with `identity_verification_monthly_limit_exceeded`; `rate_limited` remains a separate traffic control.
* The `identity.verification.completed` event, signed in `X-Signature`, reports `APPROVED`, `FAILED`, and `EXPIRED`. Evidence is available from `GET /v1/identity-verifications/{id}/artifacts`, protected by the dedicated `kyc.read` scope.

## v2.81.0 — PIX out amount leaves policy

* **`pixOut.maxAmount` and `pixOut.nightMaxAmount` no longer apply.** Stored JSON is kept and ignored. Those rules no longer appear on `policy.violation`.
* An amount refusal for PIX out, TED, boleto, or an internal transfer is **422** `limit_exceeded_transaction`. Remaining amount comes from `GET /v1/accounts/{accountId}/limits/available`.
* Each window on that read gains `source`: `account`, `tenant_default`, or `global_default`. An account cell without its own ceiling inherits the tenant default, then the global default. With neither, the cell stays open.
* Internal transfers use the local ledger when an effective ceiling exists. The legacy read is only used when the account has no `internal_out` ceiling.
* `pixIn.maxAmount`, `qrCode.minAmount`/`maxAmount`, and `refund.maxAmount` are unchanged.

## v2.81.0 — PIX out amount leaves policy

* **`pixOut.maxAmount` and `pixOut.nightMaxAmount` no longer apply.** Stored JSON is kept and ignored. Those rules no longer appear on `policy.violation`.
* An amount refusal for PIX out, TED, boleto, or an internal transfer is **422** `limit_exceeded_transaction`. Remaining amount comes from `GET /v1/accounts/{accountId}/limits/available`.
* Each window on that read gains `source`: `account`, `tenant_default`, or `global_default`. An account cell without its own ceiling inherits the tenant default, then the global default. With neither, the cell stays open.
* Internal transfers use the local ledger when an effective ceiling exists. The legacy read is only used when the account has no `internal_out` ceiling.
* `pixIn.maxAmount`, `qrCode.minAmount`/`maxAmount`, and `refund.maxAmount` are unchanged.

## v2.81.0 — PIX out amount leaves policy

* **`pixOut.maxAmount` and `pixOut.nightMaxAmount` no longer apply.** Stored JSON is kept and ignored. Those rules no longer appear on `policy.violation`.
* An amount refusal for PIX out, TED, boleto, or an internal transfer is **422** `limit_exceeded_transaction`. Remaining amount comes from `GET /v1/accounts/{accountId}/limits/available`.
* Each window on that read gains `source`: `account`, `tenant_default`, or `global_default`. An account cell without its own ceiling inherits the tenant default, then the global default. With neither, the cell stays open.
* Internal transfers use the local ledger when an effective ceiling exists. The legacy read is only used when the account has no `internal_out` ceiling.
* `pixIn.maxAmount`, `qrCode.minAmount`/`maxAmount`, and `refund.maxAmount` are unchanged.

## v2.79.1 — Webhook for refunds you start

* `pix.refund.completed` and `pix.refund.failed` are delivered again when the refund starts from `POST /pix/out/refund`.
* Payload and event IDs are unchanged. Partner redeliveries stay idempotent.

## v2.79.1 — Webhook for refunds you start

* `pix.refund.completed` and `pix.refund.failed` are delivered again when the refund starts from `POST /pix/out/refund`.
* Payload and event IDs are unchanged. Partner redeliveries stay idempotent.

## v2.79.1 — Webhook for refunds you start

* `pix.refund.completed` and `pix.refund.failed` are delivered again when the refund starts from `POST /pix/out/refund`.
* Payload and event IDs are unchanged. Partner redeliveries stay idempotent.

## Docs — webhook X-Signature is hex

Deliveries with `authType: HMAC` sign the raw body as **lowercase hex**
(`hex(HMAC_SHA256(secret, raw_body))`, 64 characters). Public docs used
to say Base64; production encoding is unchanged — only the text is.

## Docs — webhook X-Signature is hex

Deliveries with `authType: HMAC` sign the raw body as **lowercase hex**
(`hex(HMAC_SHA256(secret, raw_body))`, 64 characters). Public docs used
to say Base64; production encoding is unchanged — only the text is.

## Docs — webhook X-Signature is hex

Deliveries with `authType: HMAC` sign the raw body as **lowercase hex**
(`hex(HMAC_SHA256(secret, raw_body))`, 64 characters). Public docs used
to say Base64; production encoding is unchanged — only the text is.

## v2.75.2 — Account number on the tenant account list

* **`GET /v1/backoffice/tenants/{tenantId}/accounts`** now returns `accountNumber` on each item. It is the local override (`accounts.account_number`); when none is stored the field is `null`. IB and the backoffice no longer need a `GET /bank-account` per row.

## v2.75.2 — Account number on the tenant account list

* **`GET /v1/backoffice/tenants/{tenantId}/accounts`** now returns `accountNumber` on each item. It is the local override (`accounts.account_number`); when none is stored the field is `null`. IB and the backoffice no longer need a `GET /bank-account` per row.

## v2.75.2 — Account number on the tenant account list

* **`GET /v1/backoffice/tenants/{tenantId}/accounts`** now returns `accountNumber` on each item. It is the local override (`accounts.account_number`); when none is stored the field is `null`. IB and the backoffice no longer need a `GET /bank-account` per row.

_Showing the 20 most recent of 167 entries. Append `/llms.txt` to the changelog URL for the complete index._