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-salvador

Escopos necessários

  • tff_salvador:read - listagem, consulta por ID e download do PDF (rotas GET).
  • 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âmetroTipoDefaultObservações
id_clienteint-Filtra por cliente.
id_usuarioint-Filtra por usuário (autoria).
ano_competenciaint-Filtra pelo ano de competência.
cotastr-Filtra por cota (ex.: 01/05).
statusstr-Ex.: Concluído, Falha. Case-insensitive.
start_datedatetime-data_hora_emissao >= start_date.
end_datedatetime-data_hora_emissao <= end_date.
sort_bystr (whitelist)data_hora_emissaoWhitelist na seção Ordenação, abaixo. Valor fora dela → 422.
sort_dirasc | descdescValor fora da whitelist → 422.
pageint (≥ 1)1Página, 1-based.
per_pageint (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=20

Response 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âmetroLocalTipoObrigatórioObservações
tff_idrotaintsimID 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âmetroLocalTipoObrigatórioObservações
tff_idrotaintsimID da guia de TFF.

Response 200 OK

  • Content-Type: application/pdf
  • Content-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_byOrdena por
data_hora_emissaoData/hora de emissão. Default.
clienteNome do cliente (customer.razao_social), não o ID.
usuarioNome do usuário (user.nome), não o ID.
statusStatus do registro.
ano_competenciaAno de competência.
cotaCota, 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/.

CampoTipoObrigatórioObservações
id_clienteintsimFK do cliente.
id_usuariointsimAutor do registro.
atividade_idint | nullnãoAtividade que originou a guia. Nulo quando o registro nasce pelo CRUD.
ano_competenciaint | nullnãoAno de competência da guia.
cotastr | nullnãoIdentificação da cota (ex.: 01/05).
statusstrsimEx.: Concluído, Falha.
arquivo_nomestr | nullnãoNome do arquivo, usado no Content-Disposition do download.
arquivo_mimestr | nullnãoNormalmente application/pdf.
file_base64str | nullnãoPDF 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.

CampoTipoObservações
ano_competenciaint-
cotastr-
statusstr-
file_base64strSubstitui o PDF gravado.
arquivo_nomestr-
arquivo_mimestr-

id_cliente, id_usuario e atividade_id não fazem parte deste schema.

TFFSalvadorRead

data de POST, GET /{tff_id} e PUT.

CampoTipoObservações
idintID da guia.
id_clienteint-
id_usuariointAutor do registro.
atividade_idint | null-
data_hora_emissaodatetime | null-
ano_competenciaint | null-
cotastr | null-
statusstr-
arquivo_nomestr | null-
arquivo_mimestr | 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/.

CampoTipoObservações
itemsList[TFFSalvadorListItem]Página atual.
totalintTotal de registros que atendem aos filtros.
total_pagesint1 quando per_page é omitido.
current_pageintEcoa o page recebido.
per_pageint | nullnull quando omitido na requisição (retorno sem paginação).

Notas

  • O PDF fica em coluna MEDIUMTEXT e nunca aparece nas respostas JSON - só em GET /{tff_id}/pdf.
  • sort_by=cliente e sort_by=usuario fazem JOIN e ordenam pelo nome, que é o que o consumidor exibe. sort_by=cota faz CAST para ordenar numericamente, não como texto.
  • Apagar a atividade que originou a guia não apaga o registro: atividade_id fica null.
  • DELETE /tff-salvador/{tff_id} remove o registro por completo, incluindo o PDF gravado.