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.
invalid_identifierHTTP 400#invalid_identifier
quando
GET /customers/lookup sem cpf nem phone, ou com os dois ao mesmo tempo.
o que fazer
Enviar exatamente um dos dois identificadores.
invalid_cpfHTTP 400#invalid_cpf
quando
CPF não passa na validação de dígito verificador (confirm-phone, register e demais escritas).
o que fazer
Reconfirmar o CPF com o cliente antes de retentar.
location_lookup_requiredHTTP 400#location_lookup_required
quando
Chave Partner (ptr_) chamou uma escrita sem cnpj nem location_id. Partners operam múltiplos lojistas e precisam identificar o alvo explicitamente.
o que fazer
Enviar cnpj OU location_id (exatamente um) no payload.
location_mismatchHTTP 400#location_mismatch
quando
cnpj e location_id enviados juntos, mas resolvem para locations diferentes.
o que fazer
Conferir o mapeamento na sua base e enviar apenas um dos dois.
merchant_location_id_forbiddenHTTP 400#merchant_location_id_forbidden
quando
Chave Merchant (mch_) enviou cnpj ou location_id no payload. A location é inferida da própria chave.
o que fazer
Remover os campos do payload. Se você precisa atuar em múltiplos lojistas, o caminho é uma chave Partner.
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"
  }
}
phone_verification_staleHTTP 403#phone_verification_stale
quando
Consulta de saldo por telefone com vínculo existente, mas o atestado do número (phoneVerifiedAt) tem mais de 12 meses — proteção contra números reciclados pela operadora.
o que fazer
Pedir o CPF ao cliente e chamar POST /customers/{cpf}/confirm-phone para renovar o atestado; depois repetir a consulta.
json
{
  "error": {
    "code": "phone_verification_stale",
    "message": "Vínculo com este telefone precisa ser confirmado antes da consulta de saldo.",
    "hint": "Peça o CPF do cliente e chame POST /customers/{cpf}/confirm-phone."
  }
}
wrong_scopeHTTP 403#wrong_scope
quando
Chave do tipo errado para o endpoint: ptr_ em GET /locations/me, ou mch_ em GET /locations/lookup.
o que fazer
Merchant usa /locations/me; Partner usa /locations/lookup?cnpj=…. Os dois retornam os mesmos campos de configuração.
missing_orgHTTP 403#missing_org
quando
A chave não carrega vínculo com uma organização — chave malformada ou emitida incorretamente.
o que fazer
Gerar uma nova chave no portal e reportar a antiga à equipe Bumcash com o request_id.
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. No confirm-phone, o mesmo código também cobre "CPF existe mas você não tem vínculo" — a resposta é deliberadamente idêntica (anti-enumeration).
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."
  }
}
customer_not_linkedHTTP 404#customer_not_linked
quando
Consulta de saldo por ?cpf=: o cliente existe mas não tem vínculo com a sua chave (registro, ativação ou transação nos últimos 12 meses).
o que fazer
Criar o vínculo via POST /customers/register antes de consultar.
customer_not_linked_by_phoneHTTP 404#customer_not_linked_by_phone
quando
Consulta de saldo por telefone sem vínculo — resposta idêntica para "número de cliente de outro merchant" e "número desconhecido" (anti-enumeration).
o que fazer
Pedir o CPF ao cliente e seguir por lookup?cpf= / register / confirm-phone.
location_not_foundHTTP 404#location_not_found
quando
O cnpj enviado não resolve para nenhuma location no seu escopo — Partner: nenhuma location integrada por você com esse CNPJ; Merchant: nenhuma location sua.
o que fazer
Conferir o CNPJ. Se o lojista é novo na sua carteira, confirme com a equipe Bumcash que a location foi vinculada ao seu integrador.
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 é.
phone_conflictHTTP 409#phone_conflict
quando
confirm-phone com um número que já está atrelado a outro cliente. A resposta não identifica qual.
o que fazer
Reconfirmar o número com o cliente — pode ser linha compartilhada ou erro de digitação.
location_ambiguousHTTP 409#location_ambiguous
quando
O cnpj resolve para mais de uma location no seu escopo (documento duplicado na sua carteira).
o que fazer
Enviar location_id explícito para desambiguar.
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.