https://api.engineapi.com.br/v1/nfse
A emissão assina a DPS com o certificado A1 do emissor. O prontoPara.nfse
do cadastro recusa antes de gastar nDPS, com nome próprio em faltando.nfse:
certificado (422 CERTIFICADO_AUSENTE), certificadoVencido
(422 CERTIFICADO_VENCIDO) ou certificadoOutroCnpj
(422 CERTIFICADO_OUTRO_CNPJ, raiz diferente; filial com e-CNPJ da matriz
não recusa). Emissor em sandbox não passa por essas
checagens. NF-e e NFC-e seguem cobrando só a presença do A1.
Quais campos enviar? A lista completa de campos (todos os parâmetros, tipos e
obrigatoriedade), navegável por grupo (Identificação, Tomador, Serviço, Retenções, DPS
Nacional…) e gerada direto do contrato real, está no
Catálogo de campos: NFS-e. Para navegar por endpoint
em vez de por documento, veja a Referência da API.
Multi-prefeitura
Suporte a padrões municipais (ABRASF) e ao Padrão Nacional (SEFIN/ADN)
ISS incluso
Alíquota e retenções conforme legislação local, passthrough, a Engine não calcula
Emissão assistida
Com
resolverTributacao: true, o Cérebro Fiscal completa campos ausentes da DPSNFS-e é o único módulo em produção que exige
issuerId explícito no corpo da
requisição. Em NF-e e NFC-e o campo é opcional (obrigatório só a partir do segundo
emissor); ver Autenticação.Diferenças NFS-e vs NF-e
Emitir NFS-e
servico.itemListaServico é obrigatório no fluxo manual, só pode ficar de fora com
resolverTributacao: true.
dpsNacional pode ficar de fora. Sem o bloco, a engineAPI deriva opSimpNac,
cTribNac e tribISSQN do cadastro do emissor (crt/mei/cTribNacPadrao) — não é
preciso adivinhar código do ADN. O regApTribSN só é derivado para Issuer.crt = 1
(Simples): para Issuer.crt = 2 (Simples com excesso de sublimite) ele é obrigatório
na requisição, porque o crt sozinho não diz o regime de apuração e não existe padrão
desse regime no cadastro — sem ele a emissão recusa com 422
(CRT2_SEM_REGIME_APURACAO), inclusive com resolverTributacao: true. Se o emissor não
tiver cTribNacPadrao cadastrado, a emissão rejeita com 400 ("Campos fiscais do Padrão Nacional ausentes: cTribNac") pedindo o cadastro ou o campo manual. Num emissor
crt = 2 sem regApTribSN, porém, esse 400 não chega a acontecer: a recusa 422
acima vem primeiro, porque o 400 só nasce no provider, depois dessa verificação.
dpsNacional informado explicitamente (como no exemplo abaixo) sempre vence a
derivação, campo a campo. Ver O que significa cada código de opSimpNac
antes de copiar o exemplo para um emissor de regime diferente.Códigos de opSimpNac
dpsNacional.opSimpNac declara a situação do emissor perante o Simples Nacional —
não é uma escolha livre, é o enum oficial do leiaute da DPS. Copiar o valor errado do
regime do seu emissor é rejeitado pela SEFIN em produção (422 E0160, “a opção de
situação perante o Simples Nacional do prestador informada na DPS não está de acordo com
o cadastro”).
Issuer.crt aceita 4 valores (create-company.dto.ts): 1 (Simples), 2 (Simples com
excesso de sublimite de receita bruta), 3 (Regime Normal) e 4 (MEI). Um emissor
crt = 2 continua optante do Simples mesmo com o sublimite estourado — não é Não
Optante; é essa diferença que a tabela acima cobre.
dpsNacional.regApTribSN (regime de apuração do Simples) só acompanha opSimpNac = 3 —
MEI (opSimpNac = 2) não leva o campo. Quando você omite dpsNacional inteiro, a
engineAPI deriva opSimpNac a partir do cadastro do emissor com esta mesma tabela: é o
que mata a rejeição de quem copia o exemplo desta página sem ajustar ao próprio regime.
Para Issuer.crt = 1 a derivação também completa regApTribSN = '1' (não existe outro
valor possível nesse enum). Para Issuer.crt = 2 o crt sozinho não diz o regime de
apuração: não há campo de cadastro pra isso, e chutar '1' arriscaria trocar a rejeição
E0160 (divergência cadastral) por uma rejeição de regime incoerente na SEFIN. Sem
dpsNacional.regApTribSN explícito, a emissão de um emissor crt = 2 recusa com 422
(CRT2_SEM_REGIME_APURACAO) antes de transmitir — informe o campo pra seguir.
Essa exigência vale em qualquer forma de emissão: dpsNacional omitido, parcial,
preenchido com opSimpNac, cTribNac e tribISSQN, ou com resolverTributacao: true. Mandar
o trio completo não dispensa o regApTribSN; ligar a tributação assistida também não, porque o
Cérebro Fiscal não tem fonte pra esse campo neste regime. Declarar opSimpNac = 1 num emissor
crt = 2 não é saída — é exatamente a divergência cadastral que gera a E0160. Emissor MEI
(Issuer.mei = true ou Issuer.crt = 4) não é afetado: deriva opSimpNac = 2, que não leva o
campo. A verificação roda no último ponto antes da transmissão, sobre a DPS final: nada é
transmitido e nenhum número de DPS é consumido.
Campos de Referência
Validação de endereço e alíquota
tomador.endereco.complemento é opcional e aceita até 156 caracteres (o teto do
leiaute, publicado no contrato OpenAPI). Você pode omiti-lo ou enviar uma string
vazia ou composta só por espaços dentro desse teto, que a API trata como ausência e
não escreve na DPS; acima de 156 caracteres a recusa é 400 nomeando o campo,
mesmo que o conteúdo seja só espaço. Valor de tipo errado (por exemplo, um número)
também devolve 400 dizendo o tipo esperado.
Já logradouro, numero e bairro exigem conteúdo depois de remover os espaços das
bordas: branco somente devolve 400 com o nome do campo, antes de reservar número da
DPS. Os quatro campos recusam caracteres fora da faixa do leiaute, como travessão,
aspas curvas, reticências e emoji.
servico.aliquotaIss aceita de 0 a 9.99, com no máximo duas casas decimais. Valor
com três ou mais casas, ou dois dígitos na parte inteira, devolve 400 antes da
emissão; a API não arredonda uma alíquota declarada pelo integrador.
Serviço B2B com retenção
Na prestação para empresa, o tomador costuma reter tributos na fonte e recolher no lugar do prestador. A DPS declara isso em dois lugares do leiaute nacional, e a engineAPI escreve os dois a partir do blocoretencoes:
A alíquota da retenção federal é sua. A engineAPI transcreve o valor retido que você
informou e confere coerência: ela não aplica percentual de IRRF/CSLL/PIS/COFINS/INSS,
porque isso depende da natureza do serviço, da dispensa por valor mínimo e do regime do
tomador. Quem calcula é o seu sistema (ou o seu contador).
PIS/COFINS: indicador, não valor
O leiaute do Padrão Nacional não tem campo para o valor retido de PIS e COFINS. Os camposvPis e vCofins da DPS existem, mas são o débito de apuração própria do
prestador, e o total de retenções da NFS-e é calculado sem eles:
dpsNacional.tpRetPisCofins, que aceita os códigos 0 a 9 da tabela
oficial. Os mais usados:
Mandar valor em
retencoes.pis ou retencoes.cofins recusa com
422 RETENCAO_SEM_CAMPO_NO_LEIAUTE: escrever esse valor em vPis/vCofins declararia um
débito próprio que não é o seu.
cURL
tpRetISSQN = 2, os três valores federais nos campos
próprios e tpRetPisCofins = 3 (PIS/COFINS/CSLL retidos). O que foi declarado volta também
na consulta: GET /v1/nfse/{id} e a listagem trazem o campo retencoes com os nomes do
leiaute (tpRetISSQN, vRetCP, vRetIRRF, vRetCSLL, tpRetPisCofins), ou nulo quando
não houve retenção.
No sandbox, a emissão com retenção funciona, mas nada é escrito. A emissão simulada não
gera uma DPS real, então a retenção declarada não entra em documento nenhum e não fica
registrada na nota. A resposta traz isso em
avisos[], para você exercitar o fluxo sem
concluir que a retenção foi transmitida. Em ambiente configurado para o provedor municipal
(que também não escreve retenção), a emissão recusa com
422 RETENCAO_PROVIDER_NAO_ESCREVE, porque ali a nota sairia de verdade sem o que você
declarou.O grupo intermediario (identificação de quem intermediou a prestação) ainda não é aceito
no payload: issRetidoPor: "intermediario" declara a retenção pelo intermediário, mas sem
identificá-lo.Emissão assistida (Cérebro Fiscal)
Isto é diferente da derivação básica deopSimpNac/cTribNac/tribISSQN (e de
regApTribSN só para Issuer.crt = 1; sempre ativa, sem custo, ver
Códigos de opSimpNac): a assistida completa
mais campos (itemListaServico, codigoNBS), audita cada resolução e exige plano/feature
habilitados.
Com "resolverTributacao": true, campos ausentes da DPS (dpsNacional.cTribNac,
opSimpNac, tribISSQN, tpRetISSQN, servico.itemListaServico, servico.codigoNBS)
são preenchidos a partir do cadastro do emissor (cTribNacPadrao/servicoPadraoLc116 em
Issuer). Requer feature de plano + Issuer.fiscalBrainEnabled (403 sem isso). Campo
obrigatório sem fonte cadastrada → 422 com camposNaoResolvidos e nada é emitido.
O Cérebro Fiscal não tem fonte para regApTribSN num emissor crt = 2: nesse caso a
recusa sai nomeada, com CRT2_SEM_REGIME_APURACAO, dizendo qual campo informar — ligar
resolverTributacao não dispensa o campo.
aliquotaIss nunca é opinada pelo Cérebro: se o payload mandar um valor mesmo assim, ele é
ignorado (ecoar um valor divergente do cálculo da SEFIN causa rejeição E1235), e esse
descarte aparece na resposta, em avisos[] (string), além do log do servidor. Sem a flag,
o comportamento é o de sempre (passthrough manual, sem avisos).
Códigos de Serviço LC116
Os códigos (servico.itemListaServico) são definidos pela Lei Complementar 116/2003:
Cada município pode ter lista complementar de códigos. Consulte a legislação local ou o site da prefeitura emissora.
Response de Sucesso
Envelopado em{ data, meta }:
data.avisos (array de string) é opcional, só aparece quando há algo a avisar sobre a
emissão que acabou de acontecer (hoje: emissão assistida com servico.aliquotaIss informado
no payload, o valor foi ignorado, ver Emissão assistida
acima). Ausência do campo = nada a avisar.Para empresa do Simples, o percentual total de tributos do cadastro tem um mês de referência:
pTotTribSNCompetencia no formato AAAA-MM. Esse percentual muda todo mês. Se a emissão
usar um mês anterior ou se o mês não estiver cadastrado, a nota segue — o valor é declaratório
— e a resposta traz um aviso para confirmar com o contador e atualizar o cadastro. Um valor
enviado em dpsNacional.pTotTribSN tem prioridade e segue exatamente como foi informado.Cancelar NFS-e
{id} é o id (UUID) retornado na emissão. Diferente de NF-e/NFC-e (campo
justificativa), o corpo do cancelamento de NFS-e usa motivo.
Se a SEFIN rejeitar o cancelamento, a resposta
400 traz erros[] estruturado
(codigo/descricao/complemento verbatim do Padrão Nacional), nunca vazio,
para sua aplicação ramificar por código.
Consultar NFS-e na SEFIN
{id} é o id (UUID) retornado na emissão. Consulta a NFS-e diretamente na SEFIN/ADN
pela chave de acesso e atualiza o xmlContent local quando a SEFIN devolve um XML.
Cobertura da NFS-e por município
Nem todo município já aderiu ao Sistema Nacional da NFS-e (Padrão Nacional/ADN) — quem não aderiu emite pelo padrão municipal antigo (ABRASF), quando o município tiver um provider configurado. Antes de cadastrar um emissor ou diagnosticar por que uma DPS foi rejeitada, consulte a cobertura do IBGE:
A engineAPI mantém um espelho local (TTL padrão 24h, renovado automaticamente
quando você cadastra/atualiza certificado, muda
ibgeCode ou troca de
ambiente) e revalida diariamente as linhas vencidas — nunca varre os ~5.570
municípios de uma vez (o ADN não tem endpoint de lista em massa). Use
?atualizar=true para forçar uma reconsulta imediata, ignorando o TTL:
prontoPara.nfse em
POST/GET/PATCH /v1/companies só marca o município como bloqueante quando a
cobertura é nao_aderente confirmada — nesse caso faltando.nfse inclui
municipioAderente, e a resposta traz prontoPara.cobertura: { situacao, consultadoEm } (campo aditivo, presente sempre que já houve alguma consulta).
O POST /v1/companies consulta a cobertura na hora do cadastro, usando o
certificado de qualquer emissor do mesmo parceiro (o recém-criado ainda
não tem o próprio). Sem certificado no parceiro, a cobertura fica
desconhecido e o cadastro não falha.
A mesma resposta traz avisos[] (array sempre presente, vazio quando não há
aviso). Só emite um item quando a cobertura é nao_aderente confirmada:
desconhecido não gera aviso. Na emissão, o mesmo código vira 422
antes de numerar se o espelho já diz nao_aderente; se a SEFIN ainda assim
devolver E0037, a recusa também sai 422 com details.mensagemSefin
preservando a mensagem original. Ver Erros e respostas.
Veja também
- Emissão de NF-e: para venda de mercadorias (ICMS).
- Webhooks: receba eventos de NFS-e em tempo real.
- Paginação: contrato de
page/limit/sortByusado emGET /v1/nfse.