EYTdocs

Send PIX Payment (Cash-Out)

POST /api/pix/cash-out

POST https://api.gateway.eyt.com.br/api/pix/cash-out

Requires a Bearer token in the Authorization header. See Generate Token to obtain one.

Sends a PIX payment to a destination PIX key. The transaction is created with status PENDING and the final result is notified via webhook or can be queried via polling.

Authentication

Requires a Bearer token in the Authorization header.

Testing in sandbox? Add the X-Sandbox-Scenario header to simulate error scenarios such as insufficient funds, invalid PIX key, and document mismatch. See the Sandbox Testing guide.

Request Body

FieldTypeRequiredDescription
valuenumberYesAmount in BRL (up to 2 decimal places). Minimum: 0.01
externalIdstringYesUnique external identifier per account
descriptionstringNoTransaction description (max 140 chars)
detailsobjectYesDestination PIX key information
details.keystringYesDestination PIX key (see formats in the table below)
details.keyTypestringYesKey type: DOCUMENT, EMAIL, PHONE, RANDOM. Required because the API does not query DICT
details.namestringYesRecipient name (informational, max 100 chars)
details.documentstringYesCPF (11 digits) or CNPJ (14 digits) of the key holder. The API validates format only; checking it against the actual key holder depends on the account's settlement provider — see Ownership verification by settlement provider

Accepted formats for details.key

keyTypeFormatExample
DOCUMENTCPF: 11 digits / CNPJ: 14 digits (numbers only)12345678901, 12345678000195
EMAILValid email addressusuario@exemplo.com
PHONEArea code + number (10-11 digits, without country code +55)11999999999
RANDOMUUID (with or without hyphens)a1b2c3d4-e5f6-4890-abcd-ef1234567890

The payment is always addressed by the PIX key (details.key). The details.document field is required for all key types, including EMAIL, PHONE, and RANDOM, and is forwarded to your account's settlement provider — but only some providers check it against the actual key holder. The EYT API does not compare details.document with details.key and does not query DICT before sending. When the account's provider does not perform that check, a mismatched details.document does not block the payment: the amount is credited to the key owner. See Ownership verification by settlement provider.


Request Examples

Payment by CPF — the most common case. The details.key and details.document must be the same (both are the CPF). The API does not verify this equality: enforce it on your side before sending.

{
  "value": 150.00,
  "externalId": "PAG-2024-0001",
  "description": "Pagamento freelancer - Janeiro/2024",
  "details": {
    "key": "12345678901",
    "keyType": "DOCUMENT",
    "name": "Ana Costa",
    "document": "12345678901"
  }
}

Payment by CNPJ — common in B2B payments (suppliers, invoices).

{
  "value": 4500.00,
  "externalId": "NF-2024-0089",
  "description": "NF 0089/2024 - Serviços de hospedagem",
  "details": {
    "key": "11222333000144",
    "keyType": "DOCUMENT",
    "name": "Cloud Provider Ltda",
    "document": "11222333000144"
  }
}

Payment by email key. Note that details.document must be the CPF/CNPJ of the key holder (it cannot be inferred from the email). If your account's provider does not check ownership, a wrong document does not prevent the payment.

{
  "value": 89.90,
  "externalId": "COMM-2024-0456",
  "description": "Comissão venda #456",
  "details": {
    "key": "vendedor@loja.com.br",
    "keyType": "EMAIL",
    "name": "Roberto Vendas",
    "document": "98765432100"
  }
}

Payment by phone key. The format is area code + number (10 or 11 digits), without the country code +55.

{
  "value": 25.00,
  "externalId": "REEMB-2024-0012",
  "description": "Reembolso uber colaborador",
  "details": {
    "key": "11987654321",
    "keyType": "PHONE",
    "name": "Pedro Almeida",
    "document": "11122233344"
  }
}

Payment by random key (EVP/UUID). Generated by BACEN, it does not contain personal information.

{
  "value": 1250.00,
  "externalId": "RENT-2024-JAN",
  "description": "Aluguel janeiro/2024",
  "details": {
    "key": "a1b2c3d4-e5f6-4890-abcd-ef1234567890",
    "keyType": "RANDOM",
    "name": "Imobiliária Central",
    "document": "55666777000199"
  }
}

Ownership verification by settlement provider

The EYT API validates details.document only for format (11 or 14 digits and check digits) and validates details.key against the format expected for the keyType. It does not compare details.document with details.key, does not query DICT, and does not block the operation when the two differ. The payment is always addressed by the PIX key. Checking the document against the actual key holder, where it exists, is done by the settlement provider configured on your account:

