Changelog
Todas as mudanças da API e do Servidor MCP em ordem cronológica: o que entrou, o que mudou de comportamento e o que foi descontinuado.
Política de versionamento
Mudanças não-breaking (novos campos opcionais, novos eventos de webhook) não incrementam a versão principal. Mudanças breaking são comunicadas por e-mail aos administradores das organizações com pelo menos 30 dias de antecedência.
2026-08-11 — O toxicológico deixa de afirmar exame que não existe
Três naturezas diferentes numa entrada só. A terceira é a que pode exigir mudança do seu lado.
Mudança de valor em campo publicado
-
hasExamera sempretrue— emdetails.toxicological,diagnosis.toxicologicalenormalized.toxicological, que carregam o mesmo valor. Se você integrou antes dedetailsexistir, a mudança te alcança pelodiagnosis.O campo não era calculado: toda resposta afirmava que existia exame toxicológico, inclusive quando a própria resposta dizia que a categoria não exige um, ou que a consulta falhou. Agora ele segue a evidência — uma data de coleta, uma data de validade, ou uma situação que julgue um exame.
Se você trata
hasExamcomo "o condutor fez o exame", isso passa a ser verdade agora e não era antes. Se você o usa como condição para não alertar alguém, revise: para condutor de categoria C/D/E o campo era o que suprimia o alerta. -
statusda seção toxicológica passa a serunknown(erasuccess) quando não há exame e a categoria não exige um. Vale nos três caminhos acima: eles reportavamsuccessporque ohasExamfixo mantinha o caso fora do ramo que já existia para tratá-lo. -
details.personal.statuserasuccessfixo, mesmo num relatório sem CNH emitida com todos os campos vazios. Agora reflete a cobertura real:unknownquando a consulta não trouxe campo nenhum.
Aditivo
-
details.toxicological.situationStatusganhanot_applicableeunavailable, que antes caíam emunknown. O primeiro é "a categoria não exige o exame"; o segundo é "a consulta falhou". A distinção só existe aqui: no veredito, um exame exigido e não comprovado continua resolvendo paraBLOCKED— errar para o lado de sinalizar o condutor, e não para o de liberá-lo. O campo éstringno contrato, então valores novos não quebram nada; trate o desconhecido com umdefault. -
Duas correções de leitura no mesmo campo: uma situação irregular era classificada como
regular, e a grafia real de pendência ("com pendências") nunca casava e viravaunknown.
Correção de documentação — a API já respondia assim
detailsediagnosisnão sãonull"enquantoPROCESSING", como esta página e outras três afirmavam. Eles acompanham a existência do dado. Um relatório parcialmente entregue reportastatus: "PROCESSING"e já traz os dois preenchidos — é o corpo do webhookreport.partially_delivered. Um handler comif (status !== "DELIVERED") return;está descartando relatório com dado. Testediagnosis !== null/details !== null.wait_for_report: a entrega leva cerca de 190s na mediana, então o padrão de 120s retornaPROCESSINGna maioria das chamadas. Isso é o resultado correto da ferramenta, não uma falha.- O
202de criação devolve os sete campos dedriver, não sóidecpf.
2026-08-06 — details: paridade de campos com o relatório
-
Novo campo opcional
details, com as seções que odiagnosisnunca carregou. Odiagnosisresponde qual é o veredito;detailstraz o registro por trás dele, para quem precisa reconstruir a tela e não só a conclusão:Seção O que passa a vir details.personalnome, CPF, nascimento, filiação, documento de identidade, naturalidade, nacionalidade, gênero details.licenseos 14 campos da habilitação — RENACH, nº do formulário, 1ª habilitação, emissão, local, situação, EAR details.medicalExamsos 11 campos de cada exame, incluindo categoria permitida, cidade e UF details.toxicologicalacrescenta data de uso, situação e o status parseado details.coursesa seção inteira: cursos com período, carga horária, modalidade, validade e local details.stateLookupsaldo oficial de pontos (com inferredPointsehasPointsDiscrepancy) e o histórico completo de multas, com status de pagamento -
Não-breaking. É campo novo e anulável;
diagnosis,normalized,drivereaiAnalysisnão mudaram em nada. Nenhuma integração existente precisa de ajuste.detailsénullenquanto a consulta não respondeu. -
Duas ausências que existiam e deixaram de existir: os exames em
diagnosis.medicalExams.exams[]traziam 6 dos 11 campos (sem categoria permitida, cidade e UF), eisEARsó existia dentro dediagnosis.points— que é ausente quando não há consulta estadual. Os dois agora vêm emdetails, independentemente da consulta estadual. -
Histórico de multas completo.
diagnosis.finescontinua sendo a janela móvel de 12 meses da Lei 14.071 (é o que decide a pontuação).details.stateLookup.finestraz o histórico inteiro, com o status de pagamento de cada autuação — são coisas diferentes e as duas continuam disponíveis. -
Dados pessoais passam a ser expostos, incluindo filiação e documento de identidade. A base é a mesma que já sustenta o relatório: o titular consultado é o objeto do relatório que você contratou, e são os mesmos valores impressos na CNH. A garantia anti-leak não muda — payload bruto do provedor, custo, identificador de requisição, URLs internas e contadores de pipeline seguem fora, e agora também
rawStatuse a origem interna da pontuação de cada multa. -
Ver Shape do Payload e Montar a UI.
2026-07-31 — Bloqueio declarado pelo estado e entrega parcial mais fiel
- Novo campo opcional
diagnosis.blocks.stateDeclaredBlock({ isBlocked, statusLabel, detailedBlocks }) — a resposta direta da consulta estadual sobre a situação da CNH, independente da lista de bloqueios detalhados. Quando o estado acusa bloqueio sem detalhar nenhum, odiagnosis.statusagora reflete isso. Ver Shape do Payload. - Entrega parcial: um relatório cuja consulta estadual não chegou a rodar deixa de ser
reportado como
DELIVERED. Passa aPROCESSING, e o eventoreport.partially_deliveredé enviado a quem o tiver assinado. Antes, esses relatórios chegavam sem dados estaduais (bloqueios, pontos e multas) sem nenhuma indicação disso. - Exames clínicos vindos da consulta estadual: quando a consulta estadual reporta aptidão
física e mental ou avaliação psicológica, esses registros passam a alimentar
diagnosis.medicalExams— eles trazem resultado e validade, que a base federal deixa em branco na maior parte dos casos. Consequência: um exame vencido pode ser sinalizado em relatórios que antes não o mostravam. As provas de habilitação (direção, teórico) não entram na seção clínica. - Pontuação pela tabela RENAINF: pontos e gravidade de cada multa passam a vir do código da infração, com as strings do provedor como recuo. Multas cujo infrator é o proprietário do veículo (CTB 257 §8º) continuam listadas, mas deixam de somar pontos na CNH do condutor.
- Validade da CNH passa a vir da consulta estadual sempre que ela responder. O órgão
que emitiu a habilitação é quem a renova; a base federal é réplica e foi medida
divergindo — em 363 pares de respostas, 99 traziam datas diferentes.
diagnosis.validity(incluindovalidityStatuse os alertascnh_expired/cnh_expiring_soon) passa a ser calculado sobre essa data, e relatórios já entregues podem mudar devalidityStatusao serem consultados novamente. Sem consulta estadual, a data federal permanece. - Datas-sentinela deixam de ser gravadas como fato. As duas consultas dizem "não sei" com
31/12/1969— o epoch Unix no fuso de Brasília —, e por ser uma data válida ela era gravada no condutor: uma CNH aparecia vencida desde 1969. Os camposexpiryDate,issueDate,firstLicenseDateebirthDatepassam a vir vazios nesses casos, em vez de 1969, e a validade volta a ser decidida pela camada que respondeu de verdade. Uma data vazia é ausência de informação, não um vencimento. - Não-breaking: nenhum campo foi removido ou renomeado. O campo novo é opcional; as demais
mudanças tornam visíveis condições que já existiam — se a sua integração trata
PROCESSINGcomo "aguardar", nada muda além do volume.
2026-07-29 — Novo valor NO_LICENSE em diagnosis.status
diagnosis.status(eaiAnalysis.status) passam a poder retornar"NO_LICENSE": o CPF consultado nunca teve uma CNH emitida.- Não-breaking: valor adicional num campo já existente. O relatório é
DELIVEREDnormalmente (a resposta "sem CNH" é o resultado da consulta, não uma falha),hasReportDataéfalse, eaiAnalysisvem sempre preenchido com um texto fixo em pt-BR. Ver Shape do Payload para o detalhe completo do payload.
2026-07-23 — Análise por IA automática no fluxo B2B
- A partir de agora, o campo
aiAnalysisé gerado automaticamente para relatórios criados via API/MCP — não é mais necessário falar com o suporte para habilitá-la. - Não-breaking: o campo já era opcional e anulável. Continua
nulldurantePROCESSINGe pode virnullnum relatório entregue caso a geração falhe (é best-effort e nunca bloqueia a entrega). - Garantia de ordem: quando presente, a análise é gravada antes de o
statusvirarDELIVEREDe antes de o webhookreport.deliveredser enfileirado. Ou seja, um relatório entregue com análise a traz de forma idêntica noGET /api/v1/reports/{reportId}e no corpo do webhook.
2026-07-18 — Campo aiAnalysis (análise por IA)
- Novo campo opcional e anulável
aiAnalysisno payload do relatório ({ markdown, status, generatedAt }) — uma análise em linguagem natural gerada por IA a partir do diagnóstico. Aparece emGET /api/v1/reports/{reportId}, no corpo do webhookreport.deliverede nas ferramentas MCPget_report/wait_for_report/find_report_by_external_ref(a mesma serialização em todos). - Não-breaking: campo adicional opcional — integrações existentes não precisam de nenhuma mudança.
É
nullenquanto o relatório está emPROCESSING. (Na estreia, a geração ficava desativada por padrão no fluxo B2B; desde 2026-07-23 ela é automática — ver a entrada acima.)
2026-07 — Servidor MCP
- Novo endpoint
POST /api/mcp— um servidor Model Context Protocol (JSON-RPC 2.0, stateless) que expõe a API a agentes de IA/chatbots com a mesma API keycnh_live_. - 10 ferramentas:
request_report,get_report,wait_for_report,find_report_by_external_ref,ask_doutor_multas,get_credit_balance,get_usage,list_reports,lookup_violation_code,calculate_points. - Adição não-breaking: os endpoints REST existentes não são afetados; o MCP reutiliza a mesma autenticação, cobrança e rate limits.
2026-06-16 — Novo evento report.partially_delivered
- Novo evento de webhook
report.partially_delivered: enviado quando o relatório é entregue, mas dados complementares da consulta estadual ficam pendentes. Se a busca for recuperada depois, umreport.deliveredé enviado em seguida. - Adição não-breaking: o evento é opt-in — selecione-o em Configurações → API para começar a recebê-lo. Webhooks existentes não são afetados.
v1.0 — Lançamento
Endpoints disponíveis:
POST /api/v1/reports— criar relatório de CNH (retorna202 Accepted)GET /api/v1/reports/{reportId}— consultar relatório
Funcionalidades:
- Autenticação Bearer com formato
cnh_live_<prefix>_<secret> - Status público do relatório:
PROCESSING,DELIVERED,ERROR - Webhook HMAC-SHA256 com formato
t=<unix>,v1=<hex>(Stripe-style), assinatura recomputada por tentativa - Eventos:
report.delivered,report.failed - Idempotência via
externalRef(janela 1h) e proteção de race (janela 60s) - Billing pós-pago com débito na criação e estorno automático em falha do pipeline
- Rate limiting por minuto, por dia e concorrência
- Log de entregas com retry manual em Configurações → API
- Garantia anti-leak: payloads brutos do provider nunca são expostos