Pular para o conteúdo
YaID

Guia de integração

Integre a verificação de identidade da YaID

Da criação da conta ao webhook de resultado. Todos os exemplos desta página usam valores fictícios.

Visão geral

A integração tem seis etapas, sempre nesta ordem. As três primeiras acontecem uma vez, no dashboard. As três últimas são o ciclo que sua aplicação repete a cada verificação.

  1. 01

    Criar sua conta

    Cadastro da empresa no dashboard, com CNPJ. É o que dá acesso a tudo o que vem depois.

  2. 02

    Criar um app

    Cada app é um ponto de integração: tem nome, ambiente e, opcionalmente, uma URL de webhook.

  3. 03

    Guardar a API key

    Gerada junto com o app e exibida uma única vez. É o que autentica sua aplicação na YaID.

  4. 04

    Criar a proof request

    Seu backend chama o endpoint de verificação com a API key e recebe a sessão do holder.

  5. 05

    Redirecionar o holder

    A pessoa abre a URL da sessão, apresenta suas credenciais e decide o que compartilhar.

  6. 06

    Receber o webhook

    Com o resultado pronto, a YaID notifica a URL configurada no app e sua aplicação segue o fluxo.

A chamada da etapa 04 é um POST /api/proof-requests autenticado pelo header x-api-key. O contrato completo é detalhado na seção Solicitando uma verificação (Proof Request).

Criando sua conta e seu primeiro app

1. Cadastro da empresa

O cadastro pede quatro dados: E-mail, Senha, Nome da empresa e CNPJ. O e-mail informado vira o login do primeiro usuário, e a empresa criada é a dona de todos os apps — cada app é um ponto de integração distinto, com sua própria API key.

2. Criação do app

A criação do app pede três campos: nome do app, ambiente (homol ou prod) e Webhook HTTPS opcional. Essa URL é o endereço da sua aplicação que a YaID chama automaticamente quando uma verificação é concluída, para entregar o resultado sem que você precise ficar consultando a API (o formato do evento e como validar sua autenticidade estão detalhados na seção Webhooks, adiante).

A criação de apps depende da liberação da sua empresa. Enquanto a flag can_create_apps não estiver habilitada, não é possível criar um novo app e a chamada correspondente responde 403. Fale com o time YaID para liberar o acesso.

3. API key

Ao concluir a criação, a API key é exibida uma única vez, em um modal que só pode ser fechado depois que você confirmar que copiou a chave. Ela não é recuperável: se for perdida, o caminho é criar um novo app. Guarde-a em um gerenciador de segredos — é essa chave que autentica todas as chamadas da sua aplicação à API da YaID, como detalhado na seção Solicitando uma verificação (Proof Request), adiante.

bash
# .env do seu backend — valores fictícios, apenas ilustrativos.
# A chave real aparece uma única vez, no momento da criação do app.
YAID_API_KEY=yaid_sk_xxxxxxxxxxxxxxxxxxxxxxxx

# Toda chamada B2B autentica com o header:
#   x-api-key: $YAID_API_KEY

Ambientes: Homologação vs Produção

O ambiente é escolhido na criação do app e é imutável no MVP: para trocar, crie outro app. Cada app tem sua própria API key e seu próprio webhook.

Homologação (homol)

  • Permite Aprovar ou Reprovar uma verificação manualmente pelo dashboard, sem depender de um holder real.
  • A decisão manual dispara o webhook real do app — o mesmo evento, na mesma URL, com o mesmo formato de produção.
  • Serve para você exercitar seu handler ponta a ponta antes de subir.

Produção (prod)

  • Não expõe as ações manuais. O resultado depende exclusivamente do fluxo real do holder, que apresenta suas credenciais na sessão de verificação.
  • O webhook é disparado quando a verificação é concluída pelo holder.

Importante: não há isolamento de dados entre os ambientes. Homologação não é uma sandbox — uma proof request é real nos dois ambientes, fica registrada na mesma base e consome o mesmo fluxo. A diferença está apenas em quem pode decidir o resultado.

Solicitando uma verificação (Proof Request)

