Guia de Cash Out (PIX Out)

Este guia explica passo a passo como realizar transferências PIX (cash out) com consulta prévia de chave. O pagamento de boleto, que é o outro cash out da API, está em Pagamento de Boleto no fim desta página.

Visão Geral

O Cash Out permite enviar dinheiro via PIX para qualquer chave cadastrada no sistema PIX brasileiro. O fluxo recomendado é:

  1. Consultar a chave - Validar e obter os dados do destinatário
  2. Confirmar os dados - Exibir para o usuário para confirmação
  3. Executar a transferência - Enviar o PIX

Fluxo de Integração

┌─────────────┐ ┌─────────────┐ ┌─────────────┐
│ Consultar │ │ Confirmar │ │ Executar │
│ Chave │ ───► │ Dados │ ───► │ Transferência│
└─────────────┘ └─────────────┘ └─────────────┘
│ │ │
▼ ▼ ▼
Nome, Banco, Usuário E2E gerado,
Conta, CPF/CNPJ Confirma Webhook enviado

Tipos de Chave PIX

TipoFormatoExemplo
CPF11 dígitos12345678901
CNPJ14 dígitos12345678000199
EMAILE-mail válidojoao@email.com
PHONE+55 + DDD + número+5511999998888
EVPUUID123e4567-e89b-12d3-a456-426614174000

Passo 1: Consultar a Chave PIX (Opcional mas Recomendado)

Antes de transferir, consulte a chave para validar o destinatário e exibir os dados para confirmação do usuário:

curl -X GET "https://tenant.api.corpx.com/v1/accounts/{accountId}/pix/key/12345678901" \
-H "Authorization: Bearer {token}" \
-H "X-Tenant-Id: tenant-suaempresa"

A API consulta a chave automaticamente durante a transferência — a consulta prévia é opcional, mas melhora a experiência do usuário. O resultado fica em cache por 24 h (use ?noCache=true para forçar uma consulta nova ao DICT) e consome cota de consultas conforme as políticas do tenant. O consumo de DICT é medido em tempo real e acompanhado pela CorpX: antes de integrar, leia Consultas de chave PIX.

O que a transferência devolve

A resposta da transferência não repete os dados do destinatário: ela traz o desfecho da operação (status, paymentId, endToEndId). Nome e documento de quem recebeu aparecem no extrato e no lookup do pagamento.

Passo 2: Executar a Transferência

Execute a transferência PIX via chave:

Request

curl -X POST "https://tenant.api.corpx.com/v1/accounts/{accountId}/pix/out" \
-H "Authorization: Bearer {token}" \
-H "X-Tenant-Id: tenant-suaempresa" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: transfer-order-12345" \
-d '{
"amount": 100.00,
"keyType": "CPF",
"key": "12345678901",
"description": "Service payment",
"identifier": "order-12345"
}'

Parâmetros do Body

A conta de origem vem do path ({accountId}) e a moeda é sempre BRL — nenhum dos dois é enviado no body.

CampoTipoObrigatórioDescrição
amountnumberSimValor em BRL (ex.: 100.00)
keyTypestringSimTipo da chave: CPF, CNPJ, EMAIL, PHONE, EVP
keystringSimChave PIX do destinatário
descriptionstringNãoDescrição da transferência (máximo 140 caracteres)
identifierstringNãoIdentificador fornecido pelo integrador para rastreamento e conciliação. Aparece no extrato quando o pagamento é conciliado.

Resposta de Sucesso

O status HTTP reflete o desfecho: 200 (COMPLETED), 422 (FAILED), 202 (TIMEOUT/PENDING — indeterminado; confira o extrato antes de reenviar).

Rejeições imediatas do liquidante (antifraude ou saldo insuficiente na liquidação) retornam 422 FAILED na hora, com errorCode (partner_rejected / insufficient_funds) e errorReason preenchidos. Transferências retidas no banco liquidante aparecem como PENDING_APPROVAL nas consultas e aguardam o desfecho por até ~25 minutos antes de marcar TIMEOUT; o resultado chega pelos webhooks pix.out.completed / pix.out.failed / pix.out.timeout.

