# API do AgendAI (leitura) — Inadimplência

Guia de uso (login, convenções, erros): https://api-docs.agendai.pro/md/guia.md


Títulos vencidos e em aberto dos clientes, a partir dos recebíveis do Omie.

- `GET /financeiro/inadimplencia/resumo` — Resumo (BI) da inadimplência financeira
- `GET /financeiro/inadimplencia/itens` — Itens (linhas) em atraso do BI de inadimplência, paginados
- `GET /financeiro/inadimplencia/filter-options/{dimension}` — Catálogo paginado de opções para um filtro da inadimplência

### GET /financeiro/inadimplencia/resumo

**Resumo (BI) da inadimplência financeira** · operationId `obterResumoInadimplencia`

Autenticação: `Authorization: Bearer <token>`.

Devolve os indicadores do BI de inadimplência: cartões de totais e cinco agregações (por departamento, maiores devedores, evolução por mês de vencimento e histórico ano x mês). Todos os números respeitam os mesmos filtros e o mesmo cálculo de `/financeiro/inadimplencia/itens`; não há paginação.

Todos os valores monetários são em **reais** (número JSON com 2 casas). A resposta vem embrulhada em `{ "data": ... }`.

Atenção: no resumo da fonte canônica cada **parcela/título** é um item (`quantidadeItensAtrasados`), enquanto em `/itens` a paginação conta **linhas** agrupadas por OS. Os valores monetários totais batem entre as duas rotas; as contagens não.

**Filtros em lista:** valores separados por vírgula ou parâmetro repetido; texto vazio e segmentos vazios (`a,,b`) são ignorados; o texto `null` **não** é ignorado (vira um valor literal no filtro de lista e, em datas, `incluirIgnoradas`, `page` e `pageSize`, responde 400).

### Como a inadimplência é calculada

A pergunta respondida é "quanto a organização tem a receber, já vencido e não pago, de títulos faturados".
Os números saem da fila de **recebíveis do Omie** sincronizados no AgendAI (`omie_receivable`), não de um cálculo sobre a agenda.
Tudo é restrito à organização (tenant) do token.

**Duas fontes de dados (a organização cai em uma delas):**

- **Canônica** (a fonte atual): usada quando a organização tem ao menos um cadastro Omie ativo e **todos** os cadastros ativos terminaram a carga inicial de recebíveis (fase `READY`). Cada título/parcela do Omie é um recebível.
- **Legada**: usada quando não há cadastro Omie ativo, ou algum cadastro ainda está em carga (`BACKFILL_PENDING`) ou falhou (`BACKFILL_FAILED`). Nesse caso a base é a **ordem de serviço** (OS) em vez do título: OS com status `BOLETO_GERADO` ou `FATURADA`, valor total > 0, **uma única parcela**, vencimento anterior ao início do dia (UTC), de projeto não excluído, com `naoFaturarFinanceiro = false`, de tipo de projeto pós-pago elegível ao financeiro **ou sem tipo de projeto** e com cliente vinculado. O valor em atraso é o valor total da OS.
- A resposta não diz qual fonte foi usada, exceto pelos itens: na fonte legada `origem = "Legado"`, `omieTenantAppId = null`, `rowKey = "OS:<id>"` e `detalhe.parcelas = []`.

**O que entra (fonte canônica)** — um recebível só conta se **todas** as condições valem:

1. O cadastro Omie dele (`omie_tenant_app`) está **ativo**. Cadastro Omie inativo (por exemplo empresa baixada) sai da inadimplência; reativar devolve os títulos.
2. O estado é `OPEN` (em aberto) ou `PARTIALLY_PAID` (parcialmente pago) e o saldo em aberto (`open_amount`) é maior que zero. Títulos liquidados (`SETTLED`) e cancelados não entram.
3. A **data de vencimento efetiva** é anterior ao início do dia de hoje em Brasília (00:00 BRT). A data efetiva é a mais tardia entre o vencimento (`dDtVenc`) e a previsão de recebimento (`dDtPrevisao`) do Omie: um título vencido cujo recebimento foi reprogramado para o futuro não conta. Os filtros `dataVencimento*` e o campo `vencimento` usam essa mesma data. Título com data efetiva hoje ainda não é inadimplente.
4. O título tem **número de documento fiscal** preenchido (isto é, a nota foi emitida).
5. O tipo de documento **não** é `REE`, `DAM` nem `99999` (sem diferenciar maiúsculas de minúsculas).
6. Salvo `incluirIgnoradas=true`: a OS do título **não** tem regra de "inadimplência ignorada" ativa e o contrato (direto ou herdado da OS) também não. Essas regras são cadastradas no módulo de inadimplência (`inadimplencia_ignorada`, alvo `ORDEM_SERVICO` ou `CONTRATO`).
7. Os filtros da consulta (empresa Omie, cliente, projeto, produto, tipo de projeto, departamento, categoria, tipo de documento, intervalo de vencimento).

Overrides de status e regras de inadimplência por cliente/projeto (módulo `inadimplencia-status`/`inadimplencia-regras`) **não** influenciam estas três rotas; só as regras de "ignorada" acima entram no cálculo.

**Valores:** reais (BRL), números JSON com 2 casas (não centavos, não string).
**Datas:** `vencimento` e demais datas de calendário são `YYYY-MM-DD`.
**Dias de atraso:** dias inteiros entre o vencimento (o mais antigo, no caso de linha com várias parcelas) e hoje; 0 se não vencido.

**Permissão:** capacidade `VER_BI_INADIMPLENCIA`. Sem ela a resposta é 403. Em geral: administrador global, administrador do tipo Financeiro, ou usuário com a tela `/financeiro/inadimplencia` liberada nas permissões de tela (lida do banco a cada requisição, então revogação vale na hora). Com a regra de acesso por setor ligada na organização, vale somente a tela efetiva do usuário. Não há filtro por registros: quem passa vê todos os dados da organização.

#### Parâmetros

