> For clean Markdown of any page, append .md to the page URL. > For a complete documentation index, see https://docs.api.corpx.com/baas/guias/pagar/pix-em-lote/llms.txt. > For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.api.corpx.com/_mcp/server. # Guia de PIX em lote O **PIX em lote** resolve o caso em que você tem uma planilha — folha de pagamento, repasse a fornecedores, comissões, reembolsos — e quer pagar tudo de uma vez sem escrever um loop de `POST /pix/out`. Você sobe as linhas, a API confere chaves, duplicidades, saldo e limites **antes de qualquer débito**, e só depois do seu aceite explícito cada linha vira um PIX out comum, com os mesmos limites, políticas, webhooks e lançamentos no extrato de [PIX Out](/baas/guias/pagar/pix-out). > **Quando usar lote e quando usar PIX avulso** > > Use o lote quando as linhas já existem juntas (um arquivo, um fechamento) e > você quer um resumo para aprovar e um relatório único no fim. Use > `POST /pix/out` quando o pagamento nasce de um evento isolado e precisa de > resposta síncrona. Os dois caminhos geram o mesmo PIX e os mesmos webhooks > `pix.out.*`. ## Como funciona ```mermaid flowchart LR T["GET template"] --> C["POST batches
DRAFT"] C --> I["POST items/csv
PUT items"] I --> R["POST review
REVIEWING → REVIEWED"] R -->|"itens INVALID"| X["GET items/export?status=invalid
corrigir e reenviar"] X --> I R -->|"acknowledged: true"| D["POST dispatch
QUEUED → PROCESSING"] D --> P["1 PixOut por item
pix.out.completed / failed"] P --> F["COMPLETED | PARTIAL_FAILED | FAILED
pix.batch.completed"] F --> Z["POST receipts (ZIP)
GET items/export?status=failed"] ``` Três decisões de desenho que valem para toda a superfície: * **Somente API (M2M).** As rotas exigem credencial com escopo `pix_out.create` (ou `api2/write` legado). Token de usuário humano não cria nem dispara lote; o Portal e o Internet Banking não expõem essa superfície. Uma credencial só-leitura (`read`) consegue **acompanhar** lotes (`GET`), baixar o modelo e comprovantes, mas não cria, edita nem dispara. * **Habilitação em dois níveis.** A CorpX liga a feature `pix_batch` no tenant **e** a seção `pixBatch.enabled = true` na policy da conta. Sem a primeira a API responde `403 feature_disabled`; sem a segunda, `403 pix_batch_account_disabled`. Peça a ativação ao seu gerente de conta informando as contas que vão operar em lote. * **Nada sai sem conferência e aceite.** O dispatch exige lote `REVIEWED`, zero itens inválidos, saldo suficiente e `acknowledged: true` no corpo. O resumo da conferência existe para ser mostrado a quem aprova. ### Pré-requisitos | Item | Onde ver | | ------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------- | | Credencial M2M com escopo `pix_out.create` restrita às contas que vão pagar | [Autenticação](/baas/guias/autenticacao/oauth2) | | Feature `pix_batch` no tenant e `pixBatch.enabled` na policy da conta (ativação CorpX) | [Políticas](/baas/guias/autenticacao/politicas) | | Assinatura de webhook para `pix.batch.completed` e, se quiser granularidade, `pix.out.completed` / `pix.out.failed` | [Webhooks](/baas/guias/conta/webhooks) | | Se a conta usa travas ou PIN transacional, os cabeçalhos de cash out no dispatch | [Segurança da conta](/baas/guias/autenticacao/seguranca-da-conta) | ## Início rápido Cinco chamadas levam um arquivo do zero ao pagamento. Nos exemplos, `$BASE` é `https://tenant.api.corpx.com/v1/accounts/{accountId}` e os cabeçalhos `Authorization: Bearer $TOKEN` e `X-Tenant-Id` estão implícitos. #### Baixe o modelo ```bash curl "$BASE/pix/batches/template" -o pix-lote-modelo.csv ``` #### Crie o lote ```bash curl -X POST "$BASE/pix/batches" \ -H "Idempotency-Key: folha-2026-09" \ -H "Content-Type: application/json" \ -d '{"name": "Folha de setembro"}' # 201 → {"batchId": "pxb_…", "status": "DRAFT", …} ``` #### Suba as linhas ```bash curl -X POST "$BASE/pix/batches/$BATCH/items/csv" \ -H "Content-Type: text/csv" \ --data-binary @folha-setembro.csv # 200 com o lote e os itens; 400 com errors[] se alguma linha estiver errada (nada é salvo) ``` #### Confira ```bash curl -X POST "$BASE/pix/batches/$BATCH/review" # 202, status REVIEWING curl "$BASE/pix/batches/$BATCH" # repita até status REVIEWED; leia "review" ``` #### Aprove e dispare ```bash curl -X POST "$BASE/pix/batches/$BATCH/dispatch" \ -H "Content-Type: application/json" \ -d '{"acknowledged": true}' # 202, status QUEUED. Aguarde o webhook pix.batch.completed. ``` ## Rotas Todas sob `/v1/accounts/{accountId}/pix/batches`. A coluna **Escopo** indica o que a credencial precisa ter; `read` acompanha, `pix_out.create` opera. | Método e rota | Escopo | O que faz | | --------------------------------------- | ------------------------------------ | ---------------------------------------------------------------------------------------------- | | `GET /template` | `read` | Baixa `pix-lote-modelo.csv` com as colunas e duas linhas de exemplo. | | `POST /` | `pix_out.create` | Cria um lote `DRAFT`. `Idempotency-Key` obrigatório. | | `GET /` | `read` | Lista lotes da conta (`status`, `page`, `pageSize`). | | `GET /{batchId}` | `read` | Lote, `review`, `statistics` e itens paginados (`status`, `reviewStatus`, `page`, `pageSize`). | | `PUT /{batchId}/items` | `pix_out.create` | Adiciona de 1 a 50 itens em JSON. | | `POST /{batchId}/items/csv` | `pix_out.create` | Adiciona itens a partir de um CSV (corpo cru, até 5 MiB). | | `DELETE /{batchId}/items/{itemId}` | `pix_out.create` | Remove um item. | | `POST /{batchId}/review` | `pix_out.create` | Inicia a conferência assíncrona. | | `POST /{batchId}/dispatch` | `pix_out.create` | Dispara os pagamentos. Exige `acknowledged: true`. | | `GET /{batchId}/items/export` | `read` | CSV de correção (`status=failed` padrão, `invalid`, `completed`, `all`; `separator=comma`). | | `GET /{batchId}/items/{itemId}/receipt` | `read` | PDF do comprovante de um item `COMPLETED`. | | `POST /{batchId}/receipts` | `pix_out.create` ou `exports.create` | Job que gera o ZIP com todos os comprovantes. | A referência campo a campo está em [Referência da API → PIX em lote](/baas/referencia). ## 1. O arquivo `GET .../pix/batches/template` devolve `pix-lote-modelo.csv`: UTF-8 com BOM e separador `;`, que o Excel em português abre direto. O conteúdo é exatamente este: ```csv 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 ``` Cada linha é **um** PIX e preenche **um** dos dois blocos de destinatário: | Coluna | Regra | | ---------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | `identifier` | Obrigatório. Sua chave de negócio, até 38 caracteres, única no lote **e** entre os pagamentos vivos da conta (mesma regra do `identifier` do PIX out). Vira o `identifier` do pagamento e do extrato. | | `amount` | Obrigatório e positivo. Aceita `1234.56`, `1.234,56` ou `R$ 1.234,56`. | | `description` | Opcional, até 140 caracteres. Vai no PIX como descrição. | | `pixKeyType`, `pixKey` | **Modo chave.** `pixKey` liga o modo; `pixKeyType` (`CPF`, `CNPJ`, `EMAIL`, `PHONE`, `EVP`) é opcional e detectado pelo formato. Nome, documento e banco do recebedor são resolvidos no DICT na conferência. | | `receiverName`, `receiverDocument`, `bankIspb`, `bankCode`, `branch`, `accountNumber`, `accountType` | **Modo dados bancários.** Nome, CPF/CNPJ, ISPB **ou** código COMPE, agência, conta com dígito e tipo (`CHECKING`, `SAVINGS`, `PAYMENT`, `SALARY`; vazio = `CHECKING`). | > **Regras do parser que evitam retrabalho** > > * O cabeçalho é casado por **nome**, sem importar ordem ou caixa; colunas que > você não usa podem ficar vazias ou ser omitidas. > * `;` e `,` são detectados automaticamente; aspas seguem o padrão CSV. > * As colunas `errorCode` e `errorMessage` do arquivo de correção são > ignoradas na entrada: o arquivo exportado sobe de volta como está. > * Linha com `pixKey` **e** dados bancários ao mesmo tempo é rejeitada — > escolha um modo por linha. ## 2. Criar o lote ```bash curl -X POST "https://tenant.api.corpx.com/v1/accounts/{accountId}/pix/batches" \ -H "Authorization: Bearer $TOKEN" -H "X-Tenant-Id: tenant-suaempresa" \ -H "Idempotency-Key: folha-2026-09" \ -H "Content-Type: application/json" \ -d '{"name": "Folha de setembro"}' ``` * `Idempotency-Key` (até 128 caracteres) é **obrigatório**; repetir a mesma chave na mesma conta devolve o lote existente com `200` em vez de criar outro. Use algo que identifique o fechamento (`folha-2026-09`), não um UUID aleatório — assim um retry do seu lado nunca abre lote duplicado. * `name` é opcional (até 120 caracteres) e aparece nas listagens e no `resumo.csv` dos comprovantes. Resposta `201`: ```json { "batchId": "pxb_3f9c2a1b7d4e5f60718293a4b5c6d7e8", "name": "Folha de setembro", "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` é o tamanho máximo deste lote **nesta conta** e `limits.source` diz de onde veio (`default` = 50, `tenant` ou `account`, até 5.000). Valores monetários são sempre **strings decimais** com duas casas (`"1436.85"`), nunca números de ponto flutuante. ## 3. Enviar os itens Você pode misturar os dois métodos no mesmo lote, em quantas chamadas precisar, enquanto o lote estiver `DRAFT` ou `REVIEWED`. #### CSV ```bash curl -X POST ".../pix/batches/{batchId}/items/csv" \ -H "Authorization: Bearer $TOKEN" -H "X-Tenant-Id: tenant-suaempresa" \ -H "Content-Type: text/csv" \ --data-binary @folha-setembro.csv ``` O corpo é o arquivo cru (até 5 MiB; acima disso `413`). O upload é **atômico**: se uma linha estiver inválida a resposta é `400 pix_batch_csv_invalid` com a lista de problemas e **nada é salvo**. ```json { "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` conta a partir do cabeçalho = linha 1, então `3` é a segunda linha de dados — igual ao que o Excel mostra. Um arquivo com mais linhas que `limits.maxItems` é `400 pix_batch_too_large`. #### JSON ```bash curl -X PUT ".../pix/batches/{batchId}/items" \ -H "Authorization: Bearer $TOKEN" -H "X-Tenant-Id: tenant-suaempresa" \ -H "Content-Type: application/json" \ -d '{ "items": [ { "identifier": "folha-set-001", "amount": "1436.85", "description": "Pagamento setembro", "key": "12345678909", "keyType": "CPF" }, { "identifier": "folha-set-002", "amount": 2500.00, "description": "Fornecedor", "name": "EMPRESA EXEMPLO LTDA", "documentNumber": "12345678000195", "bankIspb": "60701190", "accountBranch": "0001", "accountNumber": "123456", "accountType": "CHECKING" } ] }' ``` De **1 a 50 itens por chamada**, no mesmo vocabulário do `POST /pix/out`: `identifier`, `amount` (string ou número), `description`, e `key`/`keyType` **ou** `name`, `documentNumber`, `bankIspb` ou `bankCode`, `accountBranch`, `accountNumber`, `accountType`. Para lotes grandes, envie chunks de 50 em sequência — cada chamada devolve o lote atualizado. Chunk vazio, com mais de 50 itens ou com qualquer item inválido é `400 pix_batch_chunk_invalid` com o mesmo envelope `errors[]` do CSV (`line` é a posição no array, começando em 1) e nada é salvo. Um `identifier` repetido dentro do próprio chunk também é apontado. ### Regras comuns aos dois métodos * **Idempotência por linha.** Repetir um `identifier` com o **mesmo** conteúdo é ignorado (não duplica, não dá erro). Repetir com conteúdo **diferente** é `409 pix_batch_item_conflict` e a chamada inteira é recusada — corrija o arquivo em vez de contar com sobrescrita. * **Remover.** `DELETE .../items/{itemId}` tira um item; o `itemId` (`pxi_…`) vem em `items[]` do lote. * **Estados editáveis.** Só `DRAFT` e `REVIEWED` aceitam itens ou remoção. Qualquer alteração num lote `REVIEWED` o devolve a `DRAFT` e zera a conferência: você precisa revisar de novo antes de disparar. Em `REVIEWING` ou depois do dispatch, `409 pix_batch_not_editable`. * **Tamanho.** O total de itens do lote nunca passa de `limits.maxItems`; a chamada que estouraria o teto é recusada inteira com `400 pix_batch_too_large`. ## 4. Conferir (review) ``` POST /v1/accounts/{accountId}/pix/batches/{batchId}/review → 202, status REVIEWING ``` A conferência é assíncrona e roda **antes de qualquer débito**. Repetir o `POST` enquanto está `REVIEWING` só devolve o estado atual. Por item, nesta ordem: | Verificação | `reviewError.errorCode` | | ------------------------------------------------------------------------------ | -------------------------------------------------- | | Valor positivo | `invalid_amount` | | `identifier` já usado por um pagamento vivo na conta (inclusive de outro lote) | `identifier_conflict` | | Valor acima do limite por operação da conta | `limit_exceeded_transaction` | | Chave PIX inexistente, inativa ou malformada (consulta DICT) | `key_not_found`, `key_inactive`, `invalid_pix_key` | | DICT indisponível após 3 tentativas | `dict_lookup_failed` | No modo chave o DICT resolve **nome, documento e banco** do recebedor, que passam a aparecer em `items[].receiver` — é o que você mostra para quem aprova. As consultas usam o cache de 24 h da conta e **contam na janela de consultas DICT** como `GET /pix/key/{pixKey}`; leia [Consultas de chave PIX](/baas/guias/pagar/consulta-dict) antes de conferir milhares de chaves novas. Itens em dados bancários são aceitos como enviados; a validação da conta destino acontece no liquidante, na execução. Acompanhe com `GET .../pix/batches/{batchId}`. Quando `status` vira `REVIEWED`, `review` traz o resumo: ```json { "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` e `limits` são um **retrato do momento**. O saldo é checado de novo no dispatch e cada PIX passa pelos limites por janela na execução. `limits[].window` é `daily_out` (6h–20h) ou `nightly_out` (20h–6h) conforme a hora da conferência, mais `monthly`; `enforced: false` significa que a conta não tem teto configurado naquela janela. * `balance.checked: false` quer dizer que o liquidante não respondeu; o aviso vai para `warnings[]` e não bloqueia. * `warnings[]` **não bloqueia** o aceite (ex.: saldo insuficiente agora — pode entrar dinheiro até o dispatch). Itens `INVALID` **bloqueiam**. * Se a conferência não conseguir rodar, o lote volta a `DRAFT` e `review` traz um campo `error`; basta chamar `review` de novo. Um item reprovado fica assim em `items[]`: ```json { "itemId": "pxi_9b1c…", "line": 17, "identifier": "folha-set-017", "mode": "KEY", "amount": "980.00", "description": "Pagamento setembro", "status": "PENDING", "reviewStatus": "INVALID", "receiver": { "name": "", "documentNumber": "", "keyType": "EMAIL", "key": "ex-funcionario@empresa.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" } ``` Para corrigir, baixe só as linhas reprovadas, ajuste e suba de novo (o `identifier` igual com conteúdo novo é recusado — remova o item antes com `DELETE`, ou use um `identifier` novo), depois confira outra vez: ``` GET /v1/accounts/{accountId}/pix/batches/{batchId}/items/export?status=invalid GET /v1/accounts/{accountId}/pix/batches/{batchId}?reviewStatus=invalid ``` ## 5. Disparar (dispatch) ```bash curl -X POST ".../pix/batches/{batchId}/dispatch" \ -H "Authorization: Bearer $TOKEN" -H "X-Tenant-Id: tenant-suaempresa" \ -H "X-Acting-Document: 12345678909" \ -H "X-Transaction-Pin: 123456" \ -H "Content-Type: application/json" \ -d '{"acknowledged": true}' ``` `acknowledged: true` é a declaração de que o resumo da conferência foi lido e aprovado — grave do seu lado quem aprovou e quando. Sem ele a API responde `409 pix_batch_acknowledgement_required`. O dispatch ainda exige, nesta ordem: 1. Lote `REVIEWED` (`409 pix_batch_not_reviewed`). 2. Ao menos um item (`409 pix_batch_empty`) e total dentro de `limits.maxItems` (`400 pix_batch_too_large`). 3. Nenhum item `INVALID` e todos conferidos (`409 pix_batch_has_invalid_items` / `409 pix_batch_not_reviewed`). 4. Saldo disponível **maior ou igual ao total do lote** no momento do dispatch (`422 pix_batch_insufficient_balance` — nada é iniciado). > **Dispatch movimenta dinheiro** > > O dispatch é uma rota de cash out: valem as travas de saída da conta, o PIN > transacional e os cabeçalhos `X-Acting-Document` / `X-Transaction-Pin` / > `X-Acting-Ip` exatamente como em `POST /pix/out` (ver > [Segurança da conta](/baas/guias/autenticacao/seguranca-da-conta)). Os > cabeçalhos só são necessários se a conta tiver PIN ou travas configurados. > Depois do `202` **não há cancelamento**: os itens já em voo seguem até > liquidar ou falhar. Resposta `202` com `status: QUEUED` e `dispatchedAt`. Repetir o dispatch de um lote já disparado é idempotente (`200` com o estado atual), então um retry por timeout de rede é seguro. ## 6. Acompanhar Cada item vira um `PixOut.Workflow` próprio — o mesmo que atende `POST /pix/out` — com `identifier` igual ao da linha e idempotência `{batchId}_{itemId}`. Ele passa pelas mesmas políticas, limites por janela e registro no extrato de um PIX avulso, e emite os mesmos `pix.out.completed`, `pix.out.failed` ou `pix.out.timeout`. O lote paga até 5 itens em paralelo (configuração CorpX) e só avança quando o liquidante responde; um item lento não trava os demais. ### Estados do lote | `status` | Significado | Editável? | | ---------------- | -------------------------------------------------------------------- | --------- | | `DRAFT` | Recebendo itens. | Sim | | `REVIEWING` | Conferência em andamento. | Não | | `REVIEWED` | Conferido; pronto para o aceite. Qualquer edição volta para `DRAFT`. | Sim | | `QUEUED` | Dispatch aceito; aguardando o processador. | Não | | `PROCESSING` | Itens sendo pagos. `statistics` avança. | Não | | `COMPLETED` | Todos os itens liquidaram. | Não | | `PARTIAL_FAILED` | Alguns liquidaram, outros falharam. Baixe o export de falhas. | Não | | `FAILED` | Nenhum item liquidou. | Não | ### Estados do item | `status` | `reviewStatus` | Quando | | ------------ | ---------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------- | | `PENDING` | `PENDING` | Recém-adicionado, ainda não conferido. | | `PENDING` | `OK` / `INVALID` | Conferido; `INVALID` traz `reviewError`. | | `PROCESSING` | `OK` | PixOut em voo. | | `COMPLETED` | `OK` | Liquidado: `paymentId`, `endToEndId`, `transactionId`, `completedAt`. | | `FAILED` | `OK` | Recusado ou expirado: `error.errorCode` e `error.message` com o vocabulário do PIX avulso (`insufficient_funds`, `limit_exceeded_daily`, `timeout`, …). | `GET .../pix/batches/{batchId}` traz `statistics` e os itens paginados (`page`, `pageSize` até 200), filtráveis por `status` (`pending`, `processing`, `completed`, `failed`) e `reviewStatus` (`pending`, `ok`, `invalid`): ```json { "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": "folha-set-001", "mode": "KEY", "amount": "1436.85", "description": "Pagamento setembro", "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" } ``` ### Webhook de fechamento Ao final a API envia **`pix.batch.completed`**. Ele é o fechamento do lote e **não substitui** os eventos por item: para reconciliar linha a linha use `pix.out.completed` / `pix.out.failed` (o `identifier` do evento é o da sua linha) ou a lista de itens. ```json { "id": "pix-batch-pxb_3f9c2a1b7d4e5f60718293a4b5c6d7e8-completed", "type": "pix.batch.completed", "occurredAt": "2026-09-30T13:12:40.000Z", "schemaVersion": "1.0", "environment": "production", "tenantId": "tenant-suaempresa", "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" } } } ``` Assine com `authType: HMAC`, valide `X-Signature` sobre os bytes brutos e deduplique pelo `id` — detalhes em [Webhooks](/baas/guias/conta/webhooks). > **Webhook primeiro, polling como reserva** > > Prefira reagir a `pix.batch.completed`. Se precisar de polling (uma barra de > progresso, por exemplo), consulte `GET .../pix/batches/{batchId}` a cada > 10–30 s e leia só `status` e `statistics`; não liste os itens a cada ciclo. ## 7. Corrigir e reenviar ``` GET /v1/accounts/{accountId}/pix/batches/{batchId}/items/export?status=failed ``` Devolve, no **mesmo formato do modelo**, só as linhas que falharam na execução ou foram marcadas inválidas na conferência, com duas colunas a mais no fim: `errorCode` e `errorMessage`. O cabeçalho `X-Total-Rows` diz quantas linhas vieram. ```csv identifier;amount;description;pixKeyType;pixKey;receiverName;receiverDocument;bankIspb;bankCode;branch;accountNumber;accountType;errorCode;errorMessage folha-set-017;980.00;Pagamento setembro;EMAIL;ex-funcionario@empresa.com;;;;;;;;key_not_found;chave PIX não encontrada no DICT folha-set-044;1200.00;Pagamento setembro;;;MARIA DA SILVA;98765432100;;001;1234;56789-0;CHECKING;limit_exceeded_daily;limite diário de saída excedido ``` Corrija e suba o arquivo **como está** em um **novo** lote — o parser ignora as colunas de erro. Um `identifier` que falhou pode ser reutilizado; um que liquidou não (a conferência o apontaria como `identifier_conflict`), o que protege contra pagar duas vezes a mesma linha. | `status=` | Linhas incluídas | | ----------------- | ---------------------------------------------------------------------- | | `failed` (padrão) | Falharam na execução **ou** reprovadas na conferência. | | `invalid` | Só as reprovadas na conferência (use enquanto o lote está `REVIEWED`). | | `completed` | Só as liquidadas — útil para conciliar com o `endToEndId`. | | `all` | Todas, com `errorCode`/`errorMessage` vazios onde não houve erro. | `separator=comma` troca `;` por `,` para ferramentas em inglês. ## 8. Comprovantes Os comprovantes são PDFs no padrão CorpX (logo do tenant quando configurada, pagador, recebedor com documento mascarado, valor, descrição, `identifier`, `endToEndId`, data de liquidação em horário de Brasília). **Um item** — resposta direta em `application/pdf`, só para itens `COMPLETED` (`409 pix_batch_receipt_unavailable`): ``` GET /v1/accounts/{accountId}/pix/batches/{batchId}/items/{itemId}/receipt ``` **Lote inteiro** — para lotes encerrados (`COMPLETED`, `PARTIAL_FAILED` ou `FAILED` com ao menos um item liquidado; senão `409 pix_batch_no_receipts`): ```bash curl -X POST ".../pix/batches/{batchId}/receipts" \ -H "Authorization: Bearer $TOKEN" -H "X-Tenant-Id: tenant-suaempresa" ``` ```json { "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" } ``` O ZIP é gerado em segundo plano. Chame a rota em `download`: enquanto o job roda ela responde `409 not_ready`; quando termina, devolve `downloadUrl` pré-assinada (válida por `expiresIn` segundos) e `checksumMd5`. O arquivo traz um PDF por item liquidado e um `resumo.csv` com as colunas `linha`, `identificador`, `destinatario`, `valor`, `endToEnd`, `data`, `arquivo` e `erro` (preenchida só se algum PDF não pôde ser gerado). Os PDFs seguem o padrão `{AAAA-MM-DD}_{HHMM}_PIX_{valor}_{destinatario}_{identifier}_{endToEnd}.pdf` — por exemplo `2026-09-30_1312_PIX_1436-85_JOAO-ANTONIO-DA-CONCEICAO_folha-set-001_E5087192120260930131200abcdef0123.pdf` — sem acentos e com sufixo `-2`, `-3`… em caso de colisão. ## Boas práticas * **Uma `Idempotency-Key` por fechamento.** `folha-2026-09`, `fornecedores-2026-09-30`… Assim um retry da criação nunca abre um segundo lote, e você consegue reencontrar o lote pelo seu próprio calendário. * **`identifier` determinístico e único por linha.** Monte-o a partir dos seus dados (`{folha}-{matricula}`), nunca de um contador em memória. É ele que liga o PIX ao seu sistema no extrato, nos webhooks e no arquivo de correção — e é ele que impede pagar a mesma linha duas vezes. * **Confira sempre antes de pedir aprovação.** Mostre `review` (totais, saldo, limites, inválidos) a quem aprova e só então envie `acknowledged: true`. Guarde quem aprovou, quando e o `reviewedAt` que estava na tela. * **Separe quem monta de quem dispara.** Uma credencial `read` pode acompanhar; só a credencial com `pix_out.create` dispara. Se a conta usa PIN transacional, o dispatch exige o PIN do operador que aprova. * **Trate `PARTIAL_FAILED` como rotina, não exceção.** Chaves excluídas e contas encerradas acontecem em qualquer folha grande. Baixe `items/export?status=failed`, corrija e suba um novo lote; não refaça o lote inteiro. * **Reconcilie por `identifier` e `endToEndId`.** O `pix.out.completed` de cada item e a linha em `items[]` trazem os dois; o `endToEndId` é o comprovante perante o Banco Central. * **Respeite as janelas de limite.** O `review` mostra `daily_out`/`nightly_out` e `monthly`. Um lote maior que o limite disponível do dia não é bloqueado no dispatch — os itens excedentes falham na execução com `limit_exceeded_*`. Se for o caso, divida em lotes por dia ou peça ajuste de limite. * **Lotes grandes.** Para milhares de linhas, suba por CSV (uma chamada) em vez de dezenas de chunks JSON, e peça à CorpX o `maxItems` adequado antes do fechamento. ## Perguntas frequentes #### Posso cancelar um lote depois do dispatch? Não. Depois do `202` os itens já estão em execução no liquidante. O que você controla é o momento do aceite: até o `dispatch` o lote é apenas um rascunho e pode ser editado ou simplesmente abandonado em `DRAFT`/`REVIEWED`. #### O que acontece se eu editar um lote REVIEWED? Ele volta para `DRAFT` e todos os itens voltam a `reviewStatus: PENDING`. Você precisa chamar `review` de novo. Isso vale para adicionar, remover ou reenviar um item — a conferência sempre reflete o conteúdo atual. #### O saldo era suficiente na conferência mas o dispatch deu 422. Por quê? `review.balance` é um retrato do momento; outro pagamento pode ter saído entre a conferência e o aceite. O dispatch checa o saldo de novo e recusa **sem iniciar nada** se ele for menor que o total do lote. Reabasteça a conta ou remova linhas e confira novamente. #### Por que um item passou na conferência e falhou na execução? A conferência valida o que dá para validar sem mover dinheiro: chave, duplicidade, valor, limite por operação, saldo e janelas no agregado. Na execução entram as regras do liquidante e do banco de destino (conta encerrada, limite diário consumido por outros pagamentos, política da conta). O código de erro é o mesmo do PIX avulso e vem em `error.errorCode`. #### Posso reaproveitar um identifier? Um `identifier` de item que **falhou** pode ser usado em um novo lote. Um que **liquidou** não: a conferência marca `identifier_conflict`, porque na conta existe um pagamento vivo com esse identificador. Essa é a proteção contra pagamento duplicado — não a contorne gerando sufixos aleatórios. #### Os itens do lote aparecem no extrato? Sim, como PIX out individuais, com o `identifier` de cada linha. Não existe um lançamento agregado do lote; `GET .../pix/batches/{batchId}` e o `resumo.csv` dos comprovantes são a visão consolidada. #### A conferência consome cota de DICT? Sim, uma consulta por chave distinta não presente no cache de 24 h da conta, contada na mesma janela de `GET /pix/key/{pixKey}`. Chaves repetidas no lote e chaves consultadas recentemente não geram nova consulta. Em dados bancários não há consulta ao DICT. #### Como testo antes de produção? Crie um lote pequeno, suba duas ou três linhas de valor simbólico para contas suas, confira e dispare — o fluxo e os webhooks são idênticos aos de um lote de milhares de linhas. Para validar apenas o arquivo sem pagar nada, pare depois do `review`: o parser e a conferência já apontam todo problema de formato, chave e duplicidade. ## Erros | Código | HTTP | Quando | | --------------------------------------------------------- | ---- | ------------------------------------------------------------------------------------- | | `feature_disabled` | 403 | Tenant sem a feature `pix_batch`. | | `pix_batch_account_disabled` | 403 | Conta sem `pixBatch.enabled = true` na policy. | | `missing_idempotency_key` | 400 | `POST /pix/batches` sem `Idempotency-Key`. | | `pix_batch_not_found` / `pix_batch_item_not_found` | 404 | Lote ou item não existe nesta conta. | | `pix_batch_chunk_invalid` / `pix_batch_csv_invalid` | 400 | Upload rejeitado; `errors[]` aponta linha e campo. `413` quando o CSV passa de 5 MiB. | | `pix_batch_too_large` | 400 | Acima de `limits.maxItems`. | | `pix_batch_item_conflict` | 409 | `identifier` repetido com conteúdo diferente. | | `pix_batch_not_editable` | 409 | Lote em `REVIEWING` ou já disparado. | | `pix_batch_empty` | 409 | Lote sem itens. | | `pix_batch_not_reviewed` | 409 | Dispatch sem conferência válida. | | `pix_batch_has_invalid_items` | 409 | Conferência marcou itens inválidos. | | `pix_batch_acknowledgement_required` | 409 | Dispatch sem `acknowledged: true`. | | `pix_batch_insufficient_balance` | 422 | Saldo disponível menor que o total no dispatch. | | `pix_batch_no_receipts` / `pix_batch_receipt_unavailable` | 409 | Lote não encerrado ou item não liquidado. | | `receipt_render_failed` | 500 | Falha ao gerar o PDF; repita a chamada. | | `workflow_unavailable` | 503 | Orquestração indisponível; repita a chamada. | A lista completa, com âncoras, está em [Tratamento de erros](/baas/guias/referencia/erros). ## Veja também * [PIX Out](/baas/guias/pagar/pix-out) — o pagamento avulso que cada linha do lote executa. * [Consultas de chave PIX](/baas/guias/pagar/consulta-dict) — cota e cache do DICT usados na conferência. * [Segurança da conta](/baas/guias/autenticacao/seguranca-da-conta) — travas, PIN transacional e cabeçalhos de cash out. * [Idempotência](/baas/guias/comece-aqui/idempotencia) — como a `Idempotency-Key` se comporta em toda a API. * [Webhooks](/baas/guias/conta/webhooks) — `pix.batch.completed` e os eventos `pix.out.*` por item. > Pague dezenas ou milhares de PIX a partir de um CSV ou de JSON, com conferência prévia e aceite explícito antes do dinheiro sair.