Nesse estado a consulta e o pix.out.timeout trazem hold (owner: "partner" + reason) e o estado bruto em partnerStatus/partnerStatusId. PENDING_APPROVAL nunca significa aprovação pendente do seu lado ou do nosso: a decisão é do liquidante. E TIMEOUT não é o fim — seguimos consultando por até 7 dias e, se ele liquidar ou recusar, você recebe pix.out.completed / pix.out.failed com late: true e o mesmo paymentId.

{
"paymentId": "pay_2f4a0f88-2147-49f2-a4e2-4f7b9f6c0f7a",
"transactionId": "txn-abc123-def456",
"endToEndId": "E12345678202301011234abcdefghijkl",
"status": "COMPLETED",
"completedAt": "2026-01-28T15:00:02Z",
"identifier": "order-12345",
"workflowId": "pix-out-{accountId}-{identifier}"
}
CampoDescrição
paymentIdID interno da intenção de pagamento (rastreio/conciliação)
transactionIdID da transação
endToEndIdID E2E BACEN (presente após liquidar)
statusCOMPLETED, FAILED, TIMEOUT, PENDING, PROCESSING
errorCode / errorReasonpreenchidos quando FAILED

Resposta de Erro

{
"errorCode": "insufficient_funds",
"message": "Saldo insuficiente na conta do liquidante para concluir a operação."
}

Timeout no fluxo síncrono

Se o liquidante não confirmar dentro da janela, a API responde 202 com status: "TIMEOUT" e um campo warning — não existe 207. O PIX pode ter sido enviado: consulte o extrato ou o lookup do pagamento antes de reenviar. O desfecho tardio chega por webhook (pix.out.completed / pix.out.failed).

Fluxo assíncrono (recomendado para alto volume)

Use POST /v1/accounts/{accountId}/pix/out/async para agendar o pagamento e receber 202 imediato:

curl -X POST "https://tenant.api.corpx.com/v1/accounts/{accountId}/pix/out/async" \
-H "Authorization: Bearer {token}" \
-H "X-Tenant-Id: tenant-suaempresa" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: transfer-order-async-12345" \
-d '{
"amount": 100.00,
"keyType": "CPF",
"key": "12345678901",
"description": "Service payment",
"identifier": "order-12345-async"
}'

Resposta:

{
"paymentId": "pay_2f4a0f88-2147-49f2-a4e2-4f7b9f6c0f7a",
"workflowId": "pix-out-{accountId}-{identifier}",
"runId": "b7c1f0e2-...",
"idempotencyKey": "transfer-order-async-12345",
"identifier": "order-12345-async",
"status": "ACCEPTED"
}

A resposta 202 inclui o header Location apontando para /v1/accounts/{accountId}/payments/{identifier} — um alias mantido por compatibilidade, que responde com headers Deprecation. A rota canônica de consulta é GET /v1/accounts/{accountId}/pix/payments/lookup?identifier=. O resultado final (sucesso/falha) é entregue por webhook e também pode ser consultado por identifier/paymentId.

Passo 3: Consultar Status da Transferência

Após executar uma transferência, você pode consultar seu status usando o ID E2E:

Request

curl -X GET "https://tenant.api.corpx.com/v1/accounts/{accountId}/pix/transactions?endToEndId=E12345678202301011234abcdefghijkl" \
-H "Authorization: Bearer {token}" \
-H "X-Tenant-Id: tenant-suaempresa"

Parâmetros de Query

ParâmetroTipoObrigatórioDescrição
endToEndIdstringSim*ID E2E da transação
identifierstringSim*Identificador da cobrança ou referência

*Pelo menos um dos dois (endToEndId ou identifier) é obrigatório. O accountId vai no path, não na query.

Resposta de Sucesso (200 OK)

