Skip to navigation

Batch PIX guide

Pay dozens or thousands of PIX transfers from a CSV or JSON, with a pre-flight review and an explicit acknowledgement before any money moves.

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.

Batch vs. single PIX

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

INVALID items acknowledged: true GET template POST batchesDRAFT POST items/csvPUT items POST reviewREVIEWING → REVIEWED GET items/export?status=invalidfix and resend POST dispatchQUEUED → PROCESSING 1 PixOut per itempix.out.completed / failed COMPLETED | PARTIAL_FAILED | FAILEDpix.batch.completed POST receipts (ZIP)GET items/export?status=failed

Three design decisions apply to the whole surface:

  • API only (M2M). The routes require a credential with the pix_out.create scope (or legacy api2/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_batch feature for the tenant and sets pixBatch.enabled = true in the account policy. Without the first the API answers 403 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 REVIEWED batch, zero invalid items, enough balance and acknowledged: true in the body. The review summary exists to be shown to whoever approves.

Prerequisites

ItemWhere
M2M credential with the pix_out.create scope, restricted to the paying accountsAuthentication
pix_batch feature on the tenant and pixBatch.enabled in the account policy (enabled by CorpX)Policies
Webhook subscription for pix.batch.completed and, for per-row detail, pix.out.completed / pix.out.failedWebhooks
If the account uses locks or a transaction PIN, the cash-out headers on dispatchAccount security

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.

1

Download the template

curl "$BASE/pix/batches/template" -o pix-lote-modelo.csv
2

Create the batch

curl -X POST "$BASE/pix/batches" \
-H "Idempotency-Key: payroll-2026-09" \
-H "Content-Type: application/json" \
-d '{"name": "September payroll"}'
# 201 → {"batchId": "pxb_…", "status": "DRAFT", …}
3

Upload the rows

curl -X POST "$BASE/pix/batches/$BATCH/items/csv" \
-H "Content-Type: text/csv" \
--data-binary @payroll-september.csv
# 200 with the batch and its items; 400 with errors[] if any row is wrong (nothing is saved)
4

Review

curl -X POST "$BASE/pix/batches/$BATCH/review" # 202, status REVIEWING
curl "$BASE/pix/batches/$BATCH" # repeat until status REVIEWED; read "review"
5

Approve and dispatch

curl -X POST "$BASE/pix/batches/$BATCH/dispatch" \
-H "Content-Type: application/json" \
-d '{"acknowledged": true}'
# 202, status QUEUED. Wait for the pix.batch.completed webhook.

Routes

All under /v1/accounts/{accountId}/pix/batches. The Scope column is what the credential needs; read follows, pix_out.create operates.

Method and routeScopeWhat it does
GET /templatereadDownloads pix-lote-modelo.csv with the columns and two example rows.
POST /pix_out.createCreates a DRAFT batch. Idempotency-Key required.
GET /readLists the account’s batches (status, page, pageSize).
GET /{batchId}readBatch, review, statistics and paginated items (status, reviewStatus, page, pageSize).
PUT /{batchId}/itemspix_out.createAdds 1 to 50 items as JSON.
POST /{batchId}/items/csvpix_out.createAdds items from a CSV (raw body, up to 5 MiB).
DELETE /{batchId}/items/{itemId}pix_out.createRemoves an item.
POST /{batchId}/reviewpix_out.createStarts the asynchronous review.
POST /{batchId}/dispatchpix_out.createDispatches the payments. Requires acknowledged: true.
GET /{batchId}/items/exportreadCorrection CSV (status=failed default, invalid, completed, all; separator=comma).
GET /{batchId}/items/{itemId}/receiptreadPDF receipt of a COMPLETED item.
POST /{batchId}/receiptspix_out.create or exports.createJob that builds the ZIP with every receipt.

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:

identifier;amount;description;pixKeyType;pixKey;receiverName;receiverDocument;bankIspb;bankCode;branch;accountNumber;accountType
folha-set-001;1436.85;Pagamento setembro;CPF;12345678909;;;;;;;
folha-set-002;2500.00;Fornecedor;;;EMPRESA EXEMPLO LTDA;12345678000195;60701190;341;0001;123456;CHECKING

Each row is one PIX and fills one of the two receiver blocks:

ColumnRule
identifierRequired. Your business key, up to 38 characters, unique within the batch and among the account’s live payments (same rule as the PIX out identifier). Becomes the payment’s identifier in the statement.
amountRequired and positive. Accepts 1234.56, 1.234,56 or R$ 1.234,56.
descriptionOptional, up to 140 characters. Travels with the PIX as its description.
pixKeyType, pixKeyKey mode. pixKey selects the mode; pixKeyType (CPF, CNPJ, EMAIL, PHONE, EVP) is optional and detected from the format. Receiver name, document and bank are resolved in DICT during review.
receiverName, receiverDocument, bankIspb, bankCode, branch, accountNumber, accountTypeBank account mode. Name, CPF/CNPJ, ISPB or COMPE code, branch, account with check digit and type (CHECKING, SAVINGS, PAYMENT, SALARY; empty = CHECKING).
Parser rules that save rework
  • 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 errorCode and errorMessage columns of the correction file are ignored on input: the exported file can be uploaded back as is.
  • A row with pixKey and bank account data at the same time is rejected — pick one mode per row.

2. Create the batch

curl -X POST "https://tenant.api.corpx.com/v1/accounts/{accountId}/pix/batches" \
-H "Authorization: Bearer $TOKEN" -H "X-Tenant-Id: tenant-yourcompany" \
-H "Idempotency-Key: payroll-2026-09" \
-H "Content-Type: application/json" \
-d '{"name": "September payroll"}'
  • Idempotency-Key (up to 128 characters) is required; repeating the same key on the same account returns the existing batch with 200 instead 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.
  • name is optional (up to 120 characters) and shows up in listings and in the receipts’ resumo.csv.

201 response:

{
"batchId": "pxb_3f9c2a1b7d4e5f60718293a4b5c6d7e8",
"name": "September payroll",
"status": "DRAFT",
"totalItems": 0,
"totalAmount": "0.00",
"completedItems": 0,
"failedItems": 0,
"limits": { "maxItems": 50, "source": "default" },
"statistics": {
"total": 0, "pending": 0, "processing": 0, "completed": 0, "failed": 0,
"reviewedOk": 0, "invalid": 0,
"totalAmount": "0.00", "validAmount": "0.00", "completedAmount": "0.00", "failedAmount": "0.00",
"progressPercentage": 0
},
"items": [],
"page": 1, "pageSize": 50, "totalPages": 0, "hasNext": false,
"createdAt": "2026-09-30T13:00:00Z",
"updatedAt": "2026-09-30T13:00:00Z"
}

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.

curl -X POST ".../pix/batches/{batchId}/items/csv" \
-H "Authorization: Bearer $TOKEN" -H "X-Tenant-Id: tenant-yourcompany" \
-H "Content-Type: text/csv" \
--data-binary @payroll-september.csv

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.

{
"errorCode": "pix_batch_csv_invalid",
"message": "one or more rows are invalid; nothing was saved",
"errors": [
{ "line": 3, "field": "amount", "message": "must be a positive amount" },
{ "line": 7, "field": "pixKey", "message": "use either pixKey or the bank account columns, not both" },
{ "line": 9, "field": "identifier", "message": "duplicated identifier (first seen on line 4)" }
],
"docs": "https://docs.api.corpx.com/baas/guias/referencia/erros#pix_batch_csv_invalid"
}

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 identifier with the same content is ignored (no duplicate, no error). Repeating it with different content is 409 pix_batch_item_conflict and the whole call is refused — fix the file instead of relying on overwrites.
  • Removing. DELETE .../items/{itemId} removes an item; the itemId (pxi_…) comes in the batch’s items[].
  • Editable states. Only DRAFT and REVIEWED accept items or removals. Any change to a REVIEWED batch sends it back to DRAFT and resets the review: you must review again before dispatching. While REVIEWING or 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 with 400 pix_batch_too_large.

4. Review

POST /v1/accounts/{accountId}/pix/batches/{batchId}/review → 202, status REVIEWING

The review is asynchronous and runs before any debit. Repeating the POST while REVIEWING just returns the current state. Per item, in this order:

CheckreviewError.errorCode
Positive amountinvalid_amount
identifier already used by a live payment on the account (including another batch)identifier_conflict
Amount above the account’s per-transaction limitlimit_exceeded_transaction
PIX key missing, inactive or malformed (DICT lookup)key_not_found, key_inactive, invalid_pix_key
DICT unavailable after 3 attemptsdict_lookup_failed

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:

{
"reviewedAt": "2026-09-30T13:09:30Z",
"totalItems": 120, "validItems": 118, "invalidItems": 2,
"totalAmount": "143685.00", "validAmount": "141200.00",
"balance": { "available": "150000.00", "sufficient": true, "checked": true },
"limits": [
{ "window": "daily_out", "enforced": true, "limit": "500000.00", "used": "12000.00", "available": "488000.00", "sufficient": true },
{ "window": "monthly", "enforced": false, "limit": "0.00", "used": "0.00", "available": "0.00", "sufficient": true }
],
"warnings": []
}
  • balance and limits are a snapshot. Balance is checked again at dispatch and every PIX goes through the per-window limits during execution. limits[].window is daily_out (6am–8pm) or nightly_out (8pm–6am) depending on the review time, plus monthly; enforced: false means the account has no ceiling configured for that window.
  • balance.checked: false means the settlement bank did not answer; the warning goes to warnings[] and does not block.
  • warnings[] does not block the acknowledgement (e.g. insufficient balance right now — funds may arrive before dispatch). INVALID items do block.
  • If the review cannot run, the batch goes back to DRAFT and review carries an error field; just call review again.

A rejected item looks like this in items[]:

{
"itemId": "pxi_9b1c…", "line": 17, "identifier": "payroll-sep-017",
"mode": "KEY", "amount": "980.00", "description": "September payroll",
"status": "PENDING", "reviewStatus": "INVALID",
"receiver": { "name": "", "documentNumber": "", "keyType": "EMAIL", "key": "former-employee@company.com", "bankCode": "", "bankIspb": "" },
"reviewError": { "errorCode": "key_not_found", "message": "chave PIX não encontrada no DICT" },
"createdAt": "2026-09-30T13:02:11Z", "updatedAt": "2026-09-30T13:09:28Z"
}

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:

GET /v1/accounts/{accountId}/pix/batches/{batchId}/items/export?status=invalid
GET /v1/accounts/{accountId}/pix/batches/{batchId}?reviewStatus=invalid

5. Dispatch

curl -X POST ".../pix/batches/{batchId}/dispatch" \
-H "Authorization: Bearer $TOKEN" -H "X-Tenant-Id: tenant-yourcompany" \
-H "X-Acting-Document: 12345678909" \
-H "X-Transaction-Pin: 123456" \
-H "Content-Type: application/json" \
-d '{"acknowledged": true}'

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:

  1. A REVIEWED batch (409 pix_batch_not_reviewed).
  2. At least one item (409 pix_batch_empty) and a total within limits.maxItems (400 pix_batch_too_large).
  3. No INVALID item and every item reviewed (409 pix_batch_has_invalid_items / 409 pix_batch_not_reviewed).
  4. Available balance greater than or equal to the batch total at dispatch time (422 pix_batch_insufficient_balance — nothing is started).
Dispatch moves money

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

statusMeaningEditable?
DRAFTReceiving items.Yes
REVIEWINGReview in progress.No
REVIEWEDReviewed; ready for acknowledgement. Any edit goes back to DRAFT.Yes
QUEUEDDispatch accepted; waiting for the processor.No
PROCESSINGItems being paid. statistics advances.No
COMPLETEDEvery item settled.No
PARTIAL_FAILEDSome settled, some failed. Download the failures export.No
FAILEDNo item settled.No

Item states

statusreviewStatusWhen
PENDINGPENDINGJust added, not reviewed yet.
PENDINGOK / INVALIDReviewed; INVALID carries reviewError.
PROCESSINGOKPixOut in flight.
COMPLETEDOKSettled: paymentId, endToEndId, transactionId, completedAt.
FAILEDOKRejected or expired: error.errorCode and error.message with the single-PIX vocabulary (insufficient_funds, limit_exceeded_daily, timeout, …).

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):

