Pular para o conteúdo principal

Documentação Técnica para Desenvolvedores — DFe Inbound

  • Produto: DFe Inbound — Recepção de NF-e e CT-e
  • Público: Desenvolvedores que integram sistemas com a API nfe.io
  • Versão da API: v2

Índice

  1. Introdução
  2. Guia de Primeiros Passos
  3. Conceitos Fundamentais
  4. Autenticação
  5. URL Base e Ambientes
  6. Ativando o Serviço de Inbound
  7. Endpoints de NF-e
  8. Endpoints de CT-e
  9. Consulta com OData (CT-e)
  10. Webhooks — Recebendo Notificações
  11. Referência de Tipos e Enums
  12. Tratamento de Erros
  13. Exemplos de Integração
  14. Perguntas Frequentes (FAQ)

1. Introdução

O DFe Inbound da nfe.io é um serviço que monitora automaticamente a SEFAZ e captura todos os Documentos Fiscais Eletrônicos (NF-e e CT-e) emitidos por terceiros que têm como destinatário o CNPJ da sua empresa.

O que você ganha com este serviço?

  • Recepção automática: Sem precisar acessar o portal da SEFAZ manualmente.
  • XML armazenado: Os XMLs ficam disponíveis para download via API a qualquer momento.
  • Notificações em tempo real: Receba webhooks assim que um documento chegar.
  • Dados estruturados: Consulte metadados (emitente, valor, data) sem precisar parsear XML.
  • Histórico completo: Acesso a documentos recebidos nos últimos 90 dias (ou desde o NSU configurado).

Visão Geral da Integração

SEFAZ (Ambiente Nacional)

│ (Polling automático via NSU)

nfe.io DFe Inbound

├──▶ Armazena XML no cloud storage
├──▶ Salva metadados (emitente, valor, data...)
└──▶ Dispara Webhook ──▶ SEU SISTEMA

├── Consulta metadados via API
└── Baixa XML via API

2. Guia de Primeiros Passos

Se você está integrando pela primeira vez, siga esta sequência em ordem. Não pule etapas.

Etapa 1 — Obter credenciais

No painel nfe.io, crie uma API Key em Configurações → Chaves de API. Guarde-a com segurança — ela só é exibida uma vez.

Etapa 2 — Localizar seu company_id

Em Empresas, clique na empresa que deseja integrar e copie o company_id exibido na URL ou nos detalhes da empresa.

Etapa 3 — Ativar o inbound

Faça uma requisição para ativar o monitoramento do CNPJ:

curl -X POST \
"https://api.nfe.io/v2/companies/SEU_COMPANY_ID/inbound/productinvoices" \
-H "Authorization: ApiKey SUA_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"StartFromNsu": 0,
"StartFromDate": "2024-01-01T00:00:00Z",
"EnvironmentSEFAZ": "Production",
"WebhookVersion": 2
}'

Resposta esperada: { "status": "Active", ... }

Etapa 4 — Configurar seu endpoint de webhook

No painel nfe.io, vá em Webhooks e cadastre a URL do seu servidor que vai receber as notificações.

Mínimo necessário no seu endpoint:

# Python (Flask)
@app.route('/webhook', methods=['POST'])
def webhook():
data = request.json
access_key = data['accessKey']
# Processar...
return '', 200 # OBRIGATÓRIO retornar 200

Etapa 5 — Verificar que documentos chegam

Após ativar, aguarde entre 15 minutos e 4 horas. Consulte documentos recebidos:

curl "https://api.nfe.io/v2/companies/SEU_COMPANY_ID/inbound/productinvoices/CHAVE_44_DIGITOS" \
-H "Authorization: ApiKey SUA_API_KEY"

Etapa 6 — Migrar para produção

Quando seus testes estiverem OK com "EnvironmentSEFAZ": "Test", recrie a configuração com "Production":

# 1. Desativar o inbound de homologação
curl -X DELETE \
"https://api.nfe.io/v2/companies/SEU_COMPANY_ID/inbound/productinvoices" \
-H "Authorization: ApiKey SUA_API_KEY"

# 2. Ativar com ambiente de produção
curl -X POST \
"https://api.nfe.io/v2/companies/SEU_COMPANY_ID/inbound/productinvoices" \
-H "Authorization: ApiKey SUA_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"StartFromNsu": 0,
"StartFromDate": "2024-01-01T00:00:00Z",
"EnvironmentSEFAZ": "Production",
"WebhookVersion": 2
}'

