ReferênciaErros

Erros

Todos os códigos de erro da API da Certivant explicados — formato da resposta, correspondência com códigos HTTP, orientações de tratamento por código e um wrapper robusto de novas tentativas que você pode incluir na sua integração.

Toda resposta de erro da API da Certivant segue o mesmo formato. Crie um único manipulador de erros que consuma esse formato e você conseguirá tratar todos os endpoints de maneira uniforme.

Formato da resposta

{
  "success": false,
  "error": {
    "code": "VALIDATION_ERROR",
    "message": "Body validation failed.",
    "fields": {
      "applicant.dateOfBirth": "Invalid date format. Expected YYYY-MM-DD.",
      "applicant.nationality": "Must be a 2-character ISO 3166-1 alpha-2 code."
    }
  }
}
CampoTipoObservações
successbooleanSempre false em erros
error.codestringLegível por máquina. Use-o para decidir o fluxo do programa
error.messagestringLegível por humanos. Seguro para registrar em log; não é seguro exibi-lo diretamente aos solicitantes
error.fieldsobjectPresente somente em VALIDATION_ERROR. Relaciona os caminhos dos campos, em notação de ponto, às mensagens de erro de cada campo

As strings de message de erro não são garantidamente estáveis entre versões. Use code em qualquer lógica; trate message como apoio a registros em log e à experiência do desenvolvedor.

Código HTTP → código de erro

HTTPerror.code típicoO que significa
400VALIDATION_ERRORO corpo da requisição falhou na validação Zod. Verifique fields
400BAD_REQUESTRequisição inválida genérica (por exemplo, enviar antes de todos os documentos terem sido carregados)
401UNAUTHORIZEDChave de API ausente, malformada, revogada ou expirada
402verification_unavailableA organização não tem mais créditos e não está configurada para continuar sem crédito
403FORBIDDENA chave é válida, mas não tem o escopo exigido, vem de um endereço fora da sua lista de permissão de IP, está restrita a outros formulários, ou o recurso pertence a outra organização
404NOT_FOUNDO recurso (req_…, doc_… etc.) não existe ou não é visível para a organização desta chave
409CONFLICTTransição de estado não permitida (por exemplo, submeter uma requisição duas vezes), ou violação de restrição de unicidade (externalRef já em uso)
413BAD_REQUESTEnvio de arquivo acima de 10 MB
415BAD_REQUESTContent-Type não suportado pelo endpoint (por exemplo, corpo JSON em um endpoint multipart)
429RATE_LIMITEDLimite de requisições por minuto excedido. Veja Limites de requisições
500INTERNAL_ERRORErro inesperado no servidor. Sempre registrado do nosso lado; repetir a chamada é seguro
502BAD_GATEWAYUm serviço upstream (provedor de sanções, gateway de pagamento, registro) está fora do ar. Tente novamente após um intervalo
503SERVICE_UNAVAILABLEBanco de dados degradado. Tente novamente com espera progressiva

Catálogo de códigos de erro

UNAUTHORIZED

A chave de API no cabeçalho Authorization está ausente, malformada ou revogada.

{ "success": false, "error": { "code": "UNAUTHORIZED", "message": "Invalid or revoked API key." } }

error.reason indica qual desses casos ocorreu: missing_api_key, invalid_api_key, api_key_revoked, api_key_expired ou api_key_rotated (a chave foi rotacionada e a janela de sobreposição terminou). A lista completa está em Autenticação.

Como tratar: confirme que o cabeçalho é Authorization: Bearer ck_live_… (ou ck_test_…; chaves mais antigas começam com kyk_). Verifique no painel o status da chave. Se ela aparecer como revogada ou expirada, crie uma nova chave ou rotacione a atual.

FORBIDDEN

A chave é válida, mas não tem o escopo exigido, ou o recurso pertence a uma organização diferente da organização da chave.

{ "success": false, "error": { "code": "FORBIDDEN", "message": "This API key does not include the kyc:manage scope required for this endpoint." } }

error.reason é insufficient_scope (a chave não tem um escopo), ip_not_allowed (o endereço de quem chama não está na lista de permissão de IP da chave) ou form_not_allowed (a chave está restrita a outros formulários).

Como tratar: verifique os escopos e as restrições da sua chave no painel (KYC → Desenvolvedor, o ícone de lápis). Você pode editar as permissões, as restrições de formulário e de fluxo de trabalho, a lista de permissão de IP e a validade de uma chave sem alterar o seu segredo; o segredo e o ambiente (produção ou teste) não podem ser alterados.

verification_unavailable (HTTP 402)

A sua organização não tem mais créditos e não está configurada para continuar sem crédito, por isso a Certivant não consegue aceitar uma nova verificação. A resposta usa o código verification_unavailable:

{ "success": false, "error": { "code": "verification_unavailable", "message": "This organization is temporarily unable to accept new verifications. Please contact them to continue." } }

