Referência da API
A Veridia expõe uma API REST pequena. JSON na entrada, JSON na saída. Sem SOAP, sem GraphQL, sem XML.
URL base
https://api.xxuxe.online
Todas as requisições devem usar HTTPS.
Endpoints
| Método | Caminho | Auth | Finalidade |
|---|---|---|---|
POST | /v1/verify/init | Chave de API | Inicia uma verificação e retorna os slots de upload |
PUT | /v1/verify/upload/:verificationId/:role | Token de upload | Envia uma imagem |
GET | /v1/verify/challenge/:verificationId/next | Token de upload | Próximo beacon de prova de vida (liveness) ativa (somente em fluxos que optaram por ela) |
POST | /v1/verify/submit | Chave de API | Executa o pipeline sobre as imagens enviadas |
GET | /v1/verify/:id | Chave de API — somente secreta | Consulta status e veredicto |
GET | /health | Nenhuma | Checagem de disponibilidade |
O widget usa todos eles por baixo dos panos. Você os chama diretamente quando está construindo um fluxo server-side ou um cliente mobile personalizado.
Dois deles passam despercebidos com facilidade, e ambos são estruturais:
PUT /v1/verify/upload/...é por onde passa cada byte de imagem do produto. Ele não aceita bearer token. Veja POST /v1/verify/init.GET /v1/verify/challenge/.../nextsó existe em fluxos que optaram pela prova de vida ativa comactiveLiveness: trueno/init.
Não existe /v1/verifications nem /v1/verifications/:id. Esses caminhos retornam 404 not_found; o endpoint de resultados é GET /v1/verify/:id.
Autenticação
A maioria dos endpoints usa um bearer token:
Authorization: Bearer qv_pub_FJJWXMA2RN2XPRDK6YJX4KTVD0XSQHW9
Existem duas famílias de chaves, e essa separação é a coisa mais importante desta página:
| Família | Prefixo live | Prefixo de teste | Onde roda | Pode ler veredictos? |
|---|---|---|---|---|
| Publicável | qv_pub_ | qv_pubt_ | Navegador, widget, app mobile | Não |
| Secreta | qv_sec_ | qv_sect_ | Apenas no seu servidor | Sim |
Uma chave publicável pode iniciar uma verificação e submetê-la. Ela não pode ler o resultado — GET /v1/verify/:id a rejeita com 401 secret_key_required. Isso é deliberado: uma chave publicável fica no código-fonte da sua página, onde qualquer pessoa pode lê-la, então ela nunca pode ser capaz de obter um veredicto de KYC.
Repare nos prefixos de teste: qv_pubt_ e qv_sect_. Não qv_pub_test_.
Os endpoints de upload e de desafio não usam nenhum dos dois. Eles se autenticam com o X-Veridia-Upload-Token de vida curta que o /init retorna dentro do campo headers de cada slot de upload.
Detalhes completos: Autenticação.
Versionamento
A API é versionada no caminho da URL: /v1/.... Mudanças que quebram compatibilidade recebem um novo caminho de versão (/v2/...).
Adições que não quebram compatibilidade — novos campos opcionais de requisição, novos campos de resposta, novos endpoints — acontecem em /v1 sem aviso. Escreva clientes que ignorem campos de resposta que não reconhecem.
Formato da requisição
Todos os corpos de POST são JSON:
POST /v1/verify/init HTTP/1.1
Host: api.xxuxe.online
Authorization: Bearer qv_pub_...
Content-Type: application/json
{
"userRef": "customer-12345",
"country": "PY",
"documentType": "dni"
}
Os corpos de requisição são validados com um schema não estrito. Uma chave que não reconhecemos é descartada sem erro — você recebe 200 OK e o valor simplesmente desaparece.
Então, se você inventar um campo (tenantId, callbackUrl, metadata no /init), nada avisa que ele não teve efeito. Confira as tabelas de campos na página de cada endpoint em vez de assumir que um campo funcionou só porque a requisição teve sucesso.
Formato da resposta
Toda resposta carrega um requestId, e o mesmo valor está no cabeçalho de resposta X-Request-Id — assim você consegue correlacionar até quando o parse do JSON falha. Registre-o em log. É o caminho mais rápido para um diagnóstico em um chamado de suporte.
{
"verificationId": "vf_AG07CDWRRFQV4T05ZXG2",
"uploads": { "docFront": { "...": "..." } },
"expiresAt": 1714604000
}
Os erros usam um formato consistente:
{
"error": "invalid_body",
"message": "Request body failed validation",
"requestId": "9f511d92ac11236d-SJC",
"detail": {
"fieldErrors": {
"country": ["expected 2 characters"]
}
}
}
Faça o switch em error, não no status HTTP. Veja Erros para o catálogo completo.
Status não é veredicto
O erro mais caro que esta API permite:
| Campo | Eixo | Valores |
|---|---|---|
status | O pipeline rodou? | queued, processing, completed, failed |
verdict | A pessoa passou? | approved, review, rejected |
status: "completed" significa que o pipeline terminou. Não diz nada sobre o solicitante ter sido aceito ou não. Ramificar por status para liberar uma conta admite todo solicitante rejeitado, silenciosamente, sem erro algum em lugar nenhum.
// ERRADO — isso faz onboarding de todo mundo que o sistema rejeitou
if (result.status === 'completed') enableAccount(userId);
// CERTO
if (result.status === 'completed' && result.verdict === 'approved') enableAccount(userId);
verdict fica ausente (ou null) até que status seja completed. Detalhes em GET /v1/verify/:id.
Limites de taxa
Duas camadas. A que pega as pessoas de surpresa é a camada por IP, que é verificada antes de a sua chave ser lida:
| Camada | Limite |
|---|---|
| Por IP do cliente, todas as rotas | 100 requisições / 60 s |
Por tenant — /v1/verify/init | 60 / 60 s |
Por tenant — /v1/verify/submit | 30 / 60 s |
Por tenant — /v1/verify/:id | 600 / 60 s |
Uma verificação com prova de vida ativa faz cerca de 26 requisições a partir do dispositivo do usuário, então um punhado de usuários mobile atrás de um único endereço CGNAT pode esgotar o orçamento por IP enquanto os contadores do seu tenant parecem ociosos. A explicação completa, e o que fazer a respeito, está em Limites de taxa — leia antes de colocar em produção para mobile.
As respostas 429 carregam um cabeçalho Retry-After.
CORS
As respostas de preflight (OPTIONS) ficam em cache por 10 minutos.
Requisições cross-origin não são restringidas por padrão. Uma chave publicável pode carregar uma lista de origens permitidas, mas toda chave é criada com essa lista vazia, e uma lista vazia permite todas as origens. Trate isso como uma forma de delimitar onde o seu widget roda depois que você a preencher — não como um controle de acesso. Veja o aviso em Autenticação.
Para onde ir agora
- Autenticação — famílias de chaves, ambientes, o que a lista de origens faz e o que não faz
- POST /v1/verify/init — inicia uma verificação, e como os uploads realmente funcionam
- POST /v1/verify/submit — executa o pipeline
- GET /v1/verify/:id — obtém o veredicto
- Erros — referência de códigos de erro
- Limites de taxa — os dois limites, e a ressalva do CGNAT