Skip to main content

Versão 2026-09-23

Mudança aditiva — nenhuma integração existente quebra.

Novo: Verificação Facial (Face Match + Passive Liveness)

  • Novo endpoint POST /verificacoes/facial — verificação facial avulsa, sem vincular a um cliente cadastrado. Requer novo escopo biometria:write. Ver Verificação facial avulsa.
  • POST /customers (via upload de documentos em sequência) e POST /customers/{id}/documents passam a disparar Face Match + Passive Liveness automaticamente, em background, quando o par selfie + documento de identidade suportado fica completo — condicionado a módulo “Verificação facial” ativo (master) e configuração habilitada (tenant); sem parâmetro para ativar/pular por chamada. Ver Criar cliente e Anexar documento.
  • GET /api/v1/customers/:id ganha o campo facial_verification — resultado da rodada mais recente, apenas para clientes PF.
  • Novo evento de webhook biometric_check.completed — disparado ao final de cada rodada de verificação facial do fluxo automático (não do endpoint avulso, que é síncrono). Requer marcar o evento em “Eventos assinados” na configuração do endpoint — diferente de run.completed/run.failed, que são sempre entregues.
  • Verificação facial bem-sucedida consome o mesmo saldo do tenant usado por bureau runs.
  • Visão geral do produto, os dois fluxos disponíveis e a pendência jurídica de LGPD em aberto: Verificação Facial.

Versão 2026-08-27

Mudança aditiva — nenhuma integração existente quebra.
  • address em POST /api/v1/customers e na resposta de GET /api/v1/customers/:id passa a validar formato: street, city (não vazias, com limite de tamanho), number e complement (limite de tamanho), state (sigla de UF válida, antes só checava 2 caracteres) e zip (8 dígitos após remover não-dígitos). Payloads já corretos não são afetados; payloads com dado inválido nesses campos passam a retornar 400 invalid_address.
  • Novos subcampos opcionais em address: complement e neighborhood.
  • GET /api/v1/customers/:id agora retorna address para clientes PJ além de PF (antes só retornava para PF, mesmo quando o endereço PJ existia salvo).

email/phone na listagem de clientes

  • GET /api/v1/customers (listagem) passa a incluir email e phone em cada item de data[] — colunas simples da mesma tabela, sem join, sem custo extra de query. Mesma regra de mascaramento de e-mail-placeholder já usada em GET /customers/:id (cliente PJ sem e-mail real não expõe o endereço @kycert.internal gerado internamente).
  • documents e latest_run continuam exclusivos de GET /customers/:id — cada um exigiria uma query por cliente numa listagem (N+1). Decisão deliberada, não uma lacuna. Ver Listar clientes, seção “Campos ausentes na listagem”.
  • POST /api/v1/customers também passa a retornar phone na resposta de criação quando enviado no payload (já era aceito e persistido, mas não voltava na resposta).

Novo endpoint: anexar documento

  • POST /customers/{id}/documents (multipart/form-data) — anexa um documento (RG, CNH, comprovante de residência etc.) a um cliente já cadastrado. Reusa o escopo customers:write, sem escopo novo. Limite de arquivo: 4MB (teto de infraestrutura da plataforma de hosting, não configurável). Ver Anexar documento.
  • GET /api/v1/customers/:id ganha o campo documents — resumo (type, status, created_at) dos documentos anexados ao cliente, sem storage_path nem signed URL.

template_id agora é opcional em run_bureau: true

  • POST /customers com run_bureau: true não exige mais template_id quando o tenant tem um template padrão configurado em Configurações → Bureau (PF e/ou PJ) — a API resolve automaticamente pelo type do cliente. Ver Criar cliente, seção “Template padrão”.
  • Novo campo opcional onboarding_profile (slug) — quando enviado e válido, o template do perfil de cadastro tem prioridade sobre o default do tenant, mesma prioridade do ?perfil=slug do portal público.
  • Chamadas com template_id explícito continuam funcionando exatamente como antes — nenhuma mudança de comportamento ou resposta para quem já envia template_id.
  • Atenção — mudança de código de erro: chamadas com run_bureau: true sem template_id e sem template padrão configurado, que antes retornavam 400 missing_template_id, agora retornam 400 missing_default_template (mensagem orienta a configurar um default ou enviar template_id). Se sua integração faz match programático no error.code missing_template_id, atualize para missing_default_template.
  • O toggle “Bureau automático” (bureau_enabled) do dashboard, que controla o disparo automático do portal público, não afeta esta resolução — run_bureau: true via API é sempre um pedido explícito do integrador.

