Skip to content
Vai integrar a API REST da Zarv com ajuda de IA? Copie a instrução que aponta o modelo para esta documentação.
Ver a instrução
Você vai integrar a API REST da Zarv. Use a documentação oficial como fonte da verdade.

- Página desta integração: https://developers.zarv.com/api/id-v3/
- Autenticação Bearer JWT e hosts: https://developers.zarv.com/setup
- Índice das APIs: https://developers.zarv.com/api
- Índice da documentação em markdown: https://developers.zarv.com/llms.txt
- Documentação completa em um arquivo: https://developers.zarv.com/llms-full.txt

Os specs OpenAPI publicados são a fonte da verdade para rotas e schemas — use o spec da API que você escolher antes de escrever qualquer request.

Antes de escrever qualquer código, leia a página desta integração. Siga exatamente os nomes de campos, endpoints, callbacks e formatos que estiverem documentados — não invente parâmetros nem endpoints, e não deduza comportamento a partir de outras APIs que você conhece. Se algo de que você precisa não estiver na documentação, diga que não está em vez de supor.

Minha tarefa: [ex.: escolher a API certa e fazer a primeira chamada autenticada]

Zarv ID v3 ​

O Zarv ID v3 é a nova versão da plataforma de análise de CPF e CNPJ da Zarv, com dados modulares vindos direto dos datasets, sem remapeamento. Ela tem dois produtos:

ProdutoO que entregaDisponibilidade
EnriquecimentoOs dados de cada módulo do perfil (cadastro, finanças, processos, relacionamentos…) exatamente como o dataset os publicaDisponível
VerificaçãoA coleta do enriquecimento mais a decisão: regras eliminatórias, segmentação, score, análise por IA e aprovação automáticaEm desenvolvimento

Esta documentação cobre o enriquecimento. Nele não há regras de decisão, score nem análise por IA: é dado puro, organizado por módulo. Para uma decisão sobre o CPF ou CNPJ, use a verificação quando ela estiver disponível.

Rota públicaO que faz
POST /api/v3/enrichmentsCria um enriquecimento
GET /api/v3/enrichmentsLista os enriquecimentos
GET /api/v3/enrichments/{id}Consulta um enriquecimento (e, opcionalmente, os dados)
GET /api/v3/enrichments/{id}/modules/{module}Consulta os dados de um módulo
GET /api/v3/profilesLista os perfis do workspace
GET /api/v3/profiles/{id}Consulta um perfil e o dataset de cada módulo
GET /api/v3/callback-secretConsulta o segredo de assinatura do callback

Todas as rotas ficam em https://services.zarv.com e usam token Bearer JWT. Veja Autenticação, o Webhook, a Referência da API e o formato de cada módulo em Datasets.

Antes de começar ​

Peça ao time da Zarv:

  • as credenciais da API do seu workspace;
  • os perfis que você vai usar, configurados para o seu workspace. O perfil define quais módulos rodam para o documento, e cada um atende uma entidade: você precisa de um perfil PF para consultar CPF e de um perfil PJ para consultar CNPJ.

Com os perfis configurados, GET /api/v3/profiles lista os que o seu workspace pode usar, com o profileId e o tipo (profile.kind) de cada um. Um enriquecimento só roda perfis enrichment: use GET /api/v3/profiles?kind=enrichment para ver só esses. GET /api/v3/profiles/{id} mostra o dataset de cada módulo, no mesmo formato de modules na resposta do enriquecimento, para você saber de antemão o formato dos dados (veja Datasets). Para mudar os módulos de um perfil, ou criar um novo, fale com o time da Zarv.

Como funciona ​

  1. Crie o enriquecimento com POST /api/v3/enrichments, informando document e profileId (e, se quiser, um callback).
  2. A requisição espera até 25 segundos. Se o enriquecimento terminar nesse tempo, a resposta é 200 com o corpo completo e os dados de todos os módulos em data.
  3. Se não terminar, a resposta é 202 com { "id", "status" }. A partir daí, escolha:
    • polling: consulte GET /api/v3/enrichments/{id} respeitando o header Retry-After; ou
    • callback: receba um POST assinado no seu endpoint quando o enriquecimento terminar (veja Webhook).
  4. Com o enriquecimento COMPLETED, leia os dados com ?include=data ou módulo a módulo.

