SysVelox SysVelox API

Referência completa — NF-e e NFC-e

Todos os campos que POST /v1/nfe e POST /v1/nfce aceitam hoje, com exemplo real de cada um. Os dois endpoints usam exatamente o mesmo formato de payload — o que muda é só a URL (e a numeração/série, que são independentes por modelo). Se você é iniciante, comece pelo guia passo a passo antes desta página — aqui é a referência técnica de cada campo, não o tutorial de cadastro.

1. Payload básico (obrigatório) 2. Destinatário 3. Pagamento (único e dividido) 4. Desconto, frete, seguro, taxa 5. ICMS regime normal (valores reais) 6. IPI 7. PIS/COFINS (valores reais) 8. IBS/CBS (Reforma Tributária) 9. Transportadora, veículo, volumes 10. Devolução 11. Consultar, baixar, cancelar 12. Tabela de todos os campos

1. Payload básico

O menor payload válido — uma NFC-e de balcão, consumidor não identificado, um item, Simples Nacional, à vista em dinheiro:

POST /v1/nfce
Authorization: Bearer sk_test_xxxxxxxxxxxxxxxx
Content-Type: application/json
Idempotency-Key: venda-00123

{
  "company_id": "emp_xxxxxxxxxxxx",
  "items": [
    {
      "description": "Pão francês",
      "ncm": "19059090",
      "cfop": "5102",
      "unit": "KG",
      "quantity": 2,
      "unit_price_cents": 1290,
      "csosn": "102",
      "cst_pis": "07",
      "cst_cofins": "07"
    }
  ]
}

Resposta imediata (a emissão continua em segundo plano):

{ "id": "nf_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", "tipo": "nfce", "status": "processando" }
CampoObrigatório?O que é
company_idobrigatórioID da empresa (CNPJ) cadastrada na sua conta — veja em Minha conta → Empresas.
itemsobrigatórioLista de itens da venda, não pode ser vazia.
items[].descriptionobrigatórioDescrição do produto/serviço, texto livre.
items[].ncmobrigatórioNCM do produto, 8 dígitos. Consulte na tabela oficial se não souber o do seu produto.
items[].cfopobrigatórioCFOP da operação, 4 dígitos começando em 1-7 (ex.: 5102 venda dentro do estado, 6102 venda pra outro estado).
items[].unitobrigatórioUnidade comercial (até 6 caracteres): UN, KG, CX, L, etc.
items[].quantityobrigatórioQuantidade vendida — aceita decimal (ex.: 2.5 kg).
items[].unit_price_centsobrigatórioSempre em centavos, inteiro. R$ 12,90 = 1290. Nunca mande 12.90.
items[].csosn ou cst_icmsum dos doiscsosn se a empresa é Simples Nacional (CRT 1); cst_icms se é Regime Normal (CRT 3). Nunca os dois juntos.
items[].cst_pisobrigatórioCST do PIS, 2 dígitos (ex.: 07 = isento, comum em Simples Nacional).
items[].cst_cofinsobrigatórioCST do COFINS, 2 dígitos (mesma lógica do PIS).
items[].origem_mercadoriaopcional, padrão 00=nacional, 1/2/3/6/7/8=variações de importado (Tabela de Origem da SEFAZ). Só afeta o cálculo do imposto aproximado (item 4), não o CST/CSOSN.
items[].cestopcionalCódigo CEST, 7 dígitos — obrigatório na prática pra alguns CSOSN de substituição tributária (ex.: 500).

A API não decide CST/CSOSN/CFOP por você — ela só monta o XML e valida o formato. Quem calcula qual código usar é o seu sistema (ou seu contador), igual você já faz hoje no seu emissor atual.

2. Destinatário

Opcional pra NFC-e (venda de balcão sem cliente identificado é normal e válida). Recomendado sempre pra NF-e (venda entre empresas).

Simples — só CPF/CNPJ

