TFF Salvador
Endpoints da WebApiAlcance para o registro interno das guias de TFF (Taxa de Fiscalização de Funcionamento) de Salvador emitidas para os clientes. Cobrem criação, listagem paginada com filtros e ordenação, consulta por ID, atualização, remoção e download do PDF. Registros nascem tanto pela automação de emissão quanto pelo CRUD manual - quando vêm da automação, atividade_id referencia a atividade que originou a guia; quando nascem pelo CRUD, atividade_id é null.
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/tff-salvadorEscopos necessários
tff_salvador:read- listagem, consulta por ID e download do PDF (rotasGET).tff_salvador:write- criação, atualização e remoção (POST,PUT,DELETE).
O escopo é derivado do prefixo público da rota: /tff-salvador vira o recurso tff_salvador (hífen → underscore), e o método HTTP define a ação (read para GET, write para POST/PUT/DELETE).
Envelope de resposta
Exceto o download de PDF (que devolve bytes), toda resposta segue o envelope padrão da WebApi:
{
"status": "success",
"message": "Mensagem em PT-BR",
"data": {}
}Endpoints
POST /tff-salvador/
Registra uma nova guia de TFF Salvador. Responde 201 Created.
Parâmetros
Sem parâmetros de rota ou query - os dados vão no corpo da requisição (TFFSalvadorCreate, ver TFFSalvadorCreate).
Request
{
"id_cliente": 123,
"id_usuario": 7,
"atividade_id": 9981,
"ano_competencia": 2026,
"cota": "01/05",
"status": "Concluído",
"arquivo_nome": "TFF_27898481000150_2026_cota01.pdf",
"arquivo_mime": "application/pdf",
"file_base64": "JVBERi0xLjQK..."
}Response 201 Created
{
"status": "success",
"message": "Guia de TFF registrada com sucesso!",
"data": {
"id": 4210,
"id_cliente": 123,
"id_usuario": 7,
"atividade_id": 9981,
"ano_competencia": 2026,
"cota": "01/05",
"status": "Concluído",
"arquivo_nome": "TFF_27898481000150_2026_cota01.pdf",
"arquivo_mime": "application/pdf",
"data_hora_emissao": "2026-08-05T09:12:44-03:00"
}
}O data segue TFFSalvadorRead e nunca inclui file_base64.
Escopo: tff_salvador:write
GET /tff-salvador/
Lista guias de TFF no envelope paginado, com filtros e ordenação. O campo file_base64 não é retornado - para o PDF use GET /tff-salvador/{tff_id}/pdf.
Parâmetros de query
| Parâmetro | Tipo | Default | Observações |
|---|---|---|---|
id_cliente | int | - | Filtra por cliente. |
id_usuario | int | - | Filtra por usuário (autoria). |
ano_competencia | int | - | Filtra pelo ano de competência. |
cota | str | - | Filtra por cota (ex.: 01/05). |
status | str | - | Ex.: Concluído, Falha. Case-insensitive. |
start_date | datetime | - | data_hora_emissao >= start_date. |
end_date | datetime | - | data_hora_emissao <= end_date. |
sort_by | str (whitelist) | data_hora_emissao | Whitelist na seção Ordenação, abaixo. Valor fora dela → 422. |
sort_dir | asc | desc | desc | Valor fora da whitelist → 422. |
page | int (≥ 1) | 1 | Página, 1-based. |
per_page | int (1-500) | - | Itens por página. Se omitido, retorna todos (sem paginar). |
Request
GET /api/v1/tff-salvador/?ano_competencia=2026&page=1&per_page=20Response 200 OK
{
"status": "success",
"message": "Guias de TFF recuperadas com sucesso!",
"data": {
"items": [
{
"id": 4210,
"id_cliente": 123,
"id_usuario": 7,
"atividade_id": 9981,
"data_hora_emissao": "2026-08-05T09:12:44-03:00",
"ano_competencia": 2026,
"cota": "01/05",
"status": "Concluído",
"arquivo_nome": "TFF_27898481000150_2026_cota01.pdf"
}
],
"total": 42,
"total_pages": 3,
"current_page": 1,
"per_page": 20
}
}Lista vazia é um estado válido - data.items: [] com total: 0, não é erro. Quando per_page é omitido, total_pages vale 1 e per_page vem null.
Escopo: tff_salvador:read
GET /tff-salvador/{tff_id}
Busca uma guia de TFF pelo ID. Retorna apenas metadados (TFFSalvadorRead), sem file_base64.
Parâmetros
| Parâmetro | Local | Tipo | Obrigatório | Observações |
|---|---|---|---|---|
tff_id | rota | int | sim | ID da guia de TFF. |
Response 200 OK
{
"status": "success",
"message": "Guia de TFF encontrada com sucesso!",
"data": {
"id": 4210,
"id_cliente": 123,
"id_usuario": 7,
"atividade_id": 9981,
"data_hora_emissao": "2026-08-05T09:12:44-03:00",
"ano_competencia": 2026,
"cota": "01/05",
"status": "Concluído",
"arquivo_nome": "TFF_27898481000150_2026_cota01.pdf",
"arquivo_mime": "application/pdf"
}
}ID inexistente retorna 404 Not Found com detail: "Guia de TFF com ID {id} não encontrada!".
Escopo: tff_salvador:read
PUT /tff-salvador/{tff_id}
Atualiza uma guia de TFF existente. Todos os campos do corpo são opcionais - só os informados são aplicados.
Parâmetros
tff_id na rota; corpo em TFFSalvadorUpdate (ver TFFSalvadorUpdate).
Campos deliberadamente não editáveis
id_cliente, id_usuario e atividade_id não existem no corpo de atualização. O PUT não pode reatribuir a guia a outro cliente/usuário nem trocar a atividade de origem.
Request
{
"status": "Falha",
"cota": "02/05"
}Response 200 OK
{
"status": "success",
"message": "Guia de TFF atualizada com sucesso!",
"data": {
"id": 4210,
"id_cliente": 123,
"id_usuario": 7,
"atividade_id": 9981,
"data_hora_emissao": "2026-08-05T09:12:44-03:00",
"ano_competencia": 2026,
"cota": "02/05",
"status": "Falha",
"arquivo_nome": "TFF_27898481000150_2026_cota01.pdf",
"arquivo_mime": "application/pdf"
}
}ID inexistente retorna 404 Not Found.
Escopo: tff_salvador:write
DELETE /tff-salvador/{tff_id}
Remove uma guia de TFF pelo ID.
Restrito por perfil
Além do escopo tff_salvador:write, esta rota exige perfil administrador ou diretoria. Um token com o escopo correto mas perfil operacional é recusado com 403.
Response 200 OK
{
"status": "success",
"message": "Guia de TFF deletada com sucesso!",
"data": null
}ID inexistente retorna 404 Not Found.
Escopo: tff_salvador:write + perfil administrador ou diretoria
GET /tff-salvador/{tff_id}/pdf
Devolve o PDF binário da guia de TFF - esta é a única rota que expõe o arquivo.
Parâmetros
| Parâmetro | Local | Tipo | Obrigatório | Observações |
|---|---|---|---|---|
tff_id | rota | int | sim | ID da guia de TFF. |
Response 200 OK
Content-Type: application/pdfContent-Disposition: attachment; filename="<arquivo_nome ou tff_salvador_{id}.pdf>"
Retorna 404 Not Found quando não há registro, quando não há PDF gravado, ou quando o base64 armazenado não pôde ser decodificado - neste último caso com detail: "PDF da guia de TFF com ID {id} não pôde ser decodificado!".
Sem envelope
Diferente das demais rotas, esta não responde { status, message, data } - o corpo é o PDF. Erros aqui saem como HTTPException ({ "detail": "..." }), com o status HTTP real.
Escopo: tff_salvador:read
Ordenação
sort_by aceita apenas os valores abaixo (validados por Literal; qualquer outro retorna 422):
sort_by | Ordena por |
|---|---|
data_hora_emissao | Data/hora de emissão. Default. |
cliente | Nome do cliente (customer.razao_social), não o ID. |
usuario | Nome do usuário (user.nome), não o ID. |
status | Status do registro. |
ano_competencia | Ano de competência. |
cota | Cota, ordenada numericamente (CAST), não como texto. |
sort_dir aceita asc ou desc (default desc). O desempate secundário é por cota ascendente.
Schemas
TFFSalvadorCreate
Corpo de POST /tff-salvador/.
| Campo | Tipo | Obrigatório | Observações |
|---|---|---|---|
id_cliente | int | sim | FK do cliente. |
id_usuario | int | sim | Autor do registro. |
atividade_id | int | null | não | Atividade que originou a guia. Nulo quando o registro nasce pelo CRUD. |
ano_competencia | int | null | não | Ano de competência da guia. |
cota | str | null | não | Identificação da cota (ex.: 01/05). |
status | str | sim | Ex.: Concluído, Falha. |
arquivo_nome | str | null | não | Nome do arquivo, usado no Content-Disposition do download. |
arquivo_mime | str | null | não | Normalmente application/pdf. |
file_base64 | str | null | não | PDF em base64. Só entra na escrita - nenhum schema de leitura o expõe. |
TFFSalvadorUpdate
Corpo de PUT /tff-salvador/{tff_id}. Todos os campos são opcionais.
| Campo | Tipo | Observações |
|---|---|---|
ano_competencia | int | - |
cota | str | - |
status | str | - |
file_base64 | str | Substitui o PDF gravado. |
arquivo_nome | str | - |
arquivo_mime | str | - |
id_cliente, id_usuario e atividade_id não fazem parte deste schema.
TFFSalvadorRead
data de POST, GET /{tff_id} e PUT.
| Campo | Tipo | Observações |
|---|---|---|
id | int | ID da guia. |
id_cliente | int | - |
id_usuario | int | Autor do registro. |
atividade_id | int | null | - |
data_hora_emissao | datetime | null | - |
ano_competencia | int | null | - |
cota | str | null | - |
status | str | - |
arquivo_nome | str | null | - |
arquivo_mime | str | null | - |
Não inclui file_base64.
TFFSalvadorListItem
Item de items[] na listagem. Igual ao TFFSalvadorRead, sem arquivo_mime e sem file_base64.
PaginatedTFFSalvador
data de GET /tff-salvador/.
| Campo | Tipo | Observações |
|---|---|---|
items | List[TFFSalvadorListItem] | Página atual. |
total | int | Total de registros que atendem aos filtros. |
total_pages | int | 1 quando per_page é omitido. |
current_page | int | Ecoa o page recebido. |
per_page | int | null | null quando omitido na requisição (retorno sem paginação). |
Notas
- O PDF fica em coluna
MEDIUMTEXTe nunca aparece nas respostas JSON - só emGET /{tff_id}/pdf. sort_by=clienteesort_by=usuariofazemJOINe ordenam pelo nome, que é o que o consumidor exibe.sort_by=cotafazCASTpara ordenar numericamente, não como texto.- Apagar a atividade que originou a guia não apaga o registro:
atividade_idficanull. DELETE /tff-salvador/{tff_id}remove o registro por completo, incluindo o PDF gravado.