Referência da APISolicitações KYC

Solicitações KYC

Referência completa da API de solicitações KYC da Certivant — criar, listar, enviar, aprovar, rejeitar, encaminhar e reenviar solicitações de verificação de identidade de pessoas físicas ou jurídicas.

Uma solicitação KYC representa uma única tentativa de verificar a identidade de uma pessoa (INDIVIDUAL) ou a identidade de uma empresa, junto com seus diretores e beneficiários finais (BUSINESS). Todos os endpoints abaixo ficam em /api/v1/kyc/requests.

Todos os endpoints exigem uma chave de API com o escopo relevante. Consulte Autenticação.


Criar uma solicitação

POST /api/v1/kyc/requests    Escopo: kyc:write

Cria uma nova solicitação no estado PENDING_UPLOAD. Os dados do solicitante são opcionais — se você não os enviar, o solicitante os preenche pela sessão hospedada.

Corpo da requisição

{
  "type": "INDIVIDUAL",
  "purpose": "Financing an iPhone 16, 24 months",
  "externalRef": "your-id-here",
  "subTenantName": "Acme Corp",
  "subTenantExternalId": "cust_8842",
  "applicant": {
    "externalRef": "your-applicant-id",
    "fullName": "Jane Doe",
    "dateOfBirth": "1990-04-12",
    "nationality": "US",
    "email": "jane@example.com",
    "phone": "+14155551234",
    "emailVerified": false,
    "phoneVerified": false,
    "metadata": { "anyKey": "anyValue" }
  }
}
CampoTipoObrigatórioObservações
typeenumsimINDIVIDUAL ou BUSINESS
purposestringnãoPor que você está verificando esta pessoa, em poucas palavras — ex.: Financing an iPhone 16, 24 months, Opening an account. 3–300 caracteres. Armazenado criptografado. Se você não enviar nenhum, a Certivant usa o motivo padrão do formulário (formId) e, se não houver, "New customer verification" (sempre armazenado em inglês). Recomenda-se um motivo específico: ele torna útil a verificação de fraude. Veja Motivo da verificação
externalRefstringnãoSua chave estrangeira. Retornada em todos os eventos
subTenantNamestringnãoModo parceiro: nome de exibição do cliente final ao qual esta solicitação pertence. Máximo de 200 caracteres
subTenantExternalIdstringnãoModo parceiro: seu próprio ID interno para esse cliente final. Filtrável no endpoint de listagem e repetido em cada webhook. Máximo de 200 caracteres
formIdstringnãoCrie a verificação por meio de um dos seus formulários (os requisitos de documentos do formulário se aplicam e a solicitação é atribuída a ele). O tipo do formulário deve corresponder a type. Obrigatório para uma chave de API restrita a formulários específicos, e precisa ser um deles — veja Restrição de formulário
faceCheckSkippablebooleannãoOmitido: a configuração do formulário (formId), senão a da sua organização (a verificação facial é obrigatória, a menos que você a altere). false força a verificação facial como obrigatória. true oferece a alternativa não biométrica, somente onde a lei a exigir (p. ex. Quebec): o solicitante pode recusar a verificação facial. Nesse caso nenhum selfie nem prova de vida é executado, o documento de identidade continua sendo coletado e a solicitação vai para a análise manual com uma verificação de identidade ao vivo recomendada. Um formulário pode ativá-la com "Permitir que os solicitantes pulem a verificação facial"; a configuração da organização fica em Configurações → KYC/B.
applicant.externalRefstringnãoChave estrangeira por solicitante, separada da referência da solicitação
applicant.fullNamestringnãoSe omitido, é coletado pela sessão hospedada
applicant.dateOfBirthstring (data ISO)nãoYYYY-MM-DD
applicant.nationalitystring (ISO 3166-1 alpha-2)nãoex.: US, GB, FR
applicant.emailstringnão
applicant.phonestring (E.164)não
applicant.emailVerifiedbooleannãoDefina true se você já verificou o e-mail do seu lado
applicant.phoneVerifiedbooleannãoIgual — pula a etapa de verificação de telefone da Certivant
applicant.metadataobjectnãoJSON arbitrário. Retornado no endpoint GET

