# ZapCar API: documentação completa para agentes de IA Documentação 2.0 (29/10/2026), API 1.1.0. Contrato lido do OpenAPI publicado (https://api.zapcarconsulta.com.br/public/openapi.json). Índice curto: https://www.zapcarconsulta.com.br/api-integradores/docs/llms.txt Documentação 2.0, atualizada em 29/10/2026. Fonte: https://www.zapcarconsulta.com.br/api-integradores/docs. Contrato oficial: https://api.zapcarconsulta.com.br/public/openapi.json. ## Regras essenciais - A chave de API (zc_live_ em produção, zc_test_ no ambiente de teste) fica só no servidor, numa variável de ambiente (ZAPCAR_API_KEY). Nunca no navegador, em app mobile, no repositório ou em log. - Autenticação: cabeçalho Authorization: Bearer (X-API-Key também é aceito). Base URL única: https://api.zapcarconsulta.com.br. Quem decide o ambiente é a chave. - Consultas são assíncronas: POST /v1/consultas cria, debita o saldo e devolve um id com status "processando". O resultado sai em GET /v1/consultas/{id} (polling a cada 3 a 5 s, teto de cerca de 5 min) ou pelo webhook query.completed / query.failed. - Estados públicos: processando, concluido e erro. concluido e erro são terminais: o mesmo id não muda mais. Consulta que termina em erro é estornada automaticamente. - retryable: true = falha transitória (crie uma consulta NOVA depois de um backoff). false ou AUSENTE = não repita sozinho. - Envie Idempotency-Key (8 a 255 caracteres, derivada do id do pedido no seu sistema) em todo POST que cobra: POST /v1/consultas, POST /v1/fipe e POST /v1/fipe/tabela. Retry com a mesma chave e o mesmo corpo não cobra de novo. - Erro de requisição: envelope { erro, codigo, retryable, request_id }. No 429, respeite o Retry-After. Limite padrão: 120 requisições/min em produção, 60 no teste. - Webhooks: X-ZapCar-Signature = t=,v1=, HMAC-SHA256 de "." com o secret do endpoint. Compare em tempo constante, recuse timestamp com mais de 5 minutos, responda 2xx em até 10 s e deduplique pelo id do evento. - POST /v1/fipe e POST /v1/fipe/tabela são síncronos: o resultado vem na mesma resposta. - Ambiente de teste: toda resposta traz ambiente: "test"; o desfecho é escolhido pela placa (TST0001 limpo, TST0002 gravame, TST0003 RENAJUD, TST0004 débitos, TST0005 sinistro e leilão, TST0404 erro definitivo, TST0503 erro transitório, TST9999 nunca conclui). Não gera documento (422 SANDBOX_SEM_DOCUMENTO). - null significa "não verificado", nunca "nada consta". Dado pessoal (nome, CPF/CNPJ) segue a LGPD. - Use só endpoints, campos e códigos desta documentação e do OpenAPI. Não invente parâmetros nem use rotas internas. ## 1. Antes de começar 1. Crie a conta em https://cliente.zapcarconsulta.com.br/primeiro-acesso (grátis, sem mensalidade). 2. No Portal do Cliente, em Conta › Integrações, gere a chave de teste (zc_test_). Ela aparece uma única vez. 3. Guarde a chave em ZAPCAR_API_KEY no ambiente do servidor. Para produção, gere a chave zc_live_ e adicione saldo na Carteira (pré-pago). ## 2. Cliente HTTP Um cliente único lê a chave, aplica timeout e converte o envelope de erro em exceção. Exemplo em TypeScript (Node 18+): `lib/zapcar.ts` ```ts // lib/zapcar.ts: cliente da API ZapCar. SÓ NO SERVIDOR: a chave dá acesso ao saldo da conta. const BASE = "https://api.zapcarconsulta.com.br"; export type StatusConsulta = "processando" | "concluido" | "erro"; export interface Servico { servico: string; // slug do campo "servico" do POST /v1/consultas nome: string; requer: string[]; // campos obrigatórios no corpo preco?: number; // o que será debitado da SUA conta (ausente quando é por UF) preco_por_uf?: { uf: string; preco: number; requer: string[]; disponivel?: boolean }[]; sincrono?: boolean; // FIPE: resposta na mesma chamada endpoint?: string; // quando não é POST /v1/consultas } export interface ConsultaCriada { id: string; servico: string; status: "processando"; valor_cobrado: number; saldo_restante: number; resultado_url: string; reaproveitada?: boolean; // só no HTTP 200: idêntica já em processamento, nada cobrado ambiente?: "test"; // presente SOMENTE no sandbox } export interface Consulta { id: string; servico: string; status: StatusConsulta; schema_version: string; placa?: string; dados?: Record | null; veiculo?: Record | null; nao_verificado?: string[]; pdf_url?: string; // só em "concluido" erro?: string; // só em "erro": frase para o usuário erro_codigo?: string; // só em "erro" retryable?: boolean; // só em "erro"; ausente = não classificado, não repita sozinho ambiente?: "test"; } export interface ApiErro { erro: string; codigo: string; retryable: boolean; request_id?: string; detalhes?: unknown[]; saldo?: number } export class ZapCarErro extends Error { readonly status: number; // 0 = rede/timeout readonly codigo: string | null; readonly retryable: boolean; readonly requestId: string | null; readonly retryAfter: number | null; // segundos, só no 429 readonly corpo: Partial; constructor(status: number, corpo: Partial = {}, retryAfter: number | null = null) { super(corpo.erro ?? "HTTP " + status); this.status = status; this.corpo = corpo; this.codigo = corpo.codigo ?? null; this.retryable = corpo.retryable === true; this.requestId = corpo.request_id ?? null; this.retryAfter = retryAfter; } } function chave(): string { const k = process.env.ZAPCAR_API_KEY ?? ""; if (!/^zc_(test|live)_/.test(k)) throw new Error("Defina ZAPCAR_API_KEY com uma chave zc_test_ ou zc_live_"); return k; } /** Resposta crua (para PDF e imagens). */ export async function zapcarFetch(caminho: string, init: RequestInit = {}): Promise { const headers = new Headers(init.headers); headers.set("Authorization", "Bearer " + chave()); if (init.body && !headers.has("Content-Type")) headers.set("Content-Type", "application/json"); try { return await fetch(BASE + caminho, { ...init, headers, signal: init.signal ?? AbortSignal.timeout(30_000) }); } catch (e) { // Timeout ou rede: não dá para saber se o servidor processou. // No POST que cobra, é a Idempotency-Key que torna o retry seguro. throw new ZapCarErro(0, { erro: "Falha de rede: " + (e as Error).message, codigo: "NETWORK_ERROR", retryable: true }); } } /** JSON já conferido: devolve o corpo no 2xx, lança ZapCarErro no resto. */ export async function zapcar(caminho: string, init: RequestInit = {}): Promise { const resp = await zapcarFetch(caminho, init); const corpo = await resp.json().catch(() => ({})); if (!resp.ok) throw new ZapCarErro(resp.status, corpo, Number(resp.headers.get("Retry-After")) || null); return corpo as T; } ``` `verificar-chave.ts` ```ts import { zapcar, ZapCarErro, type Servico } from "./lib/zapcar"; try { const { servicos } = await zapcar<{ servicos: Servico[] }>("/v1/servicos"); // gratuito console.log("Chave válida:", servicos.length, "serviços liberados."); } catch (e) { if (e instanceof ZapCarErro && e.status === 401) { console.error("Chave recusada:", e.codigo, "request_id:", e.requestId); // não repita: gere outra chave } else { throw e; } } ``` ## 3. Serviços e preços GET /v1/servicos (gratuito) devolve { servicos: [...] } com o slug (servico), o nome, os campos obrigatórios (requer), o preço que será debitado da sua conta (preco, ou preco_por_uf no CRLV) e os opcionais. Leia o preço daqui em tempo de execução; não fixe no código. Serviços liberados na API no momento em que este arquivo foi gerado: - Consulta Simples: POST /v1/consultas com servico "consulta"; campos obrigatórios: placa; leia nao_verificado: categoria listada ali não foi checada nesta consulta. Formato: https://www.zapcarconsulta.com.br/api-integradores/docs/servicos/consulta - Consulta Completa: POST /v1/consultas com servico "consulta-completa"; campos obrigatórios: placa; opcional incluir_fipe: true embute a FIPE em dados.fipe com preço adicional (opcionais.incluir_fipe em GET /v1/servicos). Formato: https://www.zapcarconsulta.com.br/api-integradores/docs/servicos/consulta-completa - Laudo ECV Premium: POST /v1/consultas com servico "ecv-premium"; campos obrigatórios: placa. Formato: https://www.zapcarconsulta.com.br/api-integradores/docs/servicos/ecv-premium - Consulta Veicular: POST /v1/consultas com servico "consulta-veicular"; campos obrigatórios: placa. Formato: https://www.zapcarconsulta.com.br/api-integradores/docs/servicos/consulta-veicular - Gravame: POST /v1/consultas com servico "gravame"; campos obrigatórios: placa. Formato: https://www.zapcarconsulta.com.br/api-integradores/docs/servicos/gravame - Renajud: POST /v1/consultas com servico "renajud"; campos obrigatórios: placa. Formato: https://www.zapcarconsulta.com.br/api-integradores/docs/servicos/renajud - Débitos + Código de Barras: POST /v1/consultas com servico "debitos"; campos obrigatórios: placa. Formato: https://www.zapcarconsulta.com.br/api-integradores/docs/servicos/debitos - Débitos Estaduais: POST /v1/consultas com servico "debitos-estadual"; campos obrigatórios: placa, uf; vale qualquer uma das 27 UFs. Formato: https://www.zapcarconsulta.com.br/api-integradores/docs/servicos/debitos-estadual - Histórico de Proprietários: POST /v1/consultas com servico "historico-proprietarios"; campos obrigatórios: placa. Formato: https://www.zapcarconsulta.com.br/api-integradores/docs/servicos/historico-proprietarios - Detalhe Comunicação de Venda: POST /v1/consultas com servico "comunicacao-venda"; campos obrigatórios: placa; dado pessoal (LGPD): exige finalidade (NEGOCIACAO_VEICULO, ANALISE_CREDITO, VERIFICACAO_CADASTRAL ou OUTRA) e declaracao_finalidade: true; sem eles, 400 FINALIDADE_OBRIGATORIA antes de cobrar. Formato: https://www.zapcarconsulta.com.br/api-integradores/docs/servicos/comunicacao-venda - Decodificação de Chassi: POST /v1/consultas com servico "decodificacao-chassi"; campos obrigatórios: chassi. Formato: https://www.zapcarconsulta.com.br/api-integradores/docs/servicos/decodificacao-chassi - Decodificação de Motor: POST /v1/consultas com servico "decodificacao-motor"; campos obrigatórios: motor. Formato: https://www.zapcarconsulta.com.br/api-integradores/docs/servicos/decodificacao-motor - Score de Crédito: POST /v1/consultas com servico "score-credito"; campos obrigatórios: documento; finalidade é registrada quando enviada; envie sempre. Formato: https://www.zapcarconsulta.com.br/api-integradores/docs/servicos/score-credito - Situação do CPF: POST /v1/consultas com servico "situacao-cpf"; campos obrigatórios: documento, data_nascimento; finalidade é registrada quando enviada; envie sempre. Formato: https://www.zapcarconsulta.com.br/api-integradores/docs/servicos/situacao-cpf - Cadastro Simples CPF: POST /v1/consultas com servico "cadastro-simples-cpf"; campos obrigatórios: documento; dado pessoal (LGPD): exige finalidade (NEGOCIACAO_VEICULO, ANALISE_CREDITO, VERIFICACAO_CADASTRAL ou OUTRA) e declaracao_finalidade: true; sem eles, 400 FINALIDADE_OBRIGATORIA antes de cobrar. Formato: https://www.zapcarconsulta.com.br/api-integradores/docs/servicos/cadastro-simples-cpf - Cadastro Completo CPF: POST /v1/consultas com servico "cadastro-completo-cpf"; campos obrigatórios: documento; dado pessoal (LGPD): exige finalidade (NEGOCIACAO_VEICULO, ANALISE_CREDITO, VERIFICACAO_CADASTRAL ou OUTRA) e declaracao_finalidade: true; sem eles, 400 FINALIDADE_OBRIGATORIA antes de cobrar. Formato: https://www.zapcarconsulta.com.br/api-integradores/docs/servicos/cadastro-completo-cpf - Cadastro Simples CNPJ: POST /v1/consultas com servico "cadastro-simples-cnpj"; campos obrigatórios: documento; dado pessoal (LGPD): exige finalidade (NEGOCIACAO_VEICULO, ANALISE_CREDITO, VERIFICACAO_CADASTRAL ou OUTRA) e declaracao_finalidade: true; sem eles, 400 FINALIDADE_OBRIGATORIA antes de cobrar. Formato: https://www.zapcarconsulta.com.br/api-integradores/docs/servicos/cadastro-simples-cnpj - Cadastro Completo CNPJ: POST /v1/consultas com servico "cadastro-completo-cnpj"; campos obrigatórios: documento; dado pessoal (LGPD): exige finalidade (NEGOCIACAO_VEICULO, ANALISE_CREDITO, VERIFICACAO_CADASTRAL ou OUTRA) e declaracao_finalidade: true; sem eles, 400 FINALIDADE_OBRIGATORIA antes de cobrar. Formato: https://www.zapcarconsulta.com.br/api-integradores/docs/servicos/cadastro-completo-cnpj - Tabela FIPE: POST /v1/fipe (não usa o campo servico); corpo: placa; responde na mesma chamada (sem id, sem polling, sem PDF); cobra por requisição e aceita Idempotency-Key. Formato: https://www.zapcarconsulta.com.br/api-integradores/docs/endpoints/fipe-placa - Crédito Único CPF: POST /v1/consultas com servico "credito-unico-cpf"; campos obrigatórios: documento; dado pessoal (LGPD): exige finalidade (NEGOCIACAO_VEICULO, ANALISE_CREDITO, VERIFICACAO_CADASTRAL ou OUTRA) e declaracao_finalidade: true; sem eles, 400 FINALIDADE_OBRIGATORIA antes de cobrar. Formato: https://www.zapcarconsulta.com.br/api-integradores/docs/servicos/credito-unico-cpf - Crédito Biro CPF: POST /v1/consultas com servico "credito-biro-cpf"; campos obrigatórios: documento, uf; dado pessoal (LGPD): exige finalidade (NEGOCIACAO_VEICULO, ANALISE_CREDITO, VERIFICACAO_CADASTRAL ou OUTRA) e declaracao_finalidade: true; sem eles, 400 FINALIDADE_OBRIGATORIA antes de cobrar. Formato: https://www.zapcarconsulta.com.br/api-integradores/docs/servicos/credito-biro-cpf - Crédito Único CNPJ: POST /v1/consultas com servico "credito-unico-cnpj"; campos obrigatórios: documento; dado pessoal (LGPD): exige finalidade (NEGOCIACAO_VEICULO, ANALISE_CREDITO, VERIFICACAO_CADASTRAL ou OUTRA) e declaracao_finalidade: true; sem eles, 400 FINALIDADE_OBRIGATORIA antes de cobrar. Formato: https://www.zapcarconsulta.com.br/api-integradores/docs/servicos/credito-unico-cnpj - Crédito Biro CNPJ: POST /v1/consultas com servico "credito-biro-cnpj"; campos obrigatórios: documento, uf; dado pessoal (LGPD): exige finalidade (NEGOCIACAO_VEICULO, ANALISE_CREDITO, VERIFICACAO_CADASTRAL ou OUTRA) e declaracao_finalidade: true; sem eles, 400 FINALIDADE_OBRIGATORIA antes de cobrar. Formato: https://www.zapcarconsulta.com.br/api-integradores/docs/servicos/credito-biro-cnpj - CNH Nacional: POST /v1/consultas com servico "cnh-nacional"; campos obrigatórios: documento, cnh, uf; dado pessoal (LGPD): exige finalidade (NEGOCIACAO_VEICULO, ANALISE_CREDITO, VERIFICACAO_CADASTRAL ou OUTRA) e declaracao_finalidade: true; sem eles, 400 FINALIDADE_OBRIGATORIA antes de cobrar. Formato: https://www.zapcarconsulta.com.br/api-integradores/docs/servicos/cnh-nacional - Débitos Trabalhistas (CNDT): POST /v1/consultas com servico "debitos-trabalhistas"; campos obrigatórios: documento; dado pessoal (LGPD): exige finalidade (NEGOCIACAO_VEICULO, ANALISE_CREDITO, VERIFICACAO_CADASTRAL ou OUTRA) e declaracao_finalidade: true; sem eles, 400 FINALIDADE_OBRIGATORIA antes de cobrar. Formato: https://www.zapcarconsulta.com.br/api-integradores/docs/servicos/debitos-trabalhistas - Dívida Ativa da União: POST /v1/consultas com servico "divida-ativa"; campos obrigatórios: documento; dado pessoal (LGPD): exige finalidade (NEGOCIACAO_VEICULO, ANALISE_CREDITO, VERIFICACAO_CADASTRAL ou OUTRA) e declaracao_finalidade: true; sem eles, 400 FINALIDADE_OBRIGATORIA antes de cobrar. Formato: https://www.zapcarconsulta.com.br/api-integradores/docs/servicos/divida-ativa - Código de Segurança: POST /v1/consultas com servico "codigo-seguranca"; campos obrigatórios: placa, renavam; entrega só o documento (dados: null): baixe por GET /v1/consultas/{id}/pdf. Formato: https://www.zapcarconsulta.com.br/api-integradores/docs/servicos/codigo-seguranca - 2ª via do ATPV-e: POST /v1/consultas com servico "atpve"; campos obrigatórios: placa; exige aceite_atpve { aceito: true, versao } com a versão de GET /public/avisos/atpve, depois de mostrar o aviso ao usuário (sem ele: 422 ACEITE_ATPVE_OBRIGATORIO; versão antiga: 409 AVISO_ATPVE_DESATUALIZADO); entrega só o documento (dados: null): baixe por GET /v1/consultas/{id}/pdf. Formato: https://www.zapcarconsulta.com.br/api-integradores/docs/servicos/atpve - Consulta NF-e: POST /v1/consultas com servico "consulta-nfe"; campos obrigatórios: chave. Formato: https://www.zapcarconsulta.com.br/api-integradores/docs/servicos/consulta-nfe - CRLV Digital: POST /v1/consultas com servico "crlv"; campos obrigatórios: placa, uf; preço, disponibilidade e campos extras (renavam, cpf) variam por UF: leia preco_por_uf de GET /v1/servicos; entrega só o documento (dados: null): baixe por GET /v1/consultas/{id}/pdf. Formato: https://www.zapcarconsulta.com.br/api-integradores/docs/servicos/crlv ## 4. Criar a consulta POST /v1/consultas com { servico, ...campos } e Idempotency-Key. 201 = criada e debitada (ou replay da mesma chave, sem novo débito); 200 = solicitação idêntica já em processamento (reaproveitada: true, nada cobrado). Erros: 400 (corrija o pedido), 402 SALDO_INSUFICIENTE (traz saldo), 409 IDEMPOTENCY_IN_PROGRESS (repita com a mesma chave), 422 (IDEMPOTENCY_KEY_REUSED, SERVICO_INDISPONIVEL, ACEITE_ATPVE_OBRIGATORIO), 429, 503. `criar-consulta.ts` ```ts import { zapcar, ZapCarErro, type ConsultaCriada } from "./lib/zapcar"; /** Cria a consulta. `pedidoId` é o id do pedido no SEU banco: estável entre retries. */ export async function criarConsulta(servico: string, campos: Record, pedidoId: string, tentativa = 1): Promise { return zapcar("/v1/consultas", { method: "POST", headers: { "Idempotency-Key": pedidoId + "-t" + tentativa }, // tentativa nova = chave nova body: JSON.stringify({ servico, ...campos }), }); } try { const c = await criarConsulta("consulta", { placa: "TST0001" }, "pedido-984281"); console.log(c.id, c.status, c.reaproveitada ? "(reaproveitada, nada cobrado)" : "cobrado: R$ " + c.valor_cobrado); } catch (e) { if (e instanceof ZapCarErro && e.status === 402) console.error("Saldo insuficiente:", e.corpo.saldo); else if (e instanceof ZapCarErro && e.status === 400) console.error("Corrija o pedido:", e.codigo, e.corpo.detalhes); else throw e; } ``` ## 5. Acompanhar até o estado terminal GET /v1/consultas/{id} a cada 3 a 5 s, fora do request do usuário (job, fila, worker), com teto de cerca de 5 minutos. processando = continue; concluido e erro = terminal. `acompanhar.ts` ```ts import { zapcar, ZapCarErro, type Consulta } from "./lib/zapcar"; const dormir = (ms: number) => new Promise((r) => setTimeout(r, ms)); /** Devolve a consulta no estado terminal ("concluido" ou "erro"). Rode num job, nunca dentro do request do usuário. */ export async function aguardarConclusao(id: string, intervaloMs = 4000, tetoMs = 5 * 60_000): Promise { const limite = Date.now() + tetoMs; while (Date.now() < limite) { try { const c = await zapcar("/v1/consultas/" + encodeURIComponent(id)); if (c.status !== "processando") return c; } catch (e) { if (!(e instanceof ZapCarErro)) throw e; if (e.status === 429) { await dormir((e.retryAfter ?? 5) * 1000); continue; } if (e.status !== 0 && e.status < 500) throw e; // 401, 404: não adianta repetir } await dormir(intervaloMs); } throw new Error("Timeout local: a consulta " + id + " segue em processamento; volte a consultá-la depois."); } const final = await aguardarConclusao(process.argv[2] ?? ""); console.log(final.status, final.status === "erro" ? final.erro_codigo : final.pdf_url); ``` ## 6. Ler o resultado Na consulta concluida: schema_version (1.x; minor só acrescenta campos), veiculo (bloco normalizado pela ZapCar, nos serviços de veículo), dados (formato de cada serviço), proprietario, risco (família da Consulta Completa), nao_verificado (Consulta Simples) e pdf_url. null = não verificado. Na consulta com erro: erro (frase pronta para o usuário), erro_codigo e retryable. `resultado.ts` ```ts import { zapcar, type Consulta } from "./lib/zapcar"; export type Resumo = | { estado: "aguardando" } | { estado: "falhou"; mensagem: string; codigo?: string; podeTentarDeNovo: boolean } | { estado: "pronto"; veiculo: Record | null; dados: Record | null; naoVerificado: string[]; temDocumento: boolean }; export async function resumoDaConsulta(id: string): Promise { const c = await zapcar("/v1/consultas/" + encodeURIComponent(id)); if (c.status === "processando") return { estado: "aguardando" }; if (c.status === "erro") { // retryable ausente = não classificado: trate como false. return { estado: "falhou", mensagem: c.erro ?? "Consulta não concluída.", codigo: c.erro_codigo, podeTentarDeNovo: c.retryable === true }; } return { estado: "pronto", veiculo: c.veiculo ?? null, // forma estável, normalizada pela ZapCar dados: c.dados ?? null, // formato do serviço; null em serviços só de documento naoVerificado: c.nao_verificado ?? [], // campo listado aqui é "não verificado", nunca "nada consta" temDocumento: !!c.pdf_url, }; } console.log(await resumoDaConsulta(process.argv[2] ?? "")); ``` ## 7. Baixar o documento GET /v1/consultas/{id}/pdf devolve o arquivo (gratuito). Confie no Content-Type: application/pdf, image/png ou image/jpeg. 400 PDF_NOT_READY é transitório. Sirva o arquivo ao seu usuário por uma rota do seu backend. `baixar-pdf.ts` ```ts import { writeFile } from "node:fs/promises"; import { zapcarFetch, ZapCarErro } from "./lib/zapcar"; export async function baixarDocumento(id: string): Promise<{ bytes: Buffer; tipo: string; nome: string | null }> { const resp = await zapcarFetch("/v1/consultas/" + encodeURIComponent(id) + "/pdf"); if (!resp.ok) throw new ZapCarErro(resp.status, await resp.json().catch(() => ({}))); // PDF_NOT_READY é retryable const disp = resp.headers.get("content-disposition") ?? ""; return { bytes: Buffer.from(await resp.arrayBuffer()), tipo: resp.headers.get("content-type") ?? "application/octet-stream", // pdf, png ou jpeg nome: /filename="?([^";]+)"?/.exec(disp)?.[1] ?? null, }; } const doc = await baixarDocumento(process.argv[2] ?? ""); await writeFile(doc.nome ?? "documento.pdf", doc.bytes); ``` ## 8. Webhooks Cadastre a URL HTTPS em Conta › Integrações › Webhooks. Eventos: query.completed, query.failed, webhook.test e os do monitoramento (vehicle.*). O evento não traz o resultado: busque GET /v1/consultas/{data.id}. Reentregas (até 6, com backoff a partir de 10 s) trazem o mesmo id de evento. Detalhes: https://www.zapcarconsulta.com.br/api-integradores/docs/webhooks `lib/assinatura.ts` ```ts import crypto from "node:crypto"; /** * X-ZapCar-Signature: t=,v1=. O HMAC-SHA256 é de ".". * corpoBruto: exatamente como chegou (parse + stringify invalida a assinatura). */ export function verificarAssinatura(corpoBruto: string | Buffer, cabecalho: string | null | undefined, secret: string, toleranciaS = 300): boolean { if (!cabecalho || !secret) return false; const partes = cabecalho.split(",").map((p) => p.trim().split("=") as [string, string | undefined]); const t = partes.find(([k]) => k === "t")?.[1]; const assinaturas = partes.filter(([k]) => k === "v1").map(([, v]) => v ?? ""); if (!t || !/^\d+$/.test(t) || assinaturas.length === 0) return false; if (Math.abs(Date.now() / 1000 - Number(t)) > toleranciaS) return false; // replay const esperado = crypto.createHmac("sha256", secret).update(t + ".").update(corpoBruto).digest(); return assinaturas.some((v1) => { const recebido = Buffer.from(v1, "hex"); return recebido.length === esperado.length && crypto.timingSafeEqual(recebido, esperado); }); } ``` `lib/webhook.ts` ```ts import { verificarAssinatura } from "./assinatura"; import { zapcar, type Consulta } from "./zapcar"; export interface EventoZapCar { id: string; // id do EVENTO: deduplique por ele type: string; // query.completed, query.failed, webhook.test, vehicle.* created_at: string; data: { id?: string; servico_slug?: string; status_publico?: "concluido" | "erro"; [k: string]: unknown }; } /** * Independente de framework: receba o corpo BRUTO (string ou Buffer) e o cabeçalho. * Devolve o status HTTP a responder e, se válido, a tarefa para rodar DEPOIS da resposta. */ export function tratarWebhook(corpoBruto: string | Buffer, assinatura: string | null, jaVisto: (id: string) => boolean) { if (!verificarAssinatura(corpoBruto, assinatura, process.env.ZAPCAR_WEBHOOK_SECRET ?? "")) return { status: 401 as const }; const evento = JSON.parse(corpoBruto.toString()) as EventoZapCar; if (jaVisto(evento.id)) return { status: 200 as const }; // reentrega: já processado return { status: 200 as const, depois: () => processar(evento) }; } async function processar(evento: EventoZapCar): Promise { if (!evento.type.startsWith("query.") || !evento.data.id) return; const c = await zapcar("/v1/consultas/" + encodeURIComponent(evento.data.id)); console.log(evento.type, c.id, c.status); // atualize o pedido aqui } ``` ## 9. Erros e retry `lib/erros.ts` ```ts import { ZapCarErro, type Consulta } from "./zapcar"; export type Acao = "bug" | "trocar_chave" | "recarregar_saldo" | "esperar_retry_after" | "repetir_com_backoff" | "corrigir_pedido"; export function acaoParaErro(e: unknown): Acao { if (!(e instanceof ZapCarErro)) return "bug"; if (e.status === 401) return "trocar_chave"; if (e.status === 402) return "recarregar_saldo"; if (e.status === 429) return "esperar_retry_after"; if (e.retryable) return "repetir_com_backoff"; return "corrigir_pedido"; } /** Só para GET ou POST com Idempotency-Key estável entre as tentativas. */ export async function comRetry(fn: () => Promise, tentativas = 4, baseMs = 1000): Promise { for (let i = 1; ; i++) { try { return await fn(); } catch (e) { const acao = acaoParaErro(e); if (i >= tentativas || (acao !== "repetir_com_backoff" && acao !== "esperar_retry_after")) throw e; const espera = acao === "esperar_retry_after" ? ((e as ZapCarErro).retryAfter ?? 5) * 1000 : baseMs * 2 ** (i - 1) + Math.random() * baseMs; await new Promise((r) => setTimeout(r, espera)); } } } /** Consulta terminada em "erro": o que mostrar e se vale uma consulta NOVA. */ export function desfechoDaFalha(c: Consulta) { return { mensagem: c.erro ?? "Não foi possível concluir a consulta.", // frase pronta para o usuário codigo: c.erro_codigo ?? null, criarNovaConsulta: c.retryable === true, // ausente = não classificado: não repita sozinho }; } ``` ## 10. Evitar cobrança duplicada `lib/sem-duplicar.ts` ```ts import { zapcar, ZapCarErro, type ConsultaCriada } from "./zapcar"; interface Pedido { id: string | number; servico: string; campos: Record } /** Mesma tentativa = mesma chave e mesmo corpo. Chave nova só para consulta NOVA. */ export async function criarSemDuplicar(pedido: Pedido, tentativa = 1): Promise { const chave = "pedido-" + pedido.id + "-t" + tentativa; const corpo = JSON.stringify({ servico: pedido.servico, ...pedido.campos }); for (let i = 1; ; i++) { try { return await zapcar("/v1/consultas", { method: "POST", headers: { "Idempotency-Key": chave }, body: corpo }); } catch (e) { if (!(e instanceof ZapCarErro)) throw e; if (e.codigo === "IDEMPOTENCY_KEY_REUSED") throw new Error("Bug: chave " + chave + " reusada com outro corpo"); const repetir = e.status === 0 || e.status === 429 || e.status === 409 || e.status >= 500; if (!repetir || i === 5) throw e; await new Promise((r) => setTimeout(r, e.status === 429 ? (e.retryAfter ?? 5) * 1000 : 1000 * 2 ** (i - 1))); } } } ``` ## 11. Checklist de produção - Chave zc_live_ só no servidor, em variável de ambiente; chave de teste separada. - Idempotency-Key estável em todo POST que cobra. - Polling com teto, ou webhook com assinatura validada e deduplicação. - 429 respeitando Retry-After; backoff com jitter só onde retryable é true. - request_id nos logs; nenhum dado pessoal ou chave em log. - Alerta de saldo baixo (GET /v1/saldo). - Checklist completo: https://www.zapcarconsulta.com.br/api-integradores/docs/guias/producao Exemplos em outras linguagens (cURL, JavaScript, Node.js com Express, Next.js, Python e PHP): https://www.zapcarconsulta.com.br/api-integradores/docs/exemplos ## Referência dos endpoints Gerada do OpenAPI publicado. Todas as rotas exigem Authorization: Bearer . ### GET /v1/servicos Catálogo de serviços e preços. Não cobra. Página: https://www.zapcarconsulta.com.br/api-integradores/docs/endpoints/listar-servicos Lista os serviços disponíveis para a conta, com os campos exigidos e o preço que será debitado (já com preço personalizado e Grupo de Desconto da API). Gratuito e ilimitado dentro do rate limit: é a chamada recomendada para conferir se a chave funciona. Respostas: - 200: Catálogo com os preços vigentes para esta conta. - 401: Chave ausente, inválida ou revogada. - 429: Rate limit excedido. Respeite o header `Retry-After` (segundos) antes de repetir. Não consome saldo. - 500: Falha interna inesperada. É transitória (`retryable: true`); informe o `request_id` ao suporte se persistir. ### GET /v1/saldo Saldo da carteira. Não cobra. Página: https://www.zapcarconsulta.com.br/api-integradores/docs/endpoints/consultar-saldo Saldo atual da conta, em reais. Gratuito. Use para recarregar antes de acabar. Respostas: - 200: Saldo atual. - 401: Chave ausente, inválida ou revogada. - 429: Rate limit excedido. Respeite o header `Retry-After` (segundos) antes de repetir. Não consome saldo. - 500: Falha interna inesperada. É transitória (`retryable: true`); informe o `request_id` ao suporte se persistir. ### POST /v1/consultas Criar consulta (assíncrona). Cobra saldo (estorno automático na falha); aceita Idempotency-Key. Página: https://www.zapcarconsulta.com.br/api-integradores/docs/endpoints/criar-consulta Debita o saldo e enfileira a consulta. O resultado NÃO vem nesta resposta: acompanhe por GET /v1/consultas/{id} (polling de 3–5s, teto de ~5 min) ou pelo webhook query.completed / query.failed. Envie Idempotency-Key para que um retry de rede não gere segunda consulta nem segundo débito. Parâmetros: - Idempotency-Key (header, string): Identificador SEU desta operação (8–255 caracteres). Repetir a requisição com a mesma chave e o mesmo corpo devolve a resposta original SEM cobrar de novo: a proteção contra cobrança dupla em retry de rede. Validade de 30 dias. Cada nova tentativa de uma consulta que falhou precisa de uma chave NOVA. Corpo (JSON): - servico (string, obrigatório): Slug do serviço (ver GET /v1/servicos). Valores: consulta, consulta-completa, ecv-premium, consulta-veicular, gravame, renajud, debitos, debitos-estadual, historico-proprietarios, comunicacao-venda, decodificacao-chassi, decodificacao-motor, score-credito, situacao-cpf, cadastro-simples-cpf, cadastro-completo-cpf, cadastro-simples-cnpj, cadastro-completo-cnpj, credito-unico-cpf, credito-biro-cpf, credito-unico-cnpj, credito-biro-cnpj, cnh-nacional, debitos-trabalhistas, divida-ativa, codigo-seguranca, atpve, consulta-nfe, crlv. - placa (string): Com ou sem hífen. Exigida em todos os serviços, exceto as decodificações, o score-credito, o situacao-cpf, o consulta-nfe e as consultas de pessoa (cadastro-*, credito-*, cnh-nacional, debitos-trabalhistas, divida-ativa). - uf (string): Exigida em crlv, debitos-estadual, credito-biro-cpf, credito-biro-cnpj e cnh-nacional. Em debitos-estadual vale qualquer uma das 27 UFs e basta a placa; UF ausente ou inválida → 400 UF_INDISPONIVEL, antes de cobrar. - renavam (string): Exigido em codigo-seguranca e em algumas UFs do CRLV. - cpf (string): CPF/CNPJ do proprietário. Exigido em algumas UFs do CRLV. - chassi (string): Exigido em decodificacao-chassi. - motor (string): Exigido em decodificacao-motor. - documento (string): CPF/CNPJ consultado: score-credito; só CPF em situacao-cpf. Nas consultas de pessoa: CPF nos produtos *-cpf e cnh-nacional, CNPJ nos *-cnpj, qualquer um em debitos-trabalhistas e divida-ativa. - cnh (string): Número de registro da CNH: exigido em cnh-nacional (com o CPF em documento e a uf). - chave (string): Chave de acesso da NF-e (44 dígitos, com ou sem espaços): exigida em consulta-nfe. - data_nascimento (string): Data de nascimento do titular (dd/mm/aaaa): exigida em situacao-cpf. - finalidade (string): Finalidade da consulta (LGPD). Obrigatória em comunicacao-venda (traz nome e CPF/CNPJ do comprador) e nas consultas de pessoa; registrada também em score-credito e situacao-cpf. Valores: NEGOCIACAO_VEICULO, ANALISE_CREDITO, VERIFICACAO_CADASTRAL, OUTRA. - declaracao_finalidade (boolean): Aceite de uso dos dados só para a finalidade informada. Em comunicacao-venda e nas consultas de pessoa precisa ser true; sem ele → 400 FINALIDADE_OBRIGATORIA, antes de cobrar. - incluir_fipe (boolean): Só consulta-completa: embute a Tabela FIPE em dados.fipe e cobra o preço da FIPE junto. Se só a FIPE falhar, apenas essa parcela é estornada. - aceite_atpve (objeto): OBRIGATÓRIO em atpve. A 2ª via não sai quando a ATPV-e anterior já foi assinada com firma reconhecida, e isso não é detectável antes da emissão. Mostre ao usuário final o aviso de GET /public/avisos/atpve e envie a declaração dele. Sem ela: 422 ACEITE_ATPVE_OBRIGATORIO; com versão antiga: 409 AVISO_ATPVE_DESATUALIZADO. Nada é cobrado em nenhum dos dois casos. A declaração fica registrada com IP e user-agent da chamada. Respostas: - 200: Nada foi cobrado: solicitação idêntica (mesmo serviço e identificador) ainda em processamento, devolvida com reaproveitada: true. O replay de uma Idempotency-Key já concluída devolve a resposta ORIGINAL, com o status dela (201). - 201: Consulta criada e saldo debitado. - 400: Pedido inválido. Nada foi criado nem cobrado. `codigo` diz o que corrigir. - 401: Chave ausente, inválida ou revogada. - 402: Saldo insuficiente. Nada foi criado nem cobrado; a resposta traz o saldo atual. - 409: Conflito: requisição idêntica (mesma Idempotency-Key) ainda em processamento (espere alguns segundos e repita, não crie outra consulta; ou, em atpve, `aceite_atpve.versao` diferente da vigente (AVISO_ATPVE_DESATUALIZADO)) busque o aviso em GET /public/avisos/atpve, mostre ao usuário e reenvie. - 422: Pedido compreendido mas não processável: serviço indisponível para a conta, Idempotency-Key reusada com outro payload, ou atpve sem a declaração `aceite_atpve`. - 429: Rate limit excedido. Respeite o header `Retry-After` (segundos) antes de repetir. Não consome saldo. - 500: Falha interna inesperada. É transitória (`retryable: true`); informe o `request_id` ao suporte se persistir. - 503: Fornecedor temporariamente indisponível (circuito aberto). Transitório. ### GET /v1/consultas/{id} Status e resultado da consulta. Não cobra. Página: https://www.zapcarconsulta.com.br/api-integradores/docs/endpoints/consultar-resultado Estado atual da consulta. "processando" = continue o polling (a base estadual chega a ~2 min numa placa fria). "concluido" traz `dados`, `veiculo` e `pdf_url`. "erro" é TERMINAL e já vem estornado: repolling o mesmo id nunca vira "concluido", se `retryable` for true, crie uma consulta NOVA após um backoff. Gratuito e ilimitado dentro do rate limit. Parâmetros: - id (path, string (uuid), obrigatório): Id da consulta (UUID), como devolvido pelo POST /v1/consultas. Respostas: - 200: Estado da consulta (qualquer um dos três status). - 401: Chave ausente, inválida ou revogada. - 404: Não encontrado, ou não pertence a esta conta (um id de outro cliente responde 404, nunca o dado). - 429: Rate limit excedido. Respeite o header `Retry-After` (segundos) antes de repetir. Não consome saldo. - 500: Falha interna inesperada. É transitória (`retryable: true`); informe o `request_id` ao suporte se persistir. ### GET /v1/consultas/{id}/pdf Documento da consulta (PDF ou imagem). Não cobra. Página: https://www.zapcarconsulta.com.br/api-integradores/docs/endpoints/baixar-pdf Baixa o documento da consulta. Gratuito: você paga pela consulta, não por lê-la. Confie no Content-Type, não na extensão: a maioria sai application/pdf, mas alguns emissores de documento oficial entregam imagem (image/png, image/jpeg). O Content-Disposition traz o nome com a extensão certa. Parâmetros: - id (path, string (uuid), obrigatório): Id da consulta (UUID), como devolvido pelo POST /v1/consultas. Respostas: - 200: Documento binário. - 400: Pedido inválido. Nada foi criado nem cobrado. `codigo` diz o que corrigir. - 401: Chave ausente, inválida ou revogada. - 404: Não encontrado, ou não pertence a esta conta (um id de outro cliente responde 404, nunca o dado). - 422: Pedido compreendido mas não processável: serviço indisponível para a conta, Idempotency-Key reusada com outro payload, ou atpve sem a declaração `aceite_atpve`. - 429: Rate limit excedido. Respeite o header `Retry-After` (segundos) antes de repetir. Não consome saldo. - 500: Falha interna inesperada. É transitória (`retryable: true`); informe o `request_id` ao suporte se persistir. ### GET /v1/consultas/{id}/imagens/{tipo}/{indice} Imagem da Consulta Completa. Não cobra. Página: https://www.zapcarconsulta.com.br/api-integradores/docs/endpoints/baixar-imagem Baixa UMA imagem da Consulta Completa. Você não monta estas URLs à mão: elas vêm prontas em dados.fotosLeilao[].url. Desde 14/10/2026 a Completa traz só fotos de leilão (`leilao`); `outra`, `csv-imagem` e `csv-pdf` existem apenas nas Completas concluídas entre 27/08/2026 e 13/10/2026. Parâmetros: - id (path, string (uuid), obrigatório): Id da consulta (UUID), como devolvido pelo POST /v1/consultas. - tipo (path, string, obrigatório): O que a imagem é (não de onde veio). Valores: leilao, outra, csv-imagem, csv-pdf. - indice (path, integer, obrigatório): Índice na lista, a partir de 0. Respostas: - 200: Imagem ou PDF do certificado. - 400: Pedido inválido. Nada foi criado nem cobrado. `codigo` diz o que corrigir. - 401: Chave ausente, inválida ou revogada. - 404: Não encontrado, ou não pertence a esta conta (um id de outro cliente responde 404, nunca o dado). - 429: Rate limit excedido. Respeite o header `Retry-After` (segundos) antes de repetir. Não consome saldo. - 500: Falha interna inesperada. É transitória (`retryable: true`); informe o `request_id` ao suporte se persistir. ### POST /v1/fipe Tabela FIPE por placa (síncrono). Cobra saldo (estorno automático na falha); aceita Idempotency-Key. Página: https://www.zapcarconsulta.com.br/api-integradores/docs/endpoints/fipe-placa Devolve os valores FIPE na MESMA chamada, sem id, sem polling, sem PDF. A placa identifica o veículo e o código FIPE; o `valor` é o da referência FIPE VIGENTE, com `historico` dos últimos meses (desde 24/09/2026). Cobrado por requisição e estornado se falhar ou não houver FIPE para a placa. Aceita Idempotency-Key: como o débito acontece antes da chamada ao provedor, é ela que impede cobrança dupla num retry de rede. Parâmetros: - Idempotency-Key (header, string): Identificador SEU desta operação (8–255 caracteres). Repetir a requisição com a mesma chave e o mesmo corpo devolve a resposta original SEM cobrar de novo: a proteção contra cobrança dupla em retry de rede. Validade de 30 dias. Cada nova tentativa de uma consulta que falhou precisa de uma chave NOVA. Corpo (JSON): - placa (string, obrigatório): Com ou sem hífen. Respostas: - 200: Valores FIPE da placa. - 400: Pedido inválido. Nada foi criado nem cobrado. `codigo` diz o que corrigir. - 401: Chave ausente, inválida ou revogada. - 402: Saldo insuficiente. Nada foi criado nem cobrado; a resposta traz o saldo atual. - 404: Não encontrado, ou não pertence a esta conta (um id de outro cliente responde 404, nunca o dado). - 409: Conflito: requisição idêntica (mesma Idempotency-Key) ainda em processamento (espere alguns segundos e repita, não crie outra consulta; ou, em atpve, `aceite_atpve.versao` diferente da vigente (AVISO_ATPVE_DESATUALIZADO)) busque o aviso em GET /public/avisos/atpve, mostre ao usuário e reenvie. - 422: Pedido compreendido mas não processável: serviço indisponível para a conta, Idempotency-Key reusada com outro payload, ou atpve sem a declaração `aceite_atpve`. - 429: Rate limit excedido. Respeite o header `Retry-After` (segundos) antes de repetir. Não consome saldo. - 500: Falha interna inesperada. É transitória (`retryable: true`); informe o `request_id` ao suporte se persistir. - 502: A fonte respondeu com erro (FIPE). Transitório: nada foi cobrado, o valor já foi estornado. - 503: Fornecedor temporariamente indisponível (circuito aberto). Transitório. ### GET /v1/fipe/tabela/referencias Meses de referência da Tabela FIPE. Não cobra. Página: https://www.zapcarconsulta.com.br/api-integradores/docs/endpoints/fipe-tabela-listas Lista os meses publicados pela FIPE, do mais recente para o mais antigo. Gratuito. O `codigo` vai em `referencia` nas demais chamadas para consultar um mês passado; sem ele, vale o vigente. Respostas: - 200: Meses publicados. - 401: Chave ausente, inválida ou revogada. - 429: Rate limit excedido. Respeite o header `Retry-After` (segundos) antes de repetir. Não consome saldo. - 500: Falha interna inesperada. É transitória (`retryable: true`); informe o `request_id` ao suporte se persistir. - 502: A fonte respondeu com erro (FIPE). Transitório: nada foi cobrado, o valor já foi estornado. - 503: Fornecedor temporariamente indisponível (circuito aberto). Transitório. ### GET /v1/fipe/tabela/{tipo}/marcas Marcas por tipo de veículo. Não cobra. Página: https://www.zapcarconsulta.com.br/api-integradores/docs/endpoints/fipe-tabela-listas Marcas da Tabela FIPE para carros, motos ou caminhões. Gratuito. Use o `codigo` da marca em /modelos. Parâmetros: - tipo (path, string, obrigatório): Tipo de veículo da Tabela FIPE. Valores: carros, motos, caminhoes. - referencia (query, string): Código do mês de referência (de /referencias). Ausente = o mês vigente. Respostas: - 200: Marcas do tipo. - 400: Pedido inválido. Nada foi criado nem cobrado. `codigo` diz o que corrigir. - 401: Chave ausente, inválida ou revogada. - 429: Rate limit excedido. Respeite o header `Retry-After` (segundos) antes de repetir. Não consome saldo. - 500: Falha interna inesperada. É transitória (`retryable: true`); informe o `request_id` ao suporte se persistir. - 502: A fonte respondeu com erro (FIPE). Transitório: nada foi cobrado, o valor já foi estornado. - 503: Fornecedor temporariamente indisponível (circuito aberto). Transitório. ### GET /v1/fipe/tabela/{tipo}/marcas/{marca}/modelos Modelos de uma marca. Não cobra. Página: https://www.zapcarconsulta.com.br/api-integradores/docs/endpoints/fipe-tabela-listas Modelos da marca na Tabela FIPE. Gratuito. Use o `codigo` do modelo em /anos. Parâmetros: - tipo (path, string, obrigatório): Tipo de veículo da Tabela FIPE. Valores: carros, motos, caminhoes. - marca (path, string, obrigatório): Código da marca (de /marcas). - referencia (query, string): Código do mês de referência (de /referencias). Ausente = o mês vigente. Respostas: - 200: Modelos da marca. - 400: Pedido inválido. Nada foi criado nem cobrado. `codigo` diz o que corrigir. - 401: Chave ausente, inválida ou revogada. - 404: Não encontrado, ou não pertence a esta conta (um id de outro cliente responde 404, nunca o dado). - 429: Rate limit excedido. Respeite o header `Retry-After` (segundos) antes de repetir. Não consome saldo. - 500: Falha interna inesperada. É transitória (`retryable: true`); informe o `request_id` ao suporte se persistir. - 502: A fonte respondeu com erro (FIPE). Transitório: nada foi cobrado, o valor já foi estornado. - 503: Fornecedor temporariamente indisponível (circuito aberto). Transitório. ### GET /v1/fipe/tabela/{tipo}/marcas/{marca}/modelos/{modelo}/anos Anos de um modelo. Não cobra. Página: https://www.zapcarconsulta.com.br/api-integradores/docs/endpoints/fipe-tabela-listas Anos/combustíveis disponíveis para o modelo. Gratuito. O `codigo` do ano ("2014-3") é o `ano` do POST /v1/fipe/tabela. Parâmetros: - tipo (path, string, obrigatório): Tipo de veículo da Tabela FIPE. Valores: carros, motos, caminhoes. - marca (path, string, obrigatório): Código da marca (de /marcas). - modelo (path, string, obrigatório): Código do modelo (de /modelos). - referencia (query, string): Código do mês de referência (de /referencias). Ausente = o mês vigente. Respostas: - 200: Anos do modelo. - 400: Pedido inválido. Nada foi criado nem cobrado. `codigo` diz o que corrigir. - 401: Chave ausente, inválida ou revogada. - 404: Não encontrado, ou não pertence a esta conta (um id de outro cliente responde 404, nunca o dado). - 429: Rate limit excedido. Respeite o header `Retry-After` (segundos) antes de repetir. Não consome saldo. - 500: Falha interna inesperada. É transitória (`retryable: true`); informe o `request_id` ao suporte se persistir. - 502: A fonte respondeu com erro (FIPE). Transitório: nada foi cobrado, o valor já foi estornado. - 503: Fornecedor temporariamente indisponível (circuito aberto). Transitório. ### GET /v1/fipe/tabela/{tipo}/codigo/{codigo_fipe}/anos Anos de um código FIPE. Não cobra. Página: https://www.zapcarconsulta.com.br/api-integradores/docs/endpoints/fipe-tabela-listas Quando você já tem o código FIPE (por exemplo, de um POST /v1/fipe anterior), pule marca e modelo: esta chamada devolve os anos do código. Gratuito. Parâmetros: - tipo (path, string, obrigatório): Tipo de veículo da Tabela FIPE. Valores: carros, motos, caminhoes. - codigo_fipe (path, string, obrigatório): Código FIPE do veículo, formato 000000-0. - referencia (query, string): Código do mês de referência (de /referencias). Ausente = o mês vigente. Respostas: - 200: Anos do código FIPE. - 400: Pedido inválido. Nada foi criado nem cobrado. `codigo` diz o que corrigir. - 401: Chave ausente, inválida ou revogada. - 404: Não encontrado, ou não pertence a esta conta (um id de outro cliente responde 404, nunca o dado). - 429: Rate limit excedido. Respeite o header `Retry-After` (segundos) antes de repetir. Não consome saldo. - 500: Falha interna inesperada. É transitória (`retryable: true`); informe o `request_id` ao suporte se persistir. - 502: A fonte respondeu com erro (FIPE). Transitório: nada foi cobrado, o valor já foi estornado. - 503: Fornecedor temporariamente indisponível (circuito aberto). Transitório. ### POST /v1/fipe/tabela Valor FIPE por marca/modelo/ano ou por código FIPE (síncrono). Cobra saldo (estorno automático na falha); aceita Idempotency-Key. Página: https://www.zapcarconsulta.com.br/api-integradores/docs/endpoints/fipe-tabela-valor Devolve o valor da Tabela FIPE na MESMA chamada, sem placa: informe `codigo_fipe` OU `marca` + `modelo` (códigos das listas), sempre com `ano`. `historico: true` acrescenta os últimos meses. Cobrado por requisição (preço do serviço fipe-tabela em GET /v1/servicos) e estornado se falhar ou não houver valor. Aceita Idempotency-Key: o débito acontece antes da chamada à fonte, e é ela que impede cobrança dupla num retry de rede. Chave de teste: 000404-0 devolve FIPE_NAO_DISPONIVEL e 000503-0 devolve FIPE_INDISPONIVEL; o resto, valor fictício. Parâmetros: - Idempotency-Key (header, string): Identificador SEU desta operação (8–255 caracteres). Repetir a requisição com a mesma chave e o mesmo corpo devolve a resposta original SEM cobrar de novo: a proteção contra cobrança dupla em retry de rede. Validade de 30 dias. Cada nova tentativa de uma consulta que falhou precisa de uma chave NOVA. Corpo (JSON): - tipo (string, obrigatório): sem descrição. Valores: carros, motos, caminhoes. - ano (string, obrigatório): Código do ano das listas ("2014-3"). 32000 = zero km. - codigo_fipe (string): Código FIPE (000000-0). Se vier, marca e modelo são ignorados. - marca (string): Código da marca (de /marcas). Exigido sem codigo_fipe. - modelo (string): Código do modelo (de /modelos). Exigido sem codigo_fipe. - referencia (string): Código do mês (de /referencias). Ausente = vigente. - historico (boolean): true = inclui os últimos meses em `historico` (o valor do mês pedido continua em `valor`). Respostas: - 200: Valor FIPE do veículo. - 400: Pedido inválido. Nada foi criado nem cobrado. `codigo` diz o que corrigir. - 401: Chave ausente, inválida ou revogada. - 402: Saldo insuficiente. Nada foi criado nem cobrado; a resposta traz o saldo atual. - 404: Não encontrado, ou não pertence a esta conta (um id de outro cliente responde 404, nunca o dado). - 409: Conflito: requisição idêntica (mesma Idempotency-Key) ainda em processamento (espere alguns segundos e repita, não crie outra consulta; ou, em atpve, `aceite_atpve.versao` diferente da vigente (AVISO_ATPVE_DESATUALIZADO)) busque o aviso em GET /public/avisos/atpve, mostre ao usuário e reenvie. - 422: Pedido compreendido mas não processável: serviço indisponível para a conta, Idempotency-Key reusada com outro payload, ou atpve sem a declaração `aceite_atpve`. - 429: Rate limit excedido. Respeite o header `Retry-After` (segundos) antes de repetir. Não consome saldo. - 500: Falha interna inesperada. É transitória (`retryable: true`); informe o `request_id` ao suporte se persistir. - 502: A fonte respondeu com erro (FIPE). Transitório: nada foi cobrado, o valor já foi estornado. - 503: Fornecedor temporariamente indisponível (circuito aberto). Transitório. ## Objetos de resposta Campo a campo, como o OpenAPI declara. ### ConsultaCriada Resposta do POST /v1/consultas. `status` é sempre "processando": o resultado sai em GET /v1/consultas/{id}. - id (string (uuid), obrigatório): sem descrição. - servico (string, obrigatório): sem descrição. Valores: consulta, consulta-completa, ecv-premium, consulta-veicular, gravame, renajud, debitos, debitos-estadual, historico-proprietarios, comunicacao-venda, decodificacao-chassi, decodificacao-motor, score-credito, situacao-cpf, cadastro-simples-cpf, cadastro-completo-cpf, cadastro-simples-cnpj, cadastro-completo-cnpj, credito-unico-cpf, credito-biro-cpf, credito-unico-cnpj, credito-biro-cnpj, cnh-nacional, debitos-trabalhistas, divida-ativa, codigo-seguranca, atpve, consulta-nfe, crlv. - status (string, obrigatório): sem descrição. Valores: processando. - ambiente (string): Presente SOMENTE em respostas do ambiente de teste. Ausente em produção. Valores: test. - cenario (string): Só no ambiente de teste: o cenário que a placa reservada seleciona. - valor_cobrado (number, obrigatório): Debitado agora, em reais. 0 quando a consulta foi reaproveitada. - preco_base (number): Só quando um Grupo de Desconto foi aplicado. - desconto (Desconto): Grupo de Desconto da API aplicado a esta conta. - saldo_restante (number, obrigatório): sem descrição. - resultado_url (string, obrigatório): Caminho para acompanhar o resultado. - reaproveitada (boolean): Só no HTTP 200: uma solicitação idêntica já estava em processamento e foi devolvida. Nada foi cobrado. - mensagem (string): Só no HTTP 200 reaproveitado: explicação para exibir ao usuário. - avisos (array de AvisoConsulta): Só aparece quando há algo a avisar. Hoje, no `crlv`: a `uf` informada não é a de registro da placa (`UF_REGISTRO_DIVERGENTE`). O pedido segue normalmente; se o DETRAN recusar, a consulta termina em erro e o valor volta ao saldo. ### ConsultaResponse Resposta do GET /v1/consultas/{id}. Os blocos presentes dependem do `status`: `dados`/`veiculo`/`pdf_url` apenas em "concluido"; `erro`/`erro_codigo`/`retryable` apenas em "erro". - id (string (uuid), obrigatório): sem descrição. - servico (string, obrigatório): sem descrição. Valores: consulta, consulta-completa, ecv-premium, consulta-veicular, gravame, renajud, debitos, debitos-estadual, historico-proprietarios, comunicacao-venda, decodificacao-chassi, decodificacao-motor, score-credito, situacao-cpf, cadastro-simples-cpf, cadastro-completo-cpf, cadastro-simples-cnpj, cadastro-completo-cnpj, credito-unico-cpf, credito-biro-cpf, credito-unico-cnpj, credito-biro-cnpj, cnh-nacional, debitos-trabalhistas, divida-ativa, codigo-seguranca, atpve, consulta-nfe, crlv. - placa (string, pode ser null): sem descrição. - status (string, obrigatório): "processando" = siga o polling. "concluido" e "erro" são TERMINAIS: o mesmo id não muda mais. Valores: processando, concluido, erro. - schema_version (string, obrigatório): Versão do contrato de resposta. Minor = só acréscimo de campo; major nunca sai sem aviso no changelog. - ambiente (string): Presente SOMENTE em respostas do ambiente de teste. Ausente em produção. Valores: test. - cenario (string): Só no ambiente de teste: o cenário que a placa reservada seleciona. - uf (string): Só em crlv e debitos-estadual. - valor_cobrado (number, pode ser null): sem descrição. - criado_em (string (date-time), pode ser null): Fuso America/Sao_Paulo. - dados (DadosPessoa ou objeto, pode ser null): Resultado como a base devolveu (camada de espelho, nomes no padrão da fonte). null em crlv e codigo-seguranca, que entregam só o PDF. Para dado com forma garantida, use `veiculo`. Na consulta-completa (desde 14/10/2026) vêm também: `historicoKm` ({ registros: [{ km, data, dataIso }], inconsistente }), `historicoProprietarios` ([{ nome, documento, anoExercicio, uf }]), `rouboFurto` ({ constaOcorrencia, ocorrenciaAtiva, ocorrencias: [{ ocorrencia, declaracao, data, boletim, municipio, uf }] }), `leilao.score` (avaliação do leiloeiro) e `fotosLeilao` ([{ indice, url }]). Em todos: null = não verificado, lista vazia = sem registro. Não vêm mais: `renainf`, `imagensOutras`, `alertasSinistro`, `informacoesAvulsas`; `restricoes.recall`, `situacaoLicenciamento` e `licenciadoAte` vêm null. O ecv-premium (desde 14/10/2026) tem o mesmo formato da consulta-completa, sem `fotosLeilao`, e acrescenta: `remarketing` ({ marcaModelo, situacaoChassi, segmento, subSegmento, checklist: { dataInspecao, itens: [{ parte, estado }], garantia, fotos } }), `anuncios` ([{ data, km, valor, opcionais, fotos }]) e `codigosFipe` ([string]). As passagens por leilão do remarketing entram em `leilao.ocorrencias`. Nas consultas de pessoa (cadastro-*, credito-*, cnh-nacional, debitos-trabalhistas, divida-ativa; desde 15/10/2026) `dados` segue o schema `DadosPessoa`, igual nos 11 serviços, e a resposta não traz `placa`, `veiculo` nem `proprietario`. - veiculo (Veiculo): Contrato ZapCar normalizado, em snake_case: a camada ESTÁVEL da resposta. Mesma forma em consulta, consulta-completa, consulta-veicular, ecv-premium, gravame e renajud, independente do fornecedor. null em `recall`/`sinistro`/`leilao` significa NÃO VERIFICADO por este serviço: nunca "não consta". - proprietario (Proprietario): sem descrição. - ultimo_licenciamento (integer, pode ser null): sem descrição. - risco (objeto): Índice de risco. Só na consulta-completa, o único serviço que verifica sinistro, leilão e roubo/furto juntos. - nao_verificado (array de string): Só na consulta simples: categorias que a base NÃO checou nesta consulta. Campo vazio em `dados` que esteja nesta lista é ausência de VERIFICAÇÃO, não ausência de restrição. Desde 09/10/2026 a base tem campo próprio para todas as restrições, então a lista costuma vir vazia; um item aparece quando o estado não respondeu aquela categoria. - pdf_url (string): Caminho do documento. Só em "concluido". - erro (string): Só em "erro": frase para o cliente, sem nome de fornecedor nem jargão técnico. - erro_codigo (string): Só em "erro": por que falhou. Ausente em consultas anteriores a 02/09/2026. Valores: INVALID_PLATE, INVALID_CHASSIS, INVALID_ENGINE, INVALID_RENAVAM, INVALID_DOCUMENT, MISSING_REQUIRED_FIELD, UF_UNAVAILABLE, QUERY_NOT_FOUND, PROVIDER_TIMEOUT, PROVIDER_UNAVAILABLE, PROVIDER_INVALID_RESPONSE, PROVIDER_AUTH_ERROR, PROVIDER_ERROR, PROVIDER_NO_DOCUMENT, CIRCUIT_OPEN, QUEUE_UNAVAILABLE, PROCESSING_INTERRUPTED, PDF_GENERATION_FAILED, ADAPTER_ERROR, CONFIG_ERROR, INTERNAL_ERROR. - retryable (boolean): Só em "erro". true = transitório, vale criar uma consulta NOVA depois de um backoff. false = definitivo. AUSENTE = a falha não foi classificada: trate como definitivo, não repita automaticamente. ### Veiculo Contrato ZapCar normalizado, em snake_case: a camada ESTÁVEL da resposta. Mesma forma em consulta, consulta-completa, consulta-veicular, ecv-premium, gravame e renajud, independente do fornecedor. null em `recall`/`sinistro`/`leilao` significa NÃO VERIFICADO por este serviço: nunca "não consta". - placa (string, obrigatório, pode ser null): sem descrição. - renavam (string, pode ser null): sem descrição. - chassi (string, pode ser null): sem descrição. - marca (string, pode ser null): sem descrição. - modelo (string, pode ser null): sem descrição. - ano_fabricacao (integer, pode ser null): sem descrição. - ano_modelo (integer, pode ser null): sem descrição. - cor (string, pode ser null): sem descrição. - combustivel (string, pode ser null): sem descrição. - especie (string, pode ser null): sem descrição. - categoria (string, pode ser null): sem descrição. - municipio (string, pode ser null): sem descrição. - uf (string, pode ser null): sem descrição. - proprietario (Proprietario, pode ser null): sem descrição. - historico_proprietarios (array de objeto, pode ser null): Cadeia de titularidade (só consulta-completa e serviço dedicado). Ausente = o serviço não consulta; null = consulta e a base não respondeu; [] = sem registro. - situacao (string, pode ser null): sem descrição. - baixado (boolean): sem descrição. - recall (boolean, pode ser null): null = este serviço não verifica recall. - sinistro (boolean, pode ser null): null = este serviço não verifica sinistro. - leilao (LeilaoInfo, pode ser null): null = nenhuma das fontes de leilão respondeu. - restricoes (array de Restricao, obrigatório): sem descrição. - debitos (array de Debito, obrigatório): sem descrição. - debitos_total_centavos (integer, obrigatório): Soma dos débitos em centavos. Com algum item `valor_informado: false`, é um PISO. - ficha_pesados (objeto, pode ser null): Só preenchido em caminhão, ônibus e implemento. - faturamento (objeto, pode ser null): Para quem a montadora faturou o veículo 0km. - ultimo_licenciamento (integer, pode ser null): Ano do último licenciamento. - _servico (string): Metadado: serviço que originou o bloco. - _normalizado_em (string (date-time)): Metadado: quando o bloco foi montado. - _fonte (string): Metadado. Sempre `zapcar`: o contrato público é nosso, não do fornecedor. ### Proprietario - nome (string, pode ser null): sem descrição. - documento (string, pode ser null): CPF/CNPJ como a fonte devolveu (pode vir mascarado). `null` quando a base não liberou o documento; o nome pode vir mesmo assim. ### ApiError Envelope único de erro da API pública. `erro` é frase para humano (pode mudar de redação); `codigo` é o identificador estável em que se programa; `retryable` diz se repetir a MESMA chamada pode dar certo. - erro (string, obrigatório): sem descrição. - codigo (string, obrigatório): sem descrição. Valores: MISSING_API_KEY, INVALID_API_KEY, CUSTOMER_NOT_FOUND, SERVICO_INVALIDO, VALIDATION_ERROR, PLACA_INVALIDA, RENAVAM_INVALIDO, DOCUMENTO_INVALIDO, CHASSI_INVALIDO, MOTOR_INVALIDO, DATA_NASCIMENTO_INVALIDA, CHAVE_NFE_INVALIDA, FINALIDADE_OBRIGATORIA, CNH_INVALIDA, UF_INVALIDA, UF_INDISPONIVEL, CRLV_DADOS_OBRIGATORIOS, DEBITOS_DADOS_OBRIGATORIOS, SERVICO_INDISPONIVEL, ACEITE_ATPVE_OBRIGATORIO, AVISO_ATPVE_DESATUALIZADO, IDEMPOTENCY_KEY_INVALIDA, IDEMPOTENCY_KEY_REUSED, IDEMPOTENCY_IN_PROGRESS, SALDO_INSUFICIENTE, CONSULTA_NOT_FOUND, PDF_NOT_READY, PDF_NOT_FOUND, CONSULTA_WITHOUT_DATA, DOCUMENTO_CORROMPIDO, IMAGEM_NOT_FOUND, IMAGEM_TIPO_INVALIDO, IMAGEM_INDICE_INVALIDO, FIPE_INDISPONIVEL, FIPE_ERRO, FIPE_NAO_DISPONIVEL, SANDBOX_INDISPONIVEL, SANDBOX_SEM_DOCUMENTO, RATE_LIMITED, CIRCUIT_OPEN, PROVIDER_TIMEOUT, INTERNAL_ERROR, ROTA_NAO_ENCONTRADA. - retryable (boolean, obrigatório): true = falha transitória (provedor/rede/limite). false = corrija o pedido antes de repetir. - request_id (string): Id de correlação desta requisição nos logs da ZapCar. - detalhes (array de objeto, pode ser null): Só em VALIDATION_ERROR: o que falhou, por campo. - saldo (number, pode ser null): Só em SALDO_INSUFICIENTE: saldo atual da carteira, em reais. ### Servico - servico (string, obrigatório): Slug usado no campo `servico` do POST /v1/consultas. Valores: consulta, consulta-completa, ecv-premium, consulta-veicular, gravame, renajud, debitos, debitos-estadual, historico-proprietarios, comunicacao-venda, decodificacao-chassi, decodificacao-motor, score-credito, situacao-cpf, cadastro-simples-cpf, cadastro-completo-cpf, cadastro-simples-cnpj, cadastro-completo-cnpj, credito-unico-cpf, credito-biro-cpf, credito-unico-cnpj, credito-biro-cnpj, cnh-nacional, debitos-trabalhistas, divida-ativa, codigo-seguranca, atpve, consulta-nfe, crlv. - nome (string, obrigatório): sem descrição. - requer (array de string, obrigatório): Campos obrigatórios no corpo da criação. - preco (number): Preço que SERÁ debitado (já com preço personalizado e desconto). Ausente quando o preço é por UF. - preco_base (number): Preço antes do Grupo de Desconto (só quando há desconto). - preco_tabela (number): Preço de tabela quando há promoção vigente (`preco` já é o promocional). - promocao (boolean): Há promoção vigente neste serviço. - desconto (Desconto): Grupo de Desconto da API aplicado a esta conta. - observacao (string, pode ser null): sem descrição. - preco_por_uf (array de objeto): Só no CRLV: preço e campos exigidos por estado. - campos_por_uf (array de objeto): Serviços estaduais (debitos-estadual): as UFs atendidas (as 27) e os campos que cada uma exige, desde 09/10/2026, só uf + placa em todas. UF fora desta lista → 400 UF_INDISPONIVEL, também no sandbox. - opcionais (objeto): Adicionais do serviço (ex.: `incluir_fipe` na consulta-completa). - sincrono (boolean): true = a resposta vem na mesma chamada (sem polling). Só a FIPE. - endpoint (string): Endpoint próprio do serviço, quando não é POST /v1/consultas. - codigo (string, obrigatório): Código interno do serviço. - categoria (string, obrigatório): sem descrição. - descricao (string, obrigatório): sem descrição. - prazo (string, pode ser null): sem descrição. - nota_precos (string, pode ser null): sem descrição. - pagina_site (string, pode ser null): sem descrição. - disponivel_painel (boolean): sem descrição. - disponivel_api (boolean, obrigatório): sem descrição. - ordem (integer, obrigatório): sem descrição. - ufs_suportadas (array de string, pode ser null): null = todas as UFs. ### CatalogoServicos - servicos (array de Servico, obrigatório): sem descrição. - desconto_api (objeto, pode ser null): Grupo de Desconto da API da conta, quando houver. ### SaldoResponse - saldo (number, obrigatório): Saldo da carteira, em reais. ### FipeResponse - id (string (uuid), obrigatório): Id desta cobrança (não há consulta para acompanhar: o endpoint é síncrono). - servico (string, obrigatório): sem descrição. Valores: fipe. - placa (string, obrigatório): sem descrição. - veiculo (objeto): sem descrição. - fipe (array de FipeItem, obrigatório): sem descrição. - valor_cobrado (number, obrigatório): sem descrição. - preco_base (number): sem descrição. - desconto (Desconto): Grupo de Desconto da API aplicado a esta conta. - saldo_restante (number, obrigatório): sem descrição. ### FipeItem Uma versão do veículo na tabela FIPE. Valores como a FIPE publica (texto em reais). - codigo_fipe (string, pode ser null): sem descrição. - marca (string, pode ser null): sem descrição. - modelo (string, pode ser null): sem descrição. - ano_modelo (string, pode ser null): sem descrição. - combustivel (string, pode ser null): sem descrição. - sigla_combustivel (string, pode ser null): sem descrição. - valor (string, pode ser null): sem descrição. - mes_referencia (string, pode ser null): sem descrição. - referencia_fipe (integer, pode ser null): sem descrição. - score (number, pode ser null): Aderência desta versão à placa consultada. - codigo_marca (string, pode ser null): sem descrição. - codigo_modelo (string, pode ser null): sem descrição. - tipo_modelo (integer, pode ser null): sem descrição. - historico (array de FipeHistoricoPonto, pode ser null): Últimos meses da tabela para esta versão, do mais recente para o mais antigo (o primeiro é o mês de `valor`). null = histórico não obtido. - fonte_valor (string): "fipe" = `valor` é o da referência FIPE vigente. "placas" = a fonte de valor atual falhou e `valor`/`mes_referencia` são os da base de identificação (podem ser de um mês antigo). Valores: fipe, placas. ### WebhookPayload Corpo do POST que a ZapCar envia ao seu endpoint. NÃO carrega o resultado da consulta: dado sensível sai só por chamada autenticada com a sua chave. - id (string (uuid), obrigatório): Id do EVENTO. Use para deduplicar: um retry reenvia o mesmo id. - type (string, obrigatório): sem descrição. Valores: webhook.test, query.completed, query.failed, vehicle.restriction.created, vehicle.gravame.created, vehicle.gravame.removed, vehicle.debt.created, vehicle.document.changed. - created_at (string (date-time), obrigatório): sem descrição. - data (objeto, obrigatório): Em query.*: { id, servico, status, servico_slug, status_publico }, o `id` é o da consulta, para GET /v1/consultas/{id}; `servico` e `status` são os nomes INTERNOS (mantidos por compatibilidade); `servico_slug` e `status_publico` são os do contrato público (desde 19/10/2026). Em vehicle.*: { placa, tipo, titulo, detalhe }. Em webhook.test: { mensagem, webhook_id }. ## Catálogo de erros da requisição Envelope: { erro, codigo, retryable, request_id }. retryable true = transitório. - 400 CHASSI_INVALIDO (retryable false): Chassi inválido. - 400 CHAVE_NFE_INVALIDA (retryable false): Chave de acesso da NF-e inválida: 44 dígitos com dígito verificador correto (consulta-nfe). - 400 CNH_INVALIDA (retryable false): Número de registro da CNH ausente ou inválido (cnh-nacional). - 400 CONSULTA_WITHOUT_DATA (retryable false): Consulta sem dados para gerar o documento. - 400 CRLV_DADOS_OBRIGATORIOS (retryable false): Faltam campos exigidos pela UF (CPF/RENAVAM). - 400 DATA_NASCIMENTO_INVALIDA (retryable false): Data de nascimento ausente ou inválida (situacao-cpf; use dd/mm/aaaa). - 400 DEBITOS_DADOS_OBRIGATORIOS (retryable false): Faltam campos exigidos pela UF. - 400 DOCUMENTO_INVALIDO (retryable false): CPF/CNPJ inválido. - 400 FINALIDADE_OBRIGATORIA (retryable false): Serviço com dado pessoal (comunicacao-venda e as consultas de pessoa: cadastro, crédito, CNH, débitos trabalhistas, dívida ativa): envie finalidade e declaracao_finalidade: true. - 400 IDEMPOTENCY_KEY_INVALIDA (retryable false): Idempotency-Key fora do formato (8–255 chars). - 400 IMAGEM_INDICE_INVALIDO (retryable false): Índice de imagem inválido (inteiro >= 0). - 400 IMAGEM_TIPO_INVALIDO (retryable false): Tipo de imagem desconhecido. Use leilao, outra, csv-imagem ou csv-pdf. - 400 MOTOR_INVALIDO (retryable false): Número do motor inválido. - 400 PDF_NOT_READY (retryable true): Documento ainda em processamento; tente novamente. - 400 PLACA_INVALIDA (retryable false): Placa em formato inválido. - 400 RENAVAM_INVALIDO (retryable false): RENAVAM inválido. - 400 SERVICO_INVALIDO (retryable false): Slug de serviço desconhecido. - 400 UF_INDISPONIVEL (retryable false): UF indisponível para o serviço. - 400 UF_INVALIDA (retryable false): UF inválida. - 400 VALIDATION_ERROR (retryable false): Corpo da requisição inválido. - 401 CUSTOMER_NOT_FOUND (retryable false): Conta associada à chave não encontrada. - 401 INVALID_API_KEY (retryable false): Chave de API inválida ou revogada. - 401 MISSING_API_KEY (retryable false): Cabeçalho Authorization: Bearer ausente. - 402 SALDO_INSUFICIENTE (retryable false): Saldo insuficiente na carteira. - 404 CONSULTA_NOT_FOUND (retryable false): Consulta não encontrada para esta conta. - 404 FIPE_NAO_DISPONIVEL (retryable false): Sem FIPE para esta placa. - 404 IMAGEM_NOT_FOUND (retryable false): Imagem inexistente para esta consulta. Consultas concluídas antes de 27/08/2026 não têm imagens armazenadas: reprocesse a consulta. - 404 PDF_NOT_FOUND (retryable false): PDF não disponível para esta consulta. - 404 ROTA_NAO_ENCONTRADA (retryable false): Rota inexistente. - 409 AVISO_ATPVE_DESATUALIZADO (retryable false): `aceite_atpve.versao` diferente da vigente. Busque o aviso novo em GET /public/avisos/atpve, mostre ao usuário e reenvie. - 409 IDEMPOTENCY_IN_PROGRESS (retryable true): Requisição idêntica ainda em processamento; repita em instantes. - 422 ACEITE_ATPVE_OBRIGATORIO (retryable false): atpve sem `aceite_atpve.aceito: true`. Mostre o aviso de GET /public/avisos/atpve ao usuário e envie a declaração. - 422 DOCUMENTO_CORROMPIDO (retryable false): O documento armazenado não é um arquivo válido (PDF/PNG/JPEG). Refaça a consulta: repetir o download não resolve. - 422 IDEMPOTENCY_KEY_REUSED (retryable false): Mesma Idempotency-Key com payload diferente. - 422 SANDBOX_SEM_DOCUMENTO (retryable false): O ambiente de teste não gera documentos (PDF/imagem). Use a chave zc_live_ para baixar um documento real. - 422 SERVICO_INDISPONIVEL (retryable false): Serviço sem preço/indisponível para a conta. - 429 RATE_LIMITED (retryable true): Limite de requisições excedido. - 500 INTERNAL_ERROR (retryable true): Erro interno inesperado. - 502 FIPE_ERRO (retryable true): Falha transitória ao consultar a FIPE. - 503 CIRCUIT_OPEN (retryable true): Fornecedor temporariamente indisponível (circuito aberto). - 503 FIPE_INDISPONIVEL (retryable true): Provedor FIPE temporariamente indisponível. - 503 SANDBOX_INDISPONIVEL (retryable true): O ambiente de teste está momentaneamente indisponível. Tente em instantes. - 504 PROVIDER_TIMEOUT (retryable true): Tempo de resposta do fornecedor excedido. ## Falhas do processamento (erro_codigo da consulta com status erro) O valor da consulta é estornado. retryable true = vale criar uma consulta NOVA depois de um backoff. - INVALID_PLATE (CLIENTE, retryable false): A placa informada é inválida. Confira os caracteres e tente novamente. - INVALID_CHASSIS (CLIENTE, retryable false): O chassi informado é inválido. Confira o número e tente novamente. - INVALID_ENGINE (CLIENTE, retryable false): O número do motor informado é inválido. Confira e tente novamente. - INVALID_RENAVAM (CLIENTE, retryable false): O RENAVAM informado é inválido. Confira os dígitos e tente novamente. - INVALID_DOCUMENT (CLIENTE, retryable false): O CPF/CNPJ informado é inválido. Confira os dígitos e tente novamente. - MISSING_REQUIRED_FIELD (CLIENTE, retryable false): Faltou um dado obrigatório para esta consulta. Confira os campos e tente novamente. - UF_UNAVAILABLE (CLIENTE, retryable false): Este serviço não está disponível para o estado informado. - QUERY_NOT_FOUND (SEM_RESULTADO, retryable false): Não encontramos registros para os dados informados nas bases consultadas. Confira as informações antes de tentar de novo. - PROVIDER_TIMEOUT (FORNECEDOR, retryable true): A base consultada demorou mais que o esperado e a consulta não foi concluída. Tente novamente em alguns minutos. - PROVIDER_UNAVAILABLE (FORNECEDOR, retryable true): A base consultada está temporariamente indisponível. Isso costuma se resolver em alguns minutos: tente novamente. - PROVIDER_INVALID_RESPONSE (FORNECEDOR, retryable true): A base consultada respondeu de forma incompleta e a consulta não pôde ser concluída. Tente novamente em alguns minutos. - PROVIDER_AUTH_ERROR (FORNECEDOR, retryable false): Não foi possível concluir a consulta neste momento. Nossa equipe já foi avisada. - PROVIDER_ERROR (FORNECEDOR, retryable false): A base consultada não conseguiu concluir esta consulta. Tente novamente mais tarde. - PROVIDER_NO_DOCUMENT (FORNECEDOR, retryable false): O órgão emissor não devolveu o documento desta solicitação. Tente novamente mais tarde. - CIRCUIT_OPEN (FORNECEDOR, retryable true): A base consultada está temporariamente indisponível. Isso costuma se resolver em alguns minutos: tente novamente. - QUEUE_UNAVAILABLE (INTERNO, retryable true): Não foi possível iniciar o processamento desta consulta agora. Tente novamente em alguns instantes. - PROCESSING_INTERRUPTED (INTERNO, retryable true): O processamento desta consulta foi interrompido e não pôde ser concluído. Você pode solicitar novamente. - PDF_GENERATION_FAILED (INTERNO, retryable false): A consulta foi realizada, mas houve um problema ao montar o documento. Nossa equipe já foi avisada. - ADAPTER_ERROR (INTERNO, retryable false): Não foi possível processar os dados retornados pela consulta. Nossa equipe já foi avisada. - CONFIG_ERROR (INTERNO, retryable false): Não foi possível processar esta consulta por um problema interno. Nossa equipe já foi avisada. - INTERNAL_ERROR (INTERNO, retryable false): Não foi possível processar esta consulta por um problema interno. Nossa equipe já foi avisada. ## Formato do campo dados por serviço Exemplos ilustrativos (dados fictícios), no formato que cada serviço devolve. O bloco veiculo, quando existe, tem a forma do objeto Veiculo acima. ### Consulta Simples (servico "consulta") Exige: placa. Entrega: JSON do veículo + PDF. Bloco veiculo: sim. Corpo mínimo: {"servico":"consulta","placa":"ABC1D23"} - A base estadual pode levar cerca de 2 minutos numa placa consultada pela primeira vez no dia. A mesma placa, repetida, volta mais rápido. - nao_verificado lista as categorias que a base não checou nesta consulta. Campo vazio que aparece nessa lista é "não verificado", nunca "nada consta". - O documento do proprietário vem de uma segunda base: quando ela não libera o dado, proprietario_s_.documento vem "" e proprietario.documento vem null, com o nome preenchido. - O PDF é desenhado pela ZapCar no layout do laudo da base, a partir do mesmo dados. Item não respondido sai como NÃO INFORMADO. - Sandbox: Cenário escolhido pela placa (TST0001 limpo, TST0002 gravame, TST0003 RENAJUD, TST0004 débitos, TST0005 sinistro e leilão, TST0404 não encontrado, TST0503 falha retentável, TST9999 nunca conclui). Bloco veiculo fiel ao contrato; dados reduzido e marcado com _sandbox. ```json { "dados_do_veiculo": { "placa": "ABC1D23", "chassi": "9BWZZZ377VT004251", "renavam": "00987495364", "marca": "VW", "modelo": "NIVUS HIGHLINE TSI", "anofabricacao": "2022", "anomodelo": "2022", "cor": "PRATA", "combustivel": "GASOLINA", "tipoveiculo": "AUTOMOVEL", "municipio": "SAO PAULO", "uf": "SP" }, "informacoes_tecnicas_e_adicionais": { "motor": "D4FB1234567", "cilindradas": "999", "especie": "PASSAGEIRO", "categoria": "PARTICULAR", "carroceria": "INEXISTENTE", "capacidadedepassageiros": "5", "quantidadedeeixos": "2", "situacaodochassi": "NORMAL", "procedencia": "NACIONAL" }, "restricoes_e_impedimentos": { "situacao_veiculo": "EM CIRCULACAO", "roubo_e_furto": "NADA CONSTA", "restricoes": [], "intencao_de_financiamento": { "restricaofinanceira": "NADA CONSTA", "restricaorenajud": "NADA CONSTA", "restricaojudicial": "NADA CONSTA", "restricaoadministrativa": "NADA CONSTA", "restricaotributaria": "NADA CONSTA", "restricaoguincho": "NADA CONSTA", "agente": "", "nomedofinanciado": "" } }, "debitos_estaduais": { "debitosdeipva": "0", "debitosdelicenciamento": "150,00", "debitosdedpvat": "0", "debitosdemultas": "0", "exerciciolicenciamento": "2024" }, "comunicacao_de_vendas": { "comunicacaodevendas": "NADA CONSTA" }, "proprietario_s_": { "proprietario_atual": "JOAO DA SILVA", "documento": "12345678901" } } ``` ### Consulta Completa (servico "consulta-completa") Exige: placa. Entrega: JSON estruturado (por seção) + PDF. Bloco veiculo: sim. Corpo mínimo: {"servico":"consulta-completa","placa":"ABC1D23","incluir_fipe":false} - incluir_fipe: true embute a Tabela FIPE em dados.fipe e cobra o adicional informado em opcionais.incluir_fipe.preco_adicional (GET /v1/servicos). Se só a FIPE falhar, só essa parcela é estornada e dados.fipeErro diz o motivo. - dados.debitos traz valores reais, estado por item e total_parcial. CONSTA_SEM_VALOR significa "deve, valor não informado": o total é um piso. debitos: null é "não verificado". - As fotos de leilão não viajam no JSON: fotosLeilao traz índice e URL de cada uma, servidas por GET /v1/consultas/{id}/imagens/leilao/{indice}. - risco é o mesmo índice exibido no painel e no laudo. Não é garantia de compra. - Sandbox: Cenário escolhido pela placa (TST0001 limpo, TST0002 gravame, TST0003 RENAJUD, TST0004 débitos, TST0005 sinistro e leilão, TST0404 não encontrado, TST0503 falha retentável, TST9999 nunca conclui). Bloco veiculo fiel ao contrato; dados reduzido e marcado com _sandbox. ```json { "placa": "ABC1D23", "chassi": "9BWZZZ377VT004251", "renavam": "00987495364", "marcaModelo": "VW/NIVUS HIGHLINE TSI", "anoFabricacao": 2022, "anoModelo": 2022, "cor": "PRATA", "combustivel": "GASOLINA", "tipoVeiculo": "AUTOMOVEL", "especie": "PASSAGEIRO", "categoria": "PARTICULAR", "potencia": 128, "cilindrada": 999, "quantidadeEixos": 2, "capacidadePassageiros": 5, "procedencia": "NACIONAL", "chassiRemarcado": false, "situacaoLicenciamento": null, "licenciadoAte": null, "anoUltimoLicenciamento": 2024, "numeroDocumentoFaturado": "12345678901", "ufFaturamento": "SP", "proprietario": { "nome": "JOAO DA SILVA", "nomeLegal": null, "documento": "12345678901", "tipoDocumento": "CPF", "situacao": null, "telefones": [], "emails": [], "enderecos": [] }, "historicoProprietarios": [ { "nome": "JOAO DA SILVA", "documento": "12345678901", "anoExercicio": 2024, "uf": "SP" }, { "nome": "LOCADORA EXEMPLO LTDA", "documento": "12345678000190", "anoExercicio": 2022, "uf": "SP" } ], "restricoes": { "rouboOuFurto": false, "sinistro": false, "restricaoRenajud": false, "restricaoRfb": null, "restricaoAdministrativa": false, "restricaoRenainf": false, "recall": null, "intencaoVenda": null, "anuncioVenda": null, "restricaoGeral": null, "veiculoBaixado": false, "restricao1": null, "restricao2": null, "restricao3": null, "restricao4": null, "ocorrencia": null }, "debitos": { "dpvat": 0, "ipva": 3821.78, "licenciamento": 0, "multa": 0, "total": 3821.78, "estado": { "dpvat": "SEM_DEBITO", "ipva": "CONSTA", "licenciamento": "SEM_DEBITO", "multa": "CONSTA_SEM_VALOR" }, "total_parcial": true }, "gravames": [ { "numeroRestricao": "123456", "dataRestricao": "10/01/2022", "ufRestricao": "SP", "status": "ATIVO", "nomeAgente": "BANCO EXEMPLO SA", "documentoAgente": "00000000000191", "dataContrato": null, "ufContrato": null, "numeroContrato": "C-0001", "documentoFinanciado": "12345678901", "nomeFinanciado": "JOAO DA SILVA" } ], "leilao": { "baseDisponivel": true, "score": { "pontuacao": "C", "descricao": "MEDIA MONTA", "aceitacao": 40, "percentualSobreTabela": 70, "exigeVistoriaEspecial": "SIM" }, "ocorrencias": [ { "lote": "1707", "patio": null, "data": "30/05/2023", "comitente": "SEGURADORA EXEMPLO SA", "leiloeiro": null, "condicao": "MEDIA MONTA", "observacao": null } ] }, "rouboFurto": { "constaOcorrencia": true, "ocorrenciaAtiva": false, "ocorrencias": [ { "ocorrencia": "Encontrado", "declaracao": null, "data": "21/12/2021", "boletim": "5219", "municipio": "CAMPINAS", "uf": "SP" }, { "ocorrencia": "Alerta de Roubo/Furto", "declaracao": "Roubo", "data": "19/12/2021", "boletim": "1466", "municipio": "CAMPINAS", "uf": "SP" } ] }, "historicoKm": { "inconsistente": false, "registros": [ { "km": 18400, "data": "12/03/2022", "dataIso": "2022-03-12" }, { "km": 39950, "data": "20/06/2023", "dataIso": "2023-06-20" } ] }, "fotosLeilao": [ { "indice": 0, "url": "/v1/consultas/{id}/imagens/leilao/0" }, { "indice": 1, "url": "/v1/consultas/{id}/imagens/leilao/1" } ], "csv": [], "blocos": { "BIN_ESTADUAL": { "respondeu": true, "quantidade": 12, "descricao": null }, "BIN_NACIONAL": { "respondeu": true, "quantidade": 0, "descricao": null }, "LEILAO": { "respondeu": true, "quantidade": 1, "descricao": "Consta histórico de leilão" }, "INDICIO_SINISTRO": { "respondeu": true, "quantidade": 0, "descricao": null }, "CSV": { "respondeu": true, "quantidade": 0, "descricao": null }, "GRAVAME": { "respondeu": true, "quantidade": 1, "descricao": null }, "HISTORICO_KM": { "respondeu": true, "quantidade": 2, "descricao": null }, "ROUBO_FURTO": { "respondeu": true, "quantidade": 2, "descricao": null }, "HISTORICO_PROPRIETARIOS": { "respondeu": true, "quantidade": 2, "descricao": null }, "IMAGENS_VEICULO": { "respondeu": true, "quantidade": 2, "descricao": null } }, "offline": null } ``` ### Laudo ECV Premium (servico "ecv-premium") Exige: placa. Entrega: JSON estruturado no formato da Consulta Completa (historicoKm, historicoProprietarios, rouboFurto, csv e blocos inclusos, sem fotosLeilao) mais remarketing, anuncios e codigosFipe + PDF. Bloco veiculo: sim. Corpo mínimo: {"servico":"ecv-premium","placa":"ABC1D23"} - Mesmo formato de dados da consulta-completa, sem fotosLeilao, com três blocos a mais: remarketing, anuncios e codigosFipe. - As passagens por leilão do remarketing entram em leilao.ocorrencias. - Traz a cadeia de proprietários com documento: dado pessoal de terceiros. - Sandbox: Cenário escolhido pela placa (TST0001 limpo, TST0002 gravame, TST0003 RENAJUD, TST0004 débitos, TST0005 sinistro e leilão, TST0404 não encontrado, TST0503 falha retentável, TST9999 nunca conclui). Bloco veiculo fiel ao contrato; dados reduzido e marcado com _sandbox. ```json { "placa": "ABC1D23", "marcaModelo": "FORD/FOCUS TI 2.0", "leilao": { "baseDisponivel": true, "ocorrencias": [ { "lote": "88", "data": "12/08/2020", "leiloeiro": "LEILOES SA", "comitente": "FROTA Y", "condicao": "PEQUENA MONTA" } ] }, "remarketing": { "marcaModelo": "FORD/FOCUS", "situacaoChassi": "NORMAL", "segmento": "FINANCEIRA", "subSegmento": "RETOMADA", "checklist": { "dataInspecao": "28/05/2019", "garantia": "SEM GARANTIA", "fotos": 2, "itens": [{ "parte": "Frente", "estado": "AMASSADO" }, { "parte": "Motor", "estado": "OK" }] } }, "anuncios": [{ "data": "10/03/2024", "km": 82000, "valor": 45900, "opcionais": ["AR CONDICIONADO"], "fotos": 1 }], "codigosFipe": ["003281-6"], "historicoKm": { "registros": [{ "km": 82000, "data": "10/03/2024", "dataIso": "2024-03-10" }], "inconsistente": false }, "blocos": { "REMARKETING": { "respondeu": true, "quantidade": 1, "descricao": null } } } ``` ### Consulta Veicular (servico "consulta-veicular") Exige: placa. Entrega: JSON estruturado no formato da Consulta Completa, sem os blocos exclusivos dela (historicoKm, historicoProprietarios, rouboFurto, csv, blocos); debitos costuma vir null (não verificado) + PDF. Bloco veiculo: sim. Corpo mínimo: {"servico":"consulta-veicular","placa":"ABC1D23"} - Formato de dados da consulta-completa, sem os blocos exclusivos dela (historicoKm, historicoProprietarios, rouboFurto, csv, blocos). - debitos costuma vir null: não verificado, diferente de "não deve". - Quando vem, a base manda o débito em centavos e a API o entrega em reais; se algum item fica fora da faixa crível, os débitos da resposta saem em debitos.estado como consta, "Consta, valor a confirmar", com valor 0 e total_parcial: true. - Os débitos vêm de uma base diferente da consulta-completa e podem divergir dela na mesma placa. Para o valor a pagar, use debitos-estadual. - Sandbox: Cenário escolhido pela placa (TST0001 limpo, TST0002 gravame, TST0003 RENAJUD, TST0004 débitos, TST0005 sinistro e leilão, TST0404 não encontrado, TST0503 falha retentável, TST9999 nunca conclui). Bloco veiculo fiel ao contrato; dados reduzido e marcado com _sandbox. ```json { "placa": "ABC1D23", "chassi": "9BWZZZ377VT004251", "numeroMotor": "CSS123456", "ufPlaca": "SP", "municipioPlaca": "SAO PAULO", "renavam": "00987495364", "status": "EM CIRCULACAO", "anoFabricacao": 2020, "anoModelo": 2021, "marcaModelo": "VW/GOL 1.0L MC4", "tipoVeiculo": "AUTOMOVEL", "especie": "PASSAGEIRO", "cor": "PRATA", "combustivel": "ALCOOL/GASOLINA", "categoria": "PARTICULAR", "potencia": 84, "cilindrada": 999, "situacaoLicenciamento": "LICENCIADO", "licenciadoAte": "2025", "anoUltimoLicenciamento": 2025, "ativo": "SIM", "codigoMarcaModelo": "0123456", "quantidadeEixos": 2, "capacidadePassageiros": 5, "capacidadeCargaKg": null, "pesoBrutoTotal": null, "capacidadeMaximaTracao": null, "capacidadeTanqueLitros": null, "numeroDocumentoFaturado": "12345678000190", "ufFaturamento": "SP", "proprietario": { "nome": "JOAO DA SILVA", "nomeLegal": null, "documento": "12345678901", "tipoDocumento": "CPF", "nomeMae": null, "nomePai": null, "situacao": "REGULAR", "porte": null, "naturezaJuridicaCodigo": null, "naturezaJuridicaDescricao": null, "telefones": [], "emails": [], "enderecos": [] }, "restricoes": { "restricaoRenainf": false, "restricaoRenajud": false, "restricaoRfb": false, "restricaoAdministrativa": false, "rouboOuFurto": false, "sinistro": false, "recall": false, "anuncioVenda": false, "intencaoVenda": false, "restricao1": null, "restricao2": null, "restricao3": null, "restricao4": null, "ocorrencia": null, "restricaoGeral": null, "veiculoBaixado": null }, "gravames": [ { "numeroRestricao": "1", "dataRestricao": "2021-03-10", "ufRestricao": "SP", "status": "ATIVO", "nomeAgente": "BANCO EXEMPLO S.A.", "documentoAgente": "00000000000191", "dataContrato": "2021-03-05", "ufContrato": "SP", "numeroContrato": "000123456", "documentoFinanciado": "12345678901", "nomeFinanciado": "JOAO DA SILVA" } ], "chassiRemarcado": false, "tipoDocumentoFaturado": "CNPJ", "procedencia": "NACIONAL", "requestId": "a1b2c3d4", "leilao": { "baseDisponivel": true, "marcaModelo": null, "anoModelo": null, "anoFabricacao": null, "placa": null, "chassi": null, "renavam": null, "score": null, "ocorrencias": [] }, "debitos": null, "fotosLeilao": null } ``` ### Gravame (servico "gravame") Exige: placa. Entrega: JSON cru do provedor + PDF. Bloco veiculo: sim. Corpo mínimo: {"servico":"gravame","placa":"ABC1D23"} - descricaostatus é "NADA CONSTA" quando não há gravame. statusdoveiculo só vem preenchido quando há: trate como sinal, sem comparar o texto, que varia conforme a base. - ocorrencias[] traz todos os registros de gravame do veículo; os campos do topo descrevem o principal. - renavam, ano, cor, municipio, combustivel e motor podem vir null, conforme a base que atendeu. Para identificação estável use o bloco veiculo. - Se a base principal falhar, a mesma chamada tenta uma segunda base antes de devolver erro, sem cobrança dupla. - Sandbox: Cenário escolhido pela placa (TST0001 limpo, TST0002 gravame, TST0003 RENAJUD, TST0004 débitos, TST0005 sinistro e leilão, TST0404 não encontrado, TST0503 falha retentável, TST9999 nunca conclui). Bloco veiculo fiel ao contrato; dados reduzido e marcado com _sandbox. ```json { "placa": "ABC1D23", "ufplaca": "SP", "chassi": "9BWZZZ377VT004251", "renavam": "00987495364", "anofabricacao": 2022, "anomodelo": 2022, "statusdoveiculo": "ALIENADO FIDUCIARIAMENTE", "descricaostatus": "INCLUSAO DE GRAVAME", "financeiranome": "BANCO XPTO S.A.", "documentofinanceira": "60701190000104", "codigofinanceira": null, "numerogravame": "8918837", "nomefinanciado": "JOAO DA SILVA", "documentoproprietarioatual": "12345678901", "numerocontrato": "000123456", "ufgravame": "SP", "datagravame": "14/05/2022", "datagravamevigencia": null, "marcamodelo": "M.BENZ/ATEGO 2425", "cor": "BRANCA", "municipio": "RIO DE JANEIRO", "combustivel": "DIESEL", "motor": "ABC123456", "ocorrencias": [ { "numero_gravame": "8918837", "nome_agente": "BANCO XPTO S.A.", "doc_agente": "60701190000104", "numero_contrato": "000123456", "uf_placa": "SP", "ativo": true } ] } ``` ### RENAJUD (servico "renajud") Exige: placa. Entrega: JSON cru do provedor + PDF. Bloco veiculo: sim. Corpo mínimo: {"servico":"renajud","placa":"ABC1D23"} - Leia consta_renajud ("SIM" ou "NADA CONSTA") e a lista renajud[]. - Base sem resposta vira erro (com estorno), nunca "nada consta". - Os campos do veículo no topo e o chassi de cada item podem vir null. - Sandbox: Cenário escolhido pela placa (TST0001 limpo, TST0002 gravame, TST0003 RENAJUD, TST0004 débitos, TST0005 sinistro e leilão, TST0404 não encontrado, TST0503 falha retentável, TST9999 nunca conclui). Bloco veiculo fiel ao contrato; dados reduzido e marcado com _sandbox. ```json { "placa": "ABC1D23", "renavam": "00987495364", "marca": "VW", "ano_fabricacao": "2022", "ano_modelo": "2022", "base": "SP", "cor": "PRATA", "combustivel": "GASOLINA", "especie": "PASSAGEIRO", "tipo": "AUTOMOVEL", "motor": "D4FB1234567", "eixos": "2", "capacidade_passageiros": "5", "municipio": "SAO PAULO", "procedencia": "NACIONAL", "consta_renajud": "SIM", "quantidade_bloqueio_ativo_localizado": 1, "quantidade_ocorrencias_exibidas_e_disponivel_pelo_detran": 1, "quantidade_ocorrencia_total": "1", "renajud": [ { "consta_restricao": "SIM", "chassi": "9BWZZZ377VT004251", "placa": "ABC1D23", "quantidade_ocorrencias": "1", "tipo_restricao_judicial": "TRANSFERENCIA", "codigo_tribunal": "TJSP", "nome_tribunal": "TRIBUNAL DE JUSTICA DE SP", "codigo_orgao_judicial": "0001", "nome_orgao_judicial": "1A VARA CIVEL", "numero_processo": "0000000-00.2024.8.26.0000", "data_inclusao": "01/06/2024" } ] } ``` ### Débitos + Código de Barras (servico "debitos") Exige: placa. Entrega: JSON cru do provedor + PDF. Bloco veiculo: não. Corpo mínimo: {"servico":"debitos","placa":"ABC1D23"} - É o serviço de linha digitável e código de barras. Para débitos por categoria na base de cada estado, use debitos-estadual. - Sandbox: Cenários de erro e de espera pela placa (TST0404 não encontrado, TST0503 falha retentável, TST9999 nunca conclui); qualquer outra placa conclui. Como em produção, a resposta não traz bloco veiculo; dados vem reduzido e marcado com _sandbox. ```json { "success": true, "statusCode": 2, "msg": "CONSULTA CONCLUIDA COM SUCESSO", "paid": true, "uuidRequest": "161461e8-87f4-46b3-85b4", "registros": [ { "descricao": "IPVA 2025", "tipo": "IPVA", "valor": 1240.55, "subtotal": 1240.55, "dataVencimento": "2025-03-31", "statusPagamento": "EM ABERTO", "linhaDigitavel": "85800000015-3 35910000...", "codigoBarra": "858000000153359100...", "detalhes": [ { "chave": "Exercício", "grupo": "IPVA", "valor": "2025" } ] } ] } ``` ### Decodificação de Chassi (servico "decodificacao-chassi") Exige: chassi. Entrega: JSON do provedor + PDF. Bloco veiculo: não. Corpo mínimo: {"servico":"decodificacao-chassi","chassi":"9C2KD0540CR506454"} - Não usa placa: o identificador é o chassi. - tipo_possivel[] traz sugestões da Tabela FIPE e pode vir vazio quando não há correspondência. - Sandbox: Sem placa, os cenários TST* não se aplicam: a consulta conclui com dados fictício reduzido e, como em produção, sem bloco veiculo. ```json { "placa": "ABC1D23", "placa_mercosul": "ABC1D23", "chassi": "9C2KD0540CR506454", "motor": "KD05E1234567", "marca": "HONDA", "modelo": "NXR150 BROS ESD", "cor": "VERMELHA", "ano_fabricacao": "2011", "ano_modelo": "2012", "tipo": "MOTOCICLO", "especie": "PASSAGEIRO", "uf": "BA", "combustivel": "ALCOOL/GASOLINA", "municipio": "CONCEICAO DO JACUIPE", "importado": "NAO", "tipo_possivel": [ { "referencia": "julho/2026", "tipo_codigo": "811154-3", "ano_modelo": "2012", "tipo_veiculo": "MOTOCICLETA", "marca": "HONDA", "modelo": "NXR 150 BROS ESD", "combustivel": "GASOLINA", "valor": "R$ 9.800,00" } ] } ``` ### Decodificação de Motor (servico "decodificacao-motor") Exige: motor. Entrega: JSON do veículo (sem FIPE) + PDF. Bloco veiculo: não. Corpo mínimo: {"servico":"decodificacao-motor","motor":"KD05E1234567"} - Não usa placa: o identificador é o número do motor. - tipo_possivel vem sempre vazio neste serviço. marca e modelo podem vir null quando a base não os informa. Para FIPE, use decodificacao-chassi ou os endpoints de FIPE. - Sandbox: Sem placa, os cenários TST* não se aplicam: a consulta conclui com dados fictício reduzido e, como em produção, sem bloco veiculo. ```json { "placa": "ABC1D23", "chassi": "9C2KD0540CR506454", "motor": "KD05E1234567", "renavam": "00123456789", "marca": "HONDA", "modelo": "NXR150 BROS ESD", "cor": "VERMELHA", "ano_fabricacao": "2011", "ano_modelo": "2012", "tipo": "MOTOCICLO", "especie": "PASSAGEIRO", "categoria": "PARTICULAR", "situacao": "CIRCULACAO", "municipio": "SALVADOR", "uf": "BA", "combustivel": "ALCOOL/GASOLINA", "tipo_possivel": [] } ``` ### Score de Crédito (servico "score-credito") Exige: documento (CPF ou CNPJ). Entrega: JSON do provedor + PDF. Bloco veiculo: não. Corpo mínimo: {"servico":"score-credito","documento":"12345678909","finalidade":"ANALISE_CREDITO","declaracao_finalidade":true} - documento aceita CPF ou CNPJ. - finalidade e declaracao_finalidade ficam registradas quando enviadas. Na API a ausência delas não recusa o pedido, mas envie sempre: é dado de pessoa e a finalidade é a base legal do seu uso. - Sandbox: Sem placa, os cenários TST* não se aplicam: a consulta conclui com dados fictício reduzido e, como em produção, sem bloco veiculo. ```json { "dados receita federal": { "tipo_pessoa": "Física", "nome": "FULANO DE TAL", "situacao_receita": "REGULAR", "data_nascimento_fundacao": "01/01/1990", "nome_mae": "CICLANA DE TAL" }, "score": { "ocorrencias": [ { "tipo_score": "score portfolio", "score": "780", "probabilidade_inadimplencia": "3,2" } ] }, "email": { "registro_localizado": "S", "informado": "fulano@exemplo.com" }, "numero_endereco": { "dados": [ { "endereco": "RUA EXEMPLO", "numero": "100", "bairro": "CENTRO", "cidade": "SAO PAULO", "uf": "SP", "cep": "01000000" } ] }, "renda_presumida": { "faixa": "R$ 3.000,00 a R$ 5.000,00", "valor_presumido": "R$ 4.200,00 ao mês" } } ``` ### Consulta NF-e (servico "consulta-nfe") Exige: chave (chave de acesso, 44 dígitos). Entrega: JSON da NF-e (situação/eventos, emitente, destinatário, itens, totais, transporte) + PDF. Bloco veiculo: não. Corpo mínimo: {"servico":"consulta-nfe","chave":"35240912345678000190550010000123451000123459"} - chave: os 44 dígitos do DANFE, com ou sem espaços. O dígito verificador é conferido antes da cobrança: chave errada volta 400 CHAVE_NFE_INVALIDA sem debitar. - Para saber se a nota vale, leia dados.dados_nfe.situacao_atual[]: um evento de cancelamento invalida a nota mesmo com a autorização também na lista. - Sandbox: Confere o dígito verificador da chave como a produção. dados fictício no formato do serviço, sem bloco veiculo. Os cenários TST0404/TST0503 não se aplicam (não há placa). ```json { "dados_nfe": { "dados": { "modelo": "55", "serie": "1", "numero": "12345", "data_emissao": "10/09/2024 10:00:00-03:00", "valor_total_nfe": "98.500,00" }, "situacao_atual": [ { "eventos_nfe": "Autorização de Uso", "protocolo": "135240000000001", "data_autorizacao": "10/09/2024 10:01:00" } ] }, "dados_emitente": { "nome_razao_social": "CONCESSIONARIA EXEMPLO LTDA", "cnpj": "12.345.678/0001-90", "uf": "SP" }, "dados_destinatario": { "nome_razao_social": "FULANO DE TAL", "cpf": "123.456.789-09", "uf": "SP" }, "dados_produtos_servicos": [ { "numero": "1", "descricao": "VEICULO NOVO MODELO X", "valor": "98.500,00", "cod_ncm": "87032310" } ], "totais": { "icms": { "valor_total_nf": "98.500,00" } }, "transporte": { "modalidade_frete": "9 - Sem Ocorrência de Transporte" } } ``` ### Situação do CPF (servico "situacao-cpf") Exige: documento (CPF) + data_nascimento (dd/mm/aaaa). Entrega: JSON da Receita Federal + PDF. Bloco veiculo: não. Corpo mínimo: {"servico":"situacao-cpf","documento":"12345678909","data_nascimento":"01/01/1990"} - documento só aceita CPF. data_nascimento em dd/mm/aaaa é obrigatória: inválida ou ausente, 400 DATA_NASCIMENTO_INVALIDA antes de cobrar. - A Receita só responde quando CPF e data batem. Se não conferirem, a consulta termina em erro com retryable: false e o valor volta ao saldo. - A situação vem em dados.situacao (Regular, Suspensa, Cancelada, Pendente de Regularização…). - Sandbox: Valida o CPF e a data_nascimento como a produção. dados fictício no formato do serviço, sem bloco veiculo. Os cenários TST0404/TST0503 não se aplicam (não há placa). ```json { "nome": "FULANO DE TAL", "cpf": "123.456.789-09", "data_nascimento": "1990-01-01", "data_inscricao": "2008-03-10", "situacao": "Regular", "digito_verificador": "00", "codigo_controle": "ABCD.1234.EF56.7890" } ``` ### Débitos Estaduais (servico "debitos-estadual") Exige: placa e uf (as 27 UFs); renavam, documento e chassi não são mais exigidos. Entrega: JSON por categoria (IPVA, licenciamento, DPVAT, multas) + PDF. Bloco veiculo: não. Corpo mínimo: {"servico":"debitos-estadual","placa":"ABC1D23","uf":"SP"} - Basta placa e uf, em qualquer uma das 27 UFs. renavam, documento e chassi, se enviados, são ignorados. - UF ausente ou inválida é recusada com 400 UF_INDISPONIVEL, antes de cobrar (também no sandbox). - Item com valor: null é débito confirmado sem valor informado, nunca "nada consta". - Sandbox: Cenários de erro e de espera pela placa (TST0404 não encontrado, TST0503 falha retentável, TST9999 nunca conclui); qualquer outra placa conclui. Como em produção, a resposta não traz bloco veiculo; dados vem reduzido e marcado com _sandbox. ```json { "veiculo": { "placa": "ABC1D23", "renavam": "12345678901", "chassi": "9BWZZZ377VT004251", "marca": "VW", "modelo": "GOL", "ano_fabricacao": "2018", "ano_modelo": "2019", "uf": "SP" }, "ipvas": [ { "descricao": "IPVA", "valor": 512.30, "status": "EM ABERTO" } ], "licenciamentos": [ { "descricao": "Licenciamento", "valor": 167.74, "status": "EM ABERTO" } ], "dpvats": [], "multas": [ { "descricao": "Multas DETRAN", "orgao": "DETRAN", "valor": 195.23, "status": "EM ABERTO" }, { "descricao": "EXCESSO DE VELOCIDADE", "orgao": "DER-MG", "ait": "X000000000", "data_infracao": "01/02/2026", "vencimento": null, "valor": 130.16, "status": "EM ABERTO" } ] } ``` ### Histórico de Proprietários (servico "historico-proprietarios") Exige: placa. Entrega: JSON com a cadeia de titularidade (proprietarios[], um item por registro, do mais recente para o mais antigo) + PDF. Bloco veiculo: não. Corpo mínimo: {"servico":"historico-proprietarios","placa":"ABC1D23"} - dados.proprietarios[] traz um item por registro de titularidade, do mais recente para o mais antigo: nome_proprietario, cgc_cpf, tipo_documento, ano_exercicio, uf, placa, chassi e renavam. - Quando a base não tem nenhum registro de proprietário para a placa, a consulta termina com status erro, erro_codigo QUERY_NOT_FOUND, e nada é cobrado. - Contém dado pessoal de terceiros (donos anteriores): use só para a finalidade da consulta e não redistribua. - Sandbox: Devolve dados fictício no formato do serviço (proprietarios[] com dois registros), sem bloco veiculo. Cenários de erro pela placa: TST0404, TST0503 e TST9999. ```json { "placa": "ABC1D23", "chassi": "9BWZZZ377VT004251", "renavam": "01234567890", "ano_fabricacao": null, "proprietarios": [ { "nome_proprietario": "FULANO DE TAL", "cgc_cpf": "12345678909", "tipo_documento": "CPF", "ano_exercicio": "2023", "uf": "SP", "placa": "ABC1D23", "chassi": "9BWZZZ377VT004251", "renavam": "01234567890" }, { "nome_proprietario": "LOCADORA EXEMPLO LTDA", "cgc_cpf": "12345678000199", "tipo_documento": "CNPJ", "ano_exercicio": "2019", "uf": "SP", "placa": "ABC1D23", "chassi": "9BWZZZ377VT004251", "renavam": "01234567890" } ] } ``` ### Informações da Comunicação de Venda (servico "comunicacao-venda") Exige: placa, finalidade e declaracao_finalidade: true. Entrega: JSON com a data da venda e do registro, o comprador (nome e CPF/CNPJ) e o documento do vendedor + PDF. Bloco veiculo: não. Corpo mínimo: {"servico":"comunicacao-venda","placa":"ABC1D23","finalidade":"NEGOCIACAO_VEICULO","declaracao_finalidade":true} - finalidade e declaracao_finalidade: true são obrigatórios: sem eles, 400 FINALIDADE_OBRIGATORIA antes de cobrar. - Sem comunicação de venda registrada, a consulta termina em erro com retryable: false e o valor é estornado. - Devolve nome e CPF/CNPJ completos do comprador: dado pessoal de terceiro. - Sandbox: Valida finalidade e declaração como a produção e devolve dados fictício no formato do serviço, sem bloco veiculo. Cenários de erro pela placa: TST0404 e TST0503. ```json { "placa": "ABC1D23", "renavam": "01253850418", "data_venda": "2025-08-22", "data_registro_venda": "2025-08-22", "comprador": { "nome": "FULANO DE TAL", "documento": "12345678909", "tipo_documento": "CPF" }, "vendedor": { "documento": "12345678000195", "tipo_documento": "CNPJ" } } ``` ### Cadastro Simples CPF (servico "cadastro-simples-cpf") Exige: documento (CPF), finalidade e declaracao_finalidade: true. Entrega: JSON de pessoa (identificacao, enderecos, telefones, emails) + PDF. Bloco veiculo: não. Corpo mínimo: {"servico":"cadastro-simples-cpf","documento":"12345678909","finalidade":"ANALISE_CREDITO","declaracao_finalidade":true} - finalidade e declaracao_finalidade: true são obrigatórios (dado pessoal): sem eles, 400 FINALIDADE_OBRIGATORIA antes de cobrar. - Cada serviço preenche os blocos que a base dele traz. Bloco null = a base não informou; lista vazia = a base respondeu e não há ocorrência. - Sem registro do documento na base, a consulta termina em erro com retryable: false e o valor volta ao saldo. - Sandbox: Valida documento, finalidade e declaração como a produção. dados fictício no formato do serviço, sem bloco veiculo. Os cenários TST0404/TST0503 não se aplicam (não há placa): teste o tratamento de erro com um serviço por placa. ### Cadastro Completo CPF (servico "cadastro-completo-cpf") Exige: documento (CPF), finalidade e declaracao_finalidade: true. Entrega: JSON de pessoa (identificacao, contatos, socios, renda_presumida) + PDF. Bloco veiculo: não. Corpo mínimo: {"servico":"cadastro-completo-cpf","documento":"12345678909","finalidade":"ANALISE_CREDITO","declaracao_finalidade":true} - finalidade e declaracao_finalidade: true são obrigatórios (dado pessoal): sem eles, 400 FINALIDADE_OBRIGATORIA antes de cobrar. - Cada serviço preenche os blocos que a base dele traz. Bloco null = a base não informou; lista vazia = a base respondeu e não há ocorrência. - Sem registro do documento na base, a consulta termina em erro com retryable: false e o valor volta ao saldo. - Sandbox: Valida documento, finalidade e declaração como a produção. dados fictício no formato do serviço, sem bloco veiculo. Os cenários TST0404/TST0503 não se aplicam (não há placa): teste o tratamento de erro com um serviço por placa. ### Cadastro Simples CNPJ (servico "cadastro-simples-cnpj") Exige: documento (CNPJ), finalidade e declaracao_finalidade: true. Entrega: JSON de pessoa (empresa ou identificacao, contatos) + PDF. Bloco veiculo: não. Corpo mínimo: {"servico":"cadastro-simples-cnpj","documento":"12345678000195","finalidade":"ANALISE_CREDITO","declaracao_finalidade":true} - finalidade e declaracao_finalidade: true são obrigatórios (dado pessoal): sem eles, 400 FINALIDADE_OBRIGATORIA antes de cobrar. - Cada serviço preenche os blocos que a base dele traz. Bloco null = a base não informou; lista vazia = a base respondeu e não há ocorrência. - Sem registro do documento na base, a consulta termina em erro com retryable: false e o valor volta ao saldo. - Sandbox: Valida documento, finalidade e declaração como a produção. dados fictício no formato do serviço, sem bloco veiculo. Os cenários TST0404/TST0503 não se aplicam (não há placa): teste o tratamento de erro com um serviço por placa. ### Cadastro Completo CNPJ (servico "cadastro-completo-cnpj") Exige: documento (CNPJ), finalidade e declaracao_finalidade: true. Entrega: JSON de pessoa (empresa, socios, filiais, contatos) + PDF. Bloco veiculo: não. Corpo mínimo: {"servico":"cadastro-completo-cnpj","documento":"12345678000195","finalidade":"ANALISE_CREDITO","declaracao_finalidade":true} - finalidade e declaracao_finalidade: true são obrigatórios (dado pessoal): sem eles, 400 FINALIDADE_OBRIGATORIA antes de cobrar. - Cada serviço preenche os blocos que a base dele traz. Bloco null = a base não informou; lista vazia = a base respondeu e não há ocorrência. - Sem registro do documento na base, a consulta termina em erro com retryable: false e o valor volta ao saldo. - Sandbox: Valida documento, finalidade e declaração como a produção. dados fictício no formato do serviço, sem bloco veiculo. Os cenários TST0404/TST0503 não se aplicam (não há placa): teste o tratamento de erro com um serviço por placa. ### Crédito Único CPF (servico "credito-unico-cpf") Exige: documento (CPF), finalidade e declaracao_finalidade: true. Entrega: JSON de pessoa (pendencias_financeiras, identificacao, contatos) + PDF. Bloco veiculo: não. Corpo mínimo: {"servico":"credito-unico-cpf","documento":"12345678909","finalidade":"ANALISE_CREDITO","declaracao_finalidade":true} - finalidade e declaracao_finalidade: true são obrigatórios (dado pessoal): sem eles, 400 FINALIDADE_OBRIGATORIA antes de cobrar. - Cada serviço preenche os blocos que a base dele traz. Bloco null = a base não informou; lista vazia = a base respondeu e não há ocorrência. - Sem registro do documento na base, a consulta termina em erro com retryable: false e o valor volta ao saldo. - Sandbox: Valida documento, finalidade e declaração como a produção. dados fictício no formato do serviço, sem bloco veiculo. Os cenários TST0404/TST0503 não se aplicam (não há placa): teste o tratamento de erro com um serviço por placa. ### Crédito Único CNPJ (servico "credito-unico-cnpj") Exige: documento (CNPJ), finalidade e declaracao_finalidade: true. Entrega: JSON de pessoa (pendencias_financeiras, empresa, contatos) + PDF. Bloco veiculo: não. Corpo mínimo: {"servico":"credito-unico-cnpj","documento":"12345678000195","finalidade":"ANALISE_CREDITO","declaracao_finalidade":true} - finalidade e declaracao_finalidade: true são obrigatórios (dado pessoal): sem eles, 400 FINALIDADE_OBRIGATORIA antes de cobrar. - Cada serviço preenche os blocos que a base dele traz. Bloco null = a base não informou; lista vazia = a base respondeu e não há ocorrência. - Sem registro do documento na base, a consulta termina em erro com retryable: false e o valor volta ao saldo. - Sandbox: Valida documento, finalidade e declaração como a produção. dados fictício no formato do serviço, sem bloco veiculo. Os cenários TST0404/TST0503 não se aplicam (não há placa): teste o tratamento de erro com um serviço por placa. ### Crédito Biro CPF (servico "credito-biro-cpf") Exige: documento (CPF), uf, finalidade e declaracao_finalidade: true. Entrega: JSON de pessoa (score, pendências, protestos, cheques, ações judiciais, consultas recentes, certidão trabalhista) + PDF. Bloco veiculo: não. Corpo mínimo: {"servico":"credito-biro-cpf","documento":"12345678909","uf":"SP","finalidade":"ANALISE_CREDITO","declaracao_finalidade":true} - finalidade e declaracao_finalidade: true são obrigatórios (dado pessoal): sem eles, 400 FINALIDADE_OBRIGATORIA antes de cobrar. - Cada serviço preenche os blocos que a base dele traz. Bloco null = a base não informou; lista vazia = a base respondeu e não há ocorrência. - Sem registro do documento na base, a consulta termina em erro com retryable: false e o valor volta ao saldo. - Exige uf. - Sandbox: Valida documento, finalidade e declaração como a produção. dados fictício no formato do serviço, sem bloco veiculo. Os cenários TST0404/TST0503 não se aplicam (não há placa): teste o tratamento de erro com um serviço por placa. ### Crédito Biro CNPJ (servico "credito-biro-cnpj") Exige: documento (CNPJ), uf, finalidade e declaracao_finalidade: true. Entrega: JSON de pessoa (score da empresa, pendências, protestos, ações judiciais, sócios, certidão trabalhista) + PDF. Bloco veiculo: não. Corpo mínimo: {"servico":"credito-biro-cnpj","documento":"12345678000195","uf":"SP","finalidade":"ANALISE_CREDITO","declaracao_finalidade":true} - finalidade e declaracao_finalidade: true são obrigatórios (dado pessoal): sem eles, 400 FINALIDADE_OBRIGATORIA antes de cobrar. - Cada serviço preenche os blocos que a base dele traz. Bloco null = a base não informou; lista vazia = a base respondeu e não há ocorrência. - Sem registro do documento na base, a consulta termina em erro com retryable: false e o valor volta ao saldo. - Exige uf. - Sandbox: Valida documento, finalidade e declaração como a produção. dados fictício no formato do serviço, sem bloco veiculo. Os cenários TST0404/TST0503 não se aplicam (não há placa): teste o tratamento de erro com um serviço por placa. ### CNH Nacional (servico "cnh-nacional") Exige: documento (CPF), cnh, uf, finalidade e declaracao_finalidade: true. Entrega: JSON de pessoa (cnh: categoria, validade, impedimento, bloqueios, pontos, exames, cursos) + PDF. Bloco veiculo: não. Corpo mínimo: {"servico":"cnh-nacional","documento":"12345678909","cnh":"01234567890","uf":"SP","finalidade":"ANALISE_CREDITO","declaracao_finalidade":true} - finalidade e declaracao_finalidade: true são obrigatórios (dado pessoal): sem eles, 400 FINALIDADE_OBRIGATORIA antes de cobrar. - Cada serviço preenche os blocos que a base dele traz. Bloco null = a base não informou; lista vazia = a base respondeu e não há ocorrência. - Sem registro do documento na base, a consulta termina em erro com retryable: false e o valor volta ao saldo. - Exige uf e o número de registro da CNH em cnh. Sem ele, 400 CNH_INVALIDA antes de cobrar. - Sandbox: Valida documento, finalidade e declaração como a produção. dados fictício no formato do serviço, sem bloco veiculo. Os cenários TST0404/TST0503 não se aplicam (não há placa): teste o tratamento de erro com um serviço por placa. ### Débitos Trabalhistas (CNDT) (servico "debitos-trabalhistas") Exige: documento (CPF ou CNPJ), finalidade e declaracao_finalidade: true. Entrega: JSON de pessoa (debitos_trabalhistas: certidão, situação, emissão, validade) + PDF com a certidão anexa quando a base envia. Bloco veiculo: não. Corpo mínimo: {"servico":"debitos-trabalhistas","documento":"12345678909","finalidade":"ANALISE_CREDITO","declaracao_finalidade":true} - finalidade e declaracao_finalidade: true são obrigatórios (dado pessoal): sem eles, 400 FINALIDADE_OBRIGATORIA antes de cobrar. - Cada serviço preenche os blocos que a base dele traz. Bloco null = a base não informou; lista vazia = a base respondeu e não há ocorrência. - Sem registro do documento na base, a consulta termina em erro com retryable: false e o valor volta ao saldo. - documento aceita CPF ou CNPJ. - Sandbox: Valida documento, finalidade e declaração como a produção. dados fictício no formato do serviço, sem bloco veiculo. Os cenários TST0404/TST0503 não se aplicam (não há placa): teste o tratamento de erro com um serviço por placa. ### Dívida Ativa da União (servico "divida-ativa") Exige: documento (CPF ou CNPJ), finalidade e declaracao_finalidade: true. Entrega: JSON de pessoa (divida_ativa: inscrições, situação, valor, ativas e extintas) + PDF. Bloco veiculo: não. Corpo mínimo: {"servico":"divida-ativa","documento":"12345678000195","finalidade":"ANALISE_CREDITO","declaracao_finalidade":true} - finalidade e declaracao_finalidade: true são obrigatórios (dado pessoal): sem eles, 400 FINALIDADE_OBRIGATORIA antes de cobrar. - Cada serviço preenche os blocos que a base dele traz. Bloco null = a base não informou; lista vazia = a base respondeu e não há ocorrência. - Sem registro do documento na base, a consulta termina em erro com retryable: false e o valor volta ao saldo. - documento aceita CPF ou CNPJ. - Sandbox: Valida documento, finalidade e declaração como a produção. dados fictício no formato do serviço, sem bloco veiculo. Os cenários TST0404/TST0503 não se aplicam (não há placa): teste o tratamento de erro com um serviço por placa. ### CRLV Digital (servico "crlv") Exige: placa, uf (+ cpf/renavam em algumas UFs). Entrega: Documento em PDF (sem JSON). Bloco veiculo: não. Corpo mínimo: {"servico":"crlv","placa":"ABC1D23","uf":"SP","cpf":"12345678909","renavam":"00987495364"} - Preço e campos exigidos variam por UF: leia crlv.preco_por_uf em GET /v1/servicos, que traz o requer de cada estado. UF fora da lista responde 422 SERVICO_INDISPONIVEL; faltando CPF/RENAVAM que a UF exige, 400 CRLV_DADOS_OBRIGATORIOS. - Em CE, DF, ES, PB, RJ, RN, RS e SC a emissão é processada pelo DETRAN de forma assíncrona e pode levar alguns minutos em processando. Não trate como erro: prefira o webhook query.completed. - O documento pode chegar como PDF ou imagem: confie no Content-Type do GET /pdf. - A uf é a do estado em que o veículo está registrado: o DETRAN de outro estado recusa a emissão. Quando a placa consta registrada em outra UF, a resposta do POST traz avisos com UF_REGISTRO_DIVERGENTE (uf_informada e uf_registro). O pedido segue; se o DETRAN recusar, a consulta termina em erro e o valor volta ao saldo. - Sandbox: Valida o formato da placa e a uf como a produção e conclui a consulta, mas não gera documento: GET /pdf responde 422 SANDBOX_SEM_DOCUMENTO. Os campos que cada UF exige (CPF, RENAVAM) só são conferidos em produção. ### 2ª via do ATPV-e (servico "atpve") Exige: placa + aceite_atpve (declaração do aviso). Entrega: Documento em PDF (sem JSON). Bloco veiculo: não. Corpo mínimo: {"servico":"atpve","placa":"ABC1D23","aceite_atpve":{"aceito":true,"versao":"2026-09-23"}} - Exige a declaração do usuário final em aceite_atpve: aceito precisa ser o booleano true e versao, a vigente em GET /public/avisos/atpve. Sem a declaração, 422 ACEITE_ATPVE_OBRIGATORIO; versão antiga, 409 AVISO_ATPVE_DESATUALIZADO. Nada é cobrado nos dois casos. - Cobertura nacional e preço único: não há preco_por_uf. Enviar uf é aceito, mas não decide preço nem disponibilidade. - É emissão: leva cerca de 1 minuto em processando. - Sandbox: Faz a mesma validação de aceite_atpve da produção (dá para testar o fluxo do aviso sem custo), mas não gera documento: GET /pdf responde 422 SANDBOX_SEM_DOCUMENTO. ### Código de Segurança (servico "codigo-seguranca") Exige: placa, renavam. Entrega: PDF com o código (sem JSON). Bloco veiculo: não. Corpo mínimo: {"servico":"codigo-seguranca","placa":"ABC1D23","renavam":"00987495364"} - placa e renavam são obrigatórios. RENAVAM com menos de 9 dígitos responde 400 RENAVAM_INVALIDO antes de cobrar. - Sandbox: Valida o formato da placa e a uf como a produção e conclui a consulta, mas não gera documento: GET /pdf responde 422 SANDBOX_SEM_DOCUMENTO. Os campos que cada UF exige (CPF, RENAVAM) só são conferidos em produção. ## Exemplos prontos (índice) Linguagens: cURL, JavaScript, TypeScript, Node.js (Express), Next.js, Python, PHP. Cada exemplo usa o cliente do exemplo Autenticação. - Autenticação: O cliente da API (chave no ambiente, timeout e erro padronizado) e uma chamada gratuita que confirma que a chave funciona. https://www.zapcarconsulta.com.br/api-integradores/docs/exemplos#autenticacao - Listar serviços e preços: O catálogo liberado para a sua conta, com o preço que será debitado e os campos que cada serviço exige. Leia daqui, nunca fixe preço no código. https://www.zapcarconsulta.com.br/api-integradores/docs/exemplos#listar-servicos - Consultar saldo: O saldo da carteira, em reais, com um alerta antes de acabar. Sem saldo, a criação de consulta devolve 402 SALDO_INSUFICIENTE. https://www.zapcarconsulta.com.br/api-integradores/docs/exemplos#consultar-saldo - Criar consulta: Cria a consulta com Idempotency-Key e trata cada resposta: 201 criada, 200 reaproveitada, 400, 402, 409 e 422. O resultado não vem aqui: guarde o id. https://www.zapcarconsulta.com.br/api-integradores/docs/exemplos#criar-consulta - Acompanhar processamento: Polling a cada 4 segundos com teto de 5 minutos, respeitando 429 e Retry-After. processando segue; concluido e erro são terminais. https://www.zapcarconsulta.com.br/api-integradores/docs/exemplos#acompanhar-processamento - Obter resultado completo: Lê a consulta concluída do jeito certo: schema_version, o bloco veiculo normalizado, o dados de cada serviço e a diferença entre null (não verificado) e "nada consta". https://www.zapcarconsulta.com.br/api-integradores/docs/exemplos#obter-resultado - Baixar PDF: Baixa o documento da consulta concluída e respeita o Content-Type (alguns documentos oficiais chegam como imagem). Gratuito; no sandbox responde 422 SANDBOX_SEM_DOCUMENTO. https://www.zapcarconsulta.com.br/api-integradores/docs/exemplos#baixar-pdf - Consultar Tabela FIPE: FIPE pela placa na mesma chamada (síncrono, sem polling). Cobra por requisição e estorna se não houver FIPE: use Idempotency-Key. https://www.zapcarconsulta.com.br/api-integradores/docs/exemplos#consultar-fipe - Receber webhooks: Endpoint que valida a assinatura sobre o corpo bruto, responde 2xx em menos de 10 s, ignora evento repetido pelo id e só então busca o resultado. https://www.zapcarconsulta.com.br/api-integradores/docs/exemplos#receber-webhooks - Validar assinatura: HMAC-SHA256 de "." com o secret do endpoint, comparado em tempo constante, recusando timestamp com mais de 5 minutos (replay). https://www.zapcarconsulta.com.br/api-integradores/docs/exemplos#validar-assinatura - Tratar erros: Os dois tipos de falha (erro da requisição e consulta com status erro), o campo retryable, o 429 com Retry-After e backoff com jitter só onde repetir é seguro. https://www.zapcarconsulta.com.br/api-integradores/docs/exemplos#tratar-erros - Evitar cobranças duplicadas: Idempotency-Key derivada do SEU pedido: o retry de rede repete a mesma chave e não cobra de novo; só uma consulta nova (depois de um erro retryable) ganha chave nova. https://www.zapcarconsulta.com.br/api-integradores/docs/exemplos#evitar-cobranca-duplicada