Importante: Documentos de ambiente Test (homologação SEFAZ) e Production são separados. Nunca misture os dois na mesma configuração.


3. Conceitos Fundamentais

NSU — Número Sequencial Único

O NSU é um número mantido pela SEFAZ que cresce a cada documento recebido pelo seu CNPJ. Pense nele como um "contador de correspondências" da SEFAZ para a sua empresa.

Exemplo:

  • NSU 1000: NF-e de fornecedor A, valor R$ 500
  • NSU 1001: NF-e de fornecedor B, valor R$ 1.200
  • NSU 1002: Evento de cancelamento da NF-e do fornecedor A

Nosso serviço consulta a SEFAZ periodicamente e baixa todos os documentos a partir do último NSU processado.

Chave de Acesso (access_key)

É um código de 44 dígitos que identifica unicamente uma NF-e ou CT-e. Exemplo:

35240112345678000195550010000012341234567890
│ │ │ │ │ │
│ │ │ │ │ └─── Dígito verificador
│ │ │ │ └────── Número NF-e
│ │ │ └─────────── Série
│ │ └────────────────────────── CNPJ emitente
│ └──────────────────────────── Mês/Ano emissão (AAAAMM)
└─────────────────────────────── UF (35 = SP)

Para eventos (cancelamento, ciência, etc.), a chave tem 55 dígitos.

Identificando o tipo de documento pela chave

A posição 20-21 da chave de acesso (0-indexed) indica o modelo do documento:

Posição 20-21TipoDescrição
55NF-eNota Fiscal Eletrônica
57CT-eConhecimento de Transporte Eletrônico
65NFC-eNota Fiscal de Consumidor
67CT-eOSCT-e para Outros Serviços
def get_document_type(access_key: str) -> str:
model = access_key[20:22] # posições 20 e 21
types = {"55": "NF-e", "57": "CT-e", "65": "NFC-e", "67": "CT-eOS"}
return types.get(model, "Desconhecido")

Tipos de Registro retornados pela API

MetadataResourceTypeSignificado
productInvoiceNF-e completa (XML disponível)
productInvoiceEventEvento de NF-e (cancelamento, ciência, etc.)
productInvoiceSummaryResumo de NF-e (apenas metadados básicos)
productInvoiceEventSummaryResumo de evento
transportationInvoiceCT-e completo
transportationInvoiceEventEvento de CT-e

4. Autenticação

Todas as requisições exigem autenticação. Suportamos dois métodos:

Método 1 — API Key (recomendado para integração server-to-server)

Passe a chave de API no header Authorization:

Authorization: ApiKey SUA_API_KEY_AQUI

Onde obter a API Key: Painel nfe.io → Configurações → Chaves de API.

Método 2 — Bearer Token (JWT)

Use um token JWT gerado via https://id.nfe.io:

Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...

Exemplo de Requisição com Autenticação

curl -X GET \
"https://api.nfe.io/v2/companies/comp_123/inbound/productinvoices" \
-H "Authorization: ApiKey sk_live_abc123..."

5. URL Base e Ambientes

AmbienteURL Base
Produçãohttps://api.nfe.io
Sandbox (testes)https://api.sandbox.nfe.io

Estrutura da URL:

{url_base}/v2/companies/{company_id}/inbound/...

O company_id é o identificador da sua empresa na plataforma nfe.io (encontrado no Painel → Empresas).


6. Ativando o Serviço de Inbound

Antes de receber documentos, você precisa ativar o serviço de inbound para cada CNPJ que deseja monitorar.

Ativar Inbound de NF-e

POST /v2/companies/{company_id}/inbound/productinvoices
Authorization: ApiKey {api_key}
Content-Type: application/json

{
"StartFromNsu": 0,
"StartFromDate": "2024-01-01T00:00:00Z",
"EnvironmentSEFAZ": "Production",
"AutomaticManifesting": {
"MinutesToWaitAwarenessOperation": 60
},
"WebhookVersion": 2
}

Campos do corpo:

CampoTipoObrigatórioDescrição
StartFromNsulongNãoNSU inicial. 0 = busca desde o início. Use um NSU específico para sincronizar com histórico
StartFromDateDateTimeNãoData inicial para busca. Padrão: 90 dias atrás
EnvironmentSEFAZstringSim"Production" (produção SEFAZ) ou "Test" (homologação SEFAZ)
EventTypestringNãoFiltro de tipos de evento (códigos separados por vírgula). null = todos
SchemaintNão0=NF-e + Eventos, 1=Somente NF-e, 2=Somente Eventos
AutomaticManifesting.MinutesToWaitAwarenessOperationintNãoMinutos aguardados antes de auto-manifestar ciência. Mínimo: 5
WebhookVersionintNãoVersão do formato de webhook. Use 2 (mais recente)