Atribuição a parceiros / subclientes. Se você executa verificações para muitos clientes finais dentro de uma mesma organização (por exemplo, uma plataforma de assinatura eletrônica que verifica signatários de centenas de empresas), defina subTenantName e subTenantExternalId em cada solicitação. Depois, você pode filtrar o endpoint de listagem por subTenantExternalId, ambos os campos são repetidos em cada webhook, e o painel exibe um filtro de subcliente — tudo isso sem criar uma organização separada para cada cliente.

Motivo da verificação

Toda solicitação tem um motivo: por que você está verificando a pessoa, em poucas palavras. Enviá-lo é opcional, mas recomenda-se um motivo específico porque ele torna útil a verificação de fraude. A Certivant lê o motivo e o associa a uma das cerca de 110 entradas de uma lista de motivos — por exemplo, financiamento de celular ou aparelho, plano de celular, ativação de SIM, empréstimo pessoal, cartão de crédito, aluguel de carro, criptomoedas, conta bancária, aluguel de imóvel, financiamento imobiliário, assinatura em cartório / escritura, seguro, emprego ou verificação de idade. Cada motivo pertence a uma família: Celulares e aparelhos, Linhas móveis e SIM, Empréstimos e crédito, Veículos, Bens de alto valor, Movimentação de dinheiro e criptomoedas, Abertura de conta, Aluguel de imóvel, Imóveis e financiamento imobiliário, Outro (sem dinheiro em risco) ou Indefinido.

  • Só a família é comparada. A rede de prevenção a fraudes compara entre empresas apenas a família — nunca o texto, nunca o motivo específico. O texto em si é armazenado criptografado, nunca é compartilhado com outra empresa e trafega somente por HTTPS.
  • Só conta o que coloca dinheiro ou crédito em risco. Uma solicitação só entra nos padrões de fraude quando há dinheiro ou crédito em jogo. Uma assinatura em cartório, um financiamento imobiliário, um seguro, contas de consumo, um emprego ou um atendimento de saúde são registrados, mas nunca contam: quem assina uma escritura no cartório e financia um celular um mês depois não é sinalizado.
  • Motivos sensíveis nunca são compartilhados. Saúde, questões jurídicas, imigração, jogos de azar, problemas com dívidas, relacionamentos, religião ou doações, falecimento ou herança e produtos com restrição de idade são armazenados como "Outro".
  • Seja específico. Um motivo como KYC ou verification não diz o que a pessoa está comprando. Por padrão, a solicitação ainda é criada, com um aviso. Se a sua organização ativou Recusar motivos vagos (Configurações → Prevenção de fraude → Regras da rede antifraude), ela é recusada com 422.
  • Não inclua dados pessoais. Endereços de e-mail, números de telefone, de cartão e de documento e datas são removidos antes de qualquer IA ler o motivo — não os escreva nele.

A resposta de criação mostra como o motivo foi interpretado:

CampoValoresSignificado
purposeQualityinformativeO motivo diz o que está sendo comprado, financiado ou aberto.
genericVago demais para ser classificado com precisão.
unusableNão foi possível entendê-lo.
warnings (somente quando relevante)purpose_too_generic · purpose_unusable · purpose_contains_personal_dataO que corrigir no motivo. O último indica que dados pessoais foram encontrados e removidos.

Os mesmos campos são retornados por POST /api/v1/kyc/forms/:formId/send. Para uma visão completa, veja Rede antifraude.

O motivo é escolhido nesta ordem: o purpose que você envia, depois o motivo padrão do formulário (defina-o no editor de formulários) e, por fim, "New customer verification", sempre armazenado em inglês com exatamente esse texto. Por isso, integrações que não enviam nenhum motivo, como plugins de assinatura eletrônica, nunca recebem um erro. O motivo padrão nunca é recusado (nem com Recusar motivos vagos), não gera aviso e não envolve dinheiro em risco, então não alimenta os padrões da rede antifraude.

Resposta (201)

{
  "id": "req_01J...",
  "status": "PENDING_UPLOAD",
  "type": "INDIVIDUAL",
  "externalRef": "your-id-here",
  "subTenantName": "Acme Corp",
  "subTenantExternalId": "cust_8842",
  "pendingDocTypes": ["GOVERNMENT_ID", "SELFIE"],
  "purposeQuality": "informative",
  "applicant": { ... },
  "createdAt": "2026-05-27T10:00:00.000Z"
}