{
  "company_id": "emp_xxxxxxxxxxxx",
  "destinatario": {
    "documento": "11122233396",
    "nome": "Cliente Exemplo"
  },
  "items": [ ... ]
}

documento: CPF (11 dígitos) ou CNPJ (14 dígitos), só números. nome é opcional — se vazio, usa "CONSUMIDOR".

Completo — com endereço e Inscrição Estadual (recomendado pra NF-e)

{
  "destinatario": {
    "documento": "18088119000123",
    "nome": "Empresa Cliente LTDA",
    "inscricao_estadual": "123456789",
    "endereco": {
      "logradouro": "Rua Exemplo",
      "numero": "100",
      "complemento": null,
      "bairro": "Centro",
      "codigo_municipio": "2104404",
      "municipio_nome": "Presidente Dutra",
      "uf": "MA",
      "cep": "65775000"
    }
  }
}

codigo_municipio é o código IBGE de 7 dígitos (não o nome da cidade) — consulte no site do IBGE. Quando o destinatário tem CNPJ e você informa inscricao_estadual, a API já monta indIEDest=1 (contribuinte) automaticamente — mande "ISENTO" nesse campo se for isento (vira indIEDest=2). Sem endereço, a nota ainda sai válida, mas o DANFE de NF-e fica sem o "canhoto" de entrega completo.

Achado real testado em produção: a API calcula sozinha se a operação é interna ou interestadual (idDest) comparando a UF da sua empresa com a UF do endereço do destinatário — não precisa informar isso.

3. Pagamento (único e dividido)

Uma forma de pagamento

{
  "payment_method": "pix"
}

Valores aceitos: dinheiro (padrão se omitido), cheque, cartao_credito, cartao_debito, credito_loja, vale_alimentacao, vale_refeicao, vale_presente, vale_combustivel, boleto, deposito_bancario, pix, transferencia, sem_pagamento, outros.

pix gera tPag=99 ("Outros") + xPag="PIX", não o código oficial 17 — de propósito, é assim que o PDV do sysvelox já emite em produção. Cartão de crédito/débito sempre inclui tpIntegra=2+tBand=99 no XML (exigido pela SEFAZ mesmo sem dados reais de maquininha).

Pagamento dividido (metade dinheiro, metade cartão, por exemplo)

{
  "payments": [
    { "method": "dinheiro", "amount_cents": 1500 },
    { "method": "cartao_credito", "amount_cents": 1500 }
  ]
}

Quando payments é enviado, ele substitui payment_method — a API monta uma tag <detPag> por entrada da lista. Testado em produção com venda real dividida dinheiro+cartão, autorizada normalmente.

Troco

{
  "payment_method": "dinheiro",
  "change_cents": 500
}

change_cents (troco) só faz sentido com pagamento em dinheiro maior que o total da venda — vira a tag vTroco. Fica de fora do XML automaticamente quando é 0 ou omitido.

4. Desconto, frete, seguro, outras despesas

{
  "discount_cents": 500,
  "freight_cents": 300,
  "insurance_cents": 0,
  "other_expenses_cents": 200,
  "items": [ ... ]
}
CampoO que faz
discount_centsDesconto total da venda, em centavos. Rateado automaticamente entre os itens (proporcional ao valor bruto de cada um) — item com discount_cents próprio usa o valor dele, o resto recebe o rateio.
freight_centsFrete, em centavos — soma no total da nota (vNF).
insurance_centsSeguro, em centavos.
other_expenses_centsOutras despesas/taxas (ex.: taxa de entrega), em centavos.

Todos os quatro são opcionais e independentes — pode usar só o que precisar. Todos sempre em centavos, nunca em reais.

5. ICMS regime normal (valores reais)

Só se aplica quando o item usa cst_icms (Regime Normal, CRT 3) — Simples Nacional (CSOSN) não destaca ICMS próprio, então este campo não se aplica com csosn.

