Error handling
API Documentation · Zypher Global
Introduction
Authentication
Sandbox
PIX charge (BRL)
SPEI charge (MXN)
USDT charge
PIX withdrawal (key)
BR Code withdrawal
SPEI withdrawal (MXN)
USDT withdrawal
Splits (pass-through)
Check Balance
Convert Currency
Query Transactions
Webhooks
Error handling
Every API failure returns a standardized JSON body with a human-readable message and a stable error_code. The HTTP status also reflects the error (not always 200). Handle errors by error_code, it does NOT change across languages or versions.
Error format
HTTP 422
{
"ok": false,
"error": "Chave PIX não encontrada.",
"error_code": "pix_key_not_found"
}
ok— alwaysfalseon error.error— human-readable message (localized). Good to display/log; do NOT use for logic.error_code— stable slug to handle in code (switch/if). This is the source of truth.
HTTP Status
- 400 — invalid request (data/fields).
- 401 — missing or invalid credentials.
- 403 — no permission, IP not allowed, or resource disabled.
- 422 — data rejected during processing (e.g., key not found, insufficient balance).
- 429 — too many attempts. Wait and try again.
- 500 / 503 — internal error or service temporarily unavailable.
The status is also sent in the
X-App-Error-Code header (for clients that only read headers).Error codes
The same error_code can appear on different routes. Always handle by the code.
Authentication and access
missing_credentials401— Client ID/Secret missing in the header.invalid_credentials401— Invalid Client ID/Secret.key_inactive403— API key is inactive.permission_denied403— The key lacks the required permission (cashin/cashout/balance).ip_not_configured403— Cash-out without an IP in the key allowlist.ip_not_allowed403— Source IP not in the allowlist (or not IPv4).invalid_account403— Account linked to the key is invalid.rate_limited429— Too many requests in a short time.
Key / recipient (PIX)
pix_key_not_found422— The PIX key does not exist in DICT.pix_key_invalid422— PIX key has an invalid format.pix_key_type_invalid422— Key type not accepted for this destination.invalid_document422— CPF/CNPJ invalid or does not match the key.name_mismatch422— Recipient name/document does not match the key.recipient_cannot_receive422— Destination account cannot receive (closed/inactive).destination_blocked422— Destination key or account blocked/suspended.
Amount and balance
insufficient_balance400— Insufficient balance for the amount + fee.amount_below_min422— Amount below the minimum allowed.amount_above_limit422— Amount above the allowed limit.amount_unavailable422— No rail covers this amount right now, try a lower amount.invalid_amount422— Invalid or zero amount.
Processing / provider
duplicate422— Duplicate operation (check if it was already processed).unauthorized403— Operation not authorized by the provider.maintenance503— Service under maintenance.provider_unavailable422— Service unavailable or timeout, you can retry.cashin_failed422— Generic failure creating the charge.cashout_failed422— Generic withdrawal failure (contact support).
Account / permissions
kyc_required403— Account without document verification (KYC).currency_not_supported400— Currency not supported (use BRL, MXN, ARS, COP or USDT).currency_not_enabled403— Currency not enabled for this account, contact support.phone_required422— Buyer phone required for COP cash-in (NEQUI/BRE-B).
Conversion
invalid_request400— Fields amount/from/to missing or invalid.conversion_failed500— Failed to execute the conversion (nothing was debited).conversion_in_progress409— A conversion with that external_id is already in progress, wait, do not resend.
Lookup / status
missing_reference400— Missing identifier (request_number / e2e / transaction_id).deposit_not_found404— No deposit for the given identifier.withdrawal_not_found404— No withdrawal for the given identifier.
Retryable:
provider_unavailable and rate_limited are transient, you can repeat the same request (with the same external_id to avoid duplicates). The rest are final: fix the data before resending.Handling example
JavaScript
const r = await fetch(url, opts);
const data = await r.json();
if (!data.ok) {
switch (data.error_code) {
case 'pix_key_not_found':
case 'pix_key_invalid':
// pedir outra chave ao usuário
break;
case 'insufficient_balance':
// avisar saldo
break;
case 'provider_unavailable':
case 'rate_limited':
// retentar com backoff (mesmo external_id)
break;
default:
// mostrar data.error e logar
}
}
Was this page helpful?
