Skip to main content

Cash Out Guide (PIX Out)

This guide explains step by step how to make PIX transfers (cash out) with prior key lookup.

Overview

Cash Out allows you to send money via PIX to any key registered in the Brazilian PIX system. The recommended flow is:

  1. Look up the key - Validate and obtain the recipient's details
  2. Confirm the details - Display to the user for confirmation
  3. Execute the transfer - Send the PIX

Integration Flow

┌─────────────┐      ┌─────────────┐      ┌─────────────┐
│ Look Up │ │ Confirm │ │ Execute │
│ Key │ ───► │ Details │ ───► │ Transfer │
└─────────────┘ └─────────────┘ └─────────────┘
│ │ │
▼ ▼ ▼
Name, Bank, User E2E generated,
Account, CPF/CNPJ Confirms Webhook sent

PIX Key Types

TypeFormatExample
CPF11 digits12345678901
CNPJ14 digits12345678000199
EMAILValid e-mailjoao@email.com
PHONE+55 + area code + number+5511999998888
EVPUUID123e4567-e89b-12d3-a456-426614174000

Before transferring, you can look up the key to validate and obtain the recipient's details. The preview response is returned when making the transfer, but a prior lookup allows you to display the details for user confirmation.

info

The API automatically performs the key lookup during the transfer. The prior lookup is optional but recommended for better UX.

Data Returned in the Transfer

When executing the transfer (next step), the response includes the recipient's details:

{
"transactionId": "txn_xyz789abc123",
"status": "APPROVED",
"endToEndId": "E36741675202601281500001234567",
"amount": 100.00,
"currency": "BRL"
}
FieldDescription
transactionIdInternal transaction ID
statusStatus: APPROVED, PENDING, REJECTED, PROCESSING
endToEndIdE2E ID for tracking at BACEN

Step 2: Execute the Transfer

Execute the PIX transfer via key:

Request

curl -X POST "https://api.corpxapi.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 '{
"accountId": "{accountId}",
"amount": 100.00,
"currency": "BRL",
"keyType": "CPF",
"key": "12345678901",
"description": "Service payment",
"identifier": "order-12345"
}'

Body Parameters

FieldTypeRequiredDescription
accountIdstringYesSource account UUID
amountnumberYesAmount in BRL (e.g., 100.00)
currencystringYesAlways BRL
keyTypestringYesKey type: CPF, CNPJ, EMAIL, PHONE, EVP
keystringYesRecipient's PIX key
descriptionstringNoTransfer description (max 140 characters)
identifierstringNoIntegrator-provided identifier for tracking and reconciliation. Appears in the statement when the payment is reconciled.

Success Response (202 Accepted)

{
"transactionId": "txn-abc123-def456",
"status": "APPROVED",
"endToEndId": "E12345678202301011234abcdefghijkl",
"amount": 100.00,
"currency": "BRL"
}
FieldDescription
transactionIdInternal transaction ID
statusAPPROVED, PENDING, REJECTED, PROCESSING
endToEndIdE2E ID for tracking at BACEN

Error Response

{
"errorCode": "insufficient_balance",
"message": "insufficient available balance: 50.00 (total: 100.00, locked: 50.00, requested: 150.00)"
}

Timeout and Rate Limit on sync flow

  • Partner timeout (207 partner_timeout): transfer may already have been sent; check statement/payment status before retrying.
  • Per-account rate limit (429 rate_limit_exceeded): sync endpoint enforces per-account limit (current default 100 req/min, policy-customizable) and returns currentRateLimit + scope.
  • Planned for the next days: the default for synchronous requests will be adjusted to 10 req/min.

Use POST /v1/accounts/{accountId}/pix/out/async to schedule payment and get immediate 202:

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

Response:

{
"paymentId": "2f4a0f88-2147-49f2-a4e2-4f7b9f6c0f7a",
"status": "SCHEDULED",
"scheduled": true
}

Final result (success/failure) is delivered by webhook and can also be checked by paymentId.

Step 3: Check Transfer Status

After executing a transfer, you can check its status using the E2E ID:

Request

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

Query Parameters

ParameterTypeRequiredDescription
accountIdstringYesAccount UUID
endToEndIdstringYes*Transaction E2E ID
identifierstringYes*Charge or reference identifier

