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."
}
}
}
| Campo | Tipo | Observações |
|---|---|---|
success | boolean | Sempre false em erros |
error.code | string | Legível por máquina. Use-o para decidir o fluxo do programa |
error.message | string | Legível por humanos. Seguro para registrar em log; não é seguro exibi-lo diretamente aos solicitantes |
error.fields | object | Presente 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
| HTTP | error.code típico | O que significa |
|---|---|---|
400 | VALIDATION_ERROR | O corpo da requisição falhou na validação Zod. Verifique fields |
400 | BAD_REQUEST | Requisição inválida genérica (por exemplo, enviar antes de todos os documentos terem sido carregados) |
401 | UNAUTHORIZED | Chave de API ausente, malformada, revogada ou expirada |
402 | verification_unavailable | A organização não tem mais créditos e não está configurada para continuar sem crédito |
403 | FORBIDDEN | A 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 |
404 | NOT_FOUND | O recurso (req_…, doc_… etc.) não existe ou não é visível para a organização desta chave |
409 | CONFLICT | Transiçã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) |
413 | BAD_REQUEST | Envio de arquivo acima de 10 MB |
415 | BAD_REQUEST | Content-Type não suportado pelo endpoint (por exemplo, corpo JSON em um endpoint multipart) |
429 | RATE_LIMITED | Limite de requisições por minuto excedido. Veja Limites de requisições |
500 | INTERNAL_ERROR | Erro inesperado no servidor. Sempre registrado do nosso lado; repetir a chamada é seguro |
502 | BAD_GATEWAY | Um serviço upstream (provedor de sanções, gateway de pagamento, registro) está fora do ar. Tente novamente após um intervalo |
503 | SERVICE_UNAVAILABLE | Banco 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→ aguardarX-RateLimit-Resete 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).
Referência da API (OpenAPI)
A API REST completa da Certivant como um documento OpenAPI 3.1 — uma especificação JSON pública que você pode importar no Postman ou usar em um gerador de código, além de uma referência interativa com todos os endpoints, esquemas, escopos e eventos de webhook.
Limites de requisições
A Certivant aplica um limite de requisições por minuto baseado no plano — aprenda a ler os cabeçalhos de limite, a tratar respostas 429, a repetir chamadas corretamente e a projetar a sua integração para ficar abaixo do limite.