Batch PIX guide
Batch PIX is for the case where you already have a spreadsheet — payroll,
supplier payouts, commissions, refunds — and want to pay everything at once
without writing a loop around POST /pix/out. You upload the rows, the API
checks keys, duplicates, balance and limits before any debit, and only
after your explicit acknowledgement does each row become a regular PIX out,
with the same limits, policies, webhooks and statement entries as
PIX Out.
Use a batch when the rows already exist together (a file, a closing) and you
want one summary to approve and one report at the end. Use POST /pix/out
when a payment is born from an isolated event and needs a synchronous
answer. Both paths produce the same PIX and the same pix.out.* webhooks.
How it works
Three design decisions apply to the whole surface:
- API only (M2M). The routes require a credential with the
pix_out.createscope (or legacyapi2/write). A human user token cannot create or dispatch a batch; the Portal and Internet Banking do not expose this surface. A read-only credential (read) can follow batches (GET), download the template and receipts, but cannot create, edit or dispatch. - Two-level enablement. CorpX turns on the
pix_batchfeature for the tenant and setspixBatch.enabled = truein the account policy. Without the first the API answers403 feature_disabled; without the second,403 pix_batch_account_disabled. Ask your account manager to enable it, listing the accounts that will pay in batches. - Nothing leaves without review and acknowledgement. Dispatch requires a
REVIEWEDbatch, zero invalid items, enough balance andacknowledged: truein the body. The review summary exists to be shown to whoever approves.
Prerequisites
Quick start
Five calls take a file from zero to paid. In the examples $BASE is
https://tenant.api.corpx.com/v1/accounts/{accountId} and the
Authorization: Bearer $TOKEN and X-Tenant-Id headers are implied.
Routes
All under /v1/accounts/{accountId}/pix/batches. The Scope column is what
the credential needs; read follows, pix_out.create operates.
The field-by-field reference is in API Reference → Batch PIX.
1. The file
GET .../pix/batches/template returns pix-lote-modelo.csv: UTF-8 with BOM
and ; as separator, which Excel in Portuguese locales opens directly. Its
content is exactly this:
Each row is one PIX and fills one of the two receiver blocks:
- The header is matched by name, regardless of order or case; columns you do not use can be left empty or omitted.
;and,are detected automatically; quoting follows the CSV standard.- The
errorCodeanderrorMessagecolumns of the correction file are ignored on input: the exported file can be uploaded back as is. - A row with
pixKeyand bank account data at the same time is rejected — pick one mode per row.
2. Create the batch
Idempotency-Key(up to 128 characters) is required; repeating the same key on the same account returns the existing batch with200instead of creating another. Use something that identifies the closing (payroll-2026-09), not a random UUID — that way a retry on your side never opens a duplicate batch.nameis optional (up to 120 characters) and shows up in listings and in the receipts’resumo.csv.
201 response:
limits.maxItems is the maximum size of this batch on this account and
limits.source says where it came from (default = 50, tenant or
account, up to 5,000). Monetary values are always decimal strings with
two places ("1436.85"), never floating-point numbers.
3. Upload the items
You may mix both methods in the same batch, across as many calls as you
need, while the batch is DRAFT or REVIEWED.
CSV
JSON
The body is the raw file (up to 5 MiB; above that, 413). The upload is
atomic: if any row is invalid the response is 400 pix_batch_csv_invalid
with the list of problems and nothing is saved.
line counts the header as line 1, so 3 is the second data row — the same
number Excel shows. A file with more rows than limits.maxItems is
400 pix_batch_too_large.
Rules common to both methods
- Per-row idempotency. Repeating an
identifierwith the same content is ignored (no duplicate, no error). Repeating it with different content is409 pix_batch_item_conflictand the whole call is refused — fix the file instead of relying on overwrites. - Removing.
DELETE .../items/{itemId}removes an item; theitemId(pxi_…) comes in the batch’sitems[]. - Editable states. Only
DRAFTandREVIEWEDaccept items or removals. Any change to aREVIEWEDbatch sends it back toDRAFTand resets the review: you must review again before dispatching. WhileREVIEWINGor after dispatch,409 pix_batch_not_editable. - Size. The batch’s item count never exceeds
limits.maxItems; the call that would cross the ceiling is refused as a whole with400 pix_batch_too_large.
4. Review
The review is asynchronous and runs before any debit. Repeating the
POST while REVIEWING just returns the current state. Per item, in this
order:
In key mode, DICT resolves the receiver’s name, document and bank, which
then appear in items[].receiver — that is what you show to the approver.
Lookups use the account’s 24 h cache and count against the DICT lookup
window like GET /pix/key/{pixKey}; read
PIX key lookups before reviewing
thousands of new keys. Bank-account items are accepted as sent; destination
account validation happens at the settlement bank during execution.
Follow with GET .../pix/batches/{batchId}. When status becomes
REVIEWED, review carries the summary:
balanceandlimitsare a snapshot. Balance is checked again at dispatch and every PIX goes through the per-window limits during execution.limits[].windowisdaily_out(6am–8pm) ornightly_out(8pm–6am) depending on the review time, plusmonthly;enforced: falsemeans the account has no ceiling configured for that window.balance.checked: falsemeans the settlement bank did not answer; the warning goes towarnings[]and does not block.warnings[]does not block the acknowledgement (e.g. insufficient balance right now — funds may arrive before dispatch).INVALIDitems do block.- If the review cannot run, the batch goes back to
DRAFTandreviewcarries anerrorfield; just callreviewagain.
A rejected item looks like this in items[]:
To fix, download only the rejected rows, adjust and upload again (the same
identifier with new content is refused — remove the item first with
DELETE, or use a new identifier), then review once more:
5. Dispatch
acknowledged: true is the statement that the review summary was read and
approved — record on your side who approved and when. Without it the API
answers 409 pix_batch_acknowledgement_required. Dispatch also requires, in
this order:
- A
REVIEWEDbatch (409 pix_batch_not_reviewed). - At least one item (
409 pix_batch_empty) and a total withinlimits.maxItems(400 pix_batch_too_large). - No
INVALIDitem and every item reviewed (409 pix_batch_has_invalid_items/409 pix_batch_not_reviewed). - Available balance greater than or equal to the batch total at dispatch
time (
422 pix_batch_insufficient_balance— nothing is started).
Dispatch is a cash-out route: the account’s outgoing locks, the transaction
PIN and the X-Acting-Document / X-Transaction-Pin / X-Acting-Ip
headers apply exactly as in POST /pix/out (see
Account security). The
headers are only needed when the account has a PIN or locks configured.
After the 202 there is no cancellation: items already in flight run
until they settle or fail.
202 response with status: QUEUED and dispatchedAt. Re-dispatching an
already dispatched batch is idempotent (200 with the current state), so a
retry after a network timeout is safe.
6. Follow up
Each item becomes its own PixOut.Workflow — the same one that serves
POST /pix/out — with the row’s identifier and idempotency
{batchId}_{itemId}. It goes through the same policies, per-window limits
and statement entry as a single PIX, and emits the same
pix.out.completed, pix.out.failed or pix.out.timeout. The batch pays
up to 5 items in parallel (CorpX setting) and only moves on when the
settlement bank answers; a slow item does not hold up the others.
Batch states
Item states
GET .../pix/batches/{batchId} returns statistics and the paginated items
(page, pageSize up to 200), filterable by status
(pending, processing, completed, failed) and reviewStatus
(pending, ok, invalid):
Closing webhook
At the end the API sends pix.batch.completed. It closes the batch and
does not replace the per-item events: to reconcile row by row use
pix.out.completed / pix.out.failed (the event’s identifier is your
row’s) or the item list.
Subscribe with authType: HMAC, validate X-Signature over the raw bytes
and deduplicate by id — details in Webhooks.
Prefer reacting to pix.batch.completed. If you need polling (a progress
bar, for instance), call GET .../pix/batches/{batchId} every 10–30 s and
read only status and statistics; do not list the items on every cycle.
7. Fix and resend
Returns, in the same format as the template, only the rows that failed
during execution or were marked invalid in the review, with two extra
columns at the end: errorCode and errorMessage. The X-Total-Rows header
tells how many rows came back.
Fix it and upload the file as is into a new batch — the parser
ignores the error columns. An identifier that failed can be reused; one
that settled cannot (the review would flag it as identifier_conflict),
which protects you from paying the same row twice.
separator=comma swaps ; for , for English-locale tools.
8. Receipts
Receipts are CorpX-standard PDFs (tenant logo when configured, payer,
receiver with masked document, amount, description, identifier,
endToEndId, settlement time in Brasília time).
One item — direct application/pdf response, only for COMPLETED items
(409 pix_batch_receipt_unavailable):
Whole batch — for finished batches (COMPLETED, PARTIAL_FAILED or
FAILED with at least one settled item; otherwise 409 pix_batch_no_receipts):
The ZIP is built in the background. Call the route in download: while the
job runs it answers 409 not_ready; when done, it returns a presigned
downloadUrl (valid for expiresIn seconds) and checksumMd5. The archive
holds one PDF per settled item and a resumo.csv with the columns linha,
identificador, destinatario, valor, endToEnd, data, arquivo and
erro (filled only when a PDF could not be rendered).
PDFs follow the pattern
{YYYY-MM-DD}_{HHMM}_PIX_{amount}_{receiver}_{identifier}_{endToEnd}.pdf
— for example
2026-09-30_1312_PIX_1436-85_JOAO-ANTONIO-DA-CONCEICAO_payroll-sep-001_E5087192120260930131200abcdef0123.pdf
— without accents and with a -2, -3… suffix on collision.
Best practices
- One
Idempotency-Keyper closing.payroll-2026-09,suppliers-2026-09-30… A retry of the create call never opens a second batch, and you can find the batch again from your own calendar. - Deterministic, per-row unique
identifier. Build it from your data ({payroll}-{employeeId}), never from an in-memory counter. It is what ties the PIX to your system in the statement, the webhooks and the correction file — and what prevents paying the same row twice. - Always review before asking for approval. Show
review(totals, balance, limits, invalid rows) to the approver and only then sendacknowledged: true. Store who approved, when, and thereviewedAtthat was on screen. - Separate who builds from who dispatches. A
readcredential can follow; only thepix_out.createcredential dispatches. If the account uses a transaction PIN, dispatch requires the approving operator’s PIN. - Treat
PARTIAL_FAILEDas routine, not an exception. Deleted keys and closed accounts happen in any large payroll. Downloaditems/export?status=failed, fix, and upload a new batch; do not redo the whole batch. - Reconcile by
identifierandendToEndId. Each item’spix.out.completedand its row initems[]carry both; theendToEndIdis the proof of payment with the Central Bank. - Respect the limit windows.
reviewshowsdaily_out/nightly_outandmonthly. A batch larger than the day’s available limit is not blocked at dispatch — the excess items fail during execution withlimit_exceeded_*. Split into per-day batches or ask for a limit adjustment. - Large batches. For thousands of rows, upload by CSV (one call) instead of dozens of JSON chunks, and ask CorpX for the right
maxItemsbefore the closing.
FAQ
Can I cancel a batch after dispatch?
No. After the 202 the items are already executing at the settlement bank.
What you control is the moment of acknowledgement: until dispatch the
batch is just a draft and can be edited or simply abandoned in
DRAFT/REVIEWED.
What happens if I edit a REVIEWED batch?
It goes back to DRAFT and every item returns to reviewStatus: PENDING.
You must call review again. This applies to adding, removing or resending
an item — the review always reflects the current content.
Balance was enough at review time but dispatch returned 422. Why?
review.balance is a snapshot; another payment may have left between the
review and the acknowledgement. Dispatch checks the balance again and refuses
without starting anything if it is below the batch total. Top up the
account or remove rows and review again.
Why did an item pass review and fail during execution?
The review validates what can be validated without moving money: key,
duplicates, amount, per-transaction limit, balance and windows in
aggregate. Execution adds the settlement bank’s and destination bank’s rules
(closed account, daily limit consumed by other payments, account policy).
The error code is the same as for a single PIX and comes in
error.errorCode.
Can I reuse an identifier?
An item identifier that failed can be used in a new batch. One that
settled cannot: the review flags identifier_conflict, because the
account has a live payment with that identifier. That is the duplicate
payment protection — do not work around it with random suffixes.
Do batch items show up in the statement?
Yes, as individual PIX out entries, each with its row’s identifier. There
is no aggregated batch entry; GET .../pix/batches/{batchId} and the
receipts’ resumo.csv are the consolidated view.
Does the review consume DICT quota?
Yes, one lookup per distinct key not present in the account’s 24 h cache,
counted in the same window as GET /pix/key/{pixKey}. Keys repeated within
the batch and keys looked up recently do not trigger a new lookup. Bank
account rows involve no DICT lookup.
How do I test before production?
Create a small batch, upload two or three rows of token amounts to accounts
of your own, review and dispatch — the flow and webhooks are identical to a
batch of thousands. To validate only the file without paying anything,
stop after review: the parser and the review already surface every
format, key and duplicate problem.
Errors
The full list, with anchors, is in Error handling.
See also
- PIX Out — the single payment every batch row executes.
- PIX key lookups — DICT quota and cache used by the review.
- Account security — locks, transaction PIN and cash-out headers.
- Idempotency — how
Idempotency-Keybehaves across the API. - Webhooks —
pix.batch.completedand the per-itempix.out.*events.