Account's settlement providerChecks details.document against the key holder?On mismatch
ONZ and providers running on ONZ (FyHub, Nixfin, OnlyUp, Treeal)Yes, whenever the field is sentRejected by the provider: transaction ERROR, no debit, webhook carrying the provider's message (e.g. "CPF/CNPJ informado não confere com o CPF/CNPJ do destinatário")
MagenNo, by defaultPayment completed to the key owner
a55, AvivPay IP (same API as a55)No. The field is forwarded to the provider but not checkedPayment completed to the key owner
GolPix, HyperwalletThe field is forwarded to the provider; the check is not guaranteed by EYTDepends on the provider
BRZip, Woovi, AvivPayNo. The field is not sent to the providerPayment completed to the key owner

Why still send details.document? On ONZ accounts (and FyHub, Nixfin, OnlyUp, Treeal) it is the only ownership check that exists: omitting it disables that verification and the transfer goes into the provider's normal-priority queue. On the other providers the field is accepted but does not change the outcome of the payment.

How do I know which settlement provider my account uses? It is configured per account at creation time. When in doubt, ask your integration manager. If your operation requires a mismatched document to block the payment, treat that as a requirement when choosing the account's settlement provider, and verify ownership on your side before sending: for keyType: DOCUMENT, make sure details.document equals details.key.


Code Examples

cURL
curl -X POST "https://api.gateway.eyt.com.br/api/pix/cash-out" \
  -H "Authorization: Bearer $EYT_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
  "value": 150.00,
  "externalId": "PAG-2024-0001",
  "description": "Pagamento freelancer - Janeiro/2024",
  "details": {
    "key": "12345678901",
    "keyType": "DOCUMENT",
    "name": "Ana Costa",
    "document": "12345678901"
  }
}'
const axios = require('axios');

const response = await axios.post('https://api.gateway.eyt.com.br/api/pix/cash-out',
  {
  "value": 150.00,
  "externalId": "PAG-2024-0001",
  "description": "Pagamento freelancer - Janeiro/2024",
  "details": {
    "key": "12345678901",
    "keyType": "DOCUMENT",
    "name": "Ana Costa",
    "document": "12345678901"
  }
},
  {
    headers: {
      'Authorization': `Bearer ${process.env.EYT_TOKEN}`,
      'Content-Type': 'application/json',
    },
  }
);
console.log(response.data);
import os, requests

response = requests.post(
    'https://api.gateway.eyt.com.br/api/pix/cash-out',
    headers={
        'Authorization': f'Bearer {os.environ["EYT_TOKEN"]}',
        'Content-Type': 'application/json',
    },
    json={
  "value": 150.00,
  "externalId": "PAG-2024-0001",
  "description": "Pagamento freelancer - Janeiro/2024",
  "details": {
    "key": "12345678901",
    "keyType": "DOCUMENT",
    "name": "Ana Costa",
    "document": "12345678901"
  }
},
)
print(response.json())
$ch = curl_init('https://api.gateway.eyt.com.br/api/pix/cash-out');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_POST => true,
    CURLOPT_HTTPHEADER => [
        'Authorization: Bearer ' . getenv('EYT_TOKEN'),
        'Content-Type: application/json',
    ],
    CURLOPT_POSTFIELDS => '{
  "value": 150.00,
  "externalId": "PAG-2024-0001",
  "description": "Pagamento freelancer - Janeiro/2024",
  "details": {
    "key": "12345678901",
    "keyType": "DOCUMENT",
    "name": "Ana Costa",
    "document": "12345678901"
  }
}',
]);
$response = curl_exec($ch);
curl_close($ch);
echo $response;
String body = """
    {
      "value": 150.00,
      "externalId": "PAG-2024-0001",
      "description": "Pagamento freelancer - Janeiro/2024",
      "details": {
        "key": "12345678901",
        "keyType": "DOCUMENT",
        "name": "Ana Costa",
        "document": "12345678901"
      }
    }
    """;
HttpRequest request = HttpRequest.newBuilder()
    .uri(URI.create("https://api.gateway.eyt.com.br/api/pix/cash-out"))
    .header("Authorization", "Bearer " + System.getenv("EYT_TOKEN"))
    .header("Content-Type", "application/json")
    .POST(HttpRequest.BodyPublishers.ofString(body))
    .build();
HttpResponse<String> response = HttpClient.newHttpClient()
    .send(request, HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());

Response (201 Created)

FieldTypeDescription
transactionIdstringInternal identifier of the generated transaction (UUID)
externalIdstringExternal identifier provided in the request
statusstringInitial status: PENDING. Confirmation via webhook: CONFIRMED or ERROR
generateTimestringTransaction generation date/time (ISO 8601 UTC)
{
  "transactionId": "8b3b85ac-394c-4144-9bcb-c5d12de3fa56",
  "externalId": "PAG-2024-0001",
  "status": "PENDING",
  "generateTime": "2024-01-15T10:30:00.000Z"
}

Errors

Returned when the body does not pass validation. The message field is an array with messages for each invalid field.