A proof request é o pedido de verificação que seu backend cria em POST /api/proof-requests, autenticado pela API key do app. A resposta traz a verificação criada e a sessão do holder, com a URL para onde a pessoa deve ser redirecionada.

Autenticação e requisição

A chamada é autenticada pela API key do app, enviada em Authorization: Bearer. O header x-api-key é aceito como forma equivalente. A chave tem o formato <uuid-do-app>.<segredo> — o app é identificado pela própria chave, então não é preciso mandar appId no corpo.

O corpo tem um campo obrigatório, proofType (personhood ou age_over_18), e um opcional, externalReference: até 255 caracteres do seu lado — id de pedido, de cadastro, do que fizer sentido — devolvido intacto na resposta e no webhook.

bash
# Chamada B2B, feita pelo seu backend. Valores fictícios.
curl -X POST https://<seu-dominio-yaid>/api/proof-requests \
  -H "Authorization: Bearer 11111111-1111-4111-8111-111111111111.yaid_sk_xxxxxxxxxxxx" \
  -H "Content-Type: application/json" \
  -d '{
    "proofType": "personhood",
    "externalReference": "pedido-fake-000123"
  }'

Resposta

O sucesso é 201 Created. O que interessa para o fluxo está em session: verificationUrl é o link para onde o holder deve ir, deepLinkUrl abre o app da carteira diretamente e expiresAt marca o fim da validade da sessão, hoje 30 minutos após a criação.

json
HTTP/1.1 201 Created

{
  "id": "22222222-2222-4222-8222-222222222222",
  "appId": "11111111-1111-4111-8111-111111111111",
  "appName": "Checkout Homologação",
  "environment": "homol",
  "proofType": "personhood",
  "status": "pending_user",
  "result": null,
  "externalReference": "pedido-fake-000123",
  "createdAt": "2026-08-28T14:03:11.000Z",
  "validatedAt": null,
  "session": {
    "id": "33333333-3333-4333-8333-333333333333",
    "verificationUrl": "https://<seu-dominio-yaid>/v/<token-da-sessao>",
    "deepLinkUrl": "yaid://verify?session=<token-da-sessao>",
    "expiresAt": "2026-08-28T14:33:11.000Z"
  }
}

result nasce null e validatedAt também: são preenchidos quando a verificação chega a um estado terminal, não no momento da criação.

Teste manual sem escrever código

Proof requests são criadas exclusivamente pela API — o dashboard não tem um atalho para isso. Para conferir o fluxo antes de integrar, use um cliente HTTP como curl, Postman ou Insomnia com a chamada acima e a API key do seu app: nenhum código precisa ser escrito, e a proof request criada é idêntica à que sua integração vai gerar em produção.

Status da proof request

É o estado que sua aplicação acompanha. Aparece em status na resposta e no webhook.

pending_user
Estado inicial, logo após o 201. A sessão existe e ninguém abriu a URL ainda.
processing
O holder abriu a sessão de verificação e o desafio criptográfico está em curso.
approved
A apresentação foi verificada com sucesso — ou aprovada manualmente em homologação. Estado terminal.
rejected
A verificação não passou: o holder cancelou a sessão ou houve reprovação manual em homologação. Estado terminal.
expired
A sessão passou de expiresAt sem conclusão. Estado terminal.

Estado da sessão do holder

É um ciclo separado, do lado da pessoa que apresenta as credenciais. Sua aplicação não precisa consumi-lo, mas ele explica por que a proof request muda de estado. São dois conjuntos distintos de nomes — não os misture.

waiting_user
Sessão criada e ainda não aberta. Corresponde à proof request em pending_user.
opened
O holder abriu a URL e recebeu o desafio. É a transição que leva a proof request para processing.
approved_by_user
O holder apresentou as credenciais e aprovou o compartilhamento. Leva a proof request para approved.
cancelled
O holder desistiu da sessão. Leva a proof request para rejected.
expired
A sessão passou do prazo de 30 minutos definido em expiresAt.

Webhooks

Se o app tiver uma URL HTTPS configurada, a YaID notifica sua aplicação quando a verificação é concluída. É o sinal para liberar o cadastro, o pedido ou o acesso do lado de vocês, sem precisar ficar consultando a API.