Resposta de sucesso (200):

{
"companyId": "comp_123",
"environmentSEFAZ": "Production",
"startFromNsu": 0,
"startFromDate": "2024-01-01T00:00:00Z",
"status": "Active",
"createdOn": "2024-03-15T10:30:00Z"
}

Ativar Inbound de CT-e

POST /v2/companies/{company_id}/inbound/transportationinvoices
Authorization: ApiKey {api_key}
Content-Type: application/json

{
"StartFromNsu": 0,
"StartFromDate": "2024-01-01T00:00:00Z",
"EnvironmentSEFAZ": "Production"
}

Verificar Configuração Atual

GET /v2/companies/{company_id}/inbound/productinvoices
Authorization: ApiKey {api_key}

Desativar Inbound

DELETE /v2/companies/{company_id}/inbound/productinvoices
Authorization: ApiKey {api_key}

7. Endpoints de NF-e

Buscar Metadados de uma NF-e

Retorna os dados estruturados de uma NF-e pela sua chave de acesso.

GET /v2/companies/{company_id}/inbound/productinvoices/{access_key}
Authorization: ApiKey {api_key}

Parâmetros de URL:

  • company_id: ID da sua empresa na nfe.io
  • access_key: Chave de acesso de 44 dígitos da NF-e

Resposta de sucesso (200):

{
"accessKey": "35240112345678000195550010000012341234567890",
"createdOn": "2024-03-15T14:22:10Z",
"nsu": "21825",
"nsuParent": null,
"nfeNumber": "1234",
"nfeSerialNumber": "1",
"issuedOn": "2024-03-15T10:00:00Z",
"type": "productInvoice",
"description": "Autorizado o uso da NF-e",
"totalInvoiceAmount": "1500.00",
"operationType": "Incoming",
"issuer": {
"federalTaxNumber": "12345678000195",
"name": "Fornecedor LTDA"
},
"buyer": {
"federalTaxNumber": "98765432000100",
"name": "Minha Empresa S.A."
},
"company": {
"id": "comp_123",
"federalTaxNumber": "98765432000100"
},
"links": {
"xml": "https://storage.nfe.io/temp/xml/...",
"pdf": "https://storage.nfe.io/temp/pdf/..."
}
}

Descrição dos campos:

CampoTipoDescrição
accessKeystringChave de acesso 44 dígitos
createdOnDateTimeQuando o documento entrou no sistema
nsustringNúmero Sequencial Único na SEFAZ
nfeNumberstringNúmero da NF-e
nfeSerialNumberstringSérie da NF-e
issuedOnDateTimeData de emissão
typestringproductInvoice, productInvoiceEvent, productInvoiceSummary
descriptionstringStatus da NF-e (ex: "Autorizado o uso da NF-e")
totalInvoiceAmountstringValor total em reais
operationTypestringIncoming (destinatário) ou Outgoing (emitente)
issuerobjectDados do emitente (quem emitiu a NF-e)
buyerobjectDados do destinatário (comprador)
links.xmlstringURL temporária para download do XML (expira em 1 hora)
links.pdfstringURL temporária para download do PDF/DANFE

Baixar XML de uma NF-e

GET /v2/companies/{company_id}/inbound/productinvoices/{access_key}/xml
Authorization: ApiKey {api_key}

# Retorna o arquivo XML diretamente (Content-Type: application/xml)

Alternativamente, use a URL temporária retornada em links.xml para download direto do storage (sem precisar passar pela API). Esse link expira em 1 hora.

Baixar PDF (DANFE) de uma NF-e

GET /v2/companies/{company_id}/inbound/productinvoices/{access_key}/pdf
Authorization: ApiKey {api_key}

# Retorna o arquivo PDF (Content-Type: application/pdf)

Buscar Dados de um Evento de NF-e

Eventos são ações sobre a NF-e: cancelamento, ciência, confirmação de operação, etc.

GET /v2/companies/{company_id}/inbound/productinvoices/{access_key}/events/{event_key}
Authorization: ApiKey {api_key}

O event_key tem 55 dígitos (chave de acesso da NF-e + código do evento + sequência).

Registrar Manifestação

