Error Handling
Errors are reported with an HTTP status code and a JSON body. The body is not identical on every endpoint (the shapes are listed below), and the message texts are currently in Portuguese. Decide what to do from the HTTP status code and use the message only for logging.
Error Body Shapes
1. Authentication (401)
Wrong or unknown credentials, or a company that is not approved. When no credentials are sent at all, the body can be empty.
{ "status": 401, "message": "API Key ausente ou inválida."}2. Message only (Withdraw, Balance and lookups)
{ "message": "Header Idempotency-Key é obrigatório."}3. Title and detail (create transaction, operation token, IP whitelist)
Some responses add extra fields, such as maxValueCents or header.
{ "title": "Valor acima do limite permitido.", "detail": "O valor máximo por cobrança PIX é R$ 1,500.00.", "maxValueCents": 150000}4. Not found (404)
{ "title": "Not Found", "status": 404, "detail": "Transação não encontrada.", "instance": "/api/Transaction/transactionByTransactionId/00000000-0000-0000-0000-000000000000"}5. Body validation (400)
Returned when the JSON body is missing, malformed or a field is out of range. The messages in errors are keyed by field name.
{ "type": "https://tools.ietf.org/html/rfc9110#section-15.5.1", "title": "One or more validation errors occurred.", "status": 400, "errors": { "Amount": ["Amount deve ser entre 1 e 100.000.000 centavos (R$1.000.000,00)."] }, "traceId": "00-6462ea6255fa6cc54684bbac2ce00e14-938b693910e4aeec-00"}6. Rate limit (429)
Plain text body and a Retry-After: 60 header.
Muitas tentativas. Aguarde 60 segundos antes de tentar novamente.HTTP Status Codes
Bad Request
Invalid request: missing or out-of-range fields, missing Idempotency-Key on withdrawals, amount above the per-PIX limit, insufficient balance, unsupported payment method.
Unauthorized
Missing or invalid X-Client-Id / X-API-Key, an unapproved company, or an invalid or expired X-Operation-Token that was sent.
Forbidden
Valid credentials but not allowed: another company's ID, an IP outside your whitelist, or an endpoint that needs a different kind of authentication.
Not Found
Transaction or withdrawal not found for your company.
Conflict
Idempotency conflict on withdrawals (rare). Repeating the same Idempotency-Key normally returns the original request.
Unsupported Media Type
A POST was sent without Content-Type: application/json.
Too Many Requests
Rate limit exceeded. Wait for the number of seconds in Retry-After before retrying.
Internal Server Error
Unexpected error on our side. The body carries only an error code and a correlationId (never internal details); send the correlationId to support. The request may or may not have been processed, so retry with the same Idempotency-Key.
Best Practices
Branch on the HTTP status code, not on the message text. Messages are in Portuguese and can change.
Send an Idempotency-Key on create transaction and withdrawal calls, and reuse the same key when you retry after a timeout or a 5xx.
Log traceId or correlationId when present and send it to support.
On 429, wait for Retry-After seconds; on 5xx, retry with exponential backoff.
Handling Example
const response = await fetch('https://api.respawnpay.com/api/v1/transactions/create', { method: 'POST', headers: { 'Content-Type': 'application/json', 'X-Client-Id': CLIENT_ID, 'X-API-Key': API_KEY, 'Idempotency-Key': idempotencyKey }, body: JSON.stringify(data)});if (response.status === 429) { const wait = Number(response.headers.get('Retry-After') ?? 60); // wait `wait` seconds, then retry with the same idempotencyKey return;}const text = await response.text();const body = text ? JSON.parse(text) : {};if (!response.ok) { // body can be { message }, { title, detail } or { title, errors } depending on the endpoint console.error('HTTP', response.status, body.message ?? body.title, body.detail ?? body.errors); console.error('Trace:', body.traceId ?? body.correlationId); return;}console.log('Success:', body.data);