Erros
Todos os erros da API Veridia seguem um shape consistente. Esta pagina e a referencia canonica para cada codigo de erro que voce pode ver.
Shape de resposta de erro
Cada resposta de erro inclui:
{
"error": "invalid_body",
"message": "Request body failed validation",
"requestId": "9f511d92ac11236d-SJC",
"detail": {
"fieldErrors": {
"country": ["expected 2 characters"]
}
}
}
| Campo | Tipo | Descricao |
|---|---|---|
error | string | Codigo machine-readable — switch neste no seu codigo |
message | string | Resumo human-readable, principalmente para logs |
requestId | string | ID unico desta request — inclua em tickets de suporte |
detail | object | Opcional. Contexto extra (erros de campo, motivo de mismatch de keys, etc.) |
O mesmo requestId tambem e retornado no response header X-Request-Id — util quando o parsing JSON falha.
Catalogo de erros
invalid_body — 400 Bad Request
O body da request falhou validacao do schema Zod. Verifique detail.fieldErrors para especificos.
Causas comuns:
- Campo obrigatorio faltando
- Tipo errado (ex: string onde se esperava number)
- String muito longa (ex:
userRef > 128chars) - Valor enum invalido (ex:
documentType: "id"em vez de"dni") verificationIdnao bate^vf_[A-Za-z0-9]{16,24}$
Em /submit especificamente, detail.reason pode ser:
| Reason | Significado |
|---|---|
doc_front_key_mismatch | O keys.docFront nao bate com o que /init retornou |
selfie_key_mismatch | O keys.selfie nao bate com o que /init retornou |
doc_back_key_mismatch | O keys.docBack nao bate com o que /init retornou |
doc_front_not_uploaded | O objeto R2 da frente nao existe — o cliente nunca fez upload |
selfie_not_uploaded | O objeto R2 da selfie nao existe |
doc_front_disappeared | O objeto R2 existia durante o HEAD mas sumiu antes do OCR (extremamente raro) |
Recovery: Conserte a request e tente de novo. Estes sao erros do cliente.
unauthorized — 401 Unauthorized
O header Authorization esta faltando, malformado, ou nao usa o scheme Bearer.
Recovery: Adicione um header Authorization: Bearer <key> valido.
invalid_key — 401 Unauthorized
O bearer token nao corresponde a uma key valida. Nunca existiu, foi revogada, ou expirou.
Recovery: Gere uma nova key no dashboard. Verifique que voce esta usando a key correta para o environment correto.
origin_not_allowed — 403 Forbidden
A publishable key foi usada de um dominio que nao esta na lista de allowed origins.
Recovery: Adicione seu dominio a lista de allowed origins no dashboard. Para desenvolvimento local, adicione http://localhost:PORT.
wrong_environment — 403 Forbidden
Uma test key (qv_pub_test_* / qv_sec_test_*) foi usada com um endpoint live, ou vice-versa.
Recovery: Use o environment correspondente. Test keys para teste, live keys para producao.
insufficient_credits — 403 Forbidden
O tenant tem 0 creditos. Novas verificacoes nao podem iniciar.
Recovery: Top up creditos no dashboard, ou contate o suporte se voce esta num plano custom.
verification_not_found — 404 Not Found
O verificationId nao existe, nao pertence a este tenant, ou o intent expirou (>1 hora apos /init).
Recovery:
- Verifique que o ID nao tenha typos
- Garanta que voce esta usando a mesma API key (ou outra do mesmo tenant)
- Se passou mais de 1 hora desde
/init, reinicie o fluxo
not_found — 404 Not Found
A rota nao existe.
Recovery: Verifique a URL. Typos comuns: /v1/verifications em vez de /v1/verify/:id.
rate_limited — 429 Too Many Requests
Atingiu o rate limit por tenant. O response header Retry-After diz quanto esperar (em segundos).
| Endpoint | Limite padrao |
|---|---|
/v1/verify/init | 60 / minuto |
/v1/verify/submit | 30 / minuto |
/v1/verify/:id | 600 / minuto |
Recovery:
- Espere a duracao em
Retry-After, depois tente de novo - Adicione throttling do seu lado
- Contate o suporte para elevar limites por-tenant
internal — 500 Internal Server Error
Algo quebrou do lado da Veridia. Raro.
Recovery:
- Tente de novo com backoff exponencial (o issue pode ser transitorio)
- Se persistir, abra um ticket de suporte com o
requestIdda resposta
Gerenciando erros bem
JavaScript / Node.js
async function callVeridia(url, options) {
const response = await fetch(url, options);
if (response.ok) {
return response.json();
}
const error = await response.json();
// Switch no error code, nao no HTTP status
switch (error.error) {
case 'invalid_body':
console.error('Validation falhou:', error.detail?.fieldErrors);
throw new ValidationError(error);
case 'rate_limited':
const retryAfter = response.headers.get('Retry-After') || 1;
await new Promise(r => setTimeout(r, retryAfter * 1000));
return callVeridia(url, options); // tenta de novo uma vez
case 'insufficient_credits':
// Notifica ops, fallback para revisao manual
await notifyCreditsExhausted();
throw new BusinessError(error);
case 'verification_not_found':
// Erro logico — reinicia o fluxo
throw new NotFoundError(error);
case 'internal':
// Issue da Veridia — logue e alerte
logger.error('Veridia internal error', {
requestId: error.requestId,
url,
});
throw new ExternalServiceError(error);
default:
throw new Error(`Veridia erro nao gerenciado: ${error.error}`);
}
}
Python
import time
import requests
def call_veridia(url, **kwargs):
response = requests.request(**kwargs, url=url)
if response.ok:
return response.json()
error = response.json()
if error["error"] == "invalid_body":
raise ValidationError(error)
if error["error"] == "rate_limited":
retry_after = int(response.headers.get("Retry-After", 1))
time.sleep(retry_after)
return call_veridia(url, **kwargs)
if error["error"] == "insufficient_credits":
notify_credits_exhausted()
raise BusinessError(error)
if error["error"] == "verification_not_found":
raise NotFoundError(error)
if error["error"] == "internal":
logger.error(
"Veridia internal error",
extra={"request_id": error["requestId"], "url": url},
)
raise ExternalServiceError(error)
raise Exception(f"Veridia erro nao gerenciado: {error['error']}")
Best practices
- Switch em
error.error, nao em HTTP status. Os codigos HTTP podem mudar por motivos nao-breaking; o codigoerrorstring e parte do nosso contrato publico de API - Sempre logue o
requestId. E o caminho mais rapido para diagnostico se voce abrir um ticket de suporte - Tente de novo com backoff para
internalerate_limited. Nao tente de novoinvalid_body,unauthorized,verification_not_found, ouinsufficient_credits - Surface erros de validation aos seus developers, nao aos usuarios finais. Usuarios finais devem ver "Algo deu errado, por favor tente de novo"
- Monitore
insufficient_creditscomo business alert — significa que voce esta perdendo faturamento
Proximos passos
- Autenticacao — keys, environments, seguranca
- Rate limits — limites e gerenciamento de cota
- Referencia API — voltar ao overview da API