A manifestação é o processo pelo qual o destinatário comunica à SEFAZ que tem conhecimento da NF-e. É obrigatória para NF-es de entrada.

POST /v2/companies/{company_id}/inbound/{access_key}/manifest?tpEvent=210210
Authorization: ApiKey {api_key}

Tipos de manifestação (tpEvent):

CódigoTipoDescrição
210210Ciência da Operação"Estou ciente desta NF-e" (não confirma recebimento físico)
210200Confirmação da Operação"Recebi a mercadoria conforme NF-e"
210220Desconhecimento da Operação"Não reconheço esta operação"
210240Operação não Realizada"A operação não foi concluída"

Resposta (200):

"Manifestação registrada com sucesso"

Manifestação Automática: Se você configurou AutomaticManifesting.MinutesToWaitAwarenessOperation, o sistema registrará "Ciência da Operação" automaticamente após esse intervalo. Você não precisa chamar este endpoint para ciência se tiver auto-manifestação ativa.

Reprocessar Webhook de uma NF-e

Use quando o webhook não foi entregue ou precisa ser reenviado.

POST /v2/companies/{company_id}/inbound/productinvoices/{access_key}/processwebhook
Authorization: ApiKey {api_key}

# Ou por NSU:
POST /v2/companies/{company_id}/inbound/productinvoices/{nsu}/processwebhook

8. Endpoints de CT-e

Ativar e Configurar CT-e

Veja a seção Ativando o Serviço de Inbound — o processo é idêntico ao NF-e mas no endpoint /transportationinvoices.

Buscar Metadados de um CT-e

GET /v2/companies/{company_id}/inbound/{access_key}
Authorization: ApiKey {api_key}

Resposta (200):

{
"id": "abc123",
"accessKey": "35240198765432000100570010000009871234567890",
"createdOn": "2024-03-15T14:22:10Z",
"nsu": 10042,
"type": "transportationInvoice",
"description": "Autorizado o uso do CT-e",
"company": {
"id": "comp_123",
"federalTaxNumber": "98765432000100"
},
"issuer": {
"federalTaxNumber": "11111111000100",
"name": "Transportadora ABC LTDA"
},
"taker": {
"federalTaxNumber": "98765432000100",
"name": "Minha Empresa S.A."
},
"totalAmount": 350.00,
"issuedOn": "2024-03-15T10:00:00Z",
"xmlUrl": "https://storage.nfe.io/temp/cte/..."
}

Campos específicos do CT-e:

CampoTipoDescrição
issuerobjectA transportadora que emitiu o CT-e
takerobjectTomador do serviço de transporte
totalAmountdecimalValor do serviço de transporte
issuedOnDateTimeData de emissão do CT-e
xmlUrlstringURL temporária para download do XML (expira em 1 hora)

Baixar XML de um CT-e

GET /v2/companies/{company_id}/inbound/{access_key}/xml
Authorization: ApiKey {api_key}

# Retorna o arquivo XML (Content-Type: application/xml)

Reprocessar Webhooks de CT-e

POST /v2/companies/{company_id}/inbound/transportationinvoices/reprocess/webhook
Authorization: ApiKey {api_key}
Content-Type: application/json

{
"Key": "35240198765432000100570010000009871234567890",
"Date": "2024-03-15"
}

Reprocessar NSUs Específicos

Útil quando um NSU falhou no processamento:

PUT /v2/companies/{company_id}/inbound/transportationinvoices/reprocess/item
Authorization: ApiKey {api_key}
Content-Type: application/json

[10042, 10043, 10044]

Consolidação de Batch

Consolida batches em um intervalo de NSU:

PUT /v2/companies/{company_id}/inbound/transportationinvoices/batch/consolidation
Authorization: ApiKey {api_key}
Content-Type: application/json

{
"StartNSU": 10000,
"EndNSU": 10500
}

9. Consulta com OData (CT-e)

O endpoint OData permite consultas avançadas com filtros, ordenação e paginação.

Buscar Lista de CT-es

GET /v2/companies/{company_id}/inbound/odata/TransportationInvoices
Authorization: ApiKey {api_key}

Parâmetros OData Suportados

ParâmetroDescriçãoExemplo
$filterFiltra registrosissuedOn ge 2024-01-01
$topMáximo de registros por página (máx: 1000)$top=100
$skipIgnora N registros (offset)$skip=200
$skiptokenToken de paginação (mais eficiente que skip)$skiptoken=abc123
$orderbyOrdenação$orderby=issuedOn desc
$selectSeleciona campos específicos$select=accessKey,issuedOn