pendingDocTypes reflete as configurações KYC da sua organização — o que é exigido depende de você ter habilitado prova de vida, comprovante de endereço etc.

purposeQuality é informative, generic ou unusable. Quando o motivo exige a sua atenção, um array warnings é adicionado com purpose_too_generic, purpose_unusable e/ou purpose_contains_personal_data.

Erros

  • 400 VALIDATION_ERROR — o corpo falhou na validação Zod. error.fields lista cada caminho com falha.
  • 403 FORBIDDEN — a chave não tem kyc:write, ou (error.reason = "form_not_allowed") a chave está restrita a formulários específicos e a solicitação não tem formId ou indica outro formulário.
  • 404 NOT_FOUND — formId não é um formulário da sua organização.
  • 409 CONFLICT — seu externalRef já está em uso por outra solicitação desta organização. Use outra referência ou consulte a solicitação existente.
  • 422 — a sua organização recusa motivos vagos (Recusar motivos vagos) e purpose é genérico demais ou inutilizável. Informe o que está sendo comprado ou financiado. Também retornado por POST /api/v1/kyc/forms/:formId/send.

Listar solicitações

GET /api/v1/kyc/requests    Escopo: kyc:read

Parâmetros de consulta

ParâmetroTipoPadrãoObservações
statusenum—Filtre por PENDING_UPLOAD, PROCESSING, APPROVED, REJECTED, ESCALATED, CANCELLED
typeenum—INDIVIDUAL ou BUSINESS
externalRefstring—Filtro de correspondência exata pela sua chave estrangeira
subTenantExternalIdstring—Modo parceiro: retorna somente as solicitações marcadas com este ID de cliente final
searchstring—Pesquisa de texto livre pelo nome e e-mail do solicitante
pageinteger1Número da página, começando em 1
limitinteger20Máximo 100

Resposta

{
  "data": [
    { "id": "req_...", "status": "APPROVED", "type": "INDIVIDUAL", "createdAt": "...", "applicant": {...} },
    ...
  ],
  "pagination": {
    "total": 248,
    "page": 1,
    "limit": 20,
    "pages": 13
  }
}

Use o filtro por externalRef para buscar uma solicitação quando você conhecer apenas a sua própria chave estrangeira — não é preciso armazenar o ID req_… da Certivant se o seu externalRef for único.


Obter uma única solicitação

GET /api/v1/kyc/requests/:id    Escopo: kyc:read

Retorna a verificação completa — o solicitante, cada documento enviado (com os campos extraídos por OCR), todas as verificações automatizadas, o detalhamento completo de risco, os sinais de fraude e o registro de auditoria. É tudo o que a tela de detalhes do painel exibe, para que você possa criar sua própria interface de revisão sem precisar enviar a sua equipe para a Certivant.

Resposta