| Nome | Onde | Tipo | Obrigatório | Descrição |
|---|---|---|---|---|
| `empresaOmie` | query | integer[] | não | Ids dos cadastros Omie (`omie_tenant_app`) da organização. Aceita parâmetro repetido (`?empresaOmie=1&empresaOmie=2`) ou lista separada por vírgula (`empresaOmie=1,2`); valores duplicados são descartados. Só tem efeito na fonte canônica; na fonte legada qualquer valor aqui zera o resultado. Os ids válidos vêm de `filter-options/empresaOmie`. Ex.: `[1]` |
| `cliente` | query | string[] | não | Clientes. Fonte canônica: ids (UUID) do cliente ou o texto exato do campo `cliente` dos itens (nome fantasia; senão a empresa do projeto; senão o nome no Omie; ou `Sem cliente vinculado`); os dois formatos podem ser misturados. Fonte legada: somente o nome fantasia. Mesmo formato de lista de `empresaOmie` (repetido ou separado por vírgula; por isso um nome com vírgula não pode ser filtrado). Na fonte canônica use o `id` de `filter-options/cliente`; na legada, o `label`. Ex.: `["0b6a1d52-3f0e-4c6a-9d0e-5a1f2f6d7a11"]` |
| `projeto` | query | string[] | não | Projetos. Fonte canônica: ids (UUID) ou nome do projeto; fonte legada: nome. Mesmo formato de lista. Na fonte canônica use o `id` de `filter-options/projeto`; na legada, o `label`. Ex.: `["Implantação Alfa"]` |
| `produto` | query | string[] | não | Produtos (id do produto). Fonte canônica: casa o título pela categoria Omie mapeada ao produto (`omie_tenant_billing_mapping` ativo). Na fonte legada qualquer valor aqui zera o resultado. Ids em `filter-options/produto`. Ex.: `["5f0c1e7a-8d2b-4a39-b0c4-1e2d3c4b5a69"]` |
| `tipoProjeto` | query | string[] | não | Tipos de projeto. Fonte canônica: id do tipo de projeto; fonte legada: nome do tipo (`Sem tipo de projeto` seleciona os projetos sem tipo). Na fonte canônica use o `id` de `filter-options/tipoProjeto`; na legada, o `label`. Ex.: `["a1b2c3d4-0000-4000-8000-000000000001"]` |
| `departamento` | query | string[] | não | Departamentos. Fonte canônica: código do departamento Omie (`SEM_DEPARTAMENTO` para títulos sem roteamento de departamento); fonte legada: nome/descrição do departamento (`Sem departamento` quando vazio). Na fonte canônica use o `id` de `filter-options/departamento`; na legada, o `label`. Ex.: `["SEM_DEPARTAMENTO"]` |
| `categoria` | query | string[] | não | Códigos de categoria Omie do título (`category_code`). Só tem efeito na fonte canônica; na legada qualquer valor zera o resultado. Códigos em `filter-options/categoria`. Ex.: `["1.01.02"]` |
| `tipoDocumento` | query | string[] | não | Tipos de documento Omie do título (`BOL`, `REC`, `TED`...). Só tem efeito na fonte canônica; na legada qualquer valor zera o resultado. Códigos em `filter-options/tipoDocumento`. Ex.: `["BOL"]` |
| `dataVencimentoInicio` | query | string (date) | não | Vencimento mínimo, inclusivo, no formato `YYYY-MM-DD` (data de calendário válida). Fonte canônica: o dia começa à 00:00 de Brasília (03:00Z). Fonte legada: dia em UTC. Texto vazio é ignorado. Ex.: `2026-01-01` |
| `dataVencimentoFim` | query | string (date) | não | Vencimento máximo, inclusivo, `YYYY-MM-DD`. Deve ser maior ou igual a `dataVencimentoInicio` (senão 400). Como só entram parcelas vencidas antes de hoje, valores futuros não ampliam o resultado. Ex.: `2026-10-31` |
| `incluirIgnoradas` | query | boolean; padrão `false` | não | Aceita `true` ou `false`. Padrão (omitido ou `false`): ordens de serviço e contratos com regra de "ignorada" ativa ficam fora. Com `true` eles entram nos números. Ex.: `false` |

#### Resposta 200

Resumo calculado.

Tipo da raiz: InadimplenciaResumoResponse