Exemplos de Filtros

CT-es do mês de janeiro de 2024:

GET /v2/companies/{company_id}/inbound/odata/TransportationInvoices
?$filter=issuedOn ge 2024-01-01T00:00:00Z and issuedOn lt 2024-02-01T00:00:00Z
&$top=100
&$orderby=issuedOn desc

CT-es com NSU maior que 5000:

GET /v2/companies/{company_id}/inbound/odata/TransportationInvoices
?$filter=nsu gt 5000
&$top=50

Paginação com $skiptoken

Para listas grandes, use $skiptoken em vez de $skip. O token é retornado na resposta quando há mais páginas:

{
"@odata.context": "...",
"@odata.nextLink": "https://api.nfe.io/v2/companies/comp_123/inbound/odata/TransportationInvoices?$skiptoken=abc123",
"value": [
{ "accessKey": "...", "issuedOn": "..." },
{ "accessKey": "...", "issuedOn": "..." }
]
}

Na próxima requisição, use a URL de @odata.nextLink diretamente.

Buscar Eventos de CT-e

GET /v2/companies/{company_id}/inbound/odata/TransportationInvoiceEvents
?$filter=receiptOn ge 2024-01-01T00:00:00Z
&$top=100

O campo de filtro para eventos é receiptOn (data de recebimento) em vez de issuedOn.

10. Webhooks — Recebendo Notificações

O webhook permite que seu sistema seja notificado automaticamente quando um novo documento é recebido.

Como Configurar

  1. Acesse o Painel nfe.io -> Empresas -> {sua empresa} -> Webhooks
  2. Cadastre a URL do seu endpoint
  3. Ative o inbound (como descrito na seção 6) com WebhookVersion: 2

Formato do Payload (Webhook v2)

Quando um documento é recebido, fazemos um POST para sua URL com o seguinte corpo:

{
"event": "nfe.received",
"companyId": "comp_123",
"accessKey": "35240112345678000195550010000012341234567890",
"nsu": "21825",
"type": "productInvoice",
"issuedOn": "2024-03-15T10:00:00Z",
"totalAmount": 1500.00,
"issuer": {
"federalTaxNumber": "12345678000195",
"name": "Fornecedor LTDA"
},
"buyer": {
"federalTaxNumber": "98765432000100",
"name": "Minha Empresa S.A."
}
}

Tipos de evento (event):

EventoQuando ocorre
nfe.receivedNova NF-e recebida
nfe.event.receivedEvento de NF-e recebido (cancelamento, etc.)
cte.receivedNovo CT-e recebido
cte.event.receivedEvento de CT-e recebido

Respondendo ao Webhook

Seu endpoint deve retornar HTTP 200 em até 30 segundos. Se não retornar 200, tentaremos novamente com backoff exponencial por até 24 horas.

# Exemplo em Python (Flask)
from flask import Flask, request, jsonify

app = Flask(__name__)

@app.route('/webhooks/nfeio', methods=['POST'])
def receive_nfe():
payload = request.json

if payload['event'] == 'nfe.received':
access_key = payload['accessKey']
# Processar o documento...
save_to_database(payload)

return jsonify({"status": "ok"}), 200

Validando a Autenticidade do Webhook

Para garantir que a requisição realmente veio da nfe.io e não de terceiros mal-intencionados, valide o header de assinatura:

import hmac
import hashlib

def validate_webhook(payload_bytes: bytes, received_signature: str, secret: str) -> bool:
"""
Valida que o webhook veio da nfe.io usando HMAC-SHA256.

- payload_bytes: corpo da requisição em bytes (sem decodificar)
- received_signature: valor do header X-NFe-Signature
- secret: seu webhook secret configurado no painel nfe.io
"""
expected = hmac.new(
secret.encode('utf-8'),
payload_bytes,
hashlib.sha256
).hexdigest()
return hmac.compare_digest(expected, received_signature)

# No seu endpoint:
@app.route('/webhooks/nfeio', methods=['POST'])
def receive_webhook():
signature = request.headers.get('X-NFe-Signature', '')

if not validate_webhook(request.data, signature, 'seu_secret_aqui'):
return 'Assinatura inválida', 401

# Processar...
return '', 200

Configure o Webhook Secret no painel nfe.io → Webhooks. Sem ele, qualquer pessoa que descobrir sua URL pode simular notificações.

Reprocessar um Webhook

Se precisar receber novamente o webhook de um documento específico:

