Erros & Idempotência
Idempotência
Seção intitulada “Idempotência”Toda operação financeira (criar cobrança PIX, emitir boleto, criar refund) exige o
header Idempotency-Key — um valor único (recomendado: um UUID) que você gera por
operação. Ele garante que repetir a mesma requisição (por timeout, retry de rede
etc.) não cria um segundo recurso.
Idempotency-Key: 3f2a9c1e-8b7d-4e6f-9a1b-2c3d4e5f6a7b| Cenário | Resultado |
|---|---|
| 1ª chamada | 201 Created — recurso novo. |
| Replay: mesma key + mesmo corpo | 200 OK — devolve o recurso original, sem criar outro. |
| Conflito: mesma key + corpo diferente | 409 IDEMPOTENCY_KEY_REUSED. |
| Key ausente | 400 IDEMPOTENCY_KEY_REQUIRED. |
Envelope de erro padrão
Seção intitulada “Envelope de erro padrão”Exceto o POST /v1/oauth/token (que segue a RFC 6749),
todos os erros da API usam o mesmo envelope:
{ "error": { "code": "CHARGE_NOT_FOUND", "message": "Cobrança não encontrada.", "request_id": "req_123", "documentation_url": "https://docs.vmixpay.com/errors/CHARGE_NOT_FOUND" }}code— código de erro estável e legível por máquina (faça branch nele, não namessage).message— descrição humana (pode mudar; não dependa do texto).request_id— identificador da requisição; inclua-o ao reportar um problema.documentation_url— link para detalhes do código.
Códigos HTTP
Seção intitulada “Códigos HTTP”| HTTP | Significado | Exemplos de code |
|---|---|---|
400 |
Requisição inválida | IDEMPOTENCY_KEY_REQUIRED, AMOUNT_INVALID, INVALID_DUE_DATE, CURSOR_INVALID, LIMIT_INVALID |
401 |
Não autenticado | Bearer ausente/inválido/expirado |
403 |
Sem permissão | Scope faltando, ACCOUNT_MISMATCH, KYC_REQUIRED |
404 |
Não encontrado | CHARGE_NOT_FOUND, REFUND_NOT_FOUND, WALLET_ACCOUNT_NOT_FOUND |
409 |
Conflito de estado | IDEMPOTENCY_KEY_REUSED, CHARGE_NOT_PENDING, CHARGE_NOT_REFUNDABLE |
422 |
Não processável | REFUND_EXCEEDS, MERCHANT_ADDRESS_REQUIRED |
429 |
Rate limit excedido | — |
502 |
Falha no banco (re-tentável) | BANK_UNAVAILABLE |
Exceção: o erro do /oauth/token
Seção intitulada “Exceção: o erro do /oauth/token”O endpoint de token não usa o envelope acima. Ele segue a RFC 6749 §5.2:
{ "error": "invalid_client" }Os valores possíveis são unsupported_grant_type (400) e invalid_client (401).
Veja Autenticação.
Status de uma cobrança
Seção intitulada “Status de uma cobrança”| Status | Significado |
|---|---|
pending |
Criada, aguardando pagamento. |
paid |
Paga. |
expired |
Vencida sem pagamento. |
cancelled |
Cancelada. |
refunded |
Totalmente devolvida. |
failed |
Falhou. |
Listagens com cursor
Seção intitulada “Listagens com cursor”As listas (charges, payments, events, ledger) usam cursor pagination
(keyset), não offset. A resposta é sempre { data, next_cursor }:
- Repasse o
next_cursor(opaco, base64url) em?cursor=<valor>para a próxima página. Quando viernull, acabou. limitcontrola o tamanho da página: default 25, máximo 100 (valores acima são reduzidos a 100).- Pagine sempre seguindo o
next_cursor— não monte cursores à mão.
Erros: 400 CURSOR_INVALID (cursor malformado) · 400 LIMIT_INVALID (limit
não-inteiro ou ≤ 0).
Saldo e extrato (por conta)
Seção intitulada “Saldo e extrato (por conta)”O saldo e o extrato são por conta (account_id), com o scope payments:read:
GET /v1/accounts/{account_id}/balance→{ "balance": "194.50", "currency": "BRL" }.GET /v1/accounts/{account_id}/ledger→ extrato da wallet com cursor pagination.
O balance/amount trafegam como string em reais. Uma conta própria sem
movimento retorna balance: "0.00" (não 404); uma conta inexistente ou de outro
merchant retorna 404 WALLET_ACCOUNT_NOT_FOUND (tenant-safe).