{
  "statusCode": 400,
  "timestamp": "2026-04-10T15:30:34.560Z",
  "path": "/public/pix/cash-out",
  "method": "POST",
  "code": "HTTP_ERROR",
  "message": [
    "value must be at least 0.01",
    "details.keyType must be one of: EMAIL, PHONE, DOCUMENT, RANDOM"
  ],
  "userMessage": "Requisição inválida. Verifique os dados enviados.",
  "errorId": "a1b2c3d4e5f6789012345678abcdef01",
  "error": "Bad Request"
}

Common causes:

  • value less than 0.01 or with more than 2 decimal places
  • details.keyType with invalid value
  • details.key does not match the keyType format
  • details.document empty or incorrect format

The available balance is less than the transaction amount + fee.

{
  "statusCode": 400,
  "timestamp": "2026-04-10T15:30:34.560Z",
  "path": "/public/pix/cash-out",
  "method": "POST",
  "code": "PIX_INSUFFICIENT_BALANCE",
  "message": "Saldo insuficiente para realizar esta operação.",
  "userMessage": "Requisição inválida. Verifique os dados enviados.",
  "errorId": "b2c3d4e5f6a7890123456789abcdef02",
  "errorCode": "PIX_INSUFFICIENT_BALANCE"
}

Other business errors in the same category:

CodeDescription
PIX_INSUFFICIENT_BALANCEInsufficient balance (amount + fee)
PIX_TRANSACTION_LIMIT_EXCEEDEDAmount exceeds per-transaction limit
PIX_DAILY_LIMIT_EXCEEDEDDaily accumulated amount exceeds daily limit
PIX_NIGHT_LIMIT_EXCEEDEDNighttime operation exceeds reduced limit (8 PM - 6 AM)
PIX_INVALID_AMOUNTAmount less than 0.01 or with more than 2 decimal places
PIX_INVALID_PIX_KEYKey format does not match the provided keyType

The externalId has already been used for this account. Use a new identifier. Returns status 400 (not 409) with details containing the existing transaction ID.

{
  "statusCode": 400,
  "timestamp": "2026-04-10T15:30:34.560Z",
  "path": "/public/pix/cash-out",
  "method": "POST",
  "code": "PIX_DUPLICATE_EXTERNAL_ID",
  "message": "Esta transação já existe no sistema.",
  "userMessage": "Requisição inválida. Verifique os dados enviados.",
  "errorId": "c57c14ee10aabd82e40dae9b940706e0",
  "errorCode": "PIX_DUPLICATE_EXTERNAL_ID",
  "details": {
    "externalId": "external-teste-002",
    "existingTransactionId": 466208
  }
}

The externalId works as an idempotency key. If you send the same request twice with the same externalId, the second call will return an error — ensuring the payment is not duplicated. The details.existingTransactionId field allows you to locate the original transaction.

When the settling bank rejects the operation after the transaction is created, the status changes to ERROR and the errorCode/errorMessage fields are sent in the Cash-Out webhook:

errorCodeDescriptionRetryable?
TAX_ID_MISMATCHThe details.document does not match the PIX key holder. Emitted by the Magen provider when ownership checking is active; on ONZ/FyHub/Nixfin/OnlyUp/Treeal accounts the mismatch arrives with the provider's own message (see Ownership verification by settlement provider)No — fix the CPF/CNPJ
INVALID_TAX_IDAlgorithmically invalid CPF/CNPJ (Magen provider)No — fix the document
BLOCKED_ACCOUNTDestination account judicially blockedNo
ACCOUNT_CLOSEDDestination account closedNo
ORDER_REJECTEDDestination bank rejected the operationNo
PAYMENT_EXPIREDTransaction expired before being processedYes — resend
SETTLEMENT_TIMEOUTDestination bank did not respond in timeYes — resend

Webhook payload example with error:

{
  "event": "CashOut",
  "status": "ERROR",
  "transactionType": "PIX",
  "movementType": "DEBIT",
  "transactionId": "466208",
  "externalId": "PAG-2024-0001",
  "endToEndId": "E17758345EYNKPHCJKMS",
  "pixKey": "12345678901",
  "feeAmount": 0.07,
  "originalAmount": 1,
  "finalAmount": 1.07,
  "processingDate": "2026-04-10T15:22:49.970Z",
  "errorCode": "TAX_ID_MISMATCH",
  "errorMessage": "O documento informado não corresponde ao titular da chave PIX",
  "counterpart": {
    "name": "João Silva",
    "document": "12345678901",
    "bank": {
      "bankISPB": "13140088",
      "bankName": "ACESSO SOLUÇÕES DE PAGAMENTO S.A.",
      "bankCode": "332",
      "accountBranch": null,
      "accountNumber": null
    }
  },
  "metadata": {}
}

When status is CONFIRMED, the errorCode and errorMessage fields are null. When status is ERROR, they indicate the reason for the rejection.

See the PIX Cash-Out integration guide for code examples, local key validation, and best practices.

On this page