Lei Vigente

Índice remissivo

O índice alfabético remissivo (Vade Mecum) liga cada assunto ao dispositivo exato, para apps de consulta.

O índice alfabético remissivo é a lista de assuntos que um leitor procuraria para achar um dispositivo — o índice de um Vade Mecum. Cada entrada liga um termo (o assunto) a um ref_key: o dispositivo mais específico que trata daquele assunto. O app agrupa pelo termo, ordena alfabeticamente e, ao toque, abre a lei no ref_key (por exemplo, GET /v1/dispositivos/{ref_key}).

O índice cobre o corpus inteiro (os diplomas de Diplomas no corpus) e é gerado offline por bun run indice:gerar, que grava em indice_artigos/indice_entradas. A API apenas lê — nada do índice depende de requisição de cliente.

As rotas são públicas (mesmo limite por IP das demais leituras do corpus). Base: https://api.leivigente.com.br.

Rotas

RotaDevolve
GET /v1/indice/exportO índice inteiro numa resposta (termos + entradas), com ETag: If-None-Match igual devolve 304
GET /v1/indice/termosTermos do índice paginados, com a contagem de entradas; q filtra por trecho
GET /v1/indice/termos/{chave}Entradas de um termo: subtermo + ref_key + sigla/artigo

A lista completa dos termos, para navegar no site, está em Termos do índice (A–Z, gerada do banco com bun run indice:exportar).

GET /v1/indice/termos

Lista os termos, ordenados alfabeticamente pela chave (o termo sem acento e em minúsculas), com quantas entradas cada um agrupa. q filtra por trecho; page/page_size paginam (padrão 1/50).

curl "$VIGENTE_URL/v1/indice/termos?q=prescri"
{
  "page": 1,
  "page_size": 50,
  "total": 2,
  "items": [
    { "termo": "Prescrição", "chave": "prescricao", "entradas": 183 },
    { "termo": "Prescrição intercorrente", "chave": "prescricao intercorrente", "entradas": 9 }
  ]
}
CampoDescrição
termoGrafia exata do assunto, estável entre lotes: é por ela que o app agrupa.
chavetermo sem acento e minúsculo: chave de agrupamento e ordenação.
entradasQuantas entradas (subtermos/refs) o termo tem.

Para montar o A–Z inteiro, pagine com page_size=200 (máximo) ou cacheie a lista.

GET /v1/indice/termos/{chave}

As entradas de um termo, pela chave devolvida acima. A entrada principal (o caput que define o assunto) vem primeiro, com subtermo: null; depois vêm os recortes, em ordem alfabética.

curl "$VIGENTE_URL/v1/indice/termos/homicidio"
{
  "termo": "Homicídio",
  "chave": "homicidio",
  "entradas": [
    { "subtermo": "simples", "ref_key": "CP.121", "sigla": "CP", "artigo": "121" },
    { "subtermo": "qualificado", "ref_key": "CP.121.2", "sigla": "CP", "artigo": "121" },
    { "subtermo": "culposo", "ref_key": "CP.121.3", "sigla": "CP", "artigo": "121" },
    { "subtermo": "simples", "ref_key": "CPM.205", "sigla": "CPM", "artigo": "205" },
    { "subtermo": null, "ref_key": "CTB.302", "sigla": "CTB", "artigo": "302" }
  ]
}
CampoDescrição
subtermoO recorte dentro do termo (ex.: qualificado, cabimento); null na entrada principal.
ref_keyO dispositivo mais específico do assunto; o app abre a lei aqui.
siglaSigla do diploma (para exibição).
artigoNúmero do artigo do ref_key (para exibição).

Chave inexistente devolve 404 com {"error":{"code":"not_found","message":"…"}}.

Como o app usa

  1. Offline (o app Vade Mecum): baixe GET /v1/indice/export uma vez, guarde junto com o ETag e, a cada sincronização, mande If-None-Match; 304 quer dizer que nada mudou.
  2. Online: liste GET /v1/indice/termos (paginado, q filtra) e, ao tocar num termo, chame GET /v1/indice/termos/{chave}.
  3. Para abrir a lei, use o ref_key da entrada em GET /v1/dispositivos/{ref_key} — ou o artigo inteiro em GET /v1/diplomas/{sigla}/artigos/{artigo}.

O mesmo índice pode ser consumido por agentes via MCP.

Como é gerado

A geração roda fora da API, na máquina de quem publica, e não usa requisições de clientes: só o texto público das leis sai daqui.

bun run indice:gerar --dry-run --siglas CC,CPC   # conta lotes, estima custo, mostra 1 prompt
bun run indice:gerar --siglas CC,CPC             # piloto
bun run indice:gerar                             # corpus inteiro
  1. O script monta um <artigo> por artigo em vigor (caput + parágrafos, incisos, alíneas e itens), com a rubrica e a seção, e agrupa os artigos em lotes por diploma e seção.
  2. Envia cada lote ao modelo (DeepSeek, deepseek-chat, JSON) e valida a resposta: termos proibidos, ref dentro do artigo, limite de 60 caracteres, deduplicação.
  3. Grava em indice_artigos (com o hash do que o modelo leu) e indice_entradas.

É incremental: uma nova execução só manda artigos novos ou cuja redação mudou, e poda do índice os que saíram do corpus. Como o resultado é gravado a cada lote, uma interrupção não perde o que já foi feito.

Na última execução (corpus inteiro): 20.480 artigos indexados, 33.571 entradas em 9.463 termos, ~US$ 5,00 em tokens. Os artigos que só têm cláusula de vigência, revogação ou remissão ficam com zero entradas — de propósito.

Nesta página