{
  "id": "req_...",
  "status": "ESCALATED",
  "type": "INDIVIDUAL",
  "externalRef": "user-9281",
  "subTenantName": null,
  "subTenantExternalId": null,
  "reviewedBy": null,
  "reviewNote": null,
  "completedAt": null,
  "createdAt": "2026-05-27T10:00:00.000Z",
  "updatedAt": "2026-05-27T10:03:12.000Z",

  "applicant": {
    "id": "app_...",
    "fullName": "Alex Singh",
    "dateOfBirth": "1988-11-03T00:00:00.000Z",
    "nationality": "GBR",
    "email": "alex@example.com",
    "emailVerified": true,
    "phone": "+447700900100",
    "phoneVerified": false,
    "metadata": {}
  },

  "documents": [
    {
      "id": "doc_...",
      "documentType": "id_card",
      "side": "front",
      "status": "done",
      "mimeType": "image/jpeg",
      "fileSize": 412938,
      "parsedData": {
        "fullName": "Alex Singh",
        "dateOfBirth": "1988-11-03",
        "documentNumber": "D1234567",
        "expiryDate": "2030-01-15",
        "nationality": "GBR",
        "issuingCountry": "GBR",
        "address": "12 High St, London"
      },
      "createdAt": "2026-05-27T10:01:00.000Z"
    }
  ],

  "checks": [
    { "id": "chk_1", "checkType": "ocr",        "provider": "aws_textract", "status": "passed", "score": 0.95, "startedAt": "...", "finishedAt": "..." },
    { "id": "chk_2", "checkType": "face_match", "provider": "azure_face",   "status": "passed", "score": 0.88 },
    { "id": "chk_3", "checkType": "liveness",   "provider": "azure_face",   "status": "passed", "score": 0.92 },
    { "id": "chk_4", "checkType": "sanctions",  "provider": "ofac",         "status": "failed", "score": 0.0 }
  ],

  "riskScore": {
    "overallScore": 62,
    "decision": "escalate",
    "autoDecision": true,
    "factors": [
      { "factor": "document_authenticity", "impact": 1.0, "description": "Barcode + metadata valid" }
    ],
    "rejectionReasons": [],
    "verdictMeta": {
      "factorVerdicts": [
        { "id": "1.1", "section": "Identity Document", "label": "Document authenticity", "weight": 15, "state": "pass", "evidence": ["barcode_valid"] },
        { "id": "4.2", "section": "Screening",         "label": "Sanctions / PEP",       "weight": 20, "state": "fail", "evidence": ["ofac_possible_match"] }
      ],
      "disqualifiers": [],
      "reviewTriggers": ["sanctions_possible_match"],
      "effectiveThresholdApprove": 80
    }
  },

  "fraudSignals": [
    { "signalType": "device_reuse", "severity": "low", "details": { "matchedFingerprint": "..." } }
  ],

  "auditLogs": [
    { "id": "log_1", "actorType": "api",    "actorId": "kyk_prod_ab",  "eventType": "request.created",   "payload": {}, "createdAt": "..." },
    { "id": "log_2", "actorType": "system", "actorId": "orchestrator", "eventType": "request.escalated", "payload": { "reason": "sanctions" }, "createdAt": "..." }
  ]
}

Referência de campos

CaminhoObservações
documents[].parsedDataCampos extraídos por OCR (variam conforme o tipo de documento): fullName, dateOfBirth, documentNumber, expiryDate, nationality, issuingCountry, address. null até que o OCR seja executado
documents[].statuspending · processing · done · failed
checks[].checkTypeocr · face_match · liveness · sanctions · llm_consistency
checks[].statuspending · running · passed · failed · skipped · error
checks[].score0.0–1.0 (null para verificações somente de aprovação/reprovação). details contém o resultado bruto do provedor
riskScore.overallScorePontuação composta de 0 a 100
riskScore.decisionapprove · reject · escalate. autoDecision: false = um humano alterou a decisão
riskScore.verdictMeta.factorVerdicts[]A matriz PASS/FAIL/N-A que explica por que a decisão ficou onde ficou — state é pass · fail · n/a
riskScore.verdictMeta.disqualifiersCódigos de nível 1 que forçam uma reprovação
riskScore.verdictMeta.reviewTriggersCódigos de nível 2 que forçam o encaminhamento para revisão
fraudSignals[]signalType (same_face · velocity · document_reuse · device_reuse), severity (low · medium · high)
auditLogs[]Histórico à prova de adulteração; actorType é api · system · user

Erros

  • 404 NOT_FOUND — não há solicitação com esse ID nesta organização. As solicitações pertencem às organizações; você não pode ler os dados de outra organização, mesmo com uma chave válida.

Exibindo uma verificação no seu próprio app

A resposta de detalhes foi projetada para ser renderizada diretamente — uma única chamada fornece tudo o que o painel mostra, para que os seus revisores nunca precisem fazer login na Certivant:

GET /api/v1/kyc/requests/:id → dados do solicitante, documents[].parsedData, checks[] e riskScore.verdictMeta.

Para cada documento, GET /api/v1/kyc/requests/:id/documents/:docId/url → uma URL assinada válida por 15 minutos. Renderize imagens com <img src> e PDFs com <iframe> — a URL é pré-assinada e não exige cabeçalho Authorization. Veja Documentos → Obter uma URL de download.

Mostre checks[] (aprovado/reprovado + pontuação) e riskScore.verdictMeta.factorVerdicts[] para que um revisor veja exatamente por que uma solicitação foi encaminhada e, em seguida, aja com POST /requests/:id/decision.

Busque as URLs dos documentos sob demanda, logo antes de exibi-las. Elas expiram após 15 minutos e nunca devem ser registradas, armazenadas em cache ou expostas a usuários não autenticados.


