Referência

Códigos de erro

Todo erro segue o mesmo envelope, com um error.code estável que você pode tratar programaticamente. Os códigos abaixo estão organizados pelo HTTP status.

HTTP 400

Bad Request — payload ou estado inválido

invalid_requestHTTP 400#invalid_request
quando
Algum campo obrigatório está faltando, fora do formato, ou tipo errado. Validação Zod falhou antes de chegar à lógica de negócio.
o que fazer
Ler error.message para o campo específico e corrigir o payload.
json
{
  "error": {
    "code": "invalid_request",
    "message": "customer_cpf must be 11 characters"
  },
  "request_id": "req_…"
}
customer_pendingHTTP 400#customer_pending
quando
Cliente existe mas está em status = pending (foi pré-cadastrado mas ainda não ativado). A chamada não trouxe o bloco activate.
o que fazer
Re-enviar a mesma chamada com o bloco activate: { cpf, phone? }. Veja o Passo 2 do quickstart de recorrência.
json
{
  "error": {
    "code": "customer_pending",
    "message": "Customer is pre-registered but not yet activated. Re-send the request with an `activate` block to perform first-touch activation, or activate the customer separately first."
  },
  "request_id": "req_…"
}
customer_blockedHTTP 400#customer_blocked
quando
Cliente está em status = blocked (suspensão administrativa ou CPF inelegível na validação interna).
o que fazer
Não retentar. Notificar o cliente externamente. Se foi um bloqueio transitório, ele será desbloqueado automaticamente pelo time interno e a próxima chamada passará.
json
{
  "error": {
    "code": "customer_blocked",
    "message": "Customer is blocked and cannot transact."
  }
}
customer_inactiveHTTP 400#customer_inactive
quando
Caso defensivo — cobrir um eventual novo status de cliente antes dele ser publicado no contrato. Em produção hoje você não deve ver esse código.
o que fazer
Reportar para a equipe Bumcash com o request_id.
HTTP 401

Unauthorized

authentication_requiredHTTP 401#authentication_required
quando
Header Authorization ausente, malformado, ou a chave foi revogada. Também dispara para chaves expiradas ou de prefixo inválido.
o que fazer
Conferir o header. Formato esperado: Authorization: Bearer bmc_…. Se sua chave foi revogada, gere uma nova no portal.
HTTP 403

Forbidden — chave válida, mas a operação está fora do escopo

insufficient_permissionsHTTP 403#insufficient_permissions
quando
Sua chave não carrega o verbo necessário (ex.: customers:register, customers:activate, recurring:bill_payment). Mensagem inclui o verbo específico, e a resposta vem com error.hint + error.docs indicando qual trilha é dona do verbo e o que usar no lugar.
o que fazer
Ler error.hint primeiro — ele já diz se o verbo é de outra trilha. Se a sua persona realmente precisa do verbo, confira as permissões da chave em Portal → API Keys. Lojistas mch_ recurrency/hybrid recebem por padrão todos os verbos do quickstart. Lojistas varejo (retail-only) recebem somente leitura — peça à equipe Bumcash para liberar payments:create se você precisa enviar cashback via API.
json
{
  "error": {
    "code": "insufficient_permissions",
    "message": "Merchant API key is missing required permission: payments:create",
    "hint": "Verbo da trilha varejo (POST /payments/pos-cashback). Empresas de recorrência (telecom, academia) usam POST /recurring/bill-payment com bloco activate.",
    "docs": "https://docs.bumcash.com.br/recurrency/quickstart#passo-2"
  }
}
terms_not_acceptedHTTP 403#terms_not_accepted
quando
Sua organização ainda não aceitou a versão vigente dos Termos de Uso.
o que fazer
Acesse Portal Bumcash e aceite os termos. Pode ser feito por qualquer membro com permissão de owner.
HTTP 404

Not Found

customer_not_foundHTTP 404#customer_not_found
quando
CPF informado não existe na rede Bumcash.
o que fazer
Duas opções: (a) chamar POST /customers/register antes de tentar transacionar, ou (b) incluir o bloco activate na própria chamada de bill-payment / pos-cashback (a ativação cria o cliente).
json
{
  "error": {
    "code": "customer_not_found",
    "message": "Customer not found. Pre-register the CPF via POST /customers/register, or include an `activate` block on this request to perform first-touch activation."
  }
}
not_foundHTTP 404#not_found
quando
Recurso genérico não existe ou não está acessível à sua chave —location_id errado, transação de outra organização, webhook inexistente, etc.
o que fazer
Conferir o ID enviado. Se a sua chave é mch_, ela só consegue ver locais da própria organização — IDs fora desse escopo aparecem como 404, não 403, para evitar enumeração.
HTTP 409

Conflict

conflictHTTP 409#conflict
quando
external_reference_id já está em uso na sua organização para um cliente diferente. O índice único (merchant_org_id, external_reference_id) bloqueia a alias acidental.
o que fazer
Verificar na sua base interna se você está tentando reciclar um ID já usado. Reusar o mesmo external_reference_id para o mesmo CPF é OK (idempotente); reusá-lo para outro CPF não é.
idempotency_conflictHTTP 409#idempotency_conflict
quando
Mesma idempotency_key usada anteriormente, mas com parâmetros diferentes. A política Bumcash é mesma chave = mesmo resultado por 90 dias; mudar o payload não é permitido.
o que fazer
Gerar uma idempotency_key nova para a nova intenção. Mesma chave + mesmo payload = retorna o registro original.
HTTP 422

Unprocessable — semantic validations

insufficient_balanceHTTP 422#insufficient_balance
quando
Tentativa de débito (POST /payments) maior que o saldo BMC do cliente.
o que fazer
Mostrar saldo atual ao cliente e ajustar o valor. Saldo é retornado em respostas anteriores de mint/burn.
HTTP 429

Rate Limit

rate_limit_exceededHTTP 429#rate_limit_exceeded
quando
Acima do limite (sandbox: 1.000 req/min, produção: 100 req/min). Header Retry-After indica em quantos segundos voltar.
o que fazer
Implementar backoff exponencial respeitando o Retry-After.
HTTP 500

Server Error

internal_errorHTTP 500#internal_error
quando
Erro inesperado do lado da Bumcash. Não retentar imediatamente — pode duplicar trabalho se a primeira já tiver sido aplicada.
o que fazer
Enviar o request_id para o suporte Bumcash e aguardar. Se for crítico, retentar com a mesma idempotency_key garante que chamadas duplicadas não causem efeito colateral.