engineAPIengineAPI
// guias

Guia: Regime Normal (Lucro Real/Presumido)

Como emitir NF-e e NFC-e com emissor CRT=3 — o ICMS que o motor calcula, o que ele recusa e por quê.

Regime Normal: emissão com ICMS calculado

Empresa de Lucro Real ou Presumido (crt: 3 no cadastro) emite NF-e e NFC-e com o ICMS calculado pelo motor fiscal: você manda o item com NCM, CFOP, origem e valores, liga "resolverTributacao": true, e o documento sai com o grupo de ICMS completo (CST 00, base, alíquota e valor — e o FCP onde ele existe).

Não existe campo de alíquota no payload. É de propósito: a alíquota vem de uma base fiscal auditada, não do que o integrador digitou.

Opt-in explícito

Só com "resolverTributacao": true — sem a flag, o emissor CRT=3 recebe 422

Fonte auditada

26 UFs curadas em fonte primária + tabela federal de interestadual

Recusa em vez de chute

Cenário fora da base → 422 com o motivo, nada é emitido


Como emitir

bash
curl -X POST https://api.engineapi.com.br/v1/nfe \
  -H "x-api-key: ek_live_..." \
  -H "Content-Type: application/json" \
  -d '{
    "resolverTributacao": true,
    "indFinal": 0,
    "destinatario": {
      "cnpjCpf": "12345678000199",
      "nome": "Cliente Exemplo LTDA",
      "endereco": {
        "logradouro": "Rua A", "numero": "1", "bairro": "Centro",
        "codigoMunicipio": "5211909", "municipio": "Jandaia",
        "uf": "GO", "cep": "75950000"
      }
    },
    "items": [
      {
        "codigo": "P1",
        "descricao": "Farinha de Trigo Tipo 1 - 1kg",
        "ncm": "11029000",
        "cfop": "5102",
        "unidade": "UN",
        "quantidade": 2,
        "valorUnitario": 500,
        "icms": { "origem": 0 }
      }
    ],
    "pagamentos": [{ "forma": "01", "valor": 1000 }]
  }'

Os três campos que mudam o imposto e por isso importam:

| Campo | Onde | Para que serve | |---|---|---| | destinatario.endereco.uf | documento | separa operação interna (alíquota da UF) de interestadual (7%/12%/4%) | | indFinal | documento | 0 = não é operação a consumidor final; 1 = é. Em UF com FCP condicionado, muda o valor devido | | icms.origem | item | Tabela A do Ajuste SINIEF 15/13 (0 a 8). Importados de 1, 2, 3 e 8 puxam os 4% da Res. Senado 13/2012 na interestadual |

Na NFC-e não há o que informar: o modelo 65 é sempre venda presencial a consumidor final na UF do emitente, e a API declara isso ao motor por você.


O que sai no documento

Para um item de R$ 1.000,00 com emissor em Goiás vendendo dentro do estado:

xml
<ICMS>
  <ICMS00>
    <orig>0</orig>
    <CST>00</CST>
    <modBC>3</modBC>
    <vBC>1000.00</vBC>
    <pICMS>19.00</pICMS>
    <vICMS>190.00</vICMS>
  </ICMS00>
</ICMS>
  • CST 00 (tributada integralmente) é o único CST que esta fase emite.
  • modBC 3 = base de cálculo pelo valor da operação (LC 87/1996, art. 13, I). É o que o motor calcula: sem redução de base, sem pauta, sem MVA.
  • Se o item traz desconto, a base é o valor da operação líquido (vBC = vProd − vDesc): descontos incondicionais não integram a base (LC 87/1996, art. 13, § 1º, II, "a" — a lei manda integrar só os concedidos sob condição). O mesmo vale para a base do IBS/CBS (LC 214/2025, art. 12, § 2º, III). Use desconto apenas para desconto incondicional: é o único que o documento carrega.
  • pFCP/vFCP entram no grupo só onde existe adicional de Fundo de Combate à Pobreza — hoje o RJ (2%, geral) e o SE (a consumidor final, por produto). Onde não há adicional, o par não aparece: ausência é diferente de "0%".
  • O ICMS não muda o total da nota — ele já está embutido no preço da mercadoria (vNF = produtos − desconto + frete + seguro + outras + II + IPI). Seu pagamentos continua fechando com o mesmo valor de antes.

O que o motor recusa — e por quê

Um 422 aqui é sempre local: nada chega à SEFAZ e nenhum número fiscal é consumido. O corpo traz code e o motivo por item.

| Situação | Resposta | |---|---| | Emissor CRT=3 sem resolverTributacao e sem ICMS no item | 422 ICMS_REGIME_NORMAL_NAO_RESOLVIDO | | icms.cst informado à mão | 422 CST_NAO_SUPORTADO_NFE | | UF do emitente fora da base curada (hoje: MT) | 422 TRIBUTACAO_NAO_RESOLVIDAsem regra vigente para operação interna em MT | | Data de emissão anterior à vigência da regra da UF | 422 TRIBUTACAO_NAO_RESOLVIDAsem regra vigente … na data de emissão | | Operação interna em SE a consumidor final com NCM fora da lista curada de FCP | 422 TRIBUTACAO_NAO_RESOLVIDA — o adicional existe e varia por produto | | Operação interna em SE sem indFinal declarado | 422 TRIBUTACAO_NAO_RESOLVIDA — omitir o campo não pode ser o contorno do problema | | icms.origem fora de 0–8, ou indFinal fora de 1 | 422 TRIBUTACAO_NAO_RESOLVIDA | | Produto sujeito a substituição tributária (NCM arrolado no CEST) | 422 TRIBUTACAO_NAO_RESOLVIDAo NCM … está arrolado no CEST … | | ICMS-ST informado no payload (icms.baseCalculoST/aliquotaST/valorST) | 422 ICMS_ST_NAO_SUPORTADO | | Venda interestadual a consumidor final NÃO contribuinte (indFinal: 1 + destinatario.indicadorIE diferente de 1, ou ausente) | 422 TRIBUTACAO_NAO_RESOLVIDAé hipótese de DIFAL (EC 87/2015)… |