O processamento continua mesmo que o seu cliente feche a conexão durante a espera.

Evite consultas repetidas ​

Envie o header Idempotency-Key em toda criação, com um valor único por consulta (um UUID, por exemplo). Ele é opcional, mas sem ele cada requisição cria um enriquecimento novo, cobrado de novo: um retry depois de um timeout de rede, ou um clique duplo, vira uma segunda consulta.

Com a chave, repetir a mesma requisição devolve o mesmo enriquecimento, sem nova consulta e sem nova cobrança, pelo tempo que for. Para uma consulta nova do mesmo documento, use uma chave nova. Os detalhes estão em Idempotência.

Exemplo ​

sh
curl -X POST "https://services.zarv.com/api/v3/enrichments" \
  -H "Authorization: Bearer SEU_TOKEN_DE_ACESSO" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: 6f1c2a9e-4b7d-4e2a-9c3f-0a1b2c3d4e5f" \
  -d '{
    "document": "111.444.777-35",
    "profileId": "8f14e45f-ceea-4e7a-9c1a-2b3c4d5e6f70",
    "callback": {
      "url": "https://sua-empresa.com/webhooks/zarv",
      "headers": { "Authorization": "Bearer <token-do-seu-endpoint>" }
    },
    "metadata": { "pedido": "12345" }
  }'