POST /v2/companies/{company_id}/inbound/productinvoices/{access_key}/processwebhook
Authorization: ApiKey {api_key}

11. Referência de Tipos e Enums

EnvironmentSEFAZ

ValorDescrição
"Test"Ambiente de homologação SEFAZ — documentos sem validade fiscal
"Production"Ambiente de produção SEFAZ — documentos com validade fiscal real

OperationType

ValorDescrição
"Incoming"Você é o destinatário (recebeu o documento)
"Outgoing"Você é o emitente (emitiu o documento)

MetadataResourceType

ValorDescrição
"productInvoice"NF-e completa
"productInvoiceEvent"Evento de NF-e
"productInvoiceSummary"Resumo de NF-e (sem XML completo)
"productInvoiceEventSummary"Resumo de evento de NF-e
"transportationInvoice"CT-e
"transportationInvoiceEvent"Evento de CT-e

EntityStatus

ValorDescrição
"Active"Configuração ativa — sistema monitorando
"Inactive"Configuração inativa — sem monitoramento

12. Tratamento de Erros

Formato do Erro

Quando ocorre um erro, a API retorna um JSON no seguinte formato:

{
"errors": [
{
"code": 404,
"message": "Document not found for the given access key."
}
]
}

Códigos HTTP

HTTPSignificaO que fazer
200SucessoProcesse a resposta normalmente
204Sucesso sem conteúdoOperação realizada, sem corpo de resposta
400Requisição inválidaVerifique os parâmetros enviados
401Não autorizadoVerifique sua API Key ou token
403ProibidoSua conta não tem permissão para este recurso
404Não encontradoO documento/empresa não existe
409Conflito (duplicado)Recurso já existe
422Entidade não processávelDados válidos mas não processáveis (ex: NF-e cancelada)
503Serviço indisponívelSEFAZ temporariamente fora. Tente novamente em alguns minutos
504TimeoutA operação demorou muito. Tente novamente
500Erro internoEntre em contato com o suporte

Headers de Rate Limiting

Todas as respostas incluem headers indicando o status do rate limit:

HeaderDescrição
X-RateLimit-LimitTotal de requisições permitidas por janela
X-RateLimit-RemainingRequisições restantes na janela atual
X-RateLimit-ResetTimestamp Unix quando a janela reinicia

Quando o limite é excedido, a API retorna 429 Too Many Requests. Aguarde até X-RateLimit-Reset antes de tentar novamente.

Estratégia de Retry

Para erros 429, 503 e 504, recomendamos retry com backoff exponencial:

import time
import requests

def get_with_retry(url, headers, max_retries=3):
for attempt in range(max_retries):
response = requests.get(url, headers=headers)

if response.status_code == 429:
reset_time = int(response.headers.get('X-RateLimit-Reset', time.time() + 60))
wait_time = max(reset_time - time.time(), 1)
time.sleep(wait_time)
continue

if response.status_code in (503, 504):
wait_time = (2 ** attempt) * 1 # 1s, 2s, 4s
time.sleep(wait_time)
continue

return response

raise Exception("Max retries exceeded")

13. Exemplos de Integração

Exemplo 1 — Buscar NF-e por Chave de Acesso (C#)

using System.Net.Http;
using System.Text.Json;

public class NfeIoClient
{
private readonly HttpClient _http;
private readonly string _companyId;
private readonly string _baseUrl = "https://api.nfe.io";

public NfeIoClient(string apiKey, string companyId)
{
_companyId = companyId;
_http = new HttpClient();
_http.DefaultRequestHeaders.Add("Authorization", $"ApiKey {apiKey}");
}

public async Task<NfeMetadata> GetNfeAsync(string accessKey)
{
var url = $"{_baseUrl}/v2/companies/{_companyId}/inbound/productinvoices/{accessKey}";
var response = await _http.GetAsync(url);

response.EnsureSuccessStatusCode();

var content = await response.Content.ReadAsStringAsync();
return JsonSerializer.Deserialize<NfeMetadata>(content);
}

public async Task<Stream> GetNfeXmlAsync(string accessKey)
{
var url = $"{_baseUrl}/v2/companies/{_companyId}/inbound/productinvoices/{accessKey}/xml";
return await _http.GetStreamAsync(url);
}
}

Exemplo 2 — Consumir Webhook e Baixar XML (Node.js)

const express = require('express');
const axios = require('axios');
const crypto = require('crypto');
const app = express();

app.use(express.raw({ type: 'application/json' })); // raw para validar assinatura

const API_KEY = 'sk_live_sua_chave_aqui';
const COMPANY_ID = 'comp_123';
const WEBHOOK_SECRET = 'seu_webhook_secret';
const BASE_URL = 'https://api.nfe.io';

function validateSignature(payload, signature, secret) {
const expected = crypto
.createHmac('sha256', secret)
.update(payload)
.digest('hex');
return crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(signature));
}