Como tratar: recarregue o saldo de créditos em Configurações → Créditos e uso (seus proprietários e administradores também recebem uma notificação e um e-mail, no máximo uma vez por dia). Os solicitantes que encontrarem a mesma condição em um formulário ou em uma página hospedada verão uma página pedindo que entrem em contato com a sua organização; essa página nunca menciona crédito ou dinheiro. Veja Faturamento e créditos.

NOT_FOUND

{ "success": false, "error": { "code": "NOT_FOUND", "message": "Request not found." } }

Como tratar: verifique o ID do recurso. Uma causa comum é usar um ID de outro ambiente — IDs de homologação não existem em produção, e vice-versa.

VALIDATION_ERROR

O corpo da requisição falhou na validação do esquema. O mapa fields lista cada campo com erro e a respectiva mensagem.

{
  "success": false,
  "error": {
    "code": "VALIDATION_ERROR",
    "message": "Body validation failed.",
    "fields": {
      "type": "Required",
      "applicant.email": "Invalid email format"
    }
  }
}

Como tratar: exiba fields ao lado dos campos do seu formulário. Os caminhos dos campos usam notação de ponto para campos aninhados e [N] para índices de array (directors[0].dateOfBirth).

BAD_REQUEST

Requisição inválida genérica, que não se encaixa em outras categorias.

{ "success": false, "error": { "code": "BAD_REQUEST", "message": "Cannot submit a request with pending documents. Upload the remaining documents first." } }

Como tratar: leia a message. Normalmente ela indica um problema de sequência — chame antes o endpoint pré-requisito.

CONFLICT

Uma transição de estado que não é permitida a partir do estado atual, ou uma violação de restrição de unicidade.

{ "success": false, "error": { "code": "CONFLICT", "message": "externalRef already in use by request req_…" } }

Como tratar: consulte o estado atual da requisição por meio de GET /requests/:id e ajuste. Para violações de referência única, busque a requisição existente (usando ?externalRef=… no endpoint de listagem) ou escolha uma referência diferente.

RATE_LIMITED

{ "success": false, "error": { "code": "RATE_LIMITED", "message": "Rate limit exceeded. Max 120 requests per 60s. Retry in 14s." } }

Os cabeçalhos desta resposta incluem X-RateLimit-Limit, X-RateLimit-Remaining e X-RateLimit-Reset (segundos até que o limite seja reabastecido). Veja Limites de requisições para a estratégia de novas tentativas.

INTERNAL_ERROR

Algo falhou do nosso lado. A Certivant registra todo erro 500 com o contexto completo.

{ "success": false, "error": { "code": "INTERNAL_ERROR", "message": "An unexpected error occurred. Please try again." } }

Como tratar: tente novamente uma vez após um breve intervalo. Se o problema persistir, consulte a página de status e entre em contato com o suporte informando o ID da requisição.

BAD_GATEWAY e SERVICE_UNAVAILABLE

Uma dependência upstream está fora do ar (API do registro comercial, provedor de dados de sanções, armazenamento) ou o banco de dados está degradado.

{ "success": false, "error": { "code": "BAD_GATEWAY", "message": "Sanctions screening provider is unreachable. The request remains in PENDING state — Certivant will retry automatically." } }

Como tratar: trate esses erros como transitórios. Implemente uma espera exponencial (1 s, 2 s, 4 s, 8 s, 16 s) e pare após cerca de 5 tentativas. A requisição não é perdida — a fila da própria Certivant retomará o processamento quando a dependência upstream se recuperar.

Um manipulador de erros robusto

async function callCertivant<T>(
  fn: () => Promise<Response>,
  options: { maxRetries?: number } = {},
): Promise<T> {
  const maxRetries = options.maxRetries ?? 3;
  let attempt = 0;
  let delay = 500;

  while (true) {
    const res = await fn();

    if (res.ok) return (await res.json()) as T;

    const body = (await res.json().catch(() => null)) as
      | { error?: { code: string; message: string } }
      | null;
    const code = body?.error?.code ?? "INTERNAL_ERROR";

    // Retry on transient errors
    if (
      attempt < maxRetries &&
      (res.status === 429 || res.status >= 500)
    ) {
      const retryAfter =
        res.status === 429
          ? Number(res.headers.get("X-RateLimit-Reset") ?? 60) * 1000
          : delay;
      await sleep(retryAfter);
      delay *= 2;
      attempt += 1;
      continue;
    }

    // Bubble everything else up
    throw new CertivantError(code, body?.error?.message ?? "Unknown error", res.status);
  }
}

Este padrão trata todos os erros documentados acima:

  • Classe 200 → interpretar e retornar.
  • 429 → aguardar X-RateLimit-Reset e tentar novamente.
  • 5xx → espera exponencial e nova tentativa.
  • 4xx → lançar o erro imediatamente (o seu código está errado; nenhuma nova tentativa vai resolver).