Esta rota responde no mesmo envelope do extrato (items[]), com 0 ou 1 item. Os horários (timestamp) saem em horário de Brasília (-03:00).

{
"accountId": "{accountId}",
"source": "live",
"page": 0,
"size": 1,
"totalElements": 1,
"totalPages": 1,
"hasNext": false,
"items": [
{
"partnerId": "a697b489-681a-451c-a043-d4ae65be8c80",
"endToEndId": "E12345678202301011234abcdefghijkl",
"direction": "OUT",
"transactionType": "D",
"operation": "PIX",
"status": "COMPLETED",
"amount": -100.00,
"currency": "BRL",
"description": "PIX - MARIA DA SILVA",
"identifier": "order-12345",
"timestamp": "2026-01-28T15:00:00-03:00",
"counterParty": {
"name": "MARIA DA SILVA",
"document": "123***01",
"bankCode": "001"
}
}
],
"fetchedAt": "2026-01-28T18:00:05Z"
}

Para receber um único objeto (em vez do envelope items[]), use GET /v1/accounts/{accountId}/pix/payments/lookup?identifier=... (ou ?endToEnd=...).

Status Possíveis

StatusDescrição
COMPLETEDLiquidada com sucesso
PROCESSINGEm processamento no parceiro
PENDING_APPROVALRetida dentro do banco liquidante (fila de autorização interna dele ou análise de risco). Leia hold.owner / hold.reason — não há aprovação pendente do seu lado nem do nosso
FAILEDFalhou / rejeitada
REVERSEDEstornada / devolvida
UNKNOWNStatus do parceiro fora do mapeamento

Fluxo de estados

  • O resultado final chega pelos webhooks pix.out.completed / pix.out.failed. Em caso de TIMEOUT, a API também emite pix.out.timeout (estado indeterminado — confira o extrato; um completed/failed tardio ainda pode chegar depois, com late: true e o mesmo paymentId).
  • Reenvio com a mesma Idempotency-Key depende do desfecho anterior: se o pagamento terminou em FAILED, a chave é liberada e a nova requisição reexecuta o pagamento (desde v2.43.3); se terminou em TIMEOUT, o reenvio não acontece — o estado é indeterminado e a API devolve o resultado registrado. Com uma chave nova, você pode duplicar o envio. Detalhes em Idempotência.

Sempre salve o identifier das transferências e consulte o status por ele — é o ID que você define, estável e disponível desde a criação (o endToEndId só existe após a liquidação).

Exemplo Completo: Script de Cash Out

#!/bin/bash
# Configuration
API_URL="https://tenant.api.corpx.com"
TOKEN="your_token_here"
TENANT_ID="tenant-suaempresa"
ACCOUNT_ID="your_account"
# Transfer details
PIX_KEY="12345678901"
PIX_KEY_TYPE="CPF"
AMOUNT=100.00
echo "=== PIX CASH OUT ==="
echo ""
echo "PIX Key: $PIX_KEY ($PIX_KEY_TYPE)"
echo "Amount: R$ $AMOUNT"
echo ""
# 1. Confirm (in production, wait for user confirmation)
read -p "Confirm transfer? (y/n): " confirm
if [ "$confirm" != "y" ]; then
echo "Transfer cancelled"
exit 0
fi
# 2. Execute transfer
echo ""
echo "Executing transfer..."
IDEMPOTENCY_KEY="cashout-$(date +%s)-$RANDOM"
transfer_response=$(curl -s -X POST "$API_URL/v1/accounts/$ACCOUNT_ID/pix/out" \
-H "Authorization: Bearer $TOKEN" \
-H "X-Tenant-Id: $TENANT_ID" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: $IDEMPOTENCY_KEY" \
-d "{
\"amount\": $AMOUNT,
\"keyType\": \"$PIX_KEY_TYPE\",
\"key\": \"$PIX_KEY\",
\"description\": \"Transfer via script\"
}")
# Check result
STATUS=$(echo "$transfer_response" | jq -r '.status')
E2E=$(echo "$transfer_response" | jq -r '.endToEndId')
if [ "$STATUS" = "COMPLETED" ]; then
echo ""
echo "=== TRANSFER COMPLETED ==="
echo "Status: $STATUS"
echo "E2E: $E2E"
echo "$transfer_response" | jq
else
echo ""
echo "=== RESULT ==="
echo "$transfer_response" | jq
fi

Consultar QR Code (Decode)

Antes de pagar, você pode decodificar o QR Code para exibir os dados do beneficiário ao usuário:

curl -X POST "https://tenant.api.corpx.com/v1/accounts/{accountId}/pix/out/qr-code/decode" \
-H "Authorization: Bearer {token}" \
-H "X-Tenant-Id: tenant-suaempresa" \
-H "Content-Type: application/json" \
-d '{
"emv": "00020126580014br.gov.bcb.pix0136123e4567-e89b-12d3-a456-426614174000..."
}'