| Campo | Tipo | Sempre presente | Descrição |
|---|---|---|---|
| `data` | object | sim |  |
| `data.cards` | object | sim |  |
| `data.cards.quantidadeItensAtrasados` | integer | sim | Quantidade de itens em atraso. Fonte canônica: número de **parcelas/títulos** em atraso (não de linhas agrupadas por OS; por isso pode ser maior que `pagination.total` de `/itens`). Fonte legada: número de OS. |
| `data.cards.valorTotalEmAtraso` | number | sim | Soma do saldo em atraso, em reais. |
| `data.cards.maiorValorEmAtraso` | number | sim | Maior valor individual entre os itens em atraso (uma parcela na fonte canônica; uma OS na legada), em reais. 0 quando não há itens. |
| `data.cards.clientesInadimplentes` | integer | sim | Quantidade de clientes distintos com item em atraso. Fonte canônica: título sem cliente vinculado conta como um "cliente" próprio por título (id sintético `OMIE:<app>:<codTitulo>`). |
| `data.graficos` | object | sim |  |
| `data.graficos.porDepartamento` | object[] | sim | Agrupado por departamento, ordenado por valor decrescente e depois por nome. |
| `data.graficos.porDepartamento[].departamento` | string | sim | Nome/descrição do departamento Omie, ou "Sem departamento". |
| `data.graficos.porDepartamento[].quantidadeItensAtrasados` | integer | sim | Itens em atraso do departamento. |
| `data.graficos.porDepartamento[].valorTotalEmAtraso` | number | sim | Valor em atraso do departamento, em reais. |
| `data.graficos.topDevedores` | object[] | sim | Os 10 clientes com maior valor em atraso (empate por nome). |
| `data.graficos.topDevedores[].clienteId` | string | sim | Id do cliente (UUID) ou id sintético `OMIE:<app>:<codTitulo>` para título sem cliente vinculado. |
| `data.graficos.topDevedores[].cliente` | string | sim | Nome do cliente. |
| `data.graficos.topDevedores[].quantidadeItensAtrasados` | integer | sim | Itens em atraso do cliente. |
| `data.graficos.topDevedores[].valorTotalEmAtraso` | number | sim | Valor em atraso do cliente, em reais. |
| `data.graficos.evolucaoPorMesVencimento` | object[] | sim | Itens agrupados pelo mês de vencimento, em ordem cronológica. Só meses com itens aparecem. |
| `data.graficos.evolucaoPorMesVencimento[].mes` | string | sim | Mês de vencimento `YYYY-MM` (UTC). |
| `data.graficos.evolucaoPorMesVencimento[].label` | string | sim | Rótulo `MM/YYYY`. |
| `data.graficos.evolucaoPorMesVencimento[].quantidadeItensAtrasados` | integer | sim | Itens em atraso que venceram no mês. |
| `data.graficos.evolucaoPorMesVencimento[].valorTotalEmAtraso` | number | sim | Valor em atraso dos itens que venceram no mês, em reais. |
| `data.graficos.matrizHistoricaAnoMes` | object | sim |  |
| `data.graficos.matrizHistoricaAnoMes.meses` | object[] | sim | Sempre os 12 meses fixos, Jan a Dez. |
| `data.graficos.matrizHistoricaAnoMes.meses[].mes` | integer | sim | Número do mês (1-12). |
| `data.graficos.matrizHistoricaAnoMes.meses[].key` | string — um de: `01`, `02`, `03`, `04`, `05`, `06`, `07`, `08`, `09`, `10`, `11`, `12` | sim | Chave `01`..`12`. |
| `data.graficos.matrizHistoricaAnoMes.meses[].label` | string | sim | Abreviação em português: Jan, Fev, Mar, Abr, Mai, Jun, Jul, Ago, Set, Out, Nov, Dez. |
| `data.graficos.matrizHistoricaAnoMes.anos` | object[] | sim | Uma linha por ano de vencimento com itens, em ordem crescente. |
| `data.graficos.matrizHistoricaAnoMes.anos[].ano` | integer | sim | Ano de vencimento. |
| `data.graficos.matrizHistoricaAnoMes.anos[].totalAno` | number | sim | Soma do ano, em reais. |
| `data.graficos.matrizHistoricaAnoMes.anos[].valoresPorMes` | object | sim | Valor em atraso por mês de vencimento; meses sem itens valem 0. |
| `data.graficos.matrizHistoricaAnoMes.anos[].valoresPorMes.10` | number | sim | Valor em atraso que venceu neste mês, em reais. |
| `data.graficos.matrizHistoricaAnoMes.anos[].valoresPorMes.11` | number | sim | Valor em atraso que venceu neste mês, em reais. |
| `data.graficos.matrizHistoricaAnoMes.anos[].valoresPorMes.12` | number | sim | Valor em atraso que venceu neste mês, em reais. |
| `data.graficos.matrizHistoricaAnoMes.anos[].valoresPorMes.01` | number | sim | Valor em atraso que venceu neste mês, em reais. |
| `data.graficos.matrizHistoricaAnoMes.anos[].valoresPorMes.02` | number | sim | Valor em atraso que venceu neste mês, em reais. |
| `data.graficos.matrizHistoricaAnoMes.anos[].valoresPorMes.03` | number | sim | Valor em atraso que venceu neste mês, em reais. |
| `data.graficos.matrizHistoricaAnoMes.anos[].valoresPorMes.04` | number | sim | Valor em atraso que venceu neste mês, em reais. |
| `data.graficos.matrizHistoricaAnoMes.anos[].valoresPorMes.05` | number | sim | Valor em atraso que venceu neste mês, em reais. |
| `data.graficos.matrizHistoricaAnoMes.anos[].valoresPorMes.06` | number | sim | Valor em atraso que venceu neste mês, em reais. |
| `data.graficos.matrizHistoricaAnoMes.anos[].valoresPorMes.07` | number | sim | Valor em atraso que venceu neste mês, em reais. |
| `data.graficos.matrizHistoricaAnoMes.anos[].valoresPorMes.08` | number | sim | Valor em atraso que venceu neste mês, em reais. |
| `data.graficos.matrizHistoricaAnoMes.anos[].valoresPorMes.09` | number | sim | Valor em atraso que venceu neste mês, em reais. |
| `data.graficos.serieHistoricaAnoMes` | object[] | sim | Mesma informação da matriz, em série por ano (12 pontos por ano). |
| `data.graficos.serieHistoricaAnoMes[].ano` | integer | sim | Ano de vencimento. |
| `data.graficos.serieHistoricaAnoMes[].totalAno` | number | sim | Soma do ano, em reais. |
| `data.graficos.serieHistoricaAnoMes[].pontos` | object[] | sim |  |
| `data.graficos.serieHistoricaAnoMes[].pontos[].mes` | integer | sim | Número do mês (1-12). |
| `data.graficos.serieHistoricaAnoMes[].pontos[].key` | string — um de: `01`, `02`, `03`, `04`, `05`, `06`, `07`, `08`, `09`, `10`, `11`, `12` | sim | Chave `01`..`12`. |
| `data.graficos.serieHistoricaAnoMes[].pontos[].label` | string | sim | Abreviação do mês. |
| `data.graficos.serieHistoricaAnoMes[].pontos[].valorTotalEmAtraso` | number | sim | Valor em atraso que venceu no mês, em reais. |

Exemplo (dados fictícios):

