Guia: Primeira Emissão
Guia completo para emitir seu primeiro documento fiscal. Todos os campos obrigatórios, erros comuns e melhores práticas.
Primeira Emissão
Este é o checklist rápido de pré-requisitos antes da 1ª emissão. Pra ver todos os campos, regimes tributários e tratamento de erros, veja o guia completo Emitir NF-e.
Antes de emitir sua primeira NFe em homologação (sandbox), você precisa ter três coisas prontas. Sem uma delas, a emissão vai falhar. Para o que muda ao ir pra produção, ver Sandbox.
Não tem os três? Volte para o Quickstart e siga os passos.
Checklist de pré-requisitos
Credencial disponível
Você tem uma API Key (ek_live_/ek_test_, formato recomendado para integração
server-to-server) ou um JWT de POST /v1/auth/login (data.access_token, fluxo de
dashboard)? Ver Autenticação.
Empresa cadastrada
Você já fez POST /v1/companies? O id retornado é o issuerId, usado para escolher
o emissor em qualquer módulo (ver aviso abaixo sobre obrigatoriedade por módulo).
Certificado enviado
Você já fez POST /v1/companies/{id}/certificate (campo multipart file, não
certificate)? Se sim, a resposta veio sem erro de senha?
Ambiente correto para o teste
Todo emissor novo nasce em homologação (ambienteFiscal: 2). Não tente emitir em
produção sem antes validar em homologação. Ver Sandbox para o
estado real da promoção pra produção.
NFe e NFCe aceitam issuerId opcional no payload. Se você só tem uma empresa
cadastrada, pode omitir; a API usa o seu emissor. Com dois ou mais emissores, informe
issuerId (UUID) para escolher o CNPJ; sem ele a API responde 400. NFSe exige
issuerId explícito no corpo da requisição.
Estrutura de uma NFe
Uma NFe é composta por 4 blocos no payload (o emissor não entra no body, é resolvido pela API Key/JWT):
POST /v1/nfe
├── 1. Identificação (naturezaOperacao, série, número, todos opcionais)
├── 2. Destinatário (cnpjCpf, nome, endereço)
├── 3. Itens (produtos, NCM, CFOP, impostos)
└── 4. Pagamentos (array, forma + valor)
Campos obrigatórios
Um payload com nomes de campo diferentes destes é rejeitado com 400 antes de chegar na SEFAZ.
Raiz
| Campo | Tipo | Obrigatório | Exemplo |
|---|---|---|---|
naturezaOperacao | string | Não | "VENDA DE MERCADORIA" |
destinatario | objeto | Sim | ver abaixo |
items | array | Sim (mín. 1) | ver abaixo, não é itens |
pagamentos | array | Sim (mín. 1) | ver abaixo, não é pagamento singular |
resolverTributacao | boolean | Não | true ativa a emissão assistida (Cérebro Fiscal, requer plano/feature habilitados) |
Destinatário
| Campo | Tipo | Obrigatório | Exemplo |
|---|---|---|---|
cnpjCpf | string (11 a 14 dígitos) | Sim, não é cnpj/cpf | "99888777000100" |
nome | string | Sim | "Cliente Exemplo SA" |
ie | string | Não, não é inscricaoEstadual | "1234567890" |
indicadorIE | número | Não (opcional) | 1 = contribuinte, 9 = não contribuinte |
endereco.logradouro | string | Sim | "Av Brasil" |
endereco.numero | string | Sim | "500" |
endereco.bairro | string | Sim | "Centro" |
endereco.codigoMunicipio | string | Sim | "3550308" (São Paulo) |
endereco.municipio | string | Sim | "São Paulo" |
endereco.uf | string (2) | Sim | "SP" |
endereco.cep | string | Sim | "01001000" |
Item (dentro de items[])
| Campo | Tipo | Obrigatório | Exemplo |
|---|---|---|---|
codigo | string | Sim | "PROD001" |
descricao | string | Sim | "Produto Teste" |
ncm | string (8 dígitos exatos) | Sim | "84713012" |
cfop | string | Sim | "5102" (venda interna) |
unidade | string | Sim | "UN" |
quantidade | número (min 0.0001) | Sim | 2 |
valorUnitario | número (min 0.01) | Sim | 150.00 |
valorTotal | número | Não (calculado se ausente) | 300.00 |
icms/pis/cofins/ipi/ibsCbs | objeto | Não | ver abaixo |
Não há campo numero por item: o índice do array já identifica o item. O item não
exige icms preenchido: sem resolverTributacao, os campos fiscais viajam como
passthrough (o que você mandar é o que vai pro XML); com resolverTributacao: true, o
Cérebro Fiscal completa icms.csosn/icms (Regime Normal)/ibsCbs ausentes.
ICMS simplificado (Simples Nacional)
"icms": {
"origem": 0,
"csosn": "400"
}
ICMS no Regime Normal (Lucro Real / Lucro Presumido)
O emissor crt: 3 não informa cst à mão: icms.cst é recusado com
422 CST_NAO_SUPORTADO_NFE (o leiaute exige a modalidade da base de cálculo, campo fora
deste contrato). O caminho que autoriza é resolverTributacao: true: o motor calcula
CST, base, alíquota e valor a partir de NCM, CFOP, UF e origem:
{
"resolverTributacao": true,
"items": [{
"codigo": "P1",
"descricao": "Farinha de Trigo Tipo 1 - 1kg",
"ncm": "11029000",
"cfop": "5102",
"unidade": "UN",
"quantidade": 2,
"valorUnitario": 500,
"icms": { "origem": 0 }
}]
}
Detalhe completo do cenário (pré-requisitos, resposta, XML, erros e limitações) em Regime Normal.
Pagamentos (array, mínimo 1)
| Campo | Tipo | Valores |
|---|---|---|
forma | string | "01" Dinheiro, "03" Cartão crédito, "04" Cartão débito, "15" Boleto, "99" Outros |
valor | número | Valor da parcela/forma |
"pagamentos": [
{ "forma": "01", "valor": 100.00 }
]
Exemplo completo mínimo
curl -X POST https://api.engineapi.com.br/v1/nfe \
-H "x-api-key: ek_test_SUA_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"naturezaOperacao": "VENDA DE MERCADORIA",
"destinatario": {
"cnpjCpf": "99888777000100",
"nome": "Cliente Exemplo SA",
"indicadorIE": 1,
"endereco": {
"logradouro": "Av Brasil",
"numero": "500",
"bairro": "Centro",
"codigoMunicipio": "3550308",
"municipio": "São Paulo",
"uf": "SP",
"cep": "01001000"
}
},
"items": [{
"codigo": "PROD001",
"descricao": "Produto Teste",
"ncm": "84713012",
"cfop": "5102",
"unidade": "UN",
"quantidade": 1,
"valorUnitario": 100.00,
"icms": {
"origem": 0,
"csosn": "400"
}
}],
"pagamentos": [
{ "forma": "01", "valor": 100.00 }
]
}'
Resposta de sucesso
Mesmo contrato de resposta nos dois caminhos de emissão (síncrono e lote), envelopado por
{ data, meta }:
{
"data": {
"id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"status": "AUTHORIZED",
"accessKey": "35260211222333000181550010000000011000000019",
"protocol": "135260000001234",
"number": 1,
"series": 1,
"model": "55",
"amount": "100",
"destCNPJ": "99888777000100",
"destName": "Cliente Exemplo SA",
"createdAt": "2026-07-06T12:00:00.000Z",
"updatedAt": "2026-07-06T12:00:01.000Z",
"downloads": {
"xml": "/v1/nfe/xml/35260211222333000181550010000000011000000019",
"pdf": "/v1/nfe/pdf/35260211222333000181550010000000011000000019"
}
},
"meta": {
"requestId": "req_abc123",
"timestamp": "2026-07-06T12:00:00.000Z"
}
}
data.status: "AUTHORIZED" (inglês, mesmo enum usado em GET /v1/nfe/{id} e no webhook
invoice.authorized) está aprovada pela SEFAZ e tem validade fiscal (se o emissor está em
produção: ambienteFiscal: 1). Não há issuer/customer embutidos, nem
xml/xmlPath/pdfPath/invoiceId/message/success/invoice aninhado: o PDF/XML têm
rotas próprias de download (downloads.xml/downloads.pdf apontam pra elas). amount é
string decimal ("100", sem zeros à direita), nunca number cru nem o Decimal.js interno serializado.
Erros mais comuns nesta etapa
| Erro | Causa | Solução |
|---|---|---|
403 Nenhum emissor configurado | Nenhuma empresa cadastrada para o partner | Faça POST /v1/companies primeiro |
500/erro de certificado na emissão | Nenhum .pfx enviado ou senha inválida | Faça POST /v1/companies/{id}/certificate com o campo file |
400 com error.erros[] (cStat 539) | Nota duplicada (mesmo número/série) | Incremente o número da nota, ou deixe a API alocar automaticamente |
400 com error.erros[] (cStat 225) | Campo NCM ou CFOP inválido | Verifique a tabela de CFOP |
400 Bad Request (validação) | Campo obrigatório ausente ou nome de campo errado (ex.: itens em vez de items) | Confira contra a tabela de campos acima |
401 Token inválido | Token expirado (24h) | Faça login novamente |
Rejeição SEFAZ é sempre 400, nunca 422. O corpo carrega error.erros[]
({codigo, descricao} verbatim da SEFAZ). Veja o formato completo em
Erros e Rejeições. O 422 existe na API, mas só para a
emissão assistida (resolverTributacao: true) quando um campo fiscal não tem
fonte para ser resolvido, não é o mesmo caso de rejeição SEFAZ.