Resposta (QR dinâmico imediato):

{
"key": "123e4567-e89b-12d3-a456-426614174000",
"amount": 150.00,
"originalAmount": 150.00,
"identifier": "8e4d8c19-1d3f-4b22-bf6f-79a4d0e1f001",
"decodeId": "8e4d8c19-1d3f-4b22-bf6f-79a4d0e1f001",
"qrCodeType": "dynamic-immediate",
"qrCodeTypeId": 1,
"allowChange": false,
"description": "Compra online",
"payeeName": "EMPRESA EXEMPLO LTDA",
"payeeDocument": "12345678000190",
"bankIspb": "50871921",
"bankBranch": "0001",
"bankAccount": "123456-7",
"accountType": "CHECKING"
}

Para QR de cobrança com vencimento (dynamic-due-date), o response inclui também os componentes do valor (discount, deduction, interest, penalty), originalAmount (valor de face antes dos ajustes), dueDate, paymentDeadline e payeeTradeName (nome fantasia da PJ). Veja o exemplo correspondente no OpenAPI.

Você pode reutilizar decodeId no body do POST /pix/out/qr-code/async para pular um segundo decode na hora do pagamento.

Após confirmar, use o endpoint de pagamento abaixo para executar.

Pagar QR Code (PIX Out via EMV)

Se você possui um código EMV (QR Code copia e cola), use o endpoint assíncrono (canônico):

Fluxo assíncrono (recomendado)

POST /v1/accounts/{accountId}/pix/out/qr-code/async — resposta 202 imediata:

curl -X POST "https://tenant.api.corpx.com/v1/accounts/{accountId}/pix/out/qr-code/async" \
-H "Authorization: Bearer {token}" \
-H "X-Tenant-Id: tenant-suaempresa" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: pay-qr-async-12345" \
-d '{
"emv": "00020126580014br.gov.bcb.pix...",
"amount": 150.00,
"description": "QR Code payment",
"identifier": "pay-qr-async-12345"
}'

Resposta:

{
"paymentId": "pay_2f4a0f88-2147-49f2-a4e2-4f7b9f6c0f7a",
"workflowId": "pix-out-{accountId}-{identifier}",
"runId": "b7c1f0e2-...",
"idempotencyKey": "pay-qr-async-12345",
"identifier": "pay-qr-async-12345",
"status": "ACCEPTED"
}

A resposta 202 inclui o header Location apontando para o lookup do pagamento. O resultado final (sucesso/falha/timeout) chega por webhook (pix.out.completed, pix.out.failed, pix.out.timeout) e também pode ser consultado por identifier/paymentId.

Endpoint síncrono (deprecated)

Deprecated

POST /v1/accounts/{accountId}/pix/out/qr-code (sync) está deprecated. Continue funcionando por compatibilidade e devolve headers Deprecation, Sunset e Link (sunset previsto: 2026-11-21). Migre para /pix/out/qr-code/async.

Webhook de Transferência

Após a transferência, você receberá um webhook no envelope canônico (id, type, occurredAt, schemaVersion, data):