*At least one of the two (endToEndId or identifier) is required.

Success Response (200 OK)

{
"transactionId": "txn-abc123-def456",
"endToEndId": "E12345678202301011234abcdefghijkl",
"status": "COMPLETED",
"type": "CASH_OUT",
"amount": -100.00,
"currency": "BRL",
"description": "PIX - MARIA DA SILVA",
"transactionDate": "2026-01-28T15:00:00Z",
"counterparty": {
"name": "MARIA DA SILVA",
"document": "123***01",
"bankCode": "001"
},
"balance": 9900.00
}

Possible Statuses

StatusDescription
COMPLETEDTransaction completed successfully
REVERSEDTransaction reversed
PENDINGAwaiting processing
FAILEDTransaction failed
tip

Always save the endToEndId of transfers so you can check the status later.

Full Example: Cash Out Script

#!/bin/bash

# Configuration
API_URL="https://api.corpxapi.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 "{
\"accountId\": \"$ACCOUNT_ID\",
\"amount\": $AMOUNT,
\"currency\": \"BRL\",
\"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" = "APPROVED" ]; then
echo ""
echo "=== TRANSFER APPROVED ==="
echo "Status: $STATUS"
echo "E2E: $E2E"
echo "$transfer_response" | jq
else
echo ""
echo "=== RESULT ==="
echo "$transfer_response" | jq
fi

Decode QR Code

Before paying, you can decode the QR Code to display beneficiary details to the user:

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

Response:

{
"amount": 150.00,
"allowChange": false,
"key": "123e4567-e89b-12d3-a456-426614174000",
"beneficiaryName": "EMPRESA EXEMPLO LTDA",
"beneficiaryType": "LEGAL_PERSON",
"document": "12345678000190",
"bankIspb": "12345678",
"bankAccount": "123456",
"bankBranch": "0001",
"accountType": "CHECKING",
"discount": 0
}

After confirming, use the payment endpoint below to execute.

Pay QR Code (PIX Out via EMV)

If you have an EMV code (QR Code copy and paste), use the specific endpoint:

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

For static QR Codes without a defined amount, include the amount field:

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

Transfer Webhook

After the transfer, you receive a webhook:

{
"event": "pix.out.completed",
"timestamp": "2026-01-28T15:00:02Z",
"data": {
"transactionId": "txn_xyz789abc123",
"status": "COMPLETED",
"value": 100.00,
"endToEndId": "E36741675202601281500001234567",
"recipient": {
"name": "MARIA DA SILVA",
"document": "12345678901"
}
}
}

BigPix (High-value transfers)

For transfers above the individual limit (R$15,000 by default), use the BigPix endpoint.

Important: BigPix is now always asynchronous.
POST /v1/accounts/{accountId}/pix/out/bigpix schedules processing (same behavior as /pix/out/async) and returns 202 with paymentId.

curl -X POST "https://api.corpxapi.com/v1/accounts/{accountId}/pix/out/bigpix" \
-H "Authorization: Bearer {token}" \
-H "X-Tenant-Id: {tenant_id}" \
-H "Content-Type: application/json" \
-d '{
"key": "recipient@email.com",
"keyType": "EMAIL",
"amount": 47500.00,
"description": "Supplier payment",
"identifier": "PAY-001"
}'

Common Errors

ErrorCauseSolution
key_not_foundPIX key does not existCheck the key and its type
insufficient_balanceInsufficient balanceCheck the account balance
invalid_key_typeInvalid key typeUse: CPF, CNPJ, EMAIL, PHONE, EVP
transfer_limit_exceededDaily limit exceededWait or request an increase
409 ConflictDuplicate Idempotency KeyUse a different key

Best Practices

  1. Always look up the key before transferring to validate the recipient
  2. Confirm with the user the details before executing
  3. Use a unique Idempotency Key per transfer
  4. Save the E2E for tracking and support
  5. Configure webhooks to receive asynchronous confirmations
  6. Implement retry with exponential backoff for temporary failures

Limits

TypeDefault Limit
Per transactionR$ 50,000.00
DailyR$ 100,000.00
MonthlyNo limit
info

Limits can be customized. Contact support for more information.

Next Steps