NFS-e/Repasse: Tomadores

Endpoints da WebApiAlcance para gerenciar os tomadores de serviço do produto NFS-e/Repasse Médico - as clínicas, hospitais e demais entidades para quem os profissionais prestam serviço e emitem nota fiscal. Cobrem criação, listagem geral com filtros, listagem por cliente associado, detalhamento por ID, atualização e exclusão.

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.

Escopo compartilhado por todo o produto NFS-e/Repasse

O escopo deriva do 1º segmento após /api/v1/, que aqui é nfse-repassenfse_repasse. Portanto os escopos nfse_repasse:read e nfse_repasse:write são compartilhados por TODO o produto NFS-e/Repasse - Tomadores e todos os demais subdomínios do produto usam os mesmos dois escopos. Uma API Key com nfse_repasse:write pode escrever em qualquer subdomínio do produto; dimensione a emissão de chaves com esse alcance em mente.

Base path

/api/v1/nfse-repasse/tomadores

Escopos necessários

  • nfse_repasse:read - listagem, listagem por cliente e detalhamento
  • nfse_repasse:write - criação, atualização e exclusão

O escopo é derivado do primeiro segmento da rota após /api/v1/: nfse-repasse vira o recurso nfse_repasse (hífen → underscore), e o método HTTP define a ação (read para GET, write para POST/PUT/DELETE). Esses escopos valem para todos os subdomínios do produto NFS-e/Repasse, não só para Tomadores.

Endpoints

POST /nfse-repasse/tomadores/

Cria um novo tomador de serviço. O id_usuario_created é preenchido a partir do usuário autenticado - não é aceito no corpo. Exige perfil administrador.

Parâmetros

Este endpoint não recebe parâmetros de rota ou query - os dados vão no corpo da requisição (TomadorCreate). O único campo obrigatório é razao_social; os demais são opcionais. status tem default "ativo" e só aceita "ativo" ou "inativo".

Request

{
  "razao_social": "Clínica Exemplo LTDA",
  "nome_fantasia": "Clínica Exemplo",
  "cpfecnpj": "12.345.678/0001-99",
  "inscricao_municipal": "1234567",
  "email": "contato@clinicaexemplo.com.br",
  "telefone": "(11) 3000-0000",
  "municipio": "São Paulo",
  "uf": "SP",
  "status": "ativo",
  "id_customer": 1
}

Response 201 Created

{
  "success": true,
  "message": "Tomador criado com sucesso!",
  "data": {
    "id": 1,
    "razao_social": "Clínica Exemplo LTDA",
    "nome_fantasia": "Clínica Exemplo",
    "cpfecnpj": "12345678000199",
    "inscricao_municipal": "1234567",
    "email": "contato@clinicaexemplo.com.br",
    "telefone": "(11) 3000-0000",
    "endereco": null,
    "municipio": "São Paulo",
    "uf": "SP",
    "status": "ativo",
    "id_customer": 1,
    "uuid_legado": null,
    "id_usuario_created": 42,
    "created_at": "2026-07-03T12:00:00Z",
    "updated_at": "2026-07-03T12:00:00Z"
  }
}

Conflitos (registro já existente) retornam 409 Conflict; validações de negócio retornam 422 Unprocessable Entity. Escopo: nfse_repasse:write

GET /nfse-repasse/tomadores/by-customer/{customer_id}

Lista os tomadores associados a um cliente (customer.id), com filtro opcional por status e paginação. Lista vazia é um estado válido - retorna 200 OK com data: [].

Parâmetros

ParâmetroTipoLocalObrigatórioDescrição
customer_idintpathsimID do cliente associado (customer.id).
statusstrquerynãoFiltro por status: ativo ou inativo.
pageint >= 1querynãoPágina (1-based).
per_pageint 1..500querynãoItens por página.

Request

Sem corpo de requisição.

Response 200 OK

{
  "success": true,
  "message": "Tomadores recuperados com sucesso!",
  "data": [
    {
      "id": 1,
      "razao_social": "Clínica Exemplo LTDA",
      "nome_fantasia": "Clínica Exemplo",
      "cpfecnpj": "12345678000199",
      "status": "ativo",
      "id_customer": 1,
      "id_usuario_created": 42,
      "created_at": "2026-07-03T12:00:00Z",
      "updated_at": "2026-07-03T12:00:00Z"
    }
  ]
}

Escopo: nfse_repasse:read

GET /nfse-repasse/tomadores/

Lista os tomadores com filtros opcionais (visão compartilhada single-company). Lista vazia é um estado válido - retorna 200 OK com data: [].

Parâmetros

ParâmetroTipoLocalObrigatórioDescrição
statusstrquerynãoFiltro por status: ativo ou inativo.
id_customerintquerynãoFiltro por cliente associado (customer.id).
pageint >= 1querynãoPágina (1-based).
per_pageint 1..500querynãoItens por página.

Request

Sem corpo de requisição.

Response 200 OK

{
  "success": true,
  "message": "Tomadores recuperados com sucesso!",
  "data": [
    {
      "id": 1,
      "razao_social": "Clínica Exemplo LTDA",
      "nome_fantasia": "Clínica Exemplo",
      "cpfecnpj": "12345678000199",
      "status": "ativo",
      "id_customer": 1,
      "id_usuario_created": 42,
      "created_at": "2026-07-03T12:00:00Z",
      "updated_at": "2026-07-03T12:00:00Z"
    }
  ]
}

Escopo: nfse_repasse:read

GET /nfse-repasse/tomadores/{tomador_id}

Detalha um tomador pelo ID inteiro. Quando não encontrado, retorna 404 Not Found.

Parâmetros

ParâmetroTipoLocalObrigatórioDescrição
tomador_idintpathsimID interno do tomador