{
"id": "pix-out-9ccd1869-7593-4feb-9602-e525e818ab8e",
"type": "pix.out.completed",
"occurredAt": "2026-09-16T20:58:46.258668746Z",
"schemaVersion": "1.0",
"environment": "production",
"tenantId": "tenant-suaempresa",
"accountId": "{accountId}",
"data": {
"paymentId": "9ccd1869-7593-4feb-9602-e525e818ab8e",
"tenantId": "tenant-suaempresa",
"accountId": "{accountId}",
"status": "SUCCESS",
"endToEnd": "E36741675202601281500001234567",
"transactionId": "162982-pix",
"amount": 100.00,
"currency": "BRL",
"description": "Pagamento fornecedor",
"identifier": "order-12345",
"originalTransactionId": "",
"initiatedAt": "2026-09-16T20:58:42.646763686Z",
"completedAt": "2026-09-16T20:58:46.258668746Z",
"key": {
"type": "CPF",
"key": "12345678901"
},
"payee": {
"name": "MARIA DA SILVA",
"document": "12345678901",
"bankCode": "001",
"bankIspb": "00000000",
"branch": "0001",
"accountNumber": "12345678"
}
}
}

O evento equivalente de falha é pix.out.failed (com error no data) e o de estado indeterminado é pix.out.timeout. A referência completa dos campos está em Webhooks.

BigPix (descontinuado)

Descontinuado

O limite de R$ 15.000 por transação foi removido — POST /v1/accounts/{accountId}/pix/out agora aceita qualquer valor em uma única transação. O BigPix (que dividia valores grandes em múltiplos PIX) não é mais necessário e está descontinuado.

Os endpoints /pix/out/bigpix e /pix/out/bank-account/bigpix continuam funcionais por retrocompatibilidade, mas retornam o header Deprecation: true. Migre para POST /pix/out (ou /pix/out/bank-account). A data de remoção definitiva será anunciada no changelog com antecedência.

Pagamento de Boleto

Boleto é o outro cash out disponível na v2 (na v1 esses endpoints respondiam 503). São três rotas: uma para ler o boleto antes de pagar, uma para pagar e uma para consultar o resultado.

Passo 1: Preview (ler o boleto)

Resolve a linha digitável no parceiro e devolve 200 com os dados do título (beneficiário, pagador, valores, vencimento) para você exibir antes de debitar.

curl -X POST "${API_URL}/v1/accounts/${ACCOUNT_ID}/boleto/preview" \
-H "Authorization: Bearer ${JWT}" \
-H "X-Tenant-Id: ${TENANT_ID}" \
-H "Content-Type: application/json" \
-d '{ "line": "34191790010104351004791020150008291070026000" }'

O campo canônico é line; barcode é aceito como alias. Boleto não encontrado no parceiro devolve 404 not_found.

{
"type": "boleto-payment",
"bank": "Itaú Unibanco S.A.",
"bankCode": "341",
"receiverName": "FORNECEDOR EXEMPLO LTDA",
"receiverTaxId": "12345678000190",
"dueDate": "2026-08-10",
"amount": 1430.63,
"discountAmount": 0,
"interestAmount": 3.29,
"fineAmount": 28.61,
"totalUpdated": 1462.53,
"status": "PAYABLE"
}

Pague o totalUpdated, não o amount

amount é o valor de face — o mesmo número que está gravado no código de barras. totalUpdated é o que o liquidante aceita hoje: face + juros + multa − desconto.

Em título vencido os dois diferem, e o liquidante recusa qualquer valor que não seja o atualizado (boleto_amount_mismatch). Como os encargos correm por dia, o totalUpdated de ontem já não serve: faça o preview no dia do pagamento, e garanta saldo para o valor atualizado, não para o de face.

Passo 2: Pagar

