portal-modumfiscal-web/docs/api-backend.md
GUILHERME e4c468e61e
All checks were successful
Dev Build & Deploy Portal / build-deploy (push) Successful in 2m58s
feat(portal): extratos reais, certidão dinâmica e filtros self-scoped
Integra débitos, pagamentos e guias emitidas com API via composables e modais de extrato. Simplifica filtros do portal ao escopo do contribuinte logado. Refatora emissão pública de certidão com modelos dinâmicos e contrato idModelo. Corrige status de taxas (2=Paga, 3=Cancelada) e melhorias no proxy BFF/Keycloak.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-22 16:21:59 -03:00

760 lines
17 KiB
Markdown

# API Backend — portal-modumfiscal-web
Documentação dos endpoints que o portal consome. Base URL: `https://sistema.modumfiscal.com.br/api/v1`.
**Envelope padrão de resposta (sucesso):**
```json
{
"timestamp": "2025-05-18T10:00:00Z",
"statusCode": 200,
"responseType": "SUCCESS",
"message": "OK",
"data": { }
}
```
**Envelope de erro:**
```json
{
"statusCode": 422,
"message": "Unprocessable Entity",
"internalCode": "119",
"description": "Registro não foi encontrado."
}
```
Respostas binárias (PDF) retornam `Content-Type: application/pdf` direto — sem envelope.
---
## Módulo Público — sem autenticação
Headers obrigatórios em toda requisição:
- `X-Municipio: <id_municipio>`
- `X-Dominio: <subdominio>`
---
### Prefeitura (bootstrap)
#### `GET /publico/prefeitura/{dominio}`
Retorna a configuração visual e institucional da prefeitura.
**Response `data`:**
```json
{
"idMunicipio": 1,
"nomePrefeitura": "Prefeitura Municipal de Tutóia",
"nomeMunicipio": "Tutóia",
"uf": "MA",
"template": "tutoia",
"pathLogo": "/logos/tutoia.png",
"pathBackground": "/backgrounds/tutoia.jpeg",
"corPrimaria": "#F59E0B",
"cnpj": "12.345.678/0001-90",
"site": "https://tutoia.ma.gov.br",
"email": "atendimento@tutoia.ma.gov.br",
"telefone": "(98) 3478-1234"
}
```
> `pathLogo` e `pathBackground` são paths relativos — o frontend resolve para URL absoluta via `resolverUrl()`.
---
### Certidão Pública
#### `GET /publico/certidao/consultar`
Consulta a situação fiscal do contribuinte.
**Query params:**
| Param | Tipo | Obrigatório | Descrição |
|---|---|---|---|
| `documento` | string | sim | CPF (11 dígitos) ou CNPJ (14 dígitos) sem formatação |
**Response `data`:**
```json
{
"situacao": "NEGATIVA",
"nomeContribuinte": "João da Silva Santos"
}
```
`situacao` possíveis: `NEGATIVA` · `POSITIVA` · `POSITIVA_EFEITOS_NEGATIVA`
---
#### `GET /publico/certidao/modelos`
Lista modelos de certidão **públicos** disponíveis para o contribuinte, filtrados pelo `cadastro.tipo` (PF=1, PJ=2) — paridade com o combo do core.
**Query params:**
| Param | Tipo | Obrigatório | Descrição |
|---|---|---|---|
| `documento` | string | sim | CPF/CNPJ sem formatação — resolve o destinatário via cadastro |
| `titulo` | string | não | Filtro parcial no título do modelo |
| `page` | int | não | Página (default: 0) |
| `size` | int | não | Tamanho (default: 50) |
**Response `data`:**
```json
{
"paginasTotais": 1,
"elementosTotais": 2,
"data": [
{
"id": 12,
"titulo": "Certidão Negativa de Débitos",
"descricaoTipoCertidao": "Certidão Negativa",
"validadeDias": 180,
"destinatario": 1
}
]
}
```
Filtros aplicados no backend: `destinatario` = tipo do cadastro · `publico=1` · vigência válida · modelo com arquivo DOCX anexado.
---
#### `GET /publico/certidao/emitir`
Emite a certidão em PDF.
**Query params:**
| Param | Tipo | Obrigatório | Descrição |
|---|---|---|---|
| `documento` | string | sim | CPF/CNPJ sem formatação |
| `idModelo` | long | sim | ID do modelo selecionado em `/modelos` |
| `finalidade` | string | não | Finalidade informada pelo contribuinte (default: "Emissão pelo portal público") |
**Response:** `application/pdf` (binário direto, sem envelope)
---
### IPTU Público
#### `GET /publico/iptu/consultar`
Retorna todos os imóveis e débitos de IPTU do contribuinte ou de uma inscrição específica.
**Query params:**
| Param | Tipo | Obrigatório | Descrição |
|---|---|---|---|
| `documento` | string | condicional | CPF/CNPJ sem formatação (informar `documento` **ou** `inscricao`) |
| `inscricao` | string | condicional | Inscrição imobiliária (ex: `0001.001.0001.001`) |
**Response `data`:**
```json
{
"content": [
{
"inscricaoImobiliaria": "0001.001.0001.001",
"enderecoCompleto": "Rua das Flores, 100 — Centro",
"debitos": [
{
"id": "d1",
"descricao": "IPTU 2025 — Cota 4/10",
"vencimento": "30/04/2025",
"valor": 125.90,
"valorAtualizado": 138.49,
"status": "VENCIDO"
}
]
}
]
}
```
`status` possíveis: `VENCIDO` · `A_VENCER` · `PAGO` · `PARCELADO`
---
#### `GET /publico/iptu/carne`
Emite o carnê completo de IPTU em PDF.
**Query params:**
| Param | Tipo | Obrigatório | Descrição |
|---|---|---|---|
| `inscricao` | string | sim | Inscrição imobiliária |
**Response:** `application/pdf`
---
#### `GET /publico/iptu/boleto`
Emite o boleto avulso de uma parcela.
**Query params:**
| Param | Tipo | Obrigatório | Descrição |
|---|---|---|---|
| `idDebito` | string | sim | ID do débito retornado por `/consultar` |
**Response:** `application/pdf`
---
### Primeiro Acesso
Fluxo de 4 etapas para o contribuinte criar senha de acesso ao portal.
#### `GET /publico/primeiro-acesso/verificar`
Valida se o documento tem cadastro e retorna os canais disponíveis para envio do código.
**Query params:**
| Param | Tipo | Obrigatório |
|---|---|---|
| `documento` | string | sim |
**Response `data`:**
```json
{
"nome": "Maria Aparecida Santos",
"canais": [
{ "tipo": "EMAIL", "valor": "ma***@gmail.com" },
{ "tipo": "WHATSAPP", "valor": "(98) *****-8901" },
{ "tipo": "SMS", "valor": "(98) *****-8901" }
]
}
```
`tipo` possíveis: `EMAIL` · `WHATSAPP` · `SMS`
---
#### `POST /publico/primeiro-acesso/codigo`
Envia o código de 6 dígitos para o canal escolhido.
**Request body:**
```json
{
"documento": "12345678900",
"canal": "EMAIL"
}
```
**Response `data`:**
```json
{ "enviado": true }
```
---
#### `POST /publico/primeiro-acesso/validar`
Valida o código digitado e retorna um token temporário para definição de senha.
**Request body:**
```json
{
"documento": "12345678900",
"codigo": "123456"
}
```
**Response `data`:**
```json
{ "token": "eyJhb..." }
```
Erros: `422` se código inválido ou expirado.
---
#### `POST /publico/primeiro-acesso/senha`
Define a nova senha usando o token temporário.
**Request body:**
```json
{
"token": "eyJhb...",
"senha": "MinhaS3nha!"
}
```
**Response `data`:**
```json
{ "sucesso": true }
```
---
### Credenciamento
Fluxo para novo contribuinte solicitar cadastro no sistema.
#### `GET /publico/credenciamento/verificar`
Verifica se o documento já tem cadastro ou pode ser credenciado.
**Query params:**
| Param | Tipo | Obrigatório |
|---|---|---|
| `documento` | string | sim |
**Response `data`:**
```json
{ "situacao": "APTO" }
```
`situacao` possíveis:
- `APTO` — pode prosseguir com o credenciamento
- `JA_CREDENCIADO` — já tem acesso ao sistema
- `BLOQUEADO` — documento bloqueado (contatar prefeitura)
---
#### `GET /publico/cep/{cep}`
Busca endereço por CEP para auto-preenchimento no formulário de credenciamento.
**Path param:** `cep` — 8 dígitos sem hífen
**Response `data`:**
```json
{
"logradouro": "Rua das Acácias",
"bairro": "Centro",
"localidade": "Tutóia",
"uf": "MA"
}
```
---
#### `POST /publico/credenciamento/solicitar`
Envia a solicitação de credenciamento para análise da prefeitura.
**Request body (Pessoa Física):**
```json
{
"documento": "12345678900",
"tipoPessoa": "FISICA",
"nomeCompleto": "João da Silva Santos",
"dataNascimento": "1990-05-15",
"email": "joao@email.com",
"emailConfirmacao": "joao@email.com",
"telefone": "98991234567",
"whatsapp": true,
"endereco": {
"cep": "65900000",
"logradouro": "Rua das Flores",
"numero": "100",
"complemento": "Apto 201",
"bairro": "Centro",
"cidade": "Tutóia",
"uf": "MA"
}
}
```
**Request body adicional (Pessoa Jurídica):**
```json
{
"tipoPessoa": "JURIDICA",
"razaoSocial": "Empresa LTDA",
"nomeFantasia": "Empresa",
"inscricaoEstadual": "12345678",
"representanteLegal": {
"nomeCompleto": "João da Silva",
"cpf": "12345678900",
"cargo": "Diretor"
}
}
```
**Response `data`:**
```json
{ "protocolo": "CRED-2025-00123" }
```
---
## Módulo Portal — requer autenticação
Header obrigatório além dos de tenant:
- `Authorization: Bearer <jwt_keycloak>`
---
### Painel
#### `GET /contribuinte/painel/resumo`
Dados do card de resumo do dashboard.
**Response `data`:**
```json
{
"totalDebitos": 1250.90,
"certidoesAtivas": 2,
"alvarasAndamento": 2,
"ultimoPagamento": 430.00,
"debitosVencidos": 1
}
```
---
#### `GET /contribuinte/painel/atividades`
Lista das últimas atividades do contribuinte.
**Response `data`:**
```json
{
"content": [
{
"tipo": "PAGAMENTO",
"descricao": "IPTU 2025 — Parcela 3/10 paga",
"data": "15/05/2025"
},
{
"tipo": "CERTIDAO",
"descricao": "Certidão Negativa emitida",
"data": "10/05/2025"
}
]
}
```
`tipo` possíveis: `PAGAMENTO` · `CERTIDAO` · `DEBITO` · `ALVARA` · `CADASTRO`
---
### Débitos (Extrato)
#### `GET /contribuinte/debitos`
Lista débitos agrupados por conta/tributo (`ContaCorrenteTributoDTO`), com os mesmos filtros do extrato interno.
**Query params:** `idTaxa`, `idContaTributo`, `periodoIni` (YYYYMM), `periodoFim` (YYYYMM), `inscMunicipal`, `idEstadoConta` (1=débito, 2=zero, 3=crédito)
**Response `data`:** array de `ContaCorrenteTributoDTO` com lista `debitos` aninhada.
---
#### `GET /contribuinte/debitos/tributos/{codigo}`
Busca tributo por código para filtros.
---
#### `GET /contribuinte/debitos/contas-tributo/{codigo}`
Busca conta tributo por código para filtros.
---
#### `GET /contribuinte/debitos/{idContaCorrente}/transacoes`
Transações da conta corrente (somente se pertencer ao contribuinte logado).
---
#### `POST /contribuinte/debitos/gerar-guia`
Gera guia para débitos selecionados. Body: `GerarGuiaDebitosRequestDTO`.
**Response `data`:** `GerarGuiaResponseDTO` (`idDoctoArr`, `numeroGuia`, etc.)
---
#### `GET /contribuinte/debitos/guia/{idDoctoArr}`
PDF de guia já emitida (validação de ownership).
---
#### `GET /contribuinte/debitos/{idContaCorrente}/guia`
Gera e retorna PDF de guia para um único débito.
---
#### `POST /contribuinte/debitos/extrato-pdf`
Gera PDF do extrato de débitos. Body: `GerarExtratoDebitosRequestDTO`.
**Response:** `application/pdf`
---
### Certidões
#### `GET /contribuinte/certidoes`
Lista todas as certidões emitidas pelo contribuinte.
**Response `data`:**
```json
{
"content": [
{
"id": "cert1",
"tipo": "Certidão Negativa de Débitos",
"numero": "CN-2025-00481",
"dataEmissao": "10/05/2025",
"dataValidade": "07/11/2025",
"status": "ATIVA"
}
]
}
```
`status` possíveis: `ATIVA` · `VENCIDA` · `CANCELADA`
---
#### `GET /contribuinte/certidoes/{id}/pdf`
Reemite uma certidão em PDF.
**Path param:** `id` — ID da certidão
**Response:** `application/pdf`
> Retorna `422` se a certidão estiver com status `CANCELADA`.
---
### Alvarás
#### `GET /contribuinte/alvaras`
Lista os processos de alvará do contribuinte.
**Query params:**
| Param | Tipo | Obrigatório | Descrição |
|---|---|---|---|
| `status` | string | não | Filtro por status do processo |
**Response `data`:**
```json
{
"content": [
{
"id": "alv1",
"tipo": "Alvará de Funcionamento — Comércio Varejista",
"numeroProcesso": "ALV-2025-00342",
"status": "EM_ANALISE",
"ultimaAtualizacao": "14/05/2025",
"etapas": [
{ "nome": "Protocolo", "concluida": true, "atual": false },
{ "nome": "Análise", "concluida": false, "atual": true },
{ "nome": "Vistoria", "concluida": false, "atual": false },
{ "nome": "Emissão", "concluida": false, "atual": false }
]
}
]
}
```
`status` possíveis: `EM_ANALISE` · `AGUARDANDO_DOCUMENTOS` · `DEFERIDO` · `INDEFERIDO` · `CANCELADO`
---
### Pagamentos (Extrato)
#### `GET /contribuinte/pagamentos`
Lista pagamentos agrupados por tributo (`ExtratoPagamentoTributoDTO`).
**Query params:** `idTaxa`, `idContaTributo`, `pagInicio`, `pagFim`, `periodoIni`, `periodoFim`, `ano` (atalho para intervalo anual)
**Response `data`:** array com `pagamentos` aninhados (principal, multa, juros, desconto, total).
---
#### `POST /contribuinte/pagamentos/extrato-pdf`
Gera PDF do extrato de pagamentos. Body: `GerarExtratoPagamentosRequestDTO`.
**Response:** `application/pdf`
---
#### `GET /contribuinte/pagamentos/{idContaCorrente}/comprovante`
Baixa comprovante de pagamento em PDF (quando houver `LancamentoTaxa` vinculado).
**Response:** `application/pdf` ou `404`
---
### Guias Emitidas
#### `GET /contribuinte/guias`
Lista guias do contribuinte logado (CPF/CNPJ injetado no backend). Paginado.
**Query params:** `numeroGuia`, `dataEmissaoInicio/Fim`, `dataVencimentoInicio/Fim`, `status`, `valorMinimo`, `valorMaximo`, `page`, `size`
**Response `data`:** `PageDTO<GuiaConsultaDTO>`
---
#### `GET /contribuinte/guias/{id}`
Detalhes completos da guia (`GuiaPagamentoDTO`).
---
#### `GET /contribuinte/guias/{id}/pdf`
PDF da guia.
---
### Dados Cadastrais
#### `GET /contribuinte/dados`
Retorna os dados cadastrais completos do contribuinte autenticado.
**Response `data` (Pessoa Física):**
```json
{
"tipoPessoa": "FISICA",
"documento": "123.456.789-00",
"nomeCompleto": "João da Silva Santos",
"dataNascimento": "15/06/1975",
"email": "joao.santos@email.com",
"telefone": "(98) 99123-4567",
"whatsapp": true,
"endereco": {
"cep": "65900-000",
"logradouro": "Rua das Flores",
"numero": "100",
"complemento": "Apto 201",
"bairro": "Centro",
"cidade": "Tutóia",
"uf": "MA"
}
}
```
**Campos adicionais (Pessoa Jurídica):**
```json
{
"tipoPessoa": "JURIDICA",
"documento": "12.345.678/0001-90",
"razaoSocial": "Empresa LTDA",
"nomeFantasia": "Empresa",
"inscricaoEstadual": "12345678"
}
```
---
#### `PUT /contribuinte/dados/contato`
Atualiza os dados de contato editáveis (email, telefone, WhatsApp).
**Request body:**
```json
{
"email": "novo@email.com",
"telefone": "98991234567",
"whatsapp": true
}
```
`telefone` deve ser enviado **sem formatação** (apenas dígitos).
**Response `data`:**
```json
{ "atualizado": true }
```
---
## Avisos (pendente no backend)
#### `GET /publico/avisos/{dominio}`
Retorna os avisos/banners exibidos no carousel da Home.
> **Status:** endpoint ainda não implementado no backend. O frontend usa dados estáticos hardcoded em `HomeView.vue`.
**Response `data` esperada:**
```json
{
"content": [
{
"id": "av1",
"titulo": "IPTU 2025 — Prazo final",
"descricao": "Últimas parcelas com desconto até 30 de junho.",
"tipo": "ALERTA",
"ativo": true
}
]
}
```
`tipo` sugeridos: `INFO` · `ALERTA` · `URGENTE`
---
## Fluxo de Autenticação
O portal usa **Keycloak PKCE** — nenhuma credencial trafega pelo frontend.
```
1. Usuário informa CPF/CNPJ na Home
2. LoginView monta — exibe doc mascarado + campo senha
3. entrar() → redireciona para Keycloak (PKCE code challenge)
4. Keycloak autentica e redireciona de volta com ?code=
5. authService troca code por access_token + refresh_token
6. authStore.setSession(token, userInfo) persiste sessão
7. router.push({ name: 'painel' })
```
**Realm:** `modumfiscal-dev`
**Client ID:** `portal-modumfiscal-web`
**Grant type:** `authorization_code` com PKCE (S256)
**Token endpoint:** `https://keycloakprod.modumfiscal.com.br/realms/modumfiscal-dev/protocol/openid-connect/token`
O `preferred_username` do JWT é o CPF/CNPJ sem formatação — usado como identificador do contribuinte nas chamadas ao backend.
---
## Status de Implementação dos Endpoints
| Endpoint | Frontend pronto | Backend pronto | Mock |
|---|---|---|---|
| `GET /publico/prefeitura/{dominio}` | ✓ | ✓ | — |
| `GET /publico/certidao/consultar` | ✓ | ✓ | — |
| `GET /publico/certidao/modelos` | ✓ | ✓ | — |
| `GET /publico/certidao/emitir` | ✓ | ✓ | — |
| `GET /publico/iptu/consultar` | ✓ | pendente | ✓ |
| `GET /publico/iptu/carne` | ✓ | pendente | ✓ |
| `GET /publico/iptu/boleto` | ✓ | pendente | ✓ |
| `GET /publico/primeiro-acesso/verificar` | ✓ | pendente | ✓ |
| `POST /publico/primeiro-acesso/codigo` | ✓ | pendente | ✓ |
| `POST /publico/primeiro-acesso/validar` | ✓ | pendente | ✓ |
| `POST /publico/primeiro-acesso/senha` | ✓ | pendente | ✓ |
| `GET /publico/credenciamento/verificar` | ✓ | pendente | ✓ |
| `GET /publico/cep/{cep}` | ✓ | pendente | ✓ |
| `POST /publico/credenciamento/solicitar` | ✓ | pendente | ✓ |
| `GET /contribuinte/painel/resumo` | ✓ | pendente | ✓ |
| `GET /contribuinte/painel/atividades` | ✓ | pendente | ✓ |
| `GET /contribuinte/debitos` | ✓ | pendente | ✓ |
| `GET /contribuinte/debitos/{id}/guia` | ✓ | pendente | ✓ |
| `GET /contribuinte/certidoes` | ✓ | pendente | ✓ |
| `GET /contribuinte/certidoes/{id}/pdf` | ✓ | pendente | ✓ |
| `GET /contribuinte/alvaras` | ✓ | pendente | ✓ |
| `GET /contribuinte/pagamentos` | ✓ | pendente | ✓ |
| `GET /contribuinte/pagamentos/{id}/comprovante` | ✓ | pendente | ✓ |
| `GET /contribuinte/dados` | ✓ | pendente | ✓ |
| `PUT /contribuinte/dados/contato` | ✓ | pendente | ✓ |
| `GET /publico/avisos/{dominio}` | parcial | pendente | — |