{
  "items": [
    {
      "description": "Produto com ICMS destacado",
      "ncm": "12345678",
      "cfop": "5102",
      "unit": "UN",
      "quantity": 1,
      "unit_price_cents": 10000,
      "cst_icms": "00",
      "icms": {
        "base_cents": 10000,
        "aliquota": 18.0,
        "valor_cents": 1800
      },
      "cst_pis": "01",
      "cst_cofins": "01"
    }
  ]
}

Sem o objeto icms, o regime normal sai com base/alíquota/valor tudo zerado (só o CST é informado). A API não recalcula — os três valores (base_cents, aliquota, valor_cents) são exatamente o que você mandar.

Atenção com o CRT da empresa: se a empresa é Simples Nacional (CRT 1), a SEFAZ rejeita qualquer cst_icms com "Informado CST para emissor do Simples Nacional" — confirmado em teste real. Regime normal só funciona pra empresa CRT 3.

6. IPI

{
  "items": [
    {
      ...,
      "ipi": {
        "cst": "50",
        "enquadramento": "999",
        "base_cents": 10000,
        "aliquota": 5.0,
        "valor_cents": 500
      }
    }
  ]
}

Opcional — sem ele, o item sai com IPI "não tributado" (CST 53, tudo zerado), igual ao padrão de quem não trabalha com produto industrializado.

Só para NF-e (modelo 55). A SEFAZ rejeita o grupo IPI inteiro em NFC-e (modelo 65) — mesmo "não tributado" — com o erro "NFC-e com grupo do IPI". Achado real, testado em produção: a API já sabe disso e nunca monta a tag IPI quando o documento é NFC-e, mesmo que você mande o campo ipi no payload (ele é ignorado silenciosamente pra NFC-e).

7. PIS/COFINS com valores reais

{
  "items": [
    {
      ...,
      "cst_pis": "01",
      "pis": { "base_cents": 10000, "aliquota": 1.65, "valor_cents": 165 },
      "cst_cofins": "01",
      "cofins": { "base_cents": 10000, "aliquota": 7.6, "valor_cents": 760 }
    }
  ]
}

Mesma lógica do ICMS/IPI: sem os objetos pis/cofins, os valores saem zerados (comum com CST 07 isento ou 99 outros). Informe só quando o CST exigir base e alíquota reais (tipicamente 01/02).

8. IBS/CBS (Reforma Tributária)

Grupo opcional da Reforma Tributária (transição 2026-2032). Só entra no XML quando os três campos abaixo vêm juntos por item:

{
  "items": [
    {
      ...,
      "cst_ibs_cbs": "000",
      "cclass_trib": "000001",
      "ibs_cbs": {
        "base_cents": 10000,
        "ibs_uf_aliquota": 0.1,
        "ibs_uf_valor_cents": 10,
        "ibs_mun_aliquota": 0.0,
        "ibs_mun_valor_cents": 0,
        "ibs_valor_cents": 10,
        "cbs_aliquota": 0.9,
        "cbs_valor_cents": 90
      }
    }
  ]
}

A API não calcula as alíquotas de transição por você (elas mudam ano a ano por lei) — você calcula por fora e manda os valores prontos, igual todo o resto desta referência.

9. Transportadora, veículo e volumes

Opcional — normalmente só usado quando há transporte de carga por terceiro (NF-e), não em venda de balcão.

{
  "modalidade_frete": 1,
  "transportadora": {
    "documento": "18088119000123",
    "nome": "Transportes ABC LTDA",
    "inscricao_estadual": "123456789",
    "endereco": "Rua Transportadora, 500",
    "municipio_nome": "São Luís",
    "uf": "MA"
  },
  "veiculo_transporte": {
    "placa": "ABC1234",
    "uf": "MA",
    "rntc": null
  },
  "volumes": {
    "quantidade": 2,
    "especie": "Caixa",
    "marca": "Fragil",
    "numeracao": "1/2",
    "peso_liquido_kg": 5.0,
    "peso_bruto_kg": 6.0
  }
}