{
"batchId": "pxb_3f9c2a1b7d4e5f60718293a4b5c6d7e8",
"status": "PROCESSING",
"totalItems": 120, "totalAmount": "141200.00",
"completedItems": 87, "failedItems": 2,
"statistics": {
"total": 120, "pending": 0, "processing": 31, "completed": 87, "failed": 2,
"reviewedOk": 120, "invalid": 0,
"totalAmount": "141200.00", "validAmount": "141200.00",
"completedAmount": "102340.00", "failedAmount": "1960.00",
"progressPercentage": 74.17
},
"items": [
{
"itemId": "pxi_1a2b…", "line": 1, "identifier": "payroll-sep-001",
"mode": "KEY", "amount": "1436.85", "description": "September payroll",
"status": "COMPLETED", "reviewStatus": "OK",
"receiver": { "name": "JOAO ANTONIO DA CONCEICAO", "documentNumber": "12345678909", "keyType": "CPF", "key": "12345678909", "bankCode": "341", "bankIspb": "60701190" },
"paymentId": "pay_1f2e3d4c", "endToEndId": "E5087192120260930131200abcdef0123",
"transactionId": "9f8e7d6c-5b4a-4321-8765-43210fedcba9",
"completedAt": "2026-09-30T13:12:01Z",
"createdAt": "2026-09-30T13:02:11Z", "updatedAt": "2026-09-30T13:12:01Z"
}
],
"page": 1, "pageSize": 50, "totalPages": 3, "hasNext": true,
"reviewedAt": "2026-09-30T13:09:30Z",
"acknowledgedAt": "2026-09-30T13:10:02Z",
"dispatchedAt": "2026-09-30T13:10:02Z",
"createdAt": "2026-09-30T13:00:00Z", "updatedAt": "2026-09-30T13:12:01Z"
}

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.