DIFAL: por que a venda interestadual a consumidor recusa

Quando você vende para outro estado e o destinatário é consumidor final não contribuinte (o caso típico do e-commerce), a EC 87/2015 manda partilhar o imposto com o estado de destino, e o documento tem que carregar o grupo ICMSUFDest (base, alíquota interna do destino, valor devido ao destino e ao remetente). Este motor calcula apenas o ICMS da operação própria — emitir assim produziria um documento que declara imposto a menos para a UF de destino. Por isso recusamos antes, em vez de emitir incompleto.

O que fazer hoje:

  • se o destinatário é contribuinte, declare destinatario.indicadorIE: 1 — a operação deixa de ser hipótese de DIFAL e o motor resolve normalmente (o diferencial nesse caso é apurado pelo próprio destinatário, fora do seu documento);
  • se é mesmo venda a consumidor de outro estado, informe o icms manualmente com o documento completo;
  • indicadorIE ausente também recusa, de propósito: sem ele não dá para afirmar que a operação não é DIFAL, e omitir um campo não pode ser o caminho fácil para escapar da checagem.

Exemplo de recusa (UF fora da base):

json
{
  "message": "Tributação assistida: 1 item(ns) não resolvidos — nada foi emitido. Corrija os itens ou informe csosn/ibsCbs manualmente.",
  "code": "TRIBUTACAO_NAO_RESOLVIDA",
  "details": {
    "itensNaoResolvidos": [
      {
        "index": 0,
        "motivo": "ICMS: sem regra vigente para operação interna em MT — informe icms manualmente"
      }
    ]
  }
}

Por que icms.cst à mão é recusado

O grupo de ICMS do leiaute 4.00 exige a modalidade da base de cálculo (modBC) — campo que este contrato não expõe. Aceitar o cst e escolher a modalidade por conta própria seria decidir tributação no lugar de quem emite, em documento assinado e permanente. É a mesma razão pela qual o ICMS-ST é recusado (falta modBCST).

Se você já calcula o ICMS no seu ERP e quer passá-lo adiante, fale com o suporte — é um caso de contrato, não de payload.

Substituição tributária: recusa por NCM

Antes de calcular qualquer coisa, o motor verifica se o NCM do item está arrolado no CEST (Convênio ICMS 142/2018). Se estiver, a resposta é 422 — mesmo que você não tenha informado nada de ST:

font-mono text-sm bg-slate-800 text-[var(--eng-glow)] rounded px-1.5 py-0.5
ICMS: o NCM 22021000 está arrolado no CEST 0300700 (mercadoria passível de
substituição tributária) e a fase Normal não calcula ST — o documento sairia
com ICMS próprio integral onde pode haver ICMS-ST; informe icms manualmente

Por que recusar em vez de emitir com ICMS próprio: em regime de ST quem recolhe é o substituto, e declarar ICMS integral no lugar da substituição é errar com o sinal invertido — o oposto do que o documento deveria dizer.

Isso recusa mais do que a ST efetivamente devida, e é deliberado: a tabela de CEST não distingue par UF×UF (a exigência depende de protocolo entre os estados), então o critério é "este produto é passível de ST", não "há ST nesta operação". Produtos de segmentos com ST ampla — bebidas, autopeças, cosméticos, medicamentos, combustíveis — caem aqui. Para eles, informe a tributação de ICMS manualmente ou fale com o suporte.


Cobertura de hoje, dita na cara

| Coberto | Fora desta fase | |---|---| | Alíquota interna das 26 UFs curadas (MT fora) | ST / CEST — detectada por NCM e recusada com 422 | | Interestadual completa: 7% (S/SE → N/NE/CO e ES), 12% geral, 4% para importados | DIFAL (EC 87/2015) | | FCP incondicional do RJ | FCP das demais UFs por lista de supérfluos | | FCP do SE a consumidor final, nos NCM curados | Benefícios por NCM×UF: redução de base, isenção, CST 20/40/41/51 | | CST 00 (tributada integralmente) | Demais CST |

A base tem prazo de validade declarado: alíquota estadual muda por lei, e uma base vencida aplicada em silêncio seria pior que a recusa. A revalidação é parte do processo de release.


Perguntas rápidas

Preciso mandar alíquota? Não — e não existe campo para isso. A alíquota vem da base auditada.

E se eu não ligar a flag? O emissor CRT=3 recebe 422 ICMS_REGIME_NORMAL_NAO_RESOLVIDO. Antes desta versão o documento saía com CSOSN (código exclusivo do Simples) e a SEFAZ rejeitava — o 422 local é o mesmo problema, descoberto antes de queimar número fiscal.

Simples Nacional muda em alguma coisa? Não. Emissor crt: 1 continua exatamente como antes, com CSOSN.

O 422 consome número? Nunca. Todas as recusas deste guia rodam antes da numeração fiscal, nos dois caminhos (síncrono e lote).