```json
{
  "data": {
    "cards": {
      "quantidadeItensAtrasados": 7,
      "valorTotalEmAtraso": 31250.5,
      "maiorValorEmAtraso": 12000,
      "clientesInadimplentes": 4
    },
    "graficos": {
      "porDepartamento": [
        {
          "departamento": "Serviços",
          "quantidadeItensAtrasados": 5,
          "valorTotalEmAtraso": 26000.5
        },
        {
          "departamento": "Sem departamento",
          "quantidadeItensAtrasados": 2,
          "valorTotalEmAtraso": 5250
        }
      ],
      "topDevedores": [
        {
          "clienteId": "0b6a1d52-3f0e-4c6a-9d0e-5a1f2f6d7a11",
          "cliente": "Empresa Alfa Ltda",
          "quantidadeItensAtrasados": 3,
          "valorTotalEmAtraso": 16500
        }
      ],
      "evolucaoPorMesVencimento": [
        {
          "mes": "2026-09",
          "label": "09/2026",
          "quantidadeItensAtrasados": 4,
          "valorTotalEmAtraso": 20250.5
        },
        {
          "mes": "2026-10",
          "label": "10/2026",
          "quantidadeItensAtrasados": 3,
          "valorTotalEmAtraso": 11000
        }
      ],
      "matrizHistoricaAnoMes": {
        "meses": [
          {
            "mes": 1,
            "key": "01",
            "label": "Jan"
          },
          {
            "mes": 2,
            "key": "02",
            "label": "Fev"
          },
          {
            "mes": 3,
            "key": "03",
            "label": "Mar"
          },
          {
            "mes": 4,
            "key": "04",
            "label": "Abr"
          },
          {
            "mes": 5,
            "key": "05",
            "label": "Mai"
          },
          {
            "mes": 6,
            "key": "06",
            "label": "Jun"
          },
          {
            "mes": 7,
            "key": "07",
            "label": "Jul"
          },
          {
            "mes": 8,
            "key": "08",
            "label": "Ago"
          },
          {
            "mes": 9,
            "key": "09",
            "label": "Set"
          },
          {
            "mes": 10,
            "key": "10",
            "label": "Out"
          },
          {
            "mes": 11,
            "key": "11",
            "label": "Nov"
          },
          {
            "mes": 12,
            "key": "12",
            "label": "Dez"
          }
        ],
        "anos": [
          {
            "ano": 2026,
            "totalAno": 31250.5,
            "valoresPorMes": {
              "10": 11000,
              "11": 0,
              "12": 0,
              "01": 0,
              "02": 0,
              "03": 0,
              "04": 0,
              "05": 0,
              "06": 0,
              "07": 0,
              "08": 0,
              "09": 20250.5
            }
          }
        ]
      },
      "serieHistoricaAnoMes": [
        {
          "ano": 2026,
          "totalAno": 31250.5,
          "pontos": [
            {
              "mes": 9,
              "key": "09",
              "label": "Set",
              "valorTotalEmAtraso": 20250.5
            },
            {
              "mes": 10,
              "key": "10",
              "label": "Out",
              "valorTotalEmAtraso": 11000
            }
          ]
        }
      ]
    }
  }
}
```

#### Erros

- **400**: Parâmetros inválidos. `message` é uma lista com um item por problema, no formato `campo: motivo`.
- **401**: Token ausente, inválido, expirado ou de usuário desativado. Faça login de novo.
- **403**: O usuário do token não tem a permissão exigida pela rota.

---

### GET /financeiro/inadimplencia/itens

**Itens (linhas) em atraso do BI de inadimplência, paginados** · operationId `listarItensInadimplencia`

Autenticação: `Authorization: Bearer <token>`.

Lista paginada das **linhas** inadimplentes. Na fonte canônica uma linha agrupa todas as parcelas em atraso da mesma OS (`OS:<id>`) ou, sem OS, um título (`TITLE:<app>:<cod>`); o valor da linha é a soma dos saldos e o vencimento é o mais antigo. Cada linha traz o detalhamento das parcelas, da OS, do contrato e do projeto.

Valores em **reais**; datas de calendário `YYYY-MM-DD`; resposta em `{ "data": { items, pagination } }`.

**Ordenação** (`sortBy`/`sortOrder`, padrão `vencimento` ascendente, ou seja, o mais antigo primeiro). O desempate é sempre vencimento mais antigo e depois a chave da linha. `sortBy=diasAtraso` com `asc` devolve primeiro os com menos dias de atraso, nas duas fontes.

**Filtros em lista:** valores separados por vírgula ou parâmetro repetido; texto vazio e segmentos vazios (`a,,b`) são ignorados; o texto `null` **não** é ignorado (vira um valor literal no filtro de lista e, em datas, `incluirIgnoradas`, `page` e `pageSize`, responde 400).

### Como a inadimplência é calculada

A pergunta respondida é "quanto a organização tem a receber, já vencido e não pago, de títulos faturados".
Os números saem da fila de **recebíveis do Omie** sincronizados no AgendAI (`omie_receivable`), não de um cálculo sobre a agenda.
Tudo é restrito à organização (tenant) do token.

**Duas fontes de dados (a organização cai em uma delas):**

- **Canônica** (a fonte atual): usada quando a organização tem ao menos um cadastro Omie ativo e **todos** os cadastros ativos terminaram a carga inicial de recebíveis (fase `READY`). Cada título/parcela do Omie é um recebível.
- **Legada**: usada quando não há cadastro Omie ativo, ou algum cadastro ainda está em carga (`BACKFILL_PENDING`) ou falhou (`BACKFILL_FAILED`). Nesse caso a base é a **ordem de serviço** (OS) em vez do título: OS com status `BOLETO_GERADO` ou `FATURADA`, valor total > 0, **uma única parcela**, vencimento anterior ao início do dia (UTC), de projeto não excluído, com `naoFaturarFinanceiro = false`, de tipo de projeto pós-pago elegível ao financeiro **ou sem tipo de projeto** e com cliente vinculado. O valor em atraso é o valor total da OS.
- A resposta não diz qual fonte foi usada, exceto pelos itens: na fonte legada `origem = "Legado"`, `omieTenantAppId = null`, `rowKey = "OS:<id>"` e `detalhe.parcelas = []`.

**O que entra (fonte canônica)** — um recebível só conta se **todas** as condições valem:

1. O cadastro Omie dele (`omie_tenant_app`) está **ativo**. Cadastro Omie inativo (por exemplo empresa baixada) sai da inadimplência; reativar devolve os títulos.
2. O estado é `OPEN` (em aberto) ou `PARTIALLY_PAID` (parcialmente pago) e o saldo em aberto (`open_amount`) é maior que zero. Títulos liquidados (`SETTLED`) e cancelados não entram.
3. A **data de vencimento efetiva** é anterior ao início do dia de hoje em Brasília (00:00 BRT). A data efetiva é a mais tardia entre o vencimento (`dDtVenc`) e a previsão de recebimento (`dDtPrevisao`) do Omie: um título vencido cujo recebimento foi reprogramado para o futuro não conta. Os filtros `dataVencimento*` e o campo `vencimento` usam essa mesma data. Título com data efetiva hoje ainda não é inadimplente.
4. O título tem **número de documento fiscal** preenchido (isto é, a nota foi emitida).
5. O tipo de documento **não** é `REE`, `DAM` nem `99999` (sem diferenciar maiúsculas de minúsculas).
6. Salvo `incluirIgnoradas=true`: a OS do título **não** tem regra de "inadimplência ignorada" ativa e o contrato (direto ou herdado da OS) também não. Essas regras são cadastradas no módulo de inadimplência (`inadimplencia_ignorada`, alvo `ORDEM_SERVICO` ou `CONTRATO`).
7. Os filtros da consulta (empresa Omie, cliente, projeto, produto, tipo de projeto, departamento, categoria, tipo de documento, intervalo de vencimento).