Enviar para processamento

POST /api/v1/kyc/requests/:id/submit    Escopo: kyc:submit

Libera uma solicitação PENDING_UPLOAD para o pipeline de processamento automatizado. A solicitação deve ter todos os documentos obrigatórios enviados (pendingDocTypes vazio) antes que você possa enviá-la.

Se a sua organização exige verificação de e-mail e/ou telefone (Configurações de KYC/B), certifique-se de que cada canal exigido esteja verificado antes do envio — defina applicant.emailVerified / applicant.phoneVerified: true na criação (quando você mesmo os tiver validado) ou faça com que o solicitante conclua a etapa do código em uma sessão hospedada. Um canal obrigatório não verificado falha na verificação de contato durante o processamento.

Resposta

{
  "id": "req_...",
  "status": "PROCESSING",
  "message": "Request submitted; you will receive a webhook when processing completes."
}

Erros

  • 400 BAD_REQUEST — pendingDocTypes não está vazio. Envie antes os documentos faltantes.
  • 409 CONFLICT — a solicitação não está em PENDING_UPLOAD. Você só pode enviar uma vez.

Decisão manual (solicitações encaminhadas)

POST /api/v1/kyc/requests/:id/decision    Escopo: kyc:manage

Substitui uma solicitação ESCALATED por uma decisão humana. Este endpoint existe para ferramentas internas — a maioria das decisões é tomada pelo painel.

Corpo da requisição

{ "decision": "APPROVED", "note": "Confirmed identity against internal CRM record" }
CampoTipoObrigatórioObservações
decisionenumsimAPPROVED ou REJECTED
notestringsim1–1000 caracteres. Armazenada no registro de auditoria; visível para todos os revisores

Resposta

{ "id": "req_...", "status": "APPROVED", "decision": "APPROVED", "reviewNote": "..." }

Erros

  • 409 CONFLICT — a solicitação não está no estado ESCALATED. Você não pode substituir uma aprovação automática.

Reenviar uma solicitação rejeitada

POST /api/v1/kyc/requests/:id/resubmit    Escopo: kyc:write

Redefine uma solicitação REJECTED para PENDING_UPLOAD, para que o solicitante possa tentar novamente. Os documentos anteriores são removidos; o solicitante envia novos.

Resposta

{ "id": "req_...", "status": "PENDING_UPLOAD" }

Erros

  • 409 CONFLICT — a solicitação não está no estado REJECTED. Somente solicitações rejeitadas podem ser reenviadas; solicitações canceladas ou aprovadas não.

Reenviar é uma operação privilegiada. Certifique-se de que a política da sua organização permite que o solicitante tente novamente. Alguns fluxos regulados exigem uma nova solicitação, e não um reenvio, para que a trilha de auditoria mostre claramente tentativas separadas.


Excluir uma solicitação

DELETE /api/v1/kyc/requests/:id    Escopo: kyc:write

Exclui permanentemente a solicitação e tudo o que está vinculado a ela: a exclusão em cascata alcança os documentos, verificações e pontuações de risco da solicitação, remove as imagens/PDFs de documentos enviados do armazenamento e apaga o registro do solicitante quando nenhuma outra solicitação o referencia. Use isso para atender a um pedido de exclusão de um cliente ou para descartar uma verificação de teste.

Resposta

{
  "success": true,
  "documentsDeleted": 3,
  "applicantDeleted": true
}
  • documentsDeleted — quantos arquivos armazenados foram removidos.
  • applicantDeleted — se o solicitante foi removido por não ter mais vínculos (false se ele ainda tiver outras solicitações).

Erros

  • 404 NOT_FOUND — não há solicitação com esse ID na sua organização.

Esta ação é irreversível — os documentos enviados são apagados. O registro de auditoria é mantido (ele é somente de acréscimo, e suas linhas fazem referência à solicitação sem vínculo obrigatório), para que o registro de que uma solicitação existiu e foi excluída sobreviva para fins de conformidade. Se você quiser apenas apagar os dados pessoais do solicitante, use Excluir um solicitante.


Informar o resultado

POST /api/v1/kyc/requests/:id/outcome    Escopo: kyc:write

