Confiabilidade
Erros
Como a API informa problemas: um único objeto de erro, poucos status HTTP e códigos de erro estáveis para você tomar decisões, incluindo os motivos de recusa de um pagamento com cartão.
Nesta página
O objeto de erro
Toda resposta fora da faixa 2xx tem um corpo JSON com um único objeto error. Tome decisões com base em type e code, que são estáveis; mostre message só para desenvolvedores, porque o texto pode mudar.
type KrokoPayError = { error: { type: | "authentication_error" | "permission_error" | "invalid_request_error" | "idempotency_error" | "card_error" | "api_error"; code: string; // stable, machine-readable message: string; // for developers, not for payers param?: string; // the request field at fault, when there is one };};Parâmetros
typestringObrigatório- A família do erro. Veja os tipos de erro.
codestringObrigatório- O motivo específico, legível por máquina, como
parameter_invalid. Veja os códigos de erro. messagestringObrigatório- Uma explicação legível, em inglês, para desenvolvedores e logs.
paramstringOpcional- O campo da requisição que causou o erro, quando houver, como
amount.
HTTP/1.1 422 Unprocessable EntityContent-Type: application/json{ "error": { "type": "invalid_request_error", "code": "parameter_invalid", "message": "amount must be a positive integer in centavos.", "param": "amount" }}Status HTTP
| Status | Significado | Códigos comuns |
|---|---|---|
200 OK | A requisição funcionou. | Nenhum |
201 Created | Um novo objeto foi criado (cobrança, reembolso, cliente…). | Nenhum |
400 Bad Request | O corpo não é um JSON válido. | invalid_json |
401 Unauthorized | Sem chave, ou a chave não é válida. | missing_api_key, invalid_api_key |
402 Payment Required | Uma tentativa de pagamento com cartão foi recusada no checkout. | card_declined, insufficient_funds, expired_card, incorrect_cvc, processing_error |
403 Forbidden | A chave é válida, mas não pode chamar este endpoint. | secret_key_required |
404 Not Found | O objeto ou a rota não existe. | resource_missing |
409 Conflict | Uma Idempotency-Key foi reutilizada com outra requisição. | idempotency_key_reused |
422 Unprocessable Entity | O JSON é válido, mas um campo falta, é inválido ou não é permitido no estado atual. | parameter_missing, parameter_invalid, not_refundable, invalid_amount, insufficient_balance |
500 Internal Server Error | Algo falhou do lado da KrokoPay. | internal_error |
Informação: Limites de requisição
429.Tipos de erro
type | O que significa | Tentar de novo? |
|---|---|---|
authentication_error | A chave está ausente ou não é válida. | Não. Corrija a chave. |
permission_error | A chave não pode fazer esta requisição. | Não. Use a chave secreta. |
invalid_request_error | A requisição em si está errada: um campo, um id ou o estado do objeto. | Não. Mude a requisição. |
idempotency_error | A Idempotency-Key já foi usada em outra requisição. | Não. Use uma chave nova para uma requisição nova. |
card_error | O pagamento com cartão foi recusado. O code diz o motivo. | Só com outro cartão ou depois que o pagador corrigir os dados. |
api_error | Um problema inesperado do lado da KrokoPay. | Sim, com a mesma Idempotency-Key. |
Códigos de erro
Erros de requisição
code | Status | Quando acontece |
|---|---|---|
invalid_json | 400 | Não foi possível ler o corpo como JSON. |
missing_api_key | 401 | Sem cabeçalho Authorization: Bearer. |
invalid_api_key | 401 | A chave está malformada, é desconhecida ou foi trocada. |
secret_key_required | 403 | Uma chave publicável foi usada onde a chave secreta é exigida. |
resource_missing | 404 | Nenhum objeto com esse id, como em GET /v1/charges/chg_doesnotexist. |
idempotency_key_reused | 409 | Mesma Idempotency-Key com outro corpo ou outro endpoint. Veja Idempotência. |
parameter_missing | 422 | Falta um campo obrigatório. O param diz qual. |
parameter_invalid | 422 | Um campo tem tipo ou valor errado, como um amount negativo. |
not_refundable | 422 | A cobrança não está paid nem partially_refunded, então não pode ser reembolsada. |
invalid_amount | 422 | O valor do reembolso é zero ou maior que o que resta para reembolsar. |
insufficient_balance | 422 | O saldo da conta não cobre o reembolso. |
internal_error | 500 | Falha inesperada. Tente de novo com a mesma Idempotency-Key. |
HTTP/1.1 404 Not FoundContent-Type: application/json{ "error": { "type": "invalid_request_error", "code": "resource_missing", "message": "No charge with id chg_doesnotexist." }}Falhas de pagamento
Um cartão recusado não faz a sua chamada POST /v1/charges falhar: a cobrança é criada primeiro, e o comprador paga depois, no checkout. Quando uma tentativa é recusada, o checkout mostra o motivo ao comprador, a cobrança vira failed com um failure_code e você recebe charge.failed.
failure_code | Significado | O que o pagador pode fazer |
|---|---|---|
card_declined | O cartão foi recusado sem um motivo mais específico. | Tentar outro cartão ou pagar com Pix. |
insufficient_funds | O cartão não tem limite disponível para este valor. | Usar outro cartão ou pagar com Pix. |
expired_card | A validade do cartão já passou. | Conferir a data ou usar outro cartão. |
incorrect_cvc | O código de segurança não confere. | Digitar o CVC de novo. |
processing_error | Não foi possível processar a tentativa. | Tentar de novo em instantes. |
O Pix não tem etapa de recusa. Uma cobrança Pix que ninguém paga antes de o código expirar vira expired e envia charge.expired; crie uma nova cobrança para tentar de novo. Todos os resultados acima podem ser reproduzidos com os cartões de teste.
{ "id": "chg_7Lc3PvN8yHd2Ws", "object": "charge", "amount": 49700, "currency": "BRL", "status": "failed", "method": "card", "card": { "brand": "visa", "last4": "0002" }, "description": "Curso Identidade Visual do Zero", "customer_id": "cus_8Hq2LmZr4TxN1a", "product_id": "prod_3Vb7QpK9sWd2Ee", "price_id": "price_5Kd1NcR8vYq3Hm", "link_id": null, "subscription_id": null, "fee": null, "net": null, "refunded_amount": 0, "failure_code": "card_declined", "created_at": "2026-11-03T16:02:19.000Z", "paid_at": null, "expires_at": null, "available_at": null, "checkout_url": "https://krokopay.app/pay/chg_7Lc3PvN8yHd2Ws"}{ "id": "evt_7Pp8Qq9Rr0Ss1T", "object": "event", "type": "charge.failed", "api_version": "2026-11-01", "created_at": "2026-11-03T16:02:24.000Z", "data": { "object": { "id": "chg_7Lc3PvN8yHd2Ws", "object": "charge", "amount": 49700, "currency": "BRL", "status": "failed", "method": "card", "card": { "brand": "visa", "last4": "0002" }, "description": "Curso Identidade Visual do Zero", "customer_id": "cus_8Hq2LmZr4TxN1a", "product_id": "prod_3Vb7QpK9sWd2Ee", "price_id": "price_5Kd1NcR8vYq3Hm", "link_id": null, "subscription_id": null, "fee": null, "net": null, "refunded_amount": 0, "failure_code": "card_declined", "created_at": "2026-11-03T16:02:19.000Z", "paid_at": null, "expires_at": null, "available_at": null, "checkout_url": "https://krokopay.app/pay/chg_7Lc3PvN8yHd2Ws" } }}Como tratar erros
async function createCharge(body, idempotencyKey) { const response = await fetch("https://api.krokopay.app/v1/charges", { method: "POST", headers: { Authorization: `Bearer ${process.env.KROKOPAY_SECRET_KEY}`, "Idempotency-Key": idempotencyKey, "Content-Type": "application/json", }, body: JSON.stringify(body), }); if (response.ok) return response.json(); const { error } = await response.json(); switch (error.type) { case "invalid_request_error": // Fix the request: error.param names the field. throw new Error(`Invalid ${error.param ?? "request"}: ${error.message}`); case "authentication_error": case "permission_error": // Configuration problem: alert the team, do not retry. throw new Error(`KrokoPay key problem: ${error.code}`); case "api_error": // Safe to retry with the same Idempotency-Key. throw Object.assign(new Error(error.message), { retryable: true }); default: throw new Error(error.message); }}Novas tentativas
- Repita só respostas
500e falhas de rede (tempo esgotado, conexão caída), em que não dá para saber se a requisição chegou. - Envie sempre a mesma
Idempotency-Keyao repetir umPOST, para que uma requisição que deu certo não seja feita duas vezes. - Espere mais a cada tentativa (por exemplo 1 s, 2 s, 4 s) e pare depois de algumas.
- Nunca repita respostas
4xxsem mudar nada. Elas vão falhar do mesmo jeito.
O que mostrar ao pagador
O checkout hospedado já explica ao comprador as recusas de cartão e a expiração do Pix. Nas suas próprias páginas, mostre uma mensagem curta e gentil ("O pagamento não foi concluído. Você pode tentar de novo.") e ofereça uma nova tentativa. Nunca mostre a message ou os códigos ao comprador.
Registros
Registre o método, o caminho, o status, o type e o code de toda chamada que falhar, junto com o id do seu pedido. Toda chamada também aparece em Desenvolvedores → Logs com um identificador req_, para você cruzar os seus registros com os nossos quando pedir ajuda.