Overrides de status e regras de inadimplência por cliente/projeto (módulo `inadimplencia-status`/`inadimplencia-regras`) **não** influenciam estas três rotas; só as regras de "ignorada" acima entram no cálculo.

**Valores:** reais (BRL), números JSON com 2 casas (não centavos, não string).
**Datas:** `vencimento` e demais datas de calendário são `YYYY-MM-DD`.
**Dias de atraso:** dias inteiros entre o vencimento (o mais antigo, no caso de linha com várias parcelas) e hoje; 0 se não vencido.

**Permissão:** capacidade `VER_BI_INADIMPLENCIA`. Sem ela a resposta é 403. Em geral: administrador global, administrador do tipo Financeiro, ou usuário com a tela `/financeiro/inadimplencia` liberada nas permissões de tela (lida do banco a cada requisição, então revogação vale na hora). Com a regra de acesso por setor ligada na organização, vale somente a tela efetiva do usuário. Não há filtro por registros: quem passa vê todos os dados da organização.

#### Parâmetros

| Nome | Onde | Tipo | Obrigatório | Descrição |
|---|---|---|---|---|
| `empresaOmie` | query | integer[] | não | Ids dos cadastros Omie (`omie_tenant_app`) da organização. Aceita parâmetro repetido (`?empresaOmie=1&empresaOmie=2`) ou lista separada por vírgula (`empresaOmie=1,2`); valores duplicados são descartados. Só tem efeito na fonte canônica; na fonte legada qualquer valor aqui zera o resultado. Os ids válidos vêm de `filter-options/empresaOmie`. Ex.: `[1]` |
| `cliente` | query | string[] | não | Clientes. Fonte canônica: ids (UUID) do cliente ou o texto exato do campo `cliente` dos itens (nome fantasia; senão a empresa do projeto; senão o nome no Omie; ou `Sem cliente vinculado`); os dois formatos podem ser misturados. Fonte legada: somente o nome fantasia. Mesmo formato de lista de `empresaOmie` (repetido ou separado por vírgula; por isso um nome com vírgula não pode ser filtrado). Na fonte canônica use o `id` de `filter-options/cliente`; na legada, o `label`. Ex.: `["0b6a1d52-3f0e-4c6a-9d0e-5a1f2f6d7a11"]` |
| `projeto` | query | string[] | não | Projetos. Fonte canônica: ids (UUID) ou nome do projeto; fonte legada: nome. Mesmo formato de lista. Na fonte canônica use o `id` de `filter-options/projeto`; na legada, o `label`. Ex.: `["Implantação Alfa"]` |
| `produto` | query | string[] | não | Produtos (id do produto). Fonte canônica: casa o título pela categoria Omie mapeada ao produto (`omie_tenant_billing_mapping` ativo). Na fonte legada qualquer valor aqui zera o resultado. Ids em `filter-options/produto`. Ex.: `["5f0c1e7a-8d2b-4a39-b0c4-1e2d3c4b5a69"]` |
| `tipoProjeto` | query | string[] | não | Tipos de projeto. Fonte canônica: id do tipo de projeto; fonte legada: nome do tipo (`Sem tipo de projeto` seleciona os projetos sem tipo). Na fonte canônica use o `id` de `filter-options/tipoProjeto`; na legada, o `label`. Ex.: `["a1b2c3d4-0000-4000-8000-000000000001"]` |
| `departamento` | query | string[] | não | Departamentos. Fonte canônica: código do departamento Omie (`SEM_DEPARTAMENTO` para títulos sem roteamento de departamento); fonte legada: nome/descrição do departamento (`Sem departamento` quando vazio). Na fonte canônica use o `id` de `filter-options/departamento`; na legada, o `label`. Ex.: `["SEM_DEPARTAMENTO"]` |
| `categoria` | query | string[] | não | Códigos de categoria Omie do título (`category_code`). Só tem efeito na fonte canônica; na legada qualquer valor zera o resultado. Códigos em `filter-options/categoria`. Ex.: `["1.01.02"]` |
| `tipoDocumento` | query | string[] | não | Tipos de documento Omie do título (`BOL`, `REC`, `TED`...). Só tem efeito na fonte canônica; na legada qualquer valor zera o resultado. Códigos em `filter-options/tipoDocumento`. Ex.: `["BOL"]` |
| `dataVencimentoInicio` | query | string (date) | não | Vencimento mínimo, inclusivo, no formato `YYYY-MM-DD` (data de calendário válida). Fonte canônica: o dia começa à 00:00 de Brasília (03:00Z). Fonte legada: dia em UTC. Texto vazio é ignorado. Ex.: `2026-01-01` |
| `dataVencimentoFim` | query | string (date) | não | Vencimento máximo, inclusivo, `YYYY-MM-DD`. Deve ser maior ou igual a `dataVencimentoInicio` (senão 400). Como só entram parcelas vencidas antes de hoje, valores futuros não ampliam o resultado. Ex.: `2026-10-31` |
| `incluirIgnoradas` | query | boolean; padrão `false` | não | Aceita `true` ou `false`. Padrão (omitido ou `false`): ordens de serviço e contratos com regra de "ignorada" ativa ficam fora. Com `true` eles entram nos números. Ex.: `false` |
| `page` | query | integer; padrão `1`; mín. 1 | não | Página, base 1 (mínimo 1; 400 se menor). Texto vazio vale o padrão. Ex.: `1` |
| `pageSize` | query | integer; padrão `20`; mín. 1; máx. 100 | não | Linhas por página (1 a 100; 400 fora disso). Ex.: `20` |
| `sortBy` | query | string — um de: `vencimento`, `diasAtraso`, `valorEmAtraso`, `cliente`, `projeto`, `departamento`, `ordemServico`, `contrato`, `produto`, `tipoProjeto`; padrão `"vencimento"` | não | Campo de ordenação. `ordemServico` ordena número de OS só de dígitos como número e o resto como texto; `contrato` pelo rótulo do contrato; textos ausentes vão ao fim nos dois sentidos. Ex.: `vencimento` |
| `sortOrder` | query | string — um de: `asc`, `desc`; padrão `"asc"` | não | Sentido da ordenação. Ex.: `asc` |

