Skip to main content
Empresa com benefício estadual (redução de base na cesta básica, isenção por convênio, diferimento no agro, regime especial) emite pela engineAPI informando os números do próprio ato concessório. O motor transcreve para o documento e recusa o que o leiaute não comporta, antes de consumir número fiscal.
Passthrough validado, não curadoria. Quem sabe o percentual de redução, o código do benefício e o valor desonerado é você: está no seu ato concessório. A engineAPI não consulta a tabela de benefícios da sua UF e não decide sozinha que a sua operação tem benefício. Dos códigos de benefício (cBenef, cBenefRBC, cCredPresumido) conferimos o formato que o leiaute exige (8 ou 10 caracteres); conferir se o código existe na tabela da sua UF, e se você tem direito a ele, é responsabilidade do emitente.

O que emite hoje

Estado da prova, por código. O cst "20" (redução de base) tem emissão real autorizada em homologação. Os demais (40, 41, 50, 51 e 90) têm a estrutura validada contra o leiaute oficial e ainda aguardam a emissão real. O estado célula a célula fica em Cobertura fiscal.
Vale para emissor em Regime Normal (crt: 3) e no Simples com excesso de sublimite (crt: 2). No Simples pleno e no MEI o documento carrega csosn, não cst: informar um desses códigos ali recusa com 422 CST_REGIME_INCOMPATIVEL. Na NFC-e o leiaute tem lista fechada de códigos e admite só 20, 40 e 41. Suspensão, diferimento e “outras” recusam com 422 ICMS_BENEFICIO_NAO_SUPORTADO e a mensagem manda emitir NF-e.
Os nomes dos campos são as tags do leiaute. O ICMS próprio destes grupos vai em vBC, pICMS e vICMS, não nos nomes clássicos baseCalculo, aliquota e valor. Os clássicos continuam valendo no ICMS sem benefício e no Simples Nacional, mas informá-los junto de um código de benefício recusa com 422 ICMS_BENEFICIO_INVALIDO: dois nomes para a mesma tag deixariam o motor escrever um e descartar o outro em silêncio. É o mesmo vocabulário da substituição tributária.

Redução de base (CST 20)

