NFS-e/Repasse: NF-e Salvador Médicos
Endpoints da WebApiAlcance para gerenciar as NFS-e do município de Salvador voltadas a médicos dentro do módulo NFS-e/Repasse. Cobrem o registro manual de NF-e, listagem, busca por ID e pelo número da nota, download do arquivo binário (imagem) da NFS-e, atualização, exclusão e a emissão assíncrona no portal Nota Salvador - esta última persiste os dados, cria um Worker no estado AGENDADO e enfileira uma task Celery executada por um scraper.
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 do módulo NFS-e/Repasse
O primeiro segmento da rota é nfse-repasse (compartilhado por todo o módulo). O escopo é derivado dele: nfse_repasse:read para leitura e nfse_repasse:write para escrita. Ou seja, os recursos internos do módulo (nfe-salvador-medicos, médicos, prestadores etc.) compartilham o mesmo par de escopos nfse_repasse:read / nfse_repasse:write, e não escopos por sub-recurso.
Base path
/api/v1/nfse-repasse/nfe-salvador-medicosEscopos necessários
nfse_repasse:read- listagem, busca por ID, busca por número da nota e download do arquivo (GET)nfse_repasse:write- registro, atualização, exclusão e emissão (POST/PUT/DELETE)
O escopo é derivado do primeiro segmento da rota: /nfse-repasse vira o recurso nfse_repasse (hífen → underscore), compartilhado por todo o módulo. O método HTTP define a ação (read para GET, write para POST/PUT/DELETE).
Endpoints
POST /nfse-repasse/nfe-salvador-medicos/
Registra manualmente uma NF-e Salvador Médicos (persistência direta, sem disparar automação). Quando não é possível persistir, retorna o envelope de erro { success: false, message: "Nao foi possivel registrar a NF-e.", details: [] }.
Parâmetros
Este endpoint não recebe parâmetros de rota ou query - os dados vão no corpo da requisição (NfeSalvadorMedicosCreate): cliente_id e usuario_id são obrigatórios; os demais campos fiscais são opcionais (str | None).
Request
{
"cliente_id": 42,
"usuario_id": 7,
"status": "REGISTRADA",
"numero_nota": "2026000123",
"inscricao_municipal": "123456",
"cnpj_tomador": "12345678000199",
"valor_total_nota": "1500.00"
}Response 200 OK
{
"success": true,
"message": "NF-e registrada com sucesso!",
"data": {
"id": 10,
"cliente_id": 42,
"usuario_id": 7,
"status": "REGISTRADA",
"numero_nota": "2026000123",
"inscricao_municipal": "123456",
"cnpj_tomador": "12345678000199",
"valor_total_nota": "1500.00",
"data_solicitacao": "2026-01-01T12:00:00Z"
}
}Escopo: nfse_repasse:write
GET /nfse-repasse/nfe-salvador-medicos/{nfe_id}
Detalha uma NF-e pelo ID inteiro. Quando não encontrada, retorna 404 Not Found com detail: "NF-e não encontrada.".
Parâmetros
| Parâmetro | Tipo | Local | Obrigatório | Descrição |
|---|---|---|---|---|
nfe_id | int | path | sim | ID interno da NF-e |
Request
Sem corpo de requisição.
Response 200 OK
{
"success": true,
"message": "NF-e encontrada!",
"data": {
"id": 10,
"cliente_id": 42,
"usuario_id": 7,
"status": "REGISTRADA",
"numero_nota": "2026000123",
"inscricao_municipal": "123456",
"cnpj_tomador": "12345678000199",
"valor_total_nota": "1500.00",
"data_solicitacao": "2026-01-01T12:00:00Z"
}
}Escopo: nfse_repasse:read
GET /nfse-repasse/nfe-salvador-medicos/numero/{numero_nota}
Busca uma NF-e pelo número da nota emitida. Quando não encontrada, retorna 404 Not Found com detail: "NF-e não encontrada.".
Parâmetros
| Parâmetro | Tipo | Local | Obrigatório | Descrição |
|---|---|---|---|---|
numero_nota | str | path | sim | Número da nota fiscal emitida |
Request
Sem corpo de requisição.
Response 200 OK
{
"success": true,
"message": "NF-e encontrada!",
"data": {
"id": 10,
"cliente_id": 42,
"usuario_id": 7,
"status": "REGISTRADA",
"numero_nota": "2026000123",
"inscricao_municipal": "123456",
"cnpj_tomador": "12345678000199",
"valor_total_nota": "1500.00",
"data_solicitacao": "2026-01-01T12:00:00Z"
}
}Escopo: nfse_repasse:read
GET /nfse-repasse/nfe-salvador-medicos/{nfe_id}/arquivo
Baixa o arquivo binário (imagem) da NFS-e como download. O backend lê o campo arquivo (uma data URL data:<mime>;base64,<payload>), decodifica para bytes e devolve com Content-Disposition: attachment. O nome do arquivo é nfse_<numero_nota|id>.<extensao> e o Content-Type reflete o MIME original (image/png, image/jpeg).
Parâmetros
| Parâmetro | Tipo | Local | Obrigatório | Descrição |
|---|---|---|---|---|
nfe_id | int | path | sim | ID interno da NF-e |
Request
Sem corpo de requisição.
Response 200 OK
Corpo binário da imagem (não é envelope JSON); o Content-Type reflete o MIME original (image/png, image/jpeg). Erros: 404 Not Found quando a NF-e não existe (detail: "NF-e id=<id> nao encontrada.") ou ainda não há arquivo persistido (detail: "NF-e ainda nao possui arquivo persistido."); 500 Internal Server Error quando a data URL armazenada não pode ser decodificada.
Baixar vs. exibir embedado
Use este endpoint quando o front quiser um botão "Baixar" (o navegador salva o arquivo direto). Para exibir a NFS-e embedada no DOM, use GET /nfse-repasse/nfe-salvador-medicos/{nfe_id} e renderize o campo arquivo (data URL) num <img>.
Escopo: nfse_repasse:read
GET /nfse-repasse/nfe-salvador-medicos/
Lista todas as NF-e Salvador Médicos cadastradas. Lista vazia é um estado válido - retorna 200 OK com data: [].
Parâmetros
Este endpoint não recebe parâmetros de rota ou query.
Request
Sem corpo de requisição.
Response 200 OK
{
"success": true,
"message": "NF-e listadas com sucesso!",
"data": [
{
"id": 10,
"cliente_id": 42,
"usuario_id": 7,
"status": "REGISTRADA",
"numero_nota": "2026000123",
"inscricao_municipal": "123456",
"cnpj_tomador": "12345678000199",
"valor_total_nota": "1500.00",
"data_solicitacao": "2026-01-01T12:00:00Z"
}
]
}Escopo: nfse_repasse:read
PUT /nfse-repasse/nfe-salvador-medicos/{nfe_id}
Atualiza uma NF-e existente. O body é um NfeSalvadorMedicosUpdate com campos parciais - somente o que vier preenchido é alterado. Não inclui cliente_id nem usuario_id.
Parâmetros
| Parâmetro | Tipo | Local | Obrigatório | Descrição |
|---|---|---|---|---|
nfe_id | int | path | sim | ID da NF-e |
Request (NfeSalvadorMedicosUpdate - todos os campos opcionais)
{
"status": "REGISTRADA",
"numero_nota": "2026000123",
"valor_total_nota": "1500.00"
}Response 200 OK
{
"success": true,
"message": "NF-e atualizada com sucesso!",
"data": {
"id": 10,
"cliente_id": 42,
"usuario_id": 7,
"status": "REGISTRADA",
"numero_nota": "2026000123",
"inscricao_municipal": "123456",
"cnpj_tomador": "12345678000199",
"valor_total_nota": "1500.00",
"data_solicitacao": "2026-01-01T12:00:00Z"
}
}Escopo: nfse_repasse:write
DELETE /nfse-repasse/nfe-salvador-medicos/{nfe_id}
Remove uma NF-e pelo ID.
Parâmetros
| Parâmetro | Tipo | Local | Obrigatório | Descrição |
|---|---|---|---|---|
nfe_id | int | path | sim | ID da NF-e |
Request
Sem corpo de requisição.
Response 200 OK
{
"success": true,
"message": "NF-e removida com sucesso!",
"data": null
}Escopo: nfse_repasse:write
POST /nfse-repasse/nfe-salvador-medicos/emitir
Enfileira a emissão assíncrona de uma NFS-e no portal Nota Salvador (Médicos). O fluxo localiza o cliente pela inscrição municipal exata do prestador (sem correspondência retorna 404; mais de uma retorna 409), persiste um registro NfeSalvadorMedicos no estado AGENDADO, cria um Worker (automation_type = "nfse_salvador_emissao", queue = "scraping", status = "AGENDADO") e enfileira a task Celery nfse_salvador_emissao via apply_async. Se o broker estiver indisponível, marca o worker como FALHA e retorna 503.
Parâmetros
Este endpoint não recebe parâmetros de rota ou query - os dados vão no corpo da requisição (NfseSalvadorEmitirRequest). O tomador deve ser identificado por apelido_tomador OU cnpj_tomador (exatamente um dos dois).
Request
{
"inscricao_municipal_prestador": "123456",
"cnpj_tomador": "12345678000199",
"valor_total_nota": "1500.00",
"discriminacao": "Serviços médicos prestados em janeiro/2026.",
"cnae": "8630501",
"ctiss": "0801",
"nbs": "115011000",
"indicador_operacao": "1",
"classificacao_tributaria": "01",
"iss_retido": "N",
"emitir_definitivo": false
}Response 200 OK (NfseSalvadorEmitirResponse)
{
"worker_id": 501,
"nfe_id": 10,
"task_id": "a3f8c1e2-9b4d-4e7a-8c1f-2d5b6a8e9f0c",
"message": "Emissao NFS-e Salvador enfileirada com sucesso. Modo seguro (nao emite)."
}Acompanhe a execução da task pelo task_id em Worker Automation (GET /worker-automation/status/{task_id}). Erros: 404 Not Found (inscrição municipal não encontrada), 409 Conflict (inscrição corresponde a mais de um cliente) e 503 Service Unavailable (broker Celery indisponível ao enfileirar).
Gate operacional de emissão definitiva
O campo emitir_definitivo só é respeitado quando a env NFSE_SALVADOR_EMITIR_HABILITADO=true (gate server-side por ambiente). Em qualquer outro caso - mesmo com emitir_definitivo: true no payload - a task roda em modo seguro: apenas preenche o formulário no portal, sem emitir a nota de fato. A identificação do cliente é feita por CNPJ/inscrição exata para evitar IDOR.
Escopo: nfse_repasse:write
Schemas
NfeSalvadorMedicosCreate
Herda de NfeSalvadorMedicosBase. Além de cliente_id e usuario_id (obrigatórios), todos os demais campos são opcionais (str | None).
| Campo | Tipo | Obrigatório | Observações |
|---|---|---|---|
cliente_id | int | sim | Cliente prestador da NFS-e. |
usuario_id | int | sim | Usuário que registrou. |
status | str | não | Situação do registro (ex.: AGENDADO, REGISTRADA). |
numero_nota | str | não | Número da nota emitida. |
arquivo | str | não | Data URL da imagem da NFS-e (data:<mime>;base64,...). |
inscricao_municipal | str | não | Inscrição municipal do prestador. |
cnpj_tomador | str | não | CNPJ/CPF do tomador. |
apelido_tomador | str | não | Apelido/identificação do tomador cadastrado no portal. |
valor_total_nota | str | não | Valor total da nota. |
iss_retido | str | não | Indicador de ISS retido. |
cnae | str | não | CNAE do serviço. |
subcnae | str | não | Subitem do CNAE. |
aliquota | str | não | Alíquota aplicada. |
ctiss | str | não | Código CTISS. |
nbs | str | não | Código NBS. |
indicador_operacao | str | não | Indicador da operação. |
classificacao_tributaria | str | não | Classificação tributária. |
discriminacao | str | não | Discriminação do serviço. |
iss | str | não | Valor de ISS. |
irrf | str | não | Valor de IRRF retido. |
cssl | str | não | Valor de CSLL retido. |
cofins | str | não | Valor de COFINS retido. |
pisepasep | str | não | Valor de PIS/PASEP retido. |
inss | str | não | Valor de INSS retido. |
NfeSalvadorMedicosUpdate
Todos os campos são opcionais; apenas os enviados são atualizados. Não inclui cliente_id nem usuario_id.
| Campo | Tipo | Observações |
|---|---|---|
status | str | Nova situação do registro. |
numero_nota | str | Número da nota emitida. |
arquivo | str | Data URL da imagem da NFS-e. |
inscricao_municipal | str | Inscrição municipal do prestador. |
cnpj_tomador | str | CNPJ/CPF do tomador. |
apelido_tomador | str | Apelido do tomador. |
valor_total_nota | str | Valor total da nota. |
iss_retido | str | Indicador de ISS retido. |
cnae | str | CNAE do serviço. |
subcnae | str | Subitem do CNAE. |
aliquota | str | Alíquota aplicada. |
ctiss | str | Código CTISS. |
nbs | str | Código NBS. |
indicador_operacao | str | Indicador da operação. |
classificacao_tributaria | str | Classificação tributária. |
discriminacao | str | Discriminação do serviço. |
iss | str | Valor de ISS. |
irrf | str | Valor de IRRF retido. |
cssl | str | Valor de CSLL retido. |
cofins | str | Valor de COFINS retido. |
pisepasep | str | Valor de PIS/PASEP retido. |
inss | str | Valor de INSS retido. |
NfeSalvadorMedicosRead
Estende NfeSalvadorMedicosBase com campos gerenciados pelo servidor.
| Campo | Tipo | Notas |
|---|---|---|
id | int | Identificador interno da NF-e. |
cliente_id | int | Cliente prestador. |
usuario_id | int | Usuário que registrou. |
status | str? | Situação atual. |
numero_nota | str? | Número da nota emitida. |
arquivo | str? | Data URL da imagem da NFS-e. |
data_solicitacao | datetime? | Timestamp da solicitação (server-side). |
| (demais campos) | str? | Todos os campos fiscais herdados de NfeSalvadorMedicosBase (ver NfeSalvadorMedicosCreate). |
NfseSalvadorEmitirRequest
Payload para disparar a automação de emissão de NFS-e Salvador. A identificação do tomador exige exatamente um entre apelido_tomador e cnpj_tomador (validação model_validator).
| Campo | Tipo | Obrigatório | Observações |
|---|---|---|---|
inscricao_municipal_prestador | str | sim | 1-20 chars. Identifica o cliente por correspondência exata (.strip()). |
valor_total_nota | str | sim | 1-50 chars. |
discriminacao | str | sim | 1-2000 chars. Discriminação do serviço. |
cnae | str | sim | 1-20 chars. |
ctiss | str | sim | 1-20 chars. |
nbs | str | sim | 1-20 chars. |
indicador_operacao | str | sim | 1-10 chars. |
classificacao_tributaria | str | sim | 1-20 chars. |
cnpj_tomador | str | condicional | Máx. 20. Deve ter 11 (CPF) ou 14 (CNPJ) dígitos. Vazio → null. |
apelido_tomador | str | condicional | Máx. 100. Vazio → null. Informe um entre este e cnpj_tomador. |
iss_retido | str | não | Máx. 10. Default "N". |
aliquota | str | não | Máx. 20. |
subcnae | str | não | Máx. 20. |
iss | str | não | Máx. 10. |
irrf | str | não | Máx. 10. |
cssl | str | não | Máx. 10. |
cofins | str | não | Máx. 10. |
pisepasep | str | não | Máx. 10. |
inss | str | não | Máx. 10. |
emitir_definitivo | bool | não | Default false. Só efetiva a emissão se NFSE_SALVADOR_EMITIR_HABILITADO=true. |
NfseSalvadorEmitirResponse
| Campo | Tipo | Notas |
|---|---|---|
worker_id | int | ID do Worker criado para acompanhar a automação. |
nfe_id | int | ID do registro NfeSalvadorMedicos persistido. |
task_id | str | UUID da task Celery - consulte em Worker Automation. |
message | str | Confirmação, indicando modo definitivo ou modo seguro. |
Notas
- Toda resposta segue o envelope
{ success, message, data }(ou{ success: false, message, details }em erro) - excetoGET /{nfe_id}/arquivo, que devolve o corpo binário da imagem, ePOST /emitir, que devolve diretamente oNfseSalvadorEmitirResponse. - O registro via
POST /é persistência manual e não dispara automação; a emissão de fato ocorre apenas viaPOST /emitir, que enfileira a task Celerynfse_salvador_emissaona fila scraping (ver Worker Automation). - Gate de segurança na emissão: o cliente é resolvido por inscrição municipal exata (evita IDOR) e
emitir_definitivosó vale com a envNFSE_SALVADOR_EMITIR_HABILITADO=true; caso contrário a automação roda em modo seguro (apenas preenche o formulário). - O campo
arquivoé armazenado como data URL base64. O download decodifica o MIME embutido (image/png,image/jpeg) e define o nome comonfse_<numero_nota|id>.<extensao>. - Falha ao enfileirar a task marca o
WorkercomoFALHA(com mensagem sanitizada, sem stacktrace/credenciais) e retorna503.