{
"id": "pix-batch-pxb_3f9c2a1b7d4e5f60718293a4b5c6d7e8-completed",
"type": "pix.batch.completed",
"occurredAt": "2026-09-30T13:12:40.000Z",
"schemaVersion": "1.0",
"environment": "production",
"tenantId": "tenant-yourcompany",
"accountId": "acc_123456",
"data": {
"batchId": "pxb_3f9c2a1b7d4e5f60718293a4b5c6d7e8",
"accountId": "acc_123456",
"status": "PARTIAL_FAILED",
"statistics": {
"total": 120, "completed": 118, "failed": 2,
"totalAmount": "141200.00", "completedAmount": "139240.00", "failedAmount": "1960.00"
}
}
}

Subscribe with authType: HMAC, validate X-Signature over the raw bytes and deduplicate by id — details in Webhooks.

Webhook first, polling as a fallback

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

GET /v1/accounts/{accountId}/pix/batches/{batchId}/items/export?status=failed

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.

identifier;amount;description;pixKeyType;pixKey;receiverName;receiverDocument;bankIspb;bankCode;branch;accountNumber;accountType;errorCode;errorMessage
payroll-sep-017;980.00;September payroll;EMAIL;former-employee@company.com;;;;;;;;key_not_found;chave PIX não encontrada no DICT
payroll-sep-044;1200.00;September payroll;;;MARIA DA SILVA;98765432100;;001;1234;56789-0;CHECKING;limit_exceeded_daily;limite diário de saída excedido

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.