#### Resposta 200

Página de itens em atraso.

Tipo da raiz: InadimplenciaItensResponse

| Campo | Tipo | Sempre presente | Descrição |
|---|---|---|---|
| `data` | object | sim |  |
| `data.items` | InadimplenciaItem[] | sim |  |
| `data.items[].rowKey` | string | sim | Chave estável da linha: `OS:<id da OS>` (títulos ligados a uma OS são agrupados em uma linha) ou `TITLE:<omieTenantAppId>:<codTituloOmie>` (título sem OS). Em casos raros (títulos da mesma OS ligados a projeto, cliente ou contrato diferentes) a mesma chave pode aparecer em mais de uma linha; nesse caso cada linha traz todas as parcelas da OS em `detalhe.parcelas` e a soma delas pode não bater com `valorEmAtraso`. |
| `data.items[].omieTenantAppId` | integer \| null | sim | Id do cadastro Omie de origem. `null` na fonte legada. |
| `data.items[].origem` | string | sim | Apelido do cadastro Omie (ou `Omie app <id>`); "Legado" na fonte legada. |
| `data.items[].codTituloOmie` | string \| null | sim | Código do título no Omie; preenchido só em linha sem OS. |
| `data.items[].cpfCnpjCliente` | string \| null | sim | CPF/CNPJ do cliente no recebível (dado pessoal, sem máscara garantida). `null` na fonte legada. |
| `data.items[].ordemServicoId` | integer \| null | sim | Id interno da OS. |
| `data.items[].ordemServicoNumero` | string \| null | sim | Número da OS. |
| `data.items[].codOsOmie` | string \| null | sim | Código da OS no Omie. |
| `data.items[].contratoId` | integer \| null | sim | Id interno do contrato vinculado. |
| `data.items[].contratoLabel` | string | sim | Rótulo do contrato (ver `detalhe.contrato.label`). |
| `data.items[].clienteId` | string \| null | sim | Id do cliente (UUID). |
| `data.items[].cliente` | string | sim | Nome do cliente (nome fantasia; senão a empresa do projeto; senão o nome vindo do Omie; senão "Sem cliente vinculado" na canônica / "Cliente não identificado" na legada). |
| `data.items[].projetoId` | string \| null | sim | Id do projeto (UUID). |
| `data.items[].projeto` | string | sim | Nome do projeto; `Projeto <id>` se o projeto não tem nome; "Sem projeto vinculado" sem projeto (só canônica). |
| `data.items[].produtoId` | string \| null | sim | Id do produto (UUID). |
| `data.items[].produto` | string | sim | Nome do produto ou "Sem produto". |
| `data.items[].tipoProjetoId` | string \| null | sim | Id do tipo de projeto. |
| `data.items[].tipoProjeto` | string | sim | Nome do tipo de projeto ou "Sem tipo de projeto". |
| `data.items[].departamento` | string | sim | Departamento ou "Sem departamento". |
| `data.items[].tipoDocumento` | string \| null | sim | Tipos de documento Omie dos títulos da linha, distintos e separados por ", " (ex.: `BOL, REC`). `null` na fonte legada. |
| `data.items[].status` | string | sim | Canônica: `OPEN`. Legada: `BOLETO_GERADO` ou `FATURADA`. |
| `data.items[].statusDescricao` | string | sim | Canônica: "Recebível em aberto". Legada: descrição do status da OS. |
| `data.items[].vencimento` | string (date) | sim | Vencimento mais antigo entre as parcelas da linha, `YYYY-MM-DD`. Usa a data de vencimento efetiva (a mais tardia entre o vencimento e a previsão de recebimento do Omie). |
| `data.items[].diasAtraso` | integer | sim | Dias inteiros de atraso a partir do vencimento mais antigo da linha. |
| `data.items[].valorEmAtraso` | number | sim | Soma do saldo em aberto das parcelas da linha que passam nos filtros, em reais. |
| `data.items[].historico` | boolean | sim | `true` quando o projeto foi excluído (soft delete) ou o cliente está inativo; o item continua devendo, mas é "histórico" no catálogo. Sempre `false` na fonte legada. |
| `data.items[].catalogoAusente` | boolean | sim | `true` quando cliente, produto ou tipo de projeto referenciado não existe, foi excluído ou (cliente) não é mais da relação CLIENTE. Sempre `false` na fonte legada. |
| `data.items[].detalhe` | object | sim |  |
| `data.items[].detalhe.tipoDocumento` | string \| null | sim | Igual a `tipoDocumento`. |
| `data.items[].detalhe.parcelas` | InadimplenciaParcela[] | sim | Parcelas em atraso da linha (vazio na fonte legada). |
| `data.items[].detalhe.parcelas[].codTituloOmie` | string | sim | Código do título no Omie. |
| `data.items[].detalhe.parcelas[].numero` | string \| null | sim | Número da parcela (por exemplo `1/3`), quando existe. |
| `data.items[].detalhe.parcelas[].vencimento` | string (date) | sim | Vencimento da parcela, `YYYY-MM-DD`. Usa a data de vencimento efetiva (a mais tardia entre o vencimento e a previsão de recebimento do Omie). |
| `data.items[].detalhe.parcelas[].valorOriginal` | number | sim | Valor original da parcela, em reais. |
| `data.items[].detalhe.parcelas[].valorEmAberto` | number | sim | Saldo em aberto da parcela, em reais. |
| `data.items[].detalhe.parcelas[].estado` | string — um de: `OPEN`, `PARTIALLY_PAID` | sim | `OPEN` (em aberto) ou `PARTIALLY_PAID` (parcialmente paga). |
| `data.items[].detalhe.parcelas[].ultimaSincronizacao` | string (date-time) | sim | Instante (ISO 8601, UTC) da última sincronização do recebível com o Omie. |
| `data.items[].detalhe.parcelas[].compoeTotalFiltrado` | boolean | sim | Sempre `true`: toda parcela devolvida compõe o total filtrado. |
| `data.items[].detalhe.ordemServico` | InadimplenciaOrdemServicoDetalhe \| qualquer \| null | sim | `null` quando a linha é de um título sem OS. |
| `data.items[].detalhe.contrato` | InadimplenciaContratoDetalhe | sim |  |
| `data.items[].detalhe.contrato.existeVinculo` | boolean | sim | `false` quando a linha não tem contrato vinculado (então `label` = "Sem contrato vinculado"). |
| `data.items[].detalhe.contrato.id` | integer \| null | sim | Id interno do contrato de serviço. |
| `data.items[].detalhe.contrato.numero` | string \| null | sim | Número do contrato (`numCtr`). |
| `data.items[].detalhe.contrato.label` | string | sim | Rótulo para exibição: número do contrato, senão código Omie, senão `Contrato #<id>`; "Sem contrato vinculado" sem vínculo. |
| `data.items[].detalhe.contrato.codCtrOmie` | string \| null | sim | Código do contrato no Omie. |
| `data.items[].detalhe.contrato.situacao` | string \| null | sim | Situação do contrato. Só preenchido na fonte legada; sempre `null` na canônica. |
| `data.items[].detalhe.contrato.descStatus` | string \| null | sim | Descrição do status do contrato. Só na fonte legada. |
| `data.items[].detalhe.contrato.vigenciaInicio` | string (date) \| null | sim | Início da vigência, `YYYY-MM-DD`. Só na fonte legada. |
| `data.items[].detalhe.contrato.vigenciaFim` | string (date) \| null | sim | Fim da vigência, `YYYY-MM-DD`. Só na fonte legada. |
| `data.items[].detalhe.contrato.valorTotalMensal` | number \| null | sim | Valor mensal total do contrato, em reais. Só na fonte legada. |
| `data.items[].detalhe.projeto` | InadimplenciaProjetoDetalhe \| qualquer \| null | sim | `null` quando não há projeto vinculado. |
| `data.pagination` | object | sim |  |
| `data.pagination.page` | integer | sim | Página atual (base 1). |
| `data.pagination.pageSize` | integer | sim | Tamanho da página. |
| `data.pagination.total` | integer | sim | Total de **linhas** (grupos por OS ou título) que passam nos filtros. Na fonte canônica, quando `page` passa da última página, vem `0` (e `totalPages` = 0); para paginar, pare quando `items` vier com menos de `pageSize` linhas ou quando `page >= totalPages` da página anterior. |
| `data.pagination.totalPages` | integer | sim | Total de páginas; 0 quando não há linhas. |

