Skip to content

APIs REST ​

A Fábrica de Cálculos expõe três APIs REST construídas com Nuxt Nitro. Cada uma publica sua própria spec OpenAPI em /_openapi.json, e o portal unificado (@fc/docs-api) agrega todas as specs em cards navegáveis. A UI automática /_swagger existe apenas para desenvolvimento local das apps API.

Visão geral ​

AppBancoAuthOpenAPI
prev-api—API key nos cálculos/_openapi.json
rmi-api—API key nos cálculos/_openapi.json
backofficePostgres (Drizzle)JWT/JWK/_openapi.json
docs-api (portal)—Nenhuma—

Namespace rgps ​

Os endpoints de cálculo canônico da prev-api e rmi-api vivem sob o módulo rgps (Regime Geral de Previdência Social): POST /rgps/api/v1/calculos-tempo, POST /rgps/api/v1/calculos-rmi, etc. A divisão entre prev-api e rmi-api é puramente operacional (isolamento de CPU/memória — cálculo de RMI é mais pesado). Do ponto de vista do contrato público, é uma única API.

Todas as respostas JSON dos endpoints /rgps/api/v1/* seguem o envelope PDPJ-Br:

json
{ "status": "ok", "code": "200", "messages": [], "result": { /* ... */ } }

Os caminhos antigos /api/v1/* da prev-api foram removidos após o sunset de 2026-05-31, anunciado via headers RFC 8594 (Deprecation: true, Sunset, Link: rel="successor-version"). Hoje respondem 404; os sucessores vivem no namespace rgps.

Portal de documentação ​

A app dedicada docs-api agrega os contratos públicos das APIs e do portal operacional em uma landing com cards navegáveis:

  • /docs-api — landing com cards por documento (RGPS em destaque como "Calculadoras")
  • /docs-api/rgps — Swagger UI com endpoints de prev-api + rmi-api sob /rgps/api/v1/*
  • /docs-api/apps — Swagger UI com os endpoints /apps/api/v1/* do backoffice
  • /docs-api/indices — Swagger UI com os endpoints /indices/api/v1/* do backoffice
  • /docs-api/raiz — Swagger UI com os endpoints operacionais públicos
  • /docs-api/tudo — documento único agregando todos os endpoints
  • /docs-api/_swagger/specs/principal.json — spec integral em formato bruto

Fontes do manifesto — dinâmica com fallback estático ​

O portal resolve cada documento nesta ordem:

  1. Fontes vivas e integrais — GET /docs-api/_openapi/manifesto e GET /docs-api/_openapi/specs/{documento}.json; a rota Nitro só publica quando todas as aplicações-fonte obrigatórias responderam e a agregação foi validada.
  2. Último cache integral — um cache curto reduz chamadas repetidas e sua última versão válida continua servindo durante uma indisponibilidade, mesmo depois do prazo normal de renovação.
  3. Artefato estático integral — /docs-api/_swagger/specs/*.json, gerado em build-time via pnpm --filter @fc/docs-api spec:gen e servido pelo Nitro.
  4. Indisponibilidade explícita — sem nenhuma versão integral, a rota responde 503.

Documento parcial, colisão entre contratos e referência interna quebrada nunca substituem o cache íntegro. O alias /docs-api/tudo usa a mesma proveniência dos documentos individuais; o JSON bruto está separado na URL de artefato explícita.

Acessar um documento que não consta do contrato (ex.: /docs-api/inexistente ou /docs-api/principal) devolve 404 antes da hidratação em vez de cair silenciosamente na spec principal.

API key estrutural nas APIs de cálculo (prev-api, rmi-api) ​

As rotas canônicas de cálculo exigem API key (x-api-key) por definição das próprias apps, sem depender de variáveis de ambiente de deploy. A seleção é declarativa, por path, com globs fixos nos respectivos nuxt.config.ts:

  • prev-api: /rgps/api/v1/calculos-tempo/** e /rgps/api/v1/calculos-atrasados/**
  • rmi-api: /rgps/api/v1/calculos-rmi/**

Os GETs de referência /rgps/api/v1/fundamentos e /rgps/api/v1/marcos-temporais ficam fora desses globs e permanecem públicos.

No ambiente local a exigência vem desligada por padrão. O assistente do pnpm dev:local permite ativá-la pela pergunta "Exigir chave de API…?" ou pelas opções de linha de comando, para que o fluxo autenticado possa ser exercitado sem tornar obrigatória a emissão de uma chave a cada sessão.

No boot, o Nuxt module api-key-opcional-validador (em base-api) valida cada glob contra as rotas efetivamente registradas no Nitro — se algum glob não casa com rota alguma, a app falha ao subir (fail-fast). Isso impede que uma alteração de rota deixe a proteção estrutural inconsistente.

A chave é validada pela plataforma contra o cadastro central, com cache curto das respostas. Essa comunicação acontece em um canal autenticado que não faz parte do contrato público.

No Swagger UI, cada operação traz o cadeado ApiKeyAuth dinamicamente conforme a config do runtime: o transformador do swagger-nuxt-module lê apiPublica.apiKey.{habilitada, rotasProtegidas} e adiciona ApiKeyAuth em operações cujo path casa — mesma fonte de verdade do middleware. Declarações security manuais no @swagger (ex.: o exchange) são preservadas. Quando uma operação já exige outro esquema, como BearerAuth, a chave entra no mesmo requisito: os dois controles são obrigatórios, e não alternativas.

Como a anotação é de runtime, ela só existe na spec servida por /_openapi.json. Os artefatos estáticos de public/_swagger/ saem sem cadeado por construção: são gerados pelo CLI, que não passa pelo transformador. Isso importa no portal docs-api, que tem as duas fontes — a dinâmica (agrega os /_openapi.json vivos das apps) e a estática. Em dev standalone com baseURL na raiz, a estática vem primeiro; nos demais casos, a dinâmica. É por isso que o cadeado aparece em dev:docker, dev, stg e prod, e não no dev:local.

Nenhuma app declara securitySchemes por padrão. O módulo não tem mais um default — quem exige credencial declara; quem não exige, não anuncia nada. Um default preenchido fazia toda API nascer oferecendo um BearerAuth que nenhuma operação referenciava, e a spec agregada herdava esse fantasma de cada fonte.

Emitir chaves é feito apenas pela equipe da CECALC, a partir de uma solicitação ou diretamente no painel administrativo (o texto claro é exibido uma única vez).

Como obter uma chave ​

O caminho para integradores é o formulário de solicitação no portal (/solicitar-api-key), acessível pelo card "Chave de API" na seção de documentação técnica da página inicial. O fluxo:

  1. O solicitante entra com sua conta PDPJ (SSO) e preenche o formulário: dados de contato, um nome para a chave, a finalidade de uso e, opcionalmente, em favor de quem ela será usada — com aceite expresso da versão vigente dos Termos de Uso.
  2. A solicitação gera um protocolo e fica pendente de análise. Se os termos forem republicados antes do envio, o formulário exige novo aceite.
  3. A equipe da CECALC analisa a solicitação: deferida, o solicitante é avisado por e-mail e retira a chave no próprio portal, autenticado com o mesmo login usado na solicitação — ela é exibida uma única vez e não pode ser recuperada depois, nem por nós; indeferida, o motivo é comunicado por e-mail. A chave nunca trafega por e-mail.

A chave é sempre de uma pessoa física: quem solicita é o titular, identificado pelo CPF da conta PDPJ, e responde pelo uso. Vínculo com órgão ou tribunal e inscrição na OAB são registrados automaticamente como contexto da solicitação, não como titularidade. "Em favor de" é informação de enriquecimento e não transfere responsabilidade a ninguém.

Suas chaves ​

O item Chaves de API no menu do usuário reúne as chaves em nome de quem está autenticado, o andamento da solicitação em aberto e o pedido de uma nova chave.

Um mesmo titular pode manter várias chaves ativas ao mesmo tempo — finalidades e favorecidos distintos justificam chaves distintas, e pedir uma nova não revoga as anteriores. Há uma restrição só: uma solicitação em aberto por vez, para não acumular pedidos repetidos na fila de análise.

O titular pode revogar as próprias chaves a qualquer momento, inclusive as emitidas diretamente pela equipe em seu nome. A revogação é imediata e definitiva: a chave não volta a funcionar, e recuperar o acesso exige solicitar outra.

Classe de consumidor e escopos ​

Cada chave carrega, desde a emissão:

  • Classe de consumidor — judiciario, institucional ou publico. Define a prioridade de uso das APIs: órgãos do Poder Judiciário têm prioridade absoluta (isentos de limite de requisições); as demais classes recebem cotas próprias. Chave sem classe conhecida é tratada como publico (a mais restritiva).
  • Escopos — rgps (rotas públicas de cálculo) e/ou exchange (criação de tokens de exchange server-to-server). Uma chave só abre as superfícies dos escopos que possui; usar a chave fora do escopo resulta em 403.

Limites de uso por classe ​

Com o rate limit habilitado, os POSTs das rotas protegidas passam a ter cota por minuto conforme a classe de consumidor da chave (judiciario é isento; as demais classes têm cotas próprias — os valores vigentes são divulgados em /docs-api/limites e podem ser ajustados operacionalmente). Requisições sem chave, enquanto a exigência não estiver ativa, são limitadas por IP com a cota de publico. Ao exceder a cota, a API responde 429 com o header Retry-After (segundos até a próxima janela). GETs — polling de jobs e dados de referência — não são limitados.

Antes disso há um limite de proteção por endereço de origem, com cota bem mais alta, aplicado assim que a exigência de chave ou o rate limit estejam ativos. Ele impede que uma rajada de chaves inválidas force uma validação (e uma escrita de telemetria) por requisição. Não afeta o uso legítimo, inclusive de órgãos atrás de um único endereço de saída.

Documentos legais ​

Os termos de uso e o aviso de privacidade vigentes são públicos e versionados: GET /apps/api/v1/documentos-legais lista os documentos ativos e GET /apps/api/v1/documentos-legais/{slug} (termos-de-uso, aviso-de-privacidade) devolve a versão publicada com o conteúdo em HTML sanitizado. As páginas canônicas para leitura ficam no portal (/termos-de-uso e /aviso-de-privacidade).

Padrões comuns ​

Todas as APIs seguem os mesmos padrões:

  • OpenAPI: cada app expõe /_openapi.json via @fc/swagger-nuxt-module. O portal em docs-api consome essas specs em runtime e preserva os artefatos de build como contingência integral.
  • Logs estruturados: operacional (requisição/resposta) + auditoria (eventos de negócio)
  • CORS e segurança: configurados no nuxt.config.ts de cada API
  • Docker: cada app tem um Dockerfile multi-stage pronto para produção

Stack ​

graph TD
  Nitro["Nuxt Nitro (runtime de server)"]
  Nitro --> Swagger["@fc/swagger-nuxt-module<br/>(OpenAPI)"]
  Nitro --> Drizzle["drizzle-orm + postgres<br/>(apenas backoffice)"]
  Nitro --> Auth["nuxt-auth-utils<br/>(apenas backoffice)"]