Campos complementares em POST /customers e GET /customers/:id

  • Novos campos opcionais: nationality, occupation, declared_income (PF) e trade_name, annual_revenue, business_activity, employee_count (PJ) — mesmos dados que o portal público de cadastro já coleta, agora disponíveis para fechar um cadastro completo via API. Ver Criar cliente.
  • Cada campo é exclusivo do type correspondente — enviar um campo PF com type: "pj" (ou vice-versa) retorna 400 invalid_request_error.
  • declared_income e annual_revenue são apenas armazenados — não acionam recálculo automático de capacidade financeira (motor de renda).
  • GET /api/v1/customers/:id retorna cada campo apenas quando foi enviado na criação — nenhum valor default é inventado.

Novo header: Idempotency-Key em POST /customers

  • POST /api/v1/customers passa a suportar o header Idempotency-Key (mesmo mecanismo já usado por POST /bureau/runs) — envie um UUID único por tentativa; reenviar a mesma chave nas próximas 24h retorna a resposta original em cache, sem criar cliente nem disparar bureau de novo. Ver Criar cliente, seção “Header Idempotency-Key”.
  • Corrige um bug de produção: retry sem essa chave num cliente que já existia em rascunho (de um convite/formulário incompleto do portal) disparava um segundo bureau run para o mesmo cliente a cada tentativa, cobrado em dobro. O header é opcional (opt-in) — chamadas sem ele continuam funcionando exatamente como hoje.
  • Correção pós-QA: a primeira versão fechava a janela só para retries sequenciais — duas chamadas com a mesma Idempotency-Key disparadas em paralelo (ex: timeout de rede curto + retry automático) ainda podiam ambas passar e duplicar o bureau run. Agora a chave é reservada atomicamente na primeira chamada: uma segunda chamada concorrente enquanto a primeira ainda processa recebe 409 idempotency_key_in_progress (com header Retry-After) em vez de reprocessar. Novo código de erro, mudança aditiva.

Versão 2026-06-03

Versão inicial pública da API kycert.

Endpoints disponíveis

  • POST /api/v1/bureau/runs — criar run de bureau
  • GET /api/v1/bureau/runs — listar runs com filtros e paginação
  • GET /api/v1/bureau/runs/:id — obter status e resultado de um run
  • GET /api/v1/bureau/runs/:id/analysis — análise completa com todos os checks
  • GET /api/v1/bureau/runs/:id/detail — detalhe técnico por fonte (escopo detail:read)

Autenticação

  • Header x-api-key: sk_live_... (recomendado)
  • Header Authorization: Bearer sk_live_... (alternativo)
  • Escopos: runs:write, runs:read, detail:read

Webhooks

  • Evento run.completed — run finalizado com decisão
  • Evento run.failed — falha técnica no run
  • Verificação de assinatura HMAC-SHA256 via header kycert-signature
  • Política de retry: 7 tentativas em até 24h

Outros

  • Idempotency-Key no POST /runs — retry seguro nas próximas 24h
  • x-kycert-api-version — versionamento explícito
  • Sandbox com CPFs e CNPJs de teste
  • Paginação cursor-based no GET /runs

Política de breaking changes

Nos comprometemos com estabilidade. Antes de qualquer breaking change:
  1. Aviso mínimo de 90 dias — comunicado por e-mail e no dashboard
  2. Headers de deprecação — respostas incluirão Deprecation e Sunset quando um endpoint ou campo for depreciado
  3. E-mail de aviso — clientes com keys ativas na versão depreciada recebem notificação
  4. Versão antiga mantida por no mínimo 12 meses após o anúncio de depreciação

O que é considerado breaking change

  • Remover ou renomear um campo de response
  • Alterar o tipo de um campo existente
  • Remover um endpoint
  • Alterar o comportamento de um código de erro existente
  • Remover um valor de enum existente

O que não é breaking change

  • Adicionar novos campos opcionais ao request ou response
  • Adicionar novos endpoints
  • Adicionar novos valores de enum
  • Melhorar mensagens de erro
  • Mudanças de performance ou latência