modalidade_frete: 0=emitente, 1=destinatário, 2=terceiros, 3=próprio emitente, 4=próprio destinatário, 9=sem transporte (padrão). Se você mandar transportadora sem informar modalidade_frete, a API assume 0 (emitente) — mandar transportadora com "sem transporte" (9) é inconsistente e a SEFAZ pode rejeitar.

10. Devolução

NF-e de devolução referencia a chave da nota original e tem finalidade/indicadores próprios:

{
  "company_id": "emp_xxxxxxxxxxxx",
  "documento_referenciado": "35260545920661000173550040000008201880873311",
  "finalidade": 4,
  "nat_op": "Devolucao de mercadoria",
  "ind_final": 0,
  "ind_pres": 9,
  "payment_method": "sem_pagamento",
  "destinatario": { "documento": "...", "nome": "Fornecedor Original", "endereco": { ... } },
  "items": [
    {
      ...,
      "ipi_devol": { "valor_cents": 500, "percentual_devolvido": 100.0 }
    }
  ]
}
CampoO que é
documento_referenciadoChave de acesso (44 dígitos) da nota original sendo devolvida. Obrigatório quando finalidade=4.
finalidade1=normal (padrão), 2=complementar, 3=ajuste, 4=devolução.
nat_opNatureza da operação (texto livre) — padrão "Venda de mercadoria", ou "Devolucao de mercadoria" automaticamente quando finalidade=4 e você não informar.
ind_final0=não é consumidor final (padrão em devolução), 1=consumidor final (padrão geral).
ind_presIndicador de presença — 9 (não se aplica) é comum em devolução.
items[].ipi_devolCrédito de IPI devolvido (grupo separado do IPI normal), só quando o produto tinha IPI destacado na compra original.

Achado real testado em produção: pagamento em devolução precisa ser sem_pagamento (tPag=90) — mandar qualquer outro método com valor gera rejeição da SEFAZ ("Informado indevidamente campo valor de pagamento"). A API já calcula sozinha se a operação é interna ou interestadual comparando a UF da empresa com a do destinatário (fornecedor original).

11. Consultar, baixar e cancelar

# Status
GET /v1/notas/{id}
Authorization: Bearer sk_live_...

# XML autorizado
GET /v1/notas/{id}/xml

# PDF (DANFE/DANFCE)
GET /v1/notas/{id}/danfe?tipo=a4       # ou ?tipo=termica

# Cancelar (justificativa exige 15+ caracteres, exigência da SEFAZ)
POST /v1/notas/{id}/cancelamento
Content-Type: application/json

{ "justificativa": "Erro de digitação no valor total da venda" }

Cancelamento é síncrono (diferente da emissão) — a resposta já vem com o resultado final, sem precisar consultar depois. Só funciona pra documento com status authorized.

12. Tabela de todos os campos do payload

CampoNívelTipo
company_idraizstring, obrigatório
itemsraizlista, obrigatório
payment_methodraizstring, opcional (padrão dinheiro)
paymentsraizlista, opcional — substitui payment_method
change_centsraizint (centavos), opcional
discount_centsraizint (centavos), opcional
freight_cents / insurance_cents / other_expenses_centsraizint (centavos), opcional
destinatarioraizobjeto, opcional
transportadora / veiculo_transporte / volumesraizobjetos, opcionais
modalidade_freteraizint 0-4 ou 9, opcional
documento_referenciado / finalidade / nat_op / ind_final / ind_presraizdevolução, opcionais
description / ncm / cfop / unit / quantity / unit_price_centsitemobrigatórios
origem_mercadoria / cest / discount_centsitemopcionais
csosn ou cst_icms + icmsitemum dos dois obrigatório
ipi / ipi_devolitemopcionais (ipi só NF-e)
cst_pis + pis / cst_cofins + cofinsitemcst_* obrigatórios, objetos opcionais
cst_ibs_cbs / cclass_trib / ibs_cbsitemopcionais, os três juntos

Pronto pra ver isso em código?

Todos os campos desta página, comentados, prontos pra copiar e adaptar.

Ver modelos de código