js
const res = await fetch("https://services.zarv.com/api/v3/enrichments", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${accessToken}`,
    "Content-Type": "application/json",
    "Idempotency-Key": crypto.randomUUID(),
  },
  body: JSON.stringify({
    document: "111.444.777-35",
    profileId: "8f14e45f-ceea-4e7a-9c1a-2b3c4d5e6f70",
    metadata: { pedido: "12345" },
  }),
});

if (res.status === 200) {
  const enrichment = await res.json(); // terminou: dados em enrichment.data
} else if (res.status === 202) {
  const { id } = await res.json(); // ainda rodando: polling ou callback
  const retryAfter = Number(res.headers.get("Retry-After") ?? 5);
}

Resposta 200 (resumida):

json
{
  "id": "enr_0199a0b2-7c1e-7d4a-9f0e-3b1c2d4e5f60",
  "status": "COMPLETED",
  "outcome": "ok",
  "entity": "person",
  "document": "11144477735",
  "profile": {
    "id": "8f14e45f-ceea-4e7a-9c1a-2b3c4d5e6f70",
    "name": "Cadastro PF",
    "kind": "enrichment"
  },
  "modules": {
    "profile": { "dataset": "person-profile-2.0", "status": "ok" },
    "lawsuits": { "dataset": "person-lawsuits-2.0", "status": "ok" }
  },
  "metadata": { "pedido": "12345" },
  "createdAt": "2026-09-28T13:00:00Z",
  "completedAt": "2026-09-28T13:00:04Z",
  "data": {
    "profile": {
      "dataset": "person-profile-2.0",
      "module": "profile",
      "profile": {
        "exists": true,
        "name": "MARIA DA SILVA",
        "taxId": { "status": "REGULAR" }
      },
      "rules": [{ "rule": "PROFILE_PERSON_DECEASED", "fired": false }]
    },
    "lawsuits": {
      "dataset": "person-lawsuits-2.0",
      "module": "lawsuits",
      "lawsuits": {},
      "rules": []
    }
  }
}

Resposta 202:

http
HTTP/1.1 202 Accepted
Retry-After: 5
Content-Type: application/json

{ "id": "enr_0199a0b2-7c1e-7d4a-9f0e-3b1c2d4e5f60", "status": "FETCHING" }

Ciclo de vida ​

Status do enriquecimento ​

statusSignificadoTerminal
CREATEDRecebido; a coleta ainda não começouNão
FETCHINGColetando os módulos do planoNão
COMPLETEDTodos os módulos do plano concluíram (ou o titular não existe)Sim
FAILEDA coleta não pôde ser concluídaSim

Um status terminal nunca muda.

Resultado (outcome) ​

Preenchido só quando COMPLETED; null nos demais status.

outcomeSignificado
okO titular foi encontrado e todos os módulos do plano rodaram.
subject_not_foundO documento não tem titular conhecido. Só o módulo profile rodou; os demais não são consultados.

O módulo profile roda em todo enriquecimento, primeiro: é ele que localiza o titular. Os demais módulos só rodam quando o titular existe.

Status de cada módulo ​

modules.{módulo} traz o estado de cada módulo do plano:

statusSignificado
pendingAinda não começou
retryingEm nova tentativa após uma falha temporária (nextAttemptAt diz quando)
okConcluído; os dados estão disponíveis
failedFalhou

modules.{módulo}.dataset diz qual dataset respondeu (por exemplo, person-profile-2.0).

Falhas e novas rodadas ​

Falhas temporárias de um módulo são repetidas automaticamente. Quando a coleta de um módulo se esgota por um motivo não permanente, o enriquecimento não falha na hora: continua FETCHING e ganha até 3 novas rodadas de coleta, 15 minutos, 1 hora e 4 horas depois da falha. Cada rodada repete só os módulos que falharam. Enquanto aguarda uma rodada, o enriquecimento traz nextRetryAt (quando ela roda) e recoveryRound (quantas já rodaram). Se a coleta falhar de novo depois da 3ª rodada, o enriquecimento termina FAILED.

Uma falha permanente termina o enriquecimento FAILED direto. failureReason diz o motivo (por exemplo, retry_exhausted ou deadline_exceeded).

Prazo total (options.deadline). Para limitar quanto tempo o enriquecimento pode levar, envie options.deadline na criação, como duração (90s, 10m, 2h; mínimo 1m). Nenhuma nova tentativa ou rodada passa desse prazo: excedido, o enriquecimento termina FAILED com failureReason: deadline_exceeded, e a resposta passa a trazer deadline. Sem options.deadline, todas as tentativas e as 3 rodadas se aplicam.

Cobrança ​

Um enriquecimento COMPLETED é cobrado pela ação do perfil, mais um add-on por módulo add-on que concluiu. Com outcome: subject_not_found, só a ação do perfil é cobrada. Um enriquecimento FAILED não é cobrado, e um replay idempotente nunca cobra de novo.

Espera síncrona e polling ​

A criação espera até 25 segundos pelo fim do enriquecimento. Configure o timeout do seu cliente HTTP acima disso (35 segundos, por exemplo).

Toda resposta não terminal — o 202 da criação, um GET de um enriquecimento em andamento e um replay idempotente em andamento — traz Retry-After, em segundos:

  • em geral, 5;
  • enquanto o enriquecimento aguarda uma nova rodada, os segundos até nextRetryAt (no mínimo 5);
  • nunca além de um deadline ainda à frente (então no mínimo 1).

Uma resposta terminal não traz Retry-After. Consulte GET /api/v3/enrichments/{id} depois do intervalo indicado; não há long polling.

js
async function waitForEnrichment(id, accessToken) {
  for (;;) {
    const res = await fetch(
      `https://services.zarv.com/api/v3/enrichments/${id}`,
      {
        headers: { Authorization: `Bearer ${accessToken}` },
      },
    );
    const body = await res.json();
    const retryAfter = res.headers.get("Retry-After");
    if (!retryAfter) return body; // COMPLETED ou FAILED
    await new Promise((r) => setTimeout(r, Number(retryAfter) * 1000));
  }
}

Idempotência ​

Envie o header Idempotency-Key (até 255 caracteres; um UUID por pedido, por exemplo) na criação. Com ele, repetir a requisição é seguro — após um timeout de rede, por exemplo:

SituaçãoResposta
Mesma chave e mesmo corpo, enriquecimento terminado200 com o corpo do GET, sem nova cobrança
Mesma chave e mesmo corpo, ainda em andamento202 com { "id", "status" }; um callback enviado junto é rearmado
Mesma chave com corpo diferente422 idempotency_key_reused

A chave não expira: ela sempre devolve o mesmo enriquecimento, que continua salvo. Para uma consulta nova do mesmo documento, use uma chave nova. options.deadline é normalizado antes da comparação: 2h e 120m são o mesmo pedido.

Dados por módulo ​

Os dados de cada módulo ficam em data.{módulo}, no formato publicado pelo dataset que respondeu — sem remapeamento. O formato de cada dataset, campo a campo, está em Datasets.