app.post('/webhooks/nfeio', async (req, res) => {
// Validar assinatura
const signature = req.headers['x-nfe-signature'] || '';
if (!validateSignature(req.body, signature, WEBHOOK_SECRET)) {
return res.status(401).send('Assinatura inválida');
}

const payload = JSON.parse(req.body);
const { event, accessKey, type, issuer, totalAmount } = payload;

console.log(`Novo documento: ${accessKey} - ${event}`);

try {
const xmlResponse = await axios.get(
`${BASE_URL}/v2/companies/${COMPANY_ID}/inbound/productinvoices/${accessKey}/xml`,
{ headers: { 'Authorization': `ApiKey ${API_KEY}` }, responseType: 'text' }
);

await saveDocumentToDatabase({ accessKey, type, issuer, totalAmount, xml: xmlResponse.data });

res.status(200).json({ status: 'ok' });
} catch (error) {
console.error('Erro:', error);
res.status(500).json({ error: error.message });
}
});

app.listen(3000);

Exemplo 3 — Listar CT-es do Último Mês com Paginação (Python)

import requests
from datetime import datetime, timedelta

API_KEY = "sk_live_sua_chave"
COMPANY_ID = "comp_123"
BASE_URL = "https://api.nfe.io"

def get_all_ctes_last_month():
"""Busca todos os CT-es do último mês usando paginação OData."""

today = datetime.utcnow()
last_month = today - timedelta(days=30)

start_date = last_month.strftime("%Y-%m-%dT%H:%M:%SZ")
end_date = today.strftime("%Y-%m-%dT%H:%M:%SZ")

url = (
f"{BASE_URL}/v2/companies/{COMPANY_ID}/inbound/odata/TransportationInvoices"
f"?$filter=issuedOn ge {start_date} and issuedOn lt {end_date}"
f"&$top=100"
f"&$orderby=issuedOn desc"
)

headers = {"Authorization": f"ApiKey {API_KEY}"}
all_ctes = []

while url:
response = requests.get(url, headers=headers)
response.raise_for_status()

data = response.json()
all_ctes.extend(data.get("value", []))

# OData retorna próxima página via @odata.nextLink
url = data.get("@odata.nextLink")
print(f"Buscados {len(all_ctes)} CT-es até agora...")

return all_ctes

ctes = get_all_ctes_last_month()
print(f"Total: {len(ctes)} CT-es")
for cte in ctes[:5]:
print(f" - {cte['accessKey']} | Emitido em: {cte['issuedOn']}")

Exemplo 4 — Ativar Inbound e Aguardar Primeiro Documento (PHP)

<?php

class NfeIoInbound
{
private string $apiKey;
private string $companyId;
private string $baseUrl = 'https://api.nfe.io';

public function __construct(string $apiKey, string $companyId)
{
$this->apiKey = $apiKey;
$this->companyId = $companyId;
}

private function makeRequest(string $method, string $path, ?array $body = null): array
{
$url = "{$this->baseUrl}/v2/companies/{$this->companyId}/{$path}";

$ch = curl_init();
curl_setopt_array($ch, [
CURLOPT_URL => $url,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_CUSTOMREQUEST => $method,
CURLOPT_HTTPHEADER => [
"Authorization: ApiKey {$this->apiKey}",
"Content-Type: application/json"
],
]);

if ($body) {
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($body));
}

$response = curl_exec($ch);
$statusCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);

if ($statusCode >= 400) {
throw new RuntimeException("API Error {$statusCode}: {$response}");
}

return json_decode($response, true);
}

public function enableNfeInbound(string $startDate = null): array
{
return $this->makeRequest('POST', 'inbound/productinvoices', [
'StartFromNsu' => 0,
'StartFromDate' => $startDate ?? date('Y-m-d\TH:i:s\Z', strtotime('-90 days')),
'EnvironmentSEFAZ' => 'Production',
'WebhookVersion' => 2,
]);
}

public function getNfeMetadata(string $accessKey): array
{
return $this->makeRequest('GET', "inbound/productinvoices/{$accessKey}");
}
}