O grupo vai inteiro: modalidade da base, percentual de redução, base, alíquota e valor.
A base que você informa JÁ É a base reduzida. A engineAPI não aplica a redução por você. No exemplo: R100,00demercadoriacom30(R 100,00 de mercadoria com 30% de redução dão `vBC: 70.00`, e `vICMS` precisa fechar com base vezes alíquota (R 12,60), com tolerância de um centavo. Divergiu, recusa com 422 ICMS_BENEFICIO_INVALIDO nomeando a conta.
Em Goiás, o cBenef é obrigatório neste código. Medimos ao vivo: uma NF-e de CST 20 sem o código do benefício volta rejeitada pela SEFAZ-GO com a rejeição 930, e o número fiscal já foi consumido. Com ele, a mesma nota é autorizada. O cBenef fica no item (ao lado de cest e cfop, não dentro de icms) e o valor tem que ser o código da tabela de benefícios da SUA UF:
Outras UFs (Paraná, Santa Catarina, Rio Grande do Sul) também exigem o campo quando há benefício. A engineAPI confere o formato do código, nunca a existência dele na tabela da sua UF: essa parte é do emitente.

Isenção, não tributada e suspensão (CST 40, 41 e 50)

O grupo desses códigos só carrega o desconto do imposto quando há desoneração. Sem ela, basta o código:
Com desoneração, os três campos vão sempre juntos:

indDeduzDeson: o campo que decide o total da nota

"1" = o valor desonerado sai do total da nota (vNF reduzido, e os pagamentos precisam fechar com esse total menor). "0" = o total continua cheio. O leiaute define o significado de "0" e de "1" e não define o da ausência. Como o total da nota depende disso, a engineAPI exige o campo sempre que vICMSDeson é informado: é mais estrito que o leiaute, de propósito. Total de nota errado em silêncio é o pior defeito que um motor fiscal pode ter. Uma nota não mistura os dois indicadores. Se um item declara "1" e outro "0", o total sairia parcialmente deduzido, e esse total não é nenhuma das duas leituras que a norma do documento comporta. Como não confirmamos em texto oficial qual conta a SEFAZ aplica ao caso misto, a API recusa com 422 ICMS_BENEFICIO_INVALIDO: use o mesmo indicador em todos os itens desonerados da nota, ou separe as operações em duas notas. Item fora do total não pode deduzir do total. indTot: 0 (o item não compõe o valor de mercadoria) junto de indDeduzDeson: "1" recusa pelo mesmo código: o item sairia do valor da mercadoria e ainda reduziria o total da nota, o que não corresponde a operação nenhuma. Valor que arredonda para zero recusa. vICMSDeson de R$ 0,004 (ou zero explícito) seria escrito como 0,00, e o documento só carrega o grupo com valor maior que zero: os três campos sumiriam da nota em silêncio. Se não há desoneração na operação, não mande o bloco.

Os motivos de desoneração mudam com o código

Motivo fora do conjunto do código informado recusa com 422 ICMS_BENEFICIO_INVALIDO, listando os que valem ali.

Diferimento (CST 51)

  • O leiaute deixa a critério de cada UF quais campos exigir, então quase tudo é opcional aqui. A exceção é modBC: o formato de entrada do motor não consegue expressar a ausência da modalidade da base, e sem o campo o documento sairia declarando “margem de valor agregado” que você não informou. Por isso ele é obrigatório neste código.
  • Quando você informa vICMSOp, vICMSDif e valor juntos, a conta precisa fechar: imposto da operação = parte diferida + parte devida, com tolerância de um centavo.
  • pDif não é conferido contra vICMSDif: a proporção fica a critério de cada UF, e conferir uma fórmula que a norma não afirma fecharia emissão legítima.
  • cBenefRBC só existe neste código. Em outro, recusa.
  • Rio de Janeiro e Paraná exigem os campos do diferimento mesmo zerados. A validação estrutural da engineAPI não impõe isso (o leiaute deixa a critério de cada UF, e a nossa prova offline roda com emissor de Goiás): nessas duas UFs, informe o grupo completo.

Outras (CST 90)

O bloco do ICMS próprio vai inteiro (modalidade, base, alíquota e valor), com pRedBC opcional dentro dele, e aceita desoneração:
O lado substituto da substituição tributária dentro desse código (margem de valor agregado, base e valor de ST) continua fora: depende de margem e alíquota interna que variam por UF, NCM e convênio, e a engineAPI não estima nenhuma das duas. Informar ST recusa com 422 ICMS_ST_NAO_SUPORTADO. O código 90 sem nenhum bloco EMITE, com a origem da mercadoria e o código apenas, sem imposto destacado: o leiaute comporta esse grupo vazio, e isso é comportamento da norma, não atalho da API. Se a sua operação tem ICMS próprio, informe o bloco completo: o grupo pela metade recusa.

Crédito presumido (gCred)

Fica no item, ao lado de cBenef, e vale com qualquer situação tributária. Até 4 por item.

Ato concessório (procRef)

Fica na raiz do payload e vale para o documento inteiro. É onde entra o regime especial, o termo de acordo ou o convênio que ampara o benefício. Até 100 por nota.
  • indProc: "0" SEFAZ, "1" Justiça Federal, "2" Justiça Estadual, "3" Secex/RFB, "4" CONFAZ, "9" outros.
  • tpAto: "08" termo de acordo, "10" regime especial, "12" autorização específica, "14" ajuste SINIEF, "15" convênio ICMS. O leiaute o prevê para processo de origem na SEFAZ: com outra origem, recusa.

O que a API recusa antes de numerar

Todas recusam antes de consumir número fiscal: nada é emitido, nenhuma numeração é queimada.

O que ainda não entra

  • Curadoria dos benefícios por UF: a API não descobre sozinha que a sua operação tem benefício, nem no caminho assistido (resolverTributacao), que segue emitindo tributação integral.
  • Existência do código na tabela da UF: conferimos formato, não filiação.
  • Códigos de operação do Simples com benefício (101, 900): outro caminho, ainda não disponível.
  • Substituição tributária dentro do código 90 e a desoneração de ST (vICMSSTDeson).