Exemplo (dados fictícios):

```json
{
  "data": {
    "items": [
      {
        "rowKey": "OS:48213",
        "omieTenantAppId": 3,
        "origem": "Empresa Alfa Serviços",
        "codTituloOmie": null,
        "cpfCnpjCliente": "12345678000190",
        "ordemServicoId": 48213,
        "ordemServicoNumero": "000412",
        "codOsOmie": "7001234567",
        "contratoId": 912,
        "contratoLabel": "CTR-0091",
        "clienteId": "0b6a1d52-3f0e-4c6a-9d0e-5a1f2f6d7a11",
        "cliente": "Empresa Alfa Ltda",
        "projetoId": "7e3d1c20-9a54-4d3b-8f21-0c6b5a4d3e22",
        "projeto": "Implantação Alfa",
        "produtoId": "5f0c1e7a-8d2b-4a39-b0c4-1e2d3c4b5a69",
        "produto": "Plataforma Exemplo",
        "tipoProjetoId": "a1b2c3d4-0000-4000-8000-000000000001",
        "tipoProjeto": "Implantação",
        "departamento": "Serviços",
        "tipoDocumento": "BOL",
        "status": "OPEN",
        "statusDescricao": "Recebível em aberto",
        "vencimento": "2026-09-10",
        "diasAtraso": 62,
        "valorEmAtraso": 4500,
        "historico": false,
        "catalogoAusente": false,
        "detalhe": {
          "tipoDocumento": "BOL",
          "parcelas": [
            {
              "codTituloOmie": "9988776655",
              "numero": "1/1",
              "vencimento": "2026-09-10",
              "valorOriginal": 4500,
              "valorEmAberto": 4500,
              "estado": "OPEN",
              "ultimaSincronizacao": "2026-11-11T09:30:00.000Z",
              "compoeTotalFiltrado": true
            }
          ],
          "ordemServico": {
            "id": 48213,
            "numero": "000412",
            "codOsOmie": "7001234567",
            "status": "OPEN",
            "statusDescricao": "Recebível em aberto",
            "vencimento": "2026-09-10",
            "dataFaturamento": null,
            "diasAtraso": 62,
            "valorEmAtraso": 4500,
            "quantidadeParcelas": 1,
            "parcelas": [
              {
                "codTituloOmie": "9988776655",
                "numero": "1/1",
                "vencimento": "2026-09-10",
                "valorOriginal": 4500,
                "valorEmAberto": 4500,
                "estado": "OPEN",
                "ultimaSincronizacao": "2026-11-11T09:30:00.000Z",
                "compoeTotalFiltrado": true
              }
            ]
          },
          "contrato": {
            "existeVinculo": true,
            "id": 912,
            "numero": "CTR-0091",
            "label": "CTR-0091",
            "codCtrOmie": "6001122334",
            "situacao": null,
            "descStatus": null,
            "vigenciaInicio": null,
            "vigenciaFim": null,
            "valorTotalMensal": null
          },
          "projeto": {
            "id": "7e3d1c20-9a54-4d3b-8f21-0c6b5a4d3e22",
            "nome": "Implantação Alfa",
            "clienteId": "0b6a1d52-3f0e-4c6a-9d0e-5a1f2f6d7a11",
            "cliente": "Empresa Alfa Ltda",
            "produtoId": "5f0c1e7a-8d2b-4a39-b0c4-1e2d3c4b5a69",
            "produto": "Plataforma Exemplo",
            "tipoProjetoId": "a1b2c3d4-0000-4000-8000-000000000001",
            "tipoProjeto": "Implantação",
            "departamento": "Serviços"
          }
        }
      }
    ],
    "pagination": {
      "page": 1,
      "pageSize": 20,
      "total": 1,
      "totalPages": 1
    }
  }
}
```

#### Erros

- **400**: Parâmetros inválidos. `message` é uma lista com um item por problema, no formato `campo: motivo`.
- **401**: Token ausente, inválido, expirado ou de usuário desativado. Faça login de novo.
- **403**: O usuário do token não tem a permissão exigida pela rota.