// Uso:
$client = new NfeIoInbound('sk_live_abc123', 'comp_123');
$config = $client->enableNfeInbound('2024-01-01T00:00:00Z');
echo "Inbound ativado! Status: " . $config['status'];

14. Perguntas Frequentes (FAQ)

Quanto tempo leva para receber um documento após a emissão?

Em condições normais, entre 30 minutos e 4 horas após a autorização da SEFAZ. O nosso sistema faz polling periódico na SEFAZ; o intervalo depende da configuração, da sincronização entre a SEFAZ de origem e o Ambiente Nacional e da disponibilidade da SEFAZ.

O que é um "resumo" (productInvoiceSummary)?

Quando o XML completo ainda não está disponível no Ambiente Nacional, a SEFAZ retorna apenas um resumo com os dados básicos da NF-e. Eventualmente, o documento completo chega e é atualizado automaticamente.

Posso buscar documentos históricos?

Sim. A SEFAZ mantém documentos disponíveis por até 90 dias para consulta via NSU. Configure StartFromDate ou StartFromNsu ao ativar o inbound para sincronizar o histórico.

A URL do XML expira?

Sim. As URLs retornadas em links.xml e links.pdf expiram em 1 hora. Para download, use a URL logo após obtê-la, ou chame o endpoint /xml a qualquer momento para obter uma nova URL.

O que acontece se meu webhook estiver fora do ar?

O sistema tentará reenviar o webhook com backoff exponencial por até 24 horas. Após esse período, você pode usar o endpoint de reprocessamento para solicitar novo envio.

Preciso manifestar todas as NF-es?

Pela legislação brasileira, o destinatário deve manifestar ciência de operação para NF-es de entrada (que você está comprando). Configure AutomaticManifesting para que o sistema faça isso automaticamente.

Como testar sem afetar o ambiente de produção?

Configure com EnvironmentSEFAZ: "Test" para usar o ambiente de homologação SEFAZ. Documentos emitidos em homologação não têm validade fiscal. Ao terminar os testes, delete a configuração e recrie com "Production".

Qual o limite de requisições?

Por padrão, o limite é de 60 requisições por minuto por empresa. Os headers X-RateLimit-Limit, X-RateLimit-Remaining e X-RateLimit-Reset informam o status atual. Para limites maiores, entre em contato com o suporte nfe.io.

Como saber se o inbound está atrasado?

Consulte GET /productinvoices e compare OperationDetail_CurrentNsu com OperationDetail_MaxNsu. Se a diferença for grande e OperationDetail_ExecutedOn for antigo, pode haver um problema. Verifique se a configuração está Active e se o certificado digital não expirou.


Documentação mantida pela equipe de desenvolvimento nfe.io. Para reportar problemas ou solicitar funcionalidades, acesse o suporte em nfe.io/suporte.

NFE.io

A NFE.io é uma empresa de tecnologia que fornece soluções para automatizar e simplificar a emissão e gestão de notas fiscais eletrônicas. Com suas ferramentas, as empresas podem economizar tempo e reduzir erros, aumentando a eficiência e precisão do processo de emissão de notas fiscais.

Um dos principais cases de sucesso da NFE.io é a implementação da solução na empresa de transporte Rodonaves. Com a automatização da emissão e gestão de notas fiscais eletrônicas, a Rodonaves conseguiu reduzir em até 80% o tempo gasto nesse processo, o que se traduziu em uma significativa melhoria na eficiência operacional. Além disso, a empresa também conseguiu eliminar erros e atrasos na emissão de notas fiscais, o que melhorou a relação com seus clientes e aumentou a confiança dos órgãos fiscais.

Outro exemplo é a implementação da NFE.io na empresa de comércio eletrônico, a Loja Integrada. Com a automatização da emissão de notas fiscais, a Loja Integrada conseguiu aumentar a velocidade de emissão de notas em até 10 vezes, o que permitiu que a empresa atendesse a uma maior quantidade de clientes e, consequentemente, aumentar as suas vendas.

Além desses exemplos, a NFE.io também tem outros cases de sucesso com empresas de setores como indústria, construção, varejo e serviços, mostrando a versatilidade e eficácia da sua solução.

Em resumo, a NFE.io é uma empresa de tecnologia que oferece soluções para automatizar e simplificar a emissão e gestão de notas fiscais eletrônicas, ajudando as empresas a economizar tempo e reduzir erros, melhorando a eficiência e precisão do processo. Com cases de sucesso em diferentes setores, a NFE.io tem se destacado como uma empresa líder em automação fiscal.