For AI agents: a documentation index is available at the root level at /llms.txt. Append /llms.txt to any URL for a page-level index, or .md for the markdown version of any page.
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.
POST /v1/accounts/{accountId}/pix/keys with email or phone no longer returns 422. The facade sends an OTP (email or SMS) and responds 202pending_verification with challengeId and a masked destination. The partner is called only after the code is confirmed.
POST /v1/accounts/{accountId}/pix/keys/verify confirms the code and registers the key (201). Errors: code_invalid, code_expired, challenge_locked, challenge_not_found.
POST /v1/accounts/{accountId}/pix/keys/verify/resend resends (60s cooldown, 3 sends max). A delivery failure returns 503otp_send_failed and the challenge is not usable.
CPF, CNPJ and random keys still return 201 immediately.
GET /v1/accounts/{accountId}/statement/advanced gains order=desc for accounts with thousands of entries a day that only want the most recent ones: the scan starts from the end and stops once it crosses occurredAfter. No cursor in this mode (400 invalid_cursor); continuation is by time, nextOccurredBefore → occurredBefore, inclusive bound (deduplicate by id).
New occurredAfter / occurredBefore filters (RFC 3339 with offset, inclusive) in either order. They only shorten the scan when they are the boundary in the scan direction; otherwise they are just filters.
order in the response now echoes asc or desc. Behaviour without order is unchanged.
New delegated credential: one credential per account, signed. A credential holding the credentials.delegate scope issues child credentials bound to one account, with scopes that are always a subset of its own, and both publicKeyPem and allowedIps (1 to 20 CIDRs) required. Issuing returns status: "pending" and an activeFrom18h in the future — until then the credential answers 403credential_not_yet_active. Revoking is immediate, including during the grace period. See Authentication.
Delegated credentials call https://client.api.corpx.com and sign every request with a detached JWS (ES256 or PS256) over METHOD\nPATH?QUERY\nTIMESTAMP\nIDEMPOTENCY_KEY\nX-Content-SHA256, plus the X-Request-Timestamp (300s tolerance), X-Content-SHA256 and X-Request-Signature headers. On the old host they get 403signed_host_required. New guide: Request Signing.
POST /v1/security/signature/verify returns the canonical string we expect, the body hash and the verification result, so you can get signing right before your first transaction. Always 200, never creates anything.
Public keys and IP allowlist per credential, at GET|POST .../credentials/{clientId}/public-keys, DELETE .../public-keys/{kid} and GET|PUT .../credentials/{clientId}/ip-allowlist. Adding a key or adding an IP waits 18h (pendingUntil); retiring a key or removing an IP is immediate. For tenants that have delegated credentials the tenant IP allowlist is derived from those credentials, and the manual PUT /v1/security/ip-allowlist now answers 409ip_allowlist_derived.
Per-account webhook subscriptions.POST /v1/webhooks accepts accountId: the subscription then receives only that account’s events. The field cannot be edited afterwards, and a credential restricted to specific accounts must provide it (422account_id_required). See Per-account subscriptions.
Cashout locks configured by the account holder at GET|PUT /v1/accounts/{accountId}/security/locks: cashoutBlocked, cashoutHours and cashoutSourceIps. Tightening applies immediately; loosening waits 6 hours (pendingEffectiveAt), field by field. DELETE .../locks/pending cancels the scheduled change and POST .../locks/pending/approve brings it forward with the PIN. A blocked cashout returns 423cashout_locked, 403cashout_outside_hours or 403cashout_source_ip_not_allowed.
Per-operator transaction PIN at PUT /v1/accounts/{accountId}/security/pin, DELETE .../security/pin/{document}, POST .../security/pin/verify and GET .../security/pin/status. When the credential requires a PIN, cashout routes start requiring X-Acting-Document and X-Transaction-Pin (428pin_required). 3 wrong attempts lock for 15 minutes (429), 6 lock until reset (423). PIN is 6 to 12 digits, no repetition, sequence or birth date (422weak_pin).
GET /v1/accounts/{accountId}/shared-access lists the tenants operating the same bank account, with displayName, status, since and isCurrent. Public metadata only.
Nothing changes for existing integrations. Current credentials keep calling https://tenant.api.corpx.com with no signature; accounts with no lock and no PIN behave as before; webhook subscriptions without accountId keep receiving every account’s events.
Two sections on the site. Navbar BaaS (tenant.api.corpx.com) and Internet banking (client.api.corpx.com). Home no longer drops you on the tenant Quick Start.
llms.txt / llms-full.txt route the two audiences. Do not assume a single base URL. Filter the OpenAPI by x-audience (baas, ib, or both). Each summary carries the prefix [BaaS], [IB] or [BaaS · IB].
The API contract does not change. Paths, PIN and locks stay those of 2.74.0.
GET /v1/accounts/{accountId}/limits/available is new. It returns the four MT windows (singleTransfer, daytime, nighttime, monthly) with usedBrl/availableBrl for PIX, TED, boleto and internal transfers. GET /v1/accounts/{accountId}/pix/limits does not change: it is still the partner ceiling list, with no used field.
TED, boleto and internal only get a local ceiling after staff writes one. Without a ceiling, behavior matches today (fail-open). Internal transfers still consult MySQL (limites_cliente); if a teto exists there and the payment fits, it authorizes without a ledger hold.
Per-operator limits at GET|PUT|DELETE /v1/accounts/{accountId}/limits/operators/{document}: the owner slices the account ceiling (available = min). Tightening is immediate; loosening waits 6 hours. PIX only reserves locally when an operator ceiling exists — the partner still enforces the account PIX ceiling.
A PIX refusal with Limite restante: R$ X aligns used for the current window. There is no periodic sync and the GET does not poll the partner.
PATCH /v1/backoffice/accounts/{accountId}/limits accepts pixOut in the same shape as the other operations. Without a local ceiling, PIX stays fail-open on the ledger; the partner still enforces the account cap.
PIX Reserve evaluates min(local account, operator) when an account ceiling exists. GET /pix/limits does not change.
used is now an atomic per-window counter (account_limit_usage), not a SUM of holds. Concurrent PIX on the same account queue on the window row and cannot overshoot. Holds remain for the saga and idempotency only.
POST /v1/accreditations/{id}/documents now requires sizeBytes (the PDF’s actual size, 20 MB max). It is part of the uploadUrl signature: the PUT must send exactly that many bytes.
The POST only reserves the slot.GET keeps the kind in missingDocumentKinds and documents[].deliveryStatus stays pending_upload until the object exists in the KYC archive with size > 0 (and passes the scan when the pipeline is on). uploadedAt is only set when deliveryStatus is delivered.
kind=other is capped at 10 files per accreditation (422 too_many_files). A PDF over 20 MB returns 413 file_too_large.
Approving without the object requires an override. An empty slot returns 409 documents_incomplete; forceIncompleteDocuments + reason writes the documentsOverride* audit trail.
BYO acceptance page: if the risk check is unavailable, acceptance returns 503risk_check_unavailable. It is retryable — the holder tries again in a moment.
PIX out and boleto payments sent without Idempotency-Key are now deduplicated by content. Two identical requests (same account, amount and destination) reuse the same payment. Keep sending the header: a payment you intend to repeat still needs its own key.
biometry.evidenceId is accepted on an accreditation only after content verification. While the file is in quarantine or rejected, the POST returns 422evidence_not_approved.
Consent page: identity not yet approved or expired returns 409identity_not_approved / identity_stale and the journey stays pending — the holder recaptures via the same link.
POST /v1/accounts/{accountId}/transfers/internal/by-document returns 503beneficiary_check_unavailable when the destination cannot be confirmed. Retry or use /transfers/internal/by-bank-account.
pix.out.completed and pix.out.failed docs now describe the HTTP body we actually POST. The envelope is unchanged (id, type, occurredAt, schemaVersion, environment, tenantId, accountId, data). Inside data we always send paymentId, status, currency ("BRL"), description, originalTransactionId, initiatedAt and completedAt (RFC 3339 with fractional seconds), plus endToEnd, identifier and amount.
payer is present only when the settlement bank webhook included the origin account.payee may include bankIspb and pixKey. We do not send reconciliationId on these events.
The “webhook delivered” JSON in the portal is only the data object, not the full POST. The outbound type is pix.out.completed — not the timeline event pix_out.confirmed.
pix.in.completed, qrcode.paid / expired / cancelled, pix.refund.completed / failed and boleto.paid / failed docs now describe the payload we actually POST. Older examples invented reconciliationId, originalEndToEnd/refundEndToEnd on refunds we initiate, txid/expiredAt on QR events, and an object-shaped error on boleto.
pix.refund.completed uses the same shape as pix.out.completed. The refund E2E is endToEnd; the original transaction is originalTransactionId. originalEndToEnd / refundEndToEnd exist only on pix.refund.received.
The portal “webhook delivered” JSON is still only data, not the full POST.
POST /v1/accounts/{accountId}/pix/keys rejects keyTypeemail and phone. The response is 422key_type_temporarily_unavailable. CPF, CNPJ, and random (random) keys can still be registered.
Listing and deleting those key types is unchanged. Existing email or phone keys remain visible and removable. PIX out to an email or phone key is also unchanged.
POST /v1/accreditations/consent/{cst} without a session cookie returns 403 session_invalid and does not record a decision. The journey stays in pending_consent.
POST /v1/accreditations/consent/{cst}/start returns 409 when the journey is not pending or a capture is already in progress.
consent_facial_failed is only an identity-verification failure. Risk or device refusal is still castle_deny. An explicit holder refusal is still consent_declined.
GET /v1/accounts/{accountId}/transfers/internal/lookup/{document} now returns maskedName and the same value in holderName. The first name is kept in full; remaining tokens become first letter + ***. holderDocument is fully masked (***.***.***-** / CNPJ equivalent) — no digits in the body.
branch, accountNumber, and accountStatus stay in the JSON.POST by-document is unchanged.
POST /v1/accounts/{accountId}/exports now accepts format: "xlsx". The Excel file uses the same columns as the CSV (including pixKey). If one sheet fills, the rest continues on Statement_2, Statement_3, …
Exports no longer truncate the statement. PDF no longer stops at 10,000 rows; CSV no longer stops at 2 million. PDF still only clamps the date window (from 21/05/2026 up to 24h ago).
An internal transfer to the operational fee accounts now shows as TARIFA on the statement, the entry detail, and CSV/PDF export, with the counterparty CNPJ masked.
When the amount comes back from those accounts, the description is ESTORNO DE TARIFA.
A commission payout (description or identifier containing “comissão”) shows as REPASSE DE COMISSÃO on credit and ESTORNO DE REPASSE DE COMISSÃO on debit. It does not become a fee.* event.
The fee.charged and fee.refunded webhooks use the same TARIFA and ESTORNO DE TARIFA descriptions.
qrcode.paid for a dynamic QR now includes endToEnd, payer, and receivedAt. On some payments those fields went out empty even though the credit had already landed.
pix.in.completed is now sent with those same payments. The documented pair (pix.in.completed + qrcode.paid) no longer drops the credit event.
CSV and PDF statement exports now include pixKey, the same field as on each statement item: on a credit, the key of this account that received the money; on a debit, the destination key. In the CSV the column is appended at the end, so existing columns stay in place.