---

### GET /financeiro/inadimplencia/filter-options/{dimension}

**Catálogo paginado de opções para um filtro da inadimplência** · operationId `listarOpcoesFiltroInadimplencia`

Autenticação: `Authorization: Bearer <token>`.

Devolve as opções (id + rótulo) que alimentam um filtro das rotas `/resumo` e `/itens`. O catálogo é da organização inteira (não só de quem está inadimplente hoje) e, na fonte canônica, `id` é o valor que os filtros esperam. Na fonte legada (itens com `origem = "Legado"`), `cliente`, `projeto`, `tipoProjeto` e `departamento` filtram por nome: envie o `label` em vez do `id`; `empresaOmie`, `produto`, `categoria` e `tipoDocumento` zeram o resultado na fonte legada.

**Dimensões aceitas** (`dimension`): `empresaOmie`, `cliente`, `projeto`, `produto`, `tipoProjeto`, `departamento`, `categoria`, `tipoDocumento`. Outro valor responde 400.

O que cada uma lista:
- `empresaOmie`: cadastros Omie; id numérico em texto, rótulo = apelido (ou `Omie app <id>`).
- `cliente`: empresas com relação CLIENTE, não excluídas e com nome fantasia; id UUID.
- `projeto`: projetos com nome; id UUID.
- `produto` e `tipoProjeto`: id UUID, rótulo = nome.
- `departamento`: departamentos do roteamento Omie; id = código do departamento Omie. `SEM_DEPARTAMENTO` (títulos sem roteamento) pode ser enviado no filtro mesmo quando não aparece na lista; ele só é listado quando algum roteamento tem código vazio (e esse caso não casa no filtro).
- `categoria`: códigos de categoria Omie existentes nos recebíveis; id = código, rótulo = "código - descrição" quando mapeada.
- `tipoDocumento`: tipos de documento existentes nos recebíveis (exceto `REE`, `DAM`, `99999`); id = código, rótulo traduzido (ex.: `BOL - Boleto`).

Só entram opções **ativas**; inativas ou excluídas só aparecem se o id vier em `selectedId` (para mostrar uma seleção que ficou obsoleta; `availability` diz o estado). Ordem: rótulo (sem diferenciar caixa) e depois id.

**Paginação por cursor:** envie `limit` e, para a página seguinte, o `nextCursor` recebido em `cursor`. Há mais páginas quando `hasMore=true`. Cursor adulterado responde 400 ("Cursor de catálogo inválido.").

**Busca:** `q` filtra por trecho do rótulo, sem diferenciar maiúsculas (os caracteres `%` e `_` valem como curingas do SQL `LIKE`).

**Permissão:** a mesma das demais rotas de inadimplência (capacidade `VER_BI_INADIMPLENCIA`): administrador global, administrador Financeiro ou tela `/financeiro/inadimplencia` liberada; senão 403. Resposta em `{ "data": { items, hasMore, nextCursor } }`.

#### Parâmetros

| Nome | Onde | Tipo | Obrigatório | Descrição |
|---|---|---|---|---|
| `dimension` | path | string — um de: `empresaOmie`, `cliente`, `projeto`, `produto`, `tipoProjeto`, `departamento`, `categoria`, `tipoDocumento` | sim | Dimensão do catálogo. Ex.: `cliente` |
| `q` | query | string | não | Busca por trecho do rótulo (1 a 120 caracteres após aparar espaços). Vazio é ignorado; só espaços responde 400. Ex.: `Alfa` |
| `cursor` | query | string | não | Cursor opaco devolvido em `nextCursor` (1 a 512 caracteres). |
| `limit` | query | integer; padrão `25`; mín. 1; máx. 50 | não | Itens por página (1 a 50); vazio, não inteiro ou fora disso responde 400. Ex.: `25` |
| `selectedId` | query | string[] | não | Ids já selecionados; trazem de volta opções inativas (empresa Omie, cliente, produto, tipo de projeto) ou projetos excluídos (cliente excluído nunca volta). Sem efeito em `departamento`, `categoria` e `tipoDocumento`. Repetido ou separado por vírgula; cada id com até 120 caracteres. Ex.: `["0b6a1d52-3f0e-4c6a-9d0e-5a1f2f6d7a11"]` |

#### Resposta 200

Página do catálogo.

Tipo da raiz: InadimplenciaOpcoesFiltroResponse

| Campo | Tipo | Sempre presente | Descrição |
|---|---|---|---|
| `data` | object | sim |  |
| `data.items` | InadimplenciaOpcaoFiltro[] | sim |  |
| `data.items[].id` | string | sim | Valor a enviar no filtro correspondente da consulta. |
| `data.items[].label` | string | sim | Rótulo para exibição. |
| `data.items[].availability` | string — um de: `ACTIVE`, `INACTIVE`, `DELETED_HISTORICAL` | sim | `ACTIVE`, `INACTIVE` (cadastro inativo) ou `DELETED_HISTORICAL` (projeto excluído). Opções não ativas só aparecem quando seu id foi pedido em `selectedId`. |
| `data.hasMore` | boolean | sim | `true` se há mais opções após esta página. |
| `data.nextCursor` | string \| null | sim | Cursor opaco para a próxima página; `null` na última. |

Exemplo (dados fictícios):

```json
{
  "data": {
    "items": [
      {
        "id": "0b6a1d52-3f0e-4c6a-9d0e-5a1f2f6d7a11",
        "label": "Empresa Alfa Ltda",
        "availability": "ACTIVE"
      },
      {
        "id": "3c9e8f10-1111-4222-8333-444455556666",
        "label": "Empresa Beta S.A.",
        "availability": "ACTIVE"
      }
    ],
    "hasMore": true,
    "nextCursor": "eyJsYWJlbCI6ImVtcHJlc2EgYmV0YSBzLmEuIiwiaWQiOiIzYzllOGYxMC0xMTExLTQyMjItODMzMy00NDQ0NTU1NTY2NjYifQ"
  }
}
```

#### Erros

- **400**: Parâmetros inválidos. `message` é uma lista com um item por problema, no formato `campo: motivo`.
- **401**: Token ausente, inválido, expirado ou de usuário desativado. Faça login de novo.
- **403**: O usuário do token não tem a permissão exigida pela rota.