status=Rows included
failed (default)Failed during execution or rejected in the review.
invalidOnly the ones rejected in the review (use while the batch is REVIEWED).
completedOnly the settled ones — handy to reconcile by endToEndId.
allEvery row, with empty errorCode/errorMessage where there was no error.

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):

GET /v1/accounts/{accountId}/pix/batches/{batchId}/items/{itemId}/receipt

Whole batch — for finished batches (COMPLETED, PARTIAL_FAILED or FAILED with at least one settled item; otherwise 409 pix_batch_no_receipts):

curl -X POST ".../pix/batches/{batchId}/receipts" \
-H "Authorization: Bearer $TOKEN" -H "X-Tenant-Id: tenant-yourcompany"
{
"exportId": "exp_7c1d2e3f-…",
"accountId": "acc_123456",
"batchId": "pxb_3f9c2a1b7d4e5f60718293a4b5c6d7e8",
"type": "pix_batch_receipts",
"format": "zip",
"status": "PENDING",
"receipts": 118,
"download": "/v1/accounts/acc_123456/exports/exp_7c1d2e3f-…/download",
"createdAt": "2026-09-30T13:15:00Z"
}

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-Key per 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 send acknowledged: true. Store who approved, when, and the reviewedAt that was on screen.
  • Separate who builds from who dispatches. A read credential can follow; only the pix_out.create credential dispatches. If the account uses a transaction PIN, dispatch requires the approving operator’s PIN.
  • Treat PARTIAL_FAILED as routine, not an exception. Deleted keys and closed accounts happen in any large payroll. Download items/export?status=failed, fix, and upload a new batch; do not redo the whole batch.
  • Reconcile by identifier and endToEndId. Each item’s pix.out.completed and its row in items[] carry both; the endToEndId is the proof of payment with the Central Bank.
  • Respect the limit windows. review shows daily_out/nightly_out and monthly. A batch larger than the day’s available limit is not blocked at dispatch — the excess items fail during execution with limit_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 maxItems before the closing.

FAQ

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.

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.

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.

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.

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.

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.

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.

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

CodeHTTPWhen
feature_disabled403Tenant without the pix_batch feature.
pix_batch_account_disabled403Account without pixBatch.enabled = true in its policy.
missing_idempotency_key400POST /pix/batches without Idempotency-Key.
pix_batch_not_found / pix_batch_item_not_found404Batch or item does not exist on this account.
pix_batch_chunk_invalid / pix_batch_csv_invalid400Upload rejected; errors[] points to row and field. 413 when the CSV exceeds 5 MiB.
pix_batch_too_large400Above limits.maxItems.
pix_batch_item_conflict409identifier repeated with different content.
pix_batch_not_editable409Batch is REVIEWING or already dispatched.
pix_batch_empty409Batch has no items.
pix_batch_not_reviewed409Dispatch without a valid review.
pix_batch_has_invalid_items409Review flagged invalid items.
pix_batch_acknowledgement_required409Dispatch without acknowledged: true.
pix_batch_insufficient_balance422Available balance below the total at dispatch.
pix_batch_no_receipts / pix_batch_receipt_unavailable409Batch not finished or item not settled.
receipt_render_failed500PDF rendering failed; retry the call.
workflow_unavailable503Orchestration unavailable; retry the call.

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-Key behaves across the API.
  • Webhooks — pix.batch.completed and the per-item pix.out.* events.