Opcional. Informe à Certivant se a compra ou o crédito que motivou a verificação foi realmente entregue ou cancelado. Chame o endpoint depois que a solicitação for decidida.

Corpo da requisição

{ "fulfilled": true }
CampoTipoObrigatórioObservações
fulfilledbooleanosimtrue = a compra ou o crédito foi entregue. false = foi cancelado

Resposta

{ "id": "req_...", "fulfilled": true, "recorded": true }

recorded: false significa que a solicitação ainda não está na rede antifraude (por exemplo, porque não tem chaves de identidade). Nada se perde: você pode enviar o resultado mais tarde. Também pode chamar o endpoint novamente a qualquer momento para alterar a resposta.

Erros

  • 404 NOT_FOUND — nenhuma solicitação com esse id nesta organização.
  • 409 CONFLICT — a solicitação ainda não foi decidida. O status deve ser APPROVED, REJECTED, ESCALATED ou PENDING_SECOND_REVIEW.

Por que isso ajuda. Na rede antifraude, uma compra entregue conta por inteiro, enquanto uma cancelada não conta em nada. Assim, um cliente que iniciou três financiamentos de celular e cancelou dois não é confundido com alguém que saiu com três celulares. Apenas o resultado é compartilhado — nada mais sai da sua organização.


Obter sinais de fraude

GET /api/v1/kyc/requests/:id/fraud-signals    Escopo: kyc:read

Retorna os sinais de fraude de dispositivo, rede e comportamento coletados durante a verificação.

Resposta

[
  {
    "signalType": "device_reused",
    "severity": "medium",
    "details": { "previousRequestIds": ["req_..."], "matchedFingerprint": "..." }
  },
  {
    "signalType": "vpn_detected",
    "severity": "low",
    "details": { "asn": 13335, "isp": "Cloudflare" }
  }
]

A severidade é low, medium ou high. Sinais de alta severidade encaminham automaticamente a solicitação para revisão manual.


Monitoramento contínuo de AML

Uma verificação aprovada pode ser reavaliada em busca de novas ocorrências em sanções, PEP e mídia adversa (veja Monitoramento contínuo). O monitoramento é um recurso do plano e é cobrado por pessoa monitorada por ano.

ChamadaEscopoEfeito
GET /api/v1/kyc/requests/:id/monitoringkyc:readEstado: enrolled, status (active, paused, cancelled), frequency, enrolledAt, lastScreenedAt, nextScreenAt, nextBillingAt, openAlerts
POST /api/v1/kyc/requests/:id/monitoringkyc:manageInicia. Corpo { "frequency": "daily" | "weekly" | "monthly" } (padrão monthly). Retorna { "success": true, "frequency": "monthly", "chargedCents": 0 }
DELETE /api/v1/kyc/requests/:id/monitoringkyc:manageInterrompe

POST retorna 409 para uma verificação que não esteja aprovada, 403 quando o seu plano não inclui o monitoramento e 402 quando não há crédito para uma pessoa além da cota incluída.

Novas ocorrências chegam como o webhook kyc.monitoring.alert (veja Eventos de webhook): data.monitoring tem alertType (sanctions_match, pep_match, adverse_media, sanctions_unverifiable), severity e, para uma PEP, pepTier — 1 chefes de Estado e ministros … 4 familiares e pessoas próximas — ou adverseMedia: true. data.sanctions.listsChecked indica as listas verificadas; os fornecedores de triagem nunca são citados.

A própria verificação traz o mesmo pepTier / adverseMedia em data.sanctions no seu webhook de decisão.


Excluir um solicitante (apagamento de dados conforme o GDPR)

DELETE /api/v1/kyc/applicants/:applicantId    Escopo: kyc:manage

Exclui permanentemente um solicitante e todas as solicitações vinculadas a ele. Este é o endpoint de direito ao apagamento previsto no Artigo 17 do GDPR. O registro de auditoria preserva um marcador de remoção com a data e hora da exclusão, mas nenhum dado pessoal.

Resposta

{ "success": true, "deletedRequestIds": ["req_...", "req_..."] }

O apagamento é irreversível. Confirme com a sua equipe de conformidade antes de chamar este endpoint — dependendo da sua jurisdição, você pode ter a obrigação regulatória de reter os registros de verificação por 5–7 anos, o que conflita com a exclusão.