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:
- Look up the key - Validate and obtain the recipient's details
- Confirm the details - Display to the user for confirmation
- 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
| Type | Format | Example |
|---|---|---|
CPF | 11 digits | 12345678901 |
CNPJ | 14 digits | 12345678000199 |
EMAIL | Valid e-mail | joao@email.com |
PHONE | +55 + area code + number | +5511999998888 |
EVP | UUID | 123e4567-e89b-12d3-a456-426614174000 |
Step 1: Look Up the PIX Key (Optional but Recommended)
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.
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"
}
| Field | Description |
|---|---|
transactionId | Internal transaction ID |
status | Status: APPROVED, PENDING, REJECTED, PROCESSING |
endToEndId | E2E 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
| Field | Type | Required | Description |
|---|---|---|---|
accountId | string | Yes | Source account UUID |
amount | number | Yes | Amount in BRL (e.g., 100.00) |
currency | string | Yes | Always BRL |
keyType | string | Yes | Key type: CPF, CNPJ, EMAIL, PHONE, EVP |
key | string | Yes | Recipient's PIX key |
description | string | No | Transfer description (max 140 characters) |
identifier | string | No | Integrator-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"
}
| Field | Description |
|---|---|
transactionId | Internal transaction ID |
status | APPROVED, PENDING, REJECTED, PROCESSING |
endToEndId | E2E 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 default100 req/min, policy-customizable) and returnscurrentRateLimit+scope. - Planned for the next days: the default for synchronous requests will be adjusted to
10 req/min.
Async flow (recommended for high volume)
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
| Parameter | Type | Required | Description |
|---|---|---|---|
accountId | string | Yes | Account UUID |
endToEndId | string | Yes* | Transaction E2E ID |
identifier | string | Yes* | 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
| Status | Description |
|---|---|
COMPLETED | Transaction completed successfully |
REVERSED | Transaction reversed |
PENDING | Awaiting processing |
FAILED | Transaction failed |
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
| Error | Cause | Solution |
|---|---|---|
key_not_found | PIX key does not exist | Check the key and its type |
insufficient_balance | Insufficient balance | Check the account balance |
invalid_key_type | Invalid key type | Use: CPF, CNPJ, EMAIL, PHONE, EVP |
transfer_limit_exceeded | Daily limit exceeded | Wait or request an increase |
409 Conflict | Duplicate Idempotency Key | Use a different key |
Best Practices
- Always look up the key before transferring to validate the recipient
- Confirm with the user the details before executing
- Use a unique Idempotency Key per transfer
- Save the E2E for tracking and support
- Configure webhooks to receive asynchronous confirmations
- Implement retry with exponential backoff for temporary failures
Limits
| Type | Default Limit |
|---|---|
| Per transaction | R$ 50,000.00 |
| Daily | R$ 100,000.00 |
| Monthly | No limit |
Limits can be customized. Contact support for more information.
Next Steps
- Refund Guide - Reverse received transfers
- Webhooks - Configure notifications
- Errors - Full list of error codes