Request

Sem corpo de requisição.

Response 200 OK

{
  "success": true,
  "message": "Tomador encontrado!",
  "data": {
    "id": 1,
    "razao_social": "Clínica Exemplo LTDA",
    "nome_fantasia": "Clínica Exemplo",
    "cpfecnpj": "12345678000199",
    "inscricao_municipal": "1234567",
    "email": "contato@clinicaexemplo.com.br",
    "telefone": "(11) 3000-0000",
    "endereco": null,
    "municipio": "São Paulo",
    "uf": "SP",
    "status": "ativo",
    "id_customer": 1,
    "uuid_legado": null,
    "id_usuario_created": 42,
    "created_at": "2026-07-03T12:00:00Z",
    "updated_at": "2026-07-03T12:00:00Z"
  }
}

Escopo: nfse_repasse:read

PUT /nfse-repasse/tomadores/{tomador_id}

Atualiza um tomador existente. O body é um TomadorUpdate com campos parciais - somente o que vier preenchido é alterado. Campos como id, uuid_legado, id_usuario_created, created_at e updated_at são imutáveis e não aparecem no schema (proteção contra mass-assignment). Exige perfil administrador.

Parâmetros

ParâmetroTipoLocalObrigatórioDescrição
tomador_idintpathsimID do tomador

Request (TomadorUpdate - todos os campos opcionais)

{
  "nome_fantasia": "Clínica Exemplo Matriz",
  "status": "inativo"
}

Response 200 OK

{
  "success": true,
  "message": "Tomador atualizado!",
  "data": {
    "id": 1,
    "razao_social": "Clínica Exemplo LTDA",
    "nome_fantasia": "Clínica Exemplo Matriz",
    "cpfecnpj": "12345678000199",
    "status": "inativo",
    "id_customer": 1,
    "id_usuario_created": 42,
    "created_at": "2026-07-03T12:00:00Z",
    "updated_at": "2026-07-03T14:30:00Z"
  }
}

Escopo: nfse_repasse:write

DELETE /nfse-repasse/tomadores/{tomador_id}

Remove um tomador pelo ID. Exige perfil administrador.

Parâmetros

ParâmetroTipoLocalObrigatórioDescrição
tomador_idintpathsimID do tomador

Request

Sem corpo de requisição.

Response 200 OK

{
  "success": true,
  "message": "Tomador removido!",
  "data": null
}

Escopo: nfse_repasse:write

Schemas

TomadorCreate

CampoTipoObrigatórioObservações
razao_socialstrsimRazão social do tomador. Máx. 200 caracteres.
nome_fantasiastrnãoNome fantasia. Máx. 200.
cpfecnpjstrnãoCPF ou CNPJ. Front pode enviar com máscara - é normalizado para só dígitos. Máx. 20.
inscricao_municipalstrnãoInscrição municipal. Máx. 50.
emailstrnãoE-mail de contato. Máx. 100.
telefonestrnãoTelefone de contato. Máx. 50.
enderecostrnãoEndereço. Máx. 200.
municipiostrnãoMunicípio. Máx. 100.
ufstrnãoUF (sigla de 2 letras).
statusstrnãoativo (default) ou inativo. Outros valores são rejeitados.
id_customerintnãoID do cliente (customer.id) associado. Associação de negócio, não isolamento.
uuid_legadostrnãoUUID do registro original no Supabase (rastreabilidade da migração). Imutável após criação. Máx. 36.

TomadorUpdate

Todos os campos são opcionais; apenas os enviados são atualizados. id, uuid_legado, id_usuario_created, created_at e updated_at são imutáveis e não aparecem aqui (bloqueio de mass-assignment).

CampoTipoObservações
razao_socialstrNova razão social. Máx. 200.
nome_fantasiastrMáx. 200.
cpfecnpjstrNormalizado para só dígitos. Máx. 20.
inscricao_municipalstrMáx. 50.
emailstrMáx. 100.
telefonestrMáx. 50.
enderecostrMáx. 200.
municipiostrMáx. 100.
ufstrSigla de 2 letras.
statusstrativo ou inativo.
id_customerintReassocia o tomador a outro cliente.

TomadorRead

Estende TomadorBase com campos gerenciados pelo servidor.

CampoTipoNotas
idintIdentificador interno do tomador.
razao_socialstrRazão social.
nome_fantasiastrNome fantasia.
cpfecnpjstrCPF/CNPJ (apenas dígitos, sem máscara).
inscricao_municipalstrInscrição municipal.
emailstrE-mail de contato.
telefonestrTelefone de contato.
enderecostrEndereço.
municipiostrMunicípio.
ufstrUF.
statusstrativo ou inativo.
id_customerintCliente associado (customer.id).
uuid_legadostrUUID do registro original no Supabase.
id_usuario_createdintUsuário que criou (auditoria).
created_atdatetimeTimestamp de criação (server-side).
updated_atdatetimeTimestamp da última atualização.

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 (404 não encontrado, 409 conflito, 403 acesso negado, 422 validação).
  • Ordem de rotas (FastAPI). A rota estática GET /by-customer/{customer_id} é declarada antes da rota dinâmica GET /{tomador_id}. Isso é intencional: invertê-las faria o router casar by-customer como um tomador_id inválido.
  • O cpfecnpj é normalizado para apenas dígitos antes da persistência - o front pode enviar com máscara. Não há validação de comprimento (aceita CPF de 11 ou CNPJ de 14 dígitos).
  • uuid_legado é metadado da migração single-company (app webapp-nfs-repasse-medico, Supabase): aceito no Create para correlação com o registro de origem, mas imutável depois.
  • id_usuario_created é preenchido pelo servidor a partir do usuário autenticado - nunca vem no corpo do Create.