# TexFiscal: emissão de NFS-e por API > Emissão, consulta e cancelamento de Nota Fiscal de Serviço eletrônica pelo seu > sistema. A API fala o contrato REST v2 de NFS-e que a maioria dos ERPs já > integra: mesmos caminhos, mesmos campos, mesmos literais de status. Quem já > emite por API troca a URL base e o token, sem mexer no código. Ambientes: produção em https://nfse.seusaude.com, homologação em https://homologacao-nfse.seusaude.com. Cada ambiente tem o seu token; o token de um apresentado no outro recebe 401. Autenticação e HTTP Basic com o token no usuário e senha VAZIA. ## As três regras que evitam quase todo erro de integração 1. A `ref` (na query do POST) e a chave de idempotencia. Repetir o POST com a mesma `ref` não emite de novo, devolve a nota existente. Derive a `ref` da sua transação, nunca de relogio nem de aleatorio. 2. Nota em `processando_autorizacao` NUNCA se reenvia. Só a consulta resolve. Reenviar duplica documento fiscal. 3. `alíquota` e PERCENTUAL (2.00 = dois por cento) e `discriminacao` tem MÍNIMO de 10 caracteres. Os dois são causa comum de recusa da prefeitura, e recusa da prefeitura consome numeracao de RPS. ## Reforma Tributária: IBS e CBS O objeto `serviço.ibs_cbs` e OPCIONAL até 31/12/2026 e passa a ser EXIGIDO em 01/01/2027 para empresas do Simples Nacional (01/10/2026 fora do Simples). Enquanto for opcional, omitir e válido. E TUDO OU NADA: `cst` (3 dígitos), `classificacao_tributaria` (6) e `indicador_operacao` (6) vao juntos, ou nenhum vai. Meio grupo e recusado pelo schema do provedor com o RPS já consumido, então a recusa acontece aqui antes de reservar número. Os três podem ficar no cadastro do emissor; o payload sempre vence o cadastro. Quais códigos usar e enquadramento tributario: e conversa com o contador, não há default e não escolhemos por ninguém. ## Contrato - [OpenAPI 3.1](https://nfse.seusaude.com/openapi.json): definicao completa de rotas, campos e erros. - [Guia de integração](https://nfse.seusaude.com/llms-full.txt): este arquivo com o guia inteiro embutido. - [Municípios atendidos](https://nfse.seusaude.com/v2/municipios): cobertura verificada, com a data de cada verificação. - [Saúde](https://nfse.seusaude.com/health): sem token. ## Rotas - `POST /v2/nfse?ref=`: emite. Repetir com a MESMA ref não reemite: devolve a nota que já existe (e assim que o retry após timeout fica seguro). A exceção e ref cuja nota foi CANCELADA: ela responde 409 `ref_encerrada`, porque a nota cancelada continua existindo como documento fiscal. Para substituir uma nota cancelada, use uma ref NOVA, por exemplo `PED-4471-R2`. A ref DISTINGUE MAIUSCULA de minuscula: `ped-1` e `PED-1` sao duas notas, e dois documentos fiscais para a mesma venda. Derive sempre da mesma forma. - `GET /v2/nfse/`: consulta (pergunta a prefeitura quando está em processamento). - `DELETE /v2/nfse/`: cancela. Corpo: `justificativa` (texto, mínimo 15 caracteres) e `motivo` (opcional, 1, 2 ou 3, default 1). Os dois NÃO sao a mesma coisa e confundi-los declara errado ao município: a `justificativa` e registro NOSSO e nunca chega a prefeitura (o padrão ABRASF não tem campo livre para ela); o `motivo` E a declaração ao fisco, e vale 1 erro na emissão, 2 serviço não prestado, 3 erro de assinatura. O PRAZO para cancelar e definido por cada PREFEITURA, não por nós, e não há nada aqui que o conheca: passado o prazo, a resposta e 422 `cancelamento_recusado` vinda do município. Não planeje um botao de cancelar que valha para sempre. - `GET /v2/nfse//pdf`: DANFSe. Exige token, não e link público. - `GET /v2/nfse//xml`: XML autorizado. - `GET /v2/uso?mes=AAAA-MM`: uso do mês, com o campo `cobravel` calculado pelo MESMO criterio do fechamento que gera a fatura: `numero IS NOT NULL AND numero <> ''` (só em produção; em homologação `cobravel` e sempre 0). Repare que **nota cancelada continua contando**: o cancelamento troca o status e não devolve o número da prefeitura. Nota recusada não conta, porque nunca recebeu número. - `GET /v2/municipios`: cobertura verificada. ## Literais de status - `autorizado`: A prefeitura autorizou. Há número, código de verificação, XML e DANFSe. - `processando_autorizacao`: Enviada, sem veredito ainda. Consulte ou espere o webhook. NUNCA reenvie: reenvio duplica documento fiscal. - `erro_autorizacao`: A prefeitura recusou. Corrija e reenvie com a MESMA ref. - `cancelado`: Cancelada com sucesso. - `processando_cancelamento`: Pedido de cancelamento sem veredito. Repita o DELETE ou consulte. ## Códigos de erro Trate pelo `código`, nunca pelo texto da `mensagem`. - `nao_autorizado` (HTTP 401): Token ausente, inválido, ou de um ambiente diferente do endereço chamado. - `emissor_bloqueado` (HTTP 403): O contrato do emissor está suspenso, encerrado ou ainda não foi ligado. Emitir e cancelar ficam barrados; CONSULTAR continua liberado, inclusive o XML e o PDF das notas já emitidas. - `ref_invalida` (HTTP 422): A ref não passou na regra: até 64 caracteres entre letras, números, ponto, hífen e sublinhado, sem começar com ponto e sem sufixo de arquivo reservado. - `json_invalido` (HTTP 422): O corpo não e um objeto JSON válido. - `requisicao_invalida` (HTTP 422): O payload foi recusado na validação. O array erros[] traz campo, mensagem e correção. Nada foi transmitido a prefeitura e nenhum RPS foi consumido. - `emissor_nao_configurado` (HTTP 422): O emissor do token está sem certificado, sem inscrição municipal, com o certificado vencido ou com o cadastro incompleto. Emissor SUSPENSO não cai aqui: cai em emissor_bloqueado (403). - `estado_invalido` (HTTP 422): A operação não cabe no estado atual da nota (cancelar nota que não está autorizada, por exemplo). - `justificativa_invalida` (HTTP 422): A justificativa de cancelamento tem menos de 15 caracteres. - `motivo_invalido` (HTTP 422): O campo motivo do cancelamento aceita 1 (erro na emissão), 2 (serviço não prestado) ou 3 (erro de assinatura). - `cancelamento_recusado` (HTTP 422): A prefeitura recusou o cancelamento. - `mes_invalido` (HTTP 422): O parâmetro mês não está em AAAA-MM. - `ref_encerrada` (HTTP 409): Esta referência já tem uma nota CANCELADA e não pode ser reutilizada. A nota cancelada continua existindo como documento fiscal: emita a substituta com uma referência NOVA (por exemplo, sufixo -R2). - `nao_encontrado` (HTTP 404): Não existe nota com essa ref neste emissor e ambiente. - `xml_indisponivel` (HTTP 404): Não há XML autorizado guardado para essa ref. - `danfse_indisponivel` (HTTP 404): Não há nota autorizada para essa ref. Situação permanente enquanto a nota não autorizar. - `danfse_falhou` (HTTP 422): A nota está autorizada mas o DANFSe não pode ser gerado agora. O XML autorizado continua em /xml. Tente o PDF de novo em instantes. - `cobertura_indisponivel` (HTTP 422): A lista de cidades atendidas não pode ser lida agora. - `contrato_indisponivel` (HTTP 404): O arquivo de contrato pedido (OpenAPI, Postman, llms.txt) não está disponível. - `servico_indisponivel` (HTTP 422): O serviço não respondeu a tempo ou está fora do ar. O DESFECHO DESTA CHAMADA E DESCONHECIDO: consulte GET /v2/nfse/{a mesma ref} antes de qualquer reenvio, e nunca reenvie com ref nova. - `rota_inexistente` (HTTP 404): Caminho não atendido por este serviço. - `metodo_nao_permitido` (HTTP 405): Método errado na rota. O cabecalho Allow diz quais valem. - `corpo_excede_limite` (HTTP 413): Corpo acima de 512 KB. - `limite_de_requisicoes` (HTTP 429): Acima de 10 requisicoes por segundo por IP. - `falha_interna` (HTTP 500): Falha não prevista. O incidente foi registrado. ## Compatibilidade: o que pode mudar sem aviso e o que não muda Esta seção e um compromisso, não uma observacao. Escreva seu cliente contando com ela e ele não quebra quando o serviço evoluir. O que PODE aparecer a qualquer momento, e por isso não quebra nada: - códigos de erro novos. Trate código desconhecido pelo STATUS HTTP: 4xx e problema no pedido ou no cadastro e não adianta repetir igual; 5xx e nosso. - campos novos na resposta. IGNORE campo que você não conhece, nunca recuse a resposta inteira por causa dele. - rotas novas e parâmetros de consulta OPCIONAIS novos. O que NÃO muda em `/v2`, e só mudaria com aviso de 90 dias e os cabecalhos `Deprecation` e `Sunset` antes: - caminho e método das rotas que já existem; - nome e significado dos campos que já existem; - os literais de `status` (`autorizado`, `processando_autorizacao`, `erro_autorizacao`, `cancelado`, `processando_cancelamento`); - o status HTTP que um código de erro já existente devolve. Duas coisas que valem repetir porque sao onde mais se erra: 202 NÃO e falha (a nota está em processamento e reenviar duplica documento fiscal), e um `código` que você não reconhece nunca deve virar retry automático. ## Webhook: o aviso que o serviço manda para você Você pode cadastrar UMA url por ambiente. Assim que a nota muda de desfecho, o serviço faz um POST nela com `Content-Type: application/json`. Eventos: `nfse_autorizada`, `nfse_erro`, `nfse_cancelada` e `nfse_cancelamento_nao_efetivado`. O último e o mais importante: ele significa que o cancelamento que você pediu NÃO valeu na prefeitura e a nota voltou a estar autorizada. Ele existe para pedir que alguém aja. Corpo: { "evento": "nfse_autorizada", "ref": "venda-000123", "evento_id": 4471, "ocorrido_em": "2026-09-03T01:20:00-03:00", ... os mesmos campos de GET /v2/nfse/ } Cabecalhos: `X-TexFiscal-Evento`, `X-TexFiscal-Tentativa` e `X-TexFiscal-Assinatura`, que e o HMAC-SHA256 do CORPO CRU com o segredo do seu webhook. Confira a assinatura antes de confiar no conteúdo, e compare com `hash_equals` ou equivalente, nunca com `==`. Três regras do receptor, e a segunda já causou prejuizo em outros integradores: 1. Responda 2xx rápido. Timeout nosso: 5 s na tentativa imediata. Faca o trabalho pesado depois de responder. 2. DESCARTE evento fora de ordem. Uma entrega que falhou e reagendada pode chegar DEPOIS de um evento mais novo da mesma ref: por exemplo, uma `nfse_autorizada` reagendada chegando depois da `nfse_cancelada`. Guarde o `ocorrido_em` do último evento aplicado por ref e ignore o que for mais antigo. Sem isso você marca como autorizada uma nota cancelada. 3. Trate entrega REPETIDA. Reenviamos até 16 vezes com espera crescente enquanto você não responder 2xx, e uma entrega pode chegar duas vezes se a sua resposta se perder. Use o `evento_id`, que e único e estável, como chave de deduplicação. Não ter webhook cadastrado e uma escolha valida: nesse caso consulte `GET /v2/nfse/`. Mas não fique consultando em laco apertado, porque cada consulta de nota pendente pergunta a prefeitura. Espere 2 s, depois 4, 8, 16, até 60 s entre consultas, e desista de consultar depois de 5 minutos: o serviço resolve sozinho e o próximo GET traz o desfecho. ## O que este serviço nunca faz - Responder 502, 503 ou 504 em rota de API. Falha de dependencia sai como 422 com corpo próprio, porque a borda da Cloudflare troca o corpo de 5xx pela página dela e o `fetch` do cliente cairia no catch sem a mensagem. - Reenviar sozinho uma nota sem resposta conclusiva. - Truncar ou "arrumar" dado fiscal em silencio: o que passa do limite e recusado com mensagem e correção, porque cortar um nome ou arredondar um valor produz uma nota diferente da que o cliente pediu e ele só descobre na apuracao. - Guardar o seu token em claro, ou o seu certificado fora do cofre. - Entregar PDF ou XML por link público.