O evento entregue

A YaID faz um POST na URL configurada no app, com Content-Type: application/json e mais dois headers: X-YaID-Signature, com a assinatura Ed25519 em base64, e X-YaID-Timestamp, o momento da assinatura em segundos Unix.

http
POST https://sua-aplicacao.exemplo.com/webhooks/yaid
Content-Type: application/json
X-YaID-Signature: <assinatura-ed25519-em-base64>
X-YaID-Timestamp: 1788012764

{
  "proofRequestId": "22222222-2222-4222-8222-222222222222",
  "status": "approved",
  "proofType": "personhood",
  "updatedAt": "2026-08-28T14:12:44.000Z",
  "externalReference": "pedido-fake-000123"
}

proofRequestId é o id devolvido na criação, updatedAt é o instante ISO 8601 da transição e externalReference só aparece se você tiver enviado um — quando está ausente, a chave é omitida do JSON, não vem como null.

A chave pública de verificação

GET /api/webhook-public-key é público e devolve a chave usada para assinar, em base64, junto com o algoritmo. Busque uma vez e guarde em configuração; não é preciso consultar a cada evento.

json
GET /api/webhook-public-key

{
  "publicKey": "<32-bytes-da-chave-publica-em-base64>",
  "algorithm": "Ed25519"
}

Verificando a assinatura

A mensagem assinada são os bytes UTF-8 do corpo exatamente como ele chegou. Configure seu framework para expor o corpo bruto: se você deixar um parser JSON transformar e reserializar o payload, a assinatura deixa de bater mesmo sendo legítima.

javascript
import * as ed from "@noble/ed25519";

// A assinatura cobre exatamente os bytes UTF-8 do corpo que chegou.
// Leia o corpo bruto e verifique antes de JSON.parse: reserializar o
// objeto muda espaços e ordem de chaves e invalida a assinatura.
// YAID_PUBLIC_KEY é o campo publicKey de GET /api/webhook-public-key,
// buscado uma vez e guardado na configuração da sua aplicação.
export async function handleYaidWebhook(rawBody, headers) {
  const signature = Buffer.from(headers["x-yaid-signature"], "base64");
  const publicKey = Buffer.from(YAID_PUBLIC_KEY, "base64");
  const message = Buffer.from(rawBody, "utf8");

  const authentic = await ed.verifyAsync(signature, message, publicKey);
  if (!authentic) {
    return new Response("invalid signature", { status: 401 });
  }

  const event = JSON.parse(rawBody);

  // O payload não inclui um campo valid: derive o booleano do status.
  const approved = event.status === "approved";
  await liberarPedido(event.externalReference, approved);

  return new Response("ok", { status: 200 });
}

Sobre o timestamp: X-YaID-Timestamp serve para observabilidade e para você descartar eventos muito antigos se quiser, mas ele não faz parte da mensagem assinada. Ou seja: a assinatura prova a origem e a integridade do corpo, não a atualidade do envio. Se replay for uma preocupação no seu domínio, trate a idempotência por proofRequestId do seu lado.

Quando dispara, e o que fazer se falhar

  • O evento é enviado nas transições terminais da proof request: approved, rejected e expired. Não há evento para pending_user nem processing.
  • A entrega é uma tentativa só, com timeout de 10 segundos. Não há retentativa automática: se sua aplicação estiver fora do ar ou responder um erro, a falha é registrada nos logs da YaID e o evento não é reenviado.
  • Por isso, trate o handler como caminho rápido: responda 2xx assim que validar a assinatura e processe o resto de forma assíncrona.
  • Se um evento se perder, o estado continua consultável no dashboard, na tela de detalhe da proof request. Vale acompanhar as verificações que ficaram sem desfecho no seu lado.

O que o webhook não carrega

O evento não transporta credencial verificável (VC), apresentação verificável (VP), DID do holder, nonce nem dados pessoais. Os cinco campos do payload são tudo o que sai da YaID: identificador, estado, tipo de prova, horário e a sua própria referência. O resultado é comunicado pelo status; se você precisa de um booleano, derive-o com status === "approved". Não existe um campo valid no payload — não escreva um handler que dependa dele.