Para saber, antes de criar o enriquecimento, qual dataset cada módulo vai usar, consulte o perfil em GET /api/v3/profiles/{id}: o modules dele traz, por módulo, o mesmo dataset que aparece na resposta do enriquecimento (por exemplo, person-finance-1.0). Para ver os perfis do seu workspace, use GET /api/v3/profiles.

  • Criação que termina a tempo (200): data traz todos os módulos.
  • GET /api/v3/enrichments/{id}: sem include, só o estado (modules), sem data.
    • ?include=data inclui todos os módulos concluídos;
    • ?include=profile,lawsuits inclui só os módulos listados.
  • GET /api/v3/enrichments/{id}/modules/{module}: o data.{módulo} de um módulo, sozinho. Módulo ainda não concluído responde 409 module_not_ready.
  • GET /api/v3/enrichments: os itens são resumos, sem modules nem data.

Módulos e add-ons ​

O perfil (profileId) define quais módulos rodam e qual versão de dataset cada um usa. Veja os módulos de um perfil em GET /api/v3/profiles/{id}. Módulos add-on (como financeAdvanced) só rodam quando pedidos em options.modules e habilitados no perfil:

json
{
  "document": "111.444.777-35",
  "profileId": "8f14e45f-ceea-4e7a-9c1a-2b3c4d5e6f70",
  "options": { "modules": { "financeAdvanced": {} } }
}

Por enquanto, o valor de cada add-on é sempre {}. Um módulo que o perfil não tem, ou não permite, responde 422 module_not_in_profile.

Erros ​

Todo erro usa o mesmo envelope:

json
{
  "error": {
    "code": "profile_not_found",
    "message": "profile not found"
  }
}

Trate o erro por error.code, que é estável; message é texto de diagnóstico e pode mudar. Nenhuma mensagem contém documento, token ou outro dado pessoal.

HTTPcodeQuando
400invalid_bodyCorpo não é JSON válido ou tem campo desconhecido
400invalid_documentCPF ou CNPJ inválido, na criação ou no filtro document da listagem
400profile_requiredprofileId ausente
400invalid_callbackcallback inválido (URL não https, destino recusado, header reservado…)
400invalid_deadlineoptions.deadline fora do formato ou abaixo de 1m
400invalid_idempotency_keyIdempotency-Key com mais de 255 caracteres
400invalid_cursor, invalid_limitPaginação inválida na listagem
400invalid_from, invalid_to, invalid_date_rangeFiltro de data da listagem fora do RFC3339, ou from não anterior a to
400invalid_entityFiltro entity da listagem diferente de person, company, pf ou pj
401—Token ausente, inválido ou expirado
402contract_requiredO workspace não tem contrato ativo do produto ID
402action_not_contractedHá contrato ativo, mas ele não cobre todas as ações que o perfil (e os add-ons pedidos) exigem; a mensagem lista as que faltam
403—O token não tem permissão para esta rota
404profile_not_foundPerfil inexistente, inativo, de outro workspace ou não disponível para o seu workspace
404not_foundEnriquecimento não encontrado
404module_not_foundMódulo fora do plano do enriquecimento
409module_not_readyMódulo ainda não concluído
422module_not_in_profileAdd-on pedido que o perfil não tem ou não permite
422profile_entity_mismatchO perfil é de outra entidade (perfil PF com CNPJ, ou o contrário)
422profile_kind_mismatchO perfil não é do tipo enrichment (é um perfil de verificação); use um perfil enrichment
422profile_misconfiguredO perfil está configurado de forma inválida; fale com o time da Zarv
422profile_not_billableO perfil ainda não é um produto precificado; fale com o time da Zarv
422idempotency_key_reusedMesma Idempotency-Key com corpo diferente
429—Limite de taxa excedido (veja Limites de uso)
500internal_errorFalha inesperada
503profiles_unavailable, billing_unavailable, idempotency_retryIndisponibilidade temporária; repita com a mesma Idempotency-Key

contract_required × action_not_contracted

Os dois são 402 e significam que a consulta não pode ser cobrada. contract_required diz que o workspace não tem nenhum contrato ativo do produto ID; action_not_contracted diz que o contrato existe, mas não inclui alguma ação necessária — tipicamente um add-on pedido em options.modules. Nenhum dos dois cria o enriquecimento nem cobra.