curl -X POST "${API_URL}/v1/accounts/${ACCOUNT_ID}/boleto/pay" \
-H "Authorization: Bearer ${JWT}" \
-H "X-Tenant-Id: ${TENANT_ID}" \
-H "Idempotency-Key: $(uuidgen)" \
-H "Content-Type: application/json" \
-d '{
"line": "34191790010104351004791020150008291070026000",
"amount": 1462.53,
"taxId": "12345678000199",
"description": "Fornecedor ACME"
}'
ParâmetroObrigatórioDescrição
line (ou barcode)SimLinha digitável / código de barras
amountSimValor a pagar — o totalUpdated do preview, não o valor de face
taxIdNãoCNPJ/CPF do pagador
scheduledNãoAgendamento (quando o parceiro suportar)
descriptionNãoDescrição livre

Valor divergente volta como boleto_amount_mismatch (422), e a mensagem traz o valor que o liquidante espera — refaça o preview e reenvie com ele.

A resposta é sempre 202, nunca 200: o pagamento roda de forma assíncrona e o corpo traz paymentId (= boletoId, no formato bol_{uuid}), status: "PROCESSING" e um header Location apontando para a consulta de status.

{
"paymentId": "bol_aabbccdd-...",
"boletoId": "bol_aabbccdd-...",
"idempotencyKey": "...",
"amount": 250.00,
"status": "PROCESSING"
}

O boletoId é derivado de (accountId, Idempotency-Key), então repetir a requisição com a mesma chave devolve o mesmo paymentId e reaproveita a execução em curso — sem débito duplicado.

Passo 3: Consultar o resultado

curl -X GET "${API_URL}/v1/accounts/${ACCOUNT_ID}/boleto/payments/bol_aabbccdd-..." \
-H "Authorization: Bearer ${JWT}" \
-H "X-Tenant-Id: ${TENANT_ID}"

Aceita tanto o paymentId canônico (bol_...) quanto a referência do parceiro. Enquanto o parceiro ainda não devolveu a referência, a rota responde 200 com o último status local conhecido (PROCESSING) em vez de erro.

O desfecho também chega por webhook: boleto.paid e boleto.failed (ver Webhooks). A compensação de um boleto pode levar horas — até o dia útil seguinte — então trate PROCESSING como estado normal e prolongado, não como falha.

Erros Comuns

ErroHTTPCausaSolução
key_not_found404Chave PIX não existe no DICTVerifique a chave e seu tipo
invalid_pix_key422Chave malformada ou incompatível com o tipo informadoUse: CPF, CNPJ, EMAIL, PHONE, EVP
insufficient_funds422Saldo insuficiente apurado pelo liquidanteVerifique o saldo da conta
limit_exceeded_daily / limit_exceeded_nightly / limit_exceeded_monthly / limit_exceeded_transaction422Limite da conta excedido na janela indicadaAguarde a virada da janela ou solicite aumento
partner_rejected422Recusa do liquidante por risco/antifraudeVeja o bloco partner com o motivo
policy_denied422Uma regra de política do tenant/conta recusou a transferênciaVeja violations no corpo e ajuste a regra no painel — Políticas e Regras

A lista completa com mensagens e semântica está em Erros.

Reenviar a mesma Idempotency-Key em PIX out não devolve 409: a API retorna o resultado já registrado (ou reexecuta, se o desfecho anterior foi FAILED).

Boas Práticas

  1. Sempre consulte a chave antes de transferir para validar o destinatário
  2. Confirme com o usuário os dados antes de executar
  3. Use uma Idempotency Key única por transferência — e reutilize a mesma chave ao repetir a requisição, nunca uma nova
  4. Salve o E2E para rastreamento e suporte
  5. Configure webhooks para receber confirmações assíncronas
  6. Implemente retry com exponential backoff para falhas temporárias

Limites

TipoLimite Padrão
Por transaçãoSem limite fixo
DiárioR$ 100.000,00
MensalSem limite

Não há mais limite fixo por transação — o valor é limitado apenas pelos limites operacionais da conta (consulte GET /v1/accounts/{accountId}/pix/limits).

Os limites podem ser personalizados. Entre em contato com o suporte para mais informações.

Próximos Passos