Saldo Acumulado
Endpoints da WebApiAlcance para gerenciar saldos acumulados - o saldo tributário acumulado de um contribuinte por tributo (ex.: valores abaixo do mínimo de recolhimento de R$ 10,00 que ficam retidos até atingir o piso). Cada saldo é identificado pela chave funcional (cnpj, tributo) no contexto do usuário autenticado (multi-tenant). Cobrem criação, upsert idempotente, listagem com filtros, detalhamento por ID, atualização e soft delete.
Todos os endpoints exigem autenticação. Veja Autenticação para o fluxo de API Key. O Swagger oficial está em api.contabilidadealcance.com.br/docs.
Base path
/api/v1/saldos-acumuladosEscopos necessários
saldos_acumulados:read- listagem e detalhamentosaldos_acumulados:write- criação, upsert, atualização e soft delete
O escopo é derivado da rota: o prefixo público /saldos-acumulados vira o recurso saldos_acumulados (hífen → underscore), e o método HTTP define a ação (read para GET, write para POST/PUT/DELETE).
Endpoints
POST /saldos-acumulados/
Cria um novo saldo acumulado vinculado ao usuário autenticado. O id_usuario_created é preenchido a partir do usuário logado - não é aceito no body.
Parâmetros
Este endpoint não recebe parâmetros de rota ou query - os dados vão no corpo da requisição (SaldoAcumuladoCreate): cnpj, tributo, saldo e mes_referencia (todos obrigatórios).
Request
{
"cnpj": "12345678000190",
"tributo": "pis",
"saldo": "8.45",
"mes_referencia": "2026-05"
}Response 201 Created
{
"success": true,
"message": "Saldo acumulado criado com sucesso!",
"data": {
"id": 1,
"cnpj": "12345678000190",
"tributo": "pis",
"saldo": "8.45",
"mes_referencia": "2026-05",
"id_usuario_created": 42,
"id_usuario_updated": null,
"created_at": "2026-05-31T12:00:00Z",
"updated_at": "2026-05-31T12:00:00Z",
"deleted_at": null
}
}Já existir saldo para (usuário, cnpj, tributo) retorna 409 Conflict (use POST /saldos-acumulados/upsert para idempotência); falhas de validação retornam 422 Unprocessable Entity. Escopo: saldos_acumulados:write
POST /saldos-acumulados/upsert
Cria ou atualiza o saldo pela chave funcional (cnpj, tributo) do usuário autenticado - idempotente. Se o saldo já existe, atualiza saldo e mes_referencia; caso contrário, cria. Saldos em soft delete são "ressuscitados" (deleted_at limpo) e atualizados.
Parâmetros
Este endpoint não recebe parâmetros de rota ou query - os dados vão no corpo da requisição (SaldoAcumuladoUpsert), com os mesmos campos de SaldoAcumuladoCreate (cnpj, tributo, saldo, mes_referencia).
Request
{
"cnpj": "12345678000190",
"tributo": "pis",
"saldo": "9.10",
"mes_referencia": "2026-06"
}Response 200 OK
{
"success": true,
"message": "Saldo acumulado upserted!",
"data": {
"id": 1,
"cnpj": "12345678000190",
"tributo": "pis",
"saldo": "9.10",
"mes_referencia": "2026-06",
"id_usuario_created": 42,
"id_usuario_updated": 42,
"created_at": "2026-05-31T12:00:00Z",
"updated_at": "2026-06-30T12:00:00Z",
"deleted_at": null
}
}Escopo: saldos_acumulados:write
GET /saldos-acumulados/
Lista os saldos acumulados do usuário autenticado, com filtros e paginação opcionais. Lista vazia é um estado válido - sempre retorna 200 OK, inclusive com data: [] e a mensagem "Nenhum saldo acumulado encontrado.".
Parâmetros
| Parâmetro | Tipo | Local | Obrigatório | Descrição |
|---|---|---|---|---|
cnpj | str | query | não | Filtro por CNPJ (14 dígitos, sem máscara). |
tributo | str | query | não | Filtro por tributo. Aceita: pis, cofins, irpj, csll. |
page | int | query | não | Página 1-based (>= 1). |
per_page | int | query | não | Itens por página (1..500). |
Request
Sem corpo de requisição.
Response 200 OK
{
"success": true,
"message": "Saldos recuperados com sucesso!",
"data": [
{
"id": 1,
"cnpj": "12345678000190",
"tributo": "pis",
"saldo": "8.45",
"mes_referencia": "2026-05",
"id_usuario_created": 42,
"id_usuario_updated": null,
"created_at": "2026-05-31T12:00:00Z",
"updated_at": "2026-05-31T12:00:00Z",
"deleted_at": null
}
]
}Escopo: saldos_acumulados:read
GET /saldos-acumulados/{saldo_id}
Detalha um saldo acumulado do usuário autenticado pelo ID inteiro. Quando não encontrado (ou pertencente a outro usuário), retorna 404 Not Found.
Parâmetros
| Parâmetro | Tipo | Local | Obrigatório | Descrição |
|---|---|---|---|---|
saldo_id | int | path | sim | ID interno do saldo |
Request
Sem corpo de requisição.
Response 200 OK
{
"success": true,
"message": "Saldo acumulado encontrado!",
"data": {
"id": 1,
"cnpj": "12345678000190",
"tributo": "pis",
"saldo": "8.45",
"mes_referencia": "2026-05",
"id_usuario_created": 42,
"id_usuario_updated": null,
"created_at": "2026-05-31T12:00:00Z",
"updated_at": "2026-05-31T12:00:00Z",
"deleted_at": null
}
}Escopo: saldos_acumulados:read
PUT /saldos-acumulados/{saldo_id}
Atualiza um saldo existente do usuário autenticado pelo ID. O body é um SaldoAcumuladoUpdate com campos parciais - somente o que vier preenchido é alterado. Os campos cnpj e tributo são imutáveis (compõem a chave única) e não aparecem no schema (proteção contra mass-assignment).
Parâmetros
| Parâmetro | Tipo | Local | Obrigatório | Descrição |
|---|---|---|---|---|
saldo_id | int | path | sim | ID do saldo |
Request (SaldoAcumuladoUpdate - saldo e/ou mes_referencia, ambos opcionais)
{
"saldo": "9.10",
"mes_referencia": "2026-06"
}Response 200 OK
{
"success": true,
"message": "Saldo acumulado atualizado!",
"data": {
"id": 1,
"cnpj": "12345678000190",
"tributo": "pis",
"saldo": "9.10",
"mes_referencia": "2026-06",
"id_usuario_created": 42,
"id_usuario_updated": 42,
"created_at": "2026-05-31T12:00:00Z",
"updated_at": "2026-06-30T12:00:00Z",
"deleted_at": null
}
}Escopo: saldos_acumulados:write
DELETE /saldos-acumulados/{saldo_id}
Soft delete: marca deleted_at = NOW() em vez de remover o registro. O saldo continua no banco para auditoria fiscal, mas fica invisível a todos os endpoints GET. Um POST /saldos-acumulados/upsert subsequente com a mesma chave (cnpj, tributo) ressuscita o registro.
Parâmetros
| Parâmetro | Tipo | Local | Obrigatório | Descrição |
|---|---|---|---|---|
saldo_id | int | path | sim | ID do saldo |
Request
Sem corpo de requisição.
Response 200 OK
{
"success": true,
"message": "Saldo acumulado removido!",
"data": null
}Quando não encontrado, retorna 404 Not Found. Escopo: saldos_acumulados:write
Schemas
SaldoAcumuladoCreate
Herda todos os campos de SaldoAcumuladoBase.
| Campo | Tipo | Obrigatório | Observações |
|---|---|---|---|
cnpj | str | sim | CNPJ do contribuinte, 14 dígitos numéricos, sem máscara. |
tributo | str | sim | Enum literal: pis, cofins, irpj, csll. |
saldo | Decimal | sim | Valor monetário acumulado, >= 0, compatível com Numeric(15,2). |
mes_referencia | str | sim | Último mês em que o saldo foi acumulado, no formato YYYY-MM (ex.: 2026-05). |
SaldoAcumuladoUpsert
Mesmos campos de SaldoAcumuladoCreate (cnpj, tributo, saldo, mes_referencia). O par (cnpj, tributo) é usado como chave funcional para decidir entre criar e atualizar.
SaldoAcumuladoUpdate
Todos os campos são opcionais; apenas os enviados são atualizados. cnpj e tributo não aparecem aqui - são imutáveis (bloqueia mass-assignment).
| Campo | Tipo | Observações |
|---|---|---|
saldo | Decimal | Novo valor acumulado (>= 0). |
mes_referencia | str | Nova competência de referência, formato YYYY-MM. |
SaldoAcumuladoRead
Estende SaldoAcumuladoBase com os campos gerenciados pelo service.
| Campo | Tipo | Notas |
|---|---|---|
id | int | Identificador do saldo acumulado. |
cnpj | str | CNPJ do contribuinte (14 dígitos). |
tributo | str | pis, cofins, irpj ou csll. |
saldo | Decimal | Valor acumulado. |
mes_referencia | str | Competência de referência (YYYY-MM). |
id_usuario_created | int | ID do usuário que criou (multi-tenant). |
id_usuario_updated | int | null | ID do último usuário que atualizou o registro. |
created_at | datetime | Timestamp de criação (server-side). |
updated_at | datetime | Timestamp da última atualização (server-side). |
deleted_at | datetime | null | Timestamp do soft delete (null = registro ativo). |
Notas
- Toda resposta segue o envelope
{ success, message, data }(ou{ success: false, message, details }em erro). Códigos HTTP refletem semântica REST padrão. - Os saldos são isolados por usuário (multi-tenant): a listagem e o detalhamento só retornam registros do usuário autenticado.
- Validações:
cnpjdeve ter exatamente 14 dígitos (não valida dígito verificador);saldonão pode ser negativo e deve ser< 10.000.000.000.000(arredondado a 2 casas);mes_referenciadeve casarYYYY-MMcom mês01-12.
Armadilha de roteamento FastAPI
A rota estática POST /saldos-acumulados/upsert é declarada antes da rota dinâmica GET|PUT|DELETE /saldos-acumulados/{saldo_id}. Inverter a ordem faria o FastAPI casar upsert como um saldo_id inválido. A ordem de declaração das rotas é intencional.