Ir para o conteúdo
Documentação

DF-e: notas recebidas

O DF-e de entrada traz para o seu sistema as NF-e que fornecedores emitiram contra o CNPJ do seu emitente. O MadNotas baixa essas notas do Ambiente Nacional da SEFAZ, guarda e entrega para você pela API. Você lê, manifesta (ciência, confirmação…) e importa o XML.

Palavras desta página. Ambiente Nacional é o serviço da SEFAZ que distribui as notas recebidas. NSU é o número de ordem de cada documento que ele distribui. Resumo é o aviso curto de que a nota existe (sem os itens). XML completo é a nota inteira. Manifestar é dizer à SEFAZ o que você fez com a nota: ciência, confirmação, desconhecimento ou operação não realizada.

Vale só para NF-e modelo 55. A NFC-e não entra na distribuição, e a NFS-e em que você é o tomador também não.

Ligar o DF-e no emitente

O DF-e é por emitente (por CNPJ) e começa desligado. Em homologação e produção, o emitente precisa de certificado A1 válido: a SEFAZ entrega as notas ao dono do certificado. Sem ele, 422 certificado_indisponivel. Em simulação não precisa.

PUT /emitentes/{id}/dfe
curl -X PUT "$MADNOTAS_URL/emitentes/12/dfe" \
  -H "Authorization: Bearer $MADNOTAS_CHAVE" \
  -H "Content-Type: application/json" \
  -d '{"habilitado":true}'

A resposta é o emitente, com o bloco dfe (habilitado e a situação da distribuição). Enquanto estiver desligado, as rotas de situação, sincronização, simulação e manifestação respondem 422 dfe_nao_habilitado.

Quem consulta a SEFAZ é o MadNotas, não você

O Ambiente Nacional tem regras duras de frequência: quem consulta demais recebe o erro 656 (consumo indevido) e fica bloqueado por uma hora. Por isso o seu sistema nunca dispara a consulta. Você lê as notas do banco do MadNotas, e um job do MadNotas faz as consultas, uma por emitente, no ritmo que a SEFAZ aceita.

O que o job faz, para você saber o que esperar:

  1. Guarda, por emitente e ambiente, o último NSU gravado. Cada consulta pede “a partir do último NSU”: nunca recomeça do zero e nunca pula número.
  2. Quando a SEFAZ devolve documentos, grava todos e consulta de novo logo em seguida, até alcançar o último NSU disponível.
  3. Quando não há nada novo, a próxima consulta só acontece depois de 1 hora.
  4. Se a SEFAZ responder 656 mesmo assim, o emitente fica bloqueado por 1 hora e o NSU não muda. O MadNotas é alertado.
  5. Erro de rede ou instabilidade da SEFAZ: nova tentativa em 5 minutos, depois com intervalos maiores, até 1 hora. Isso não conta como consulta.
  6. As consultas dos emitentes são espalhadas ao longo da hora, uma de cada vez por certificado: nunca duas ao mesmo tempo para o mesmo CNPJ.

Na prática, uma nota emitida contra o seu CNPJ aparece em até cerca de 1 hora. Isso não é lentidão do MadNotas: é o ritmo permitido pela SEFAZ.

Ver a situação

GET /dfe/situacao?emitente_id=12
{
    "emitente_id": 130,
    "ambiente": "simulacao",
    "ultimo_nsu": 61,
    "max_nsu": 61,
    "ultima_consulta_em": "2026-10-31T18:48:20-03:00",
    "proxima_consulta_em": "2026-10-31T19:48:30-03:00",
    "estado": "em_dia",
    "motivo": null
}
estadoO que quer dizerO que fazer
em_diaVocê já tem tudo o que a SEFAZ distribuiu até agora.Nada. Veja proxima_consulta_em.
baixandoHá mais notas esperando: o MadNotas está buscando em sequência.Espere alguns instantes e leia de novo.
aguardandoA próxima consulta está agendada.Nada. proxima_consulta_em diz quando.
bloqueadoA SEFAZ pediu para esperar. O motivo diz até quando.Nada: o MadNotas volta sozinho depois do prazo.
sem_certificadoHomologação ou produção sem certificado A1 válido.Envie o certificado do emitente.

Pedir uma consulta

POST /dfe/sincronizar com {"emitente_id": 12} só pede: responde 202 com a situação e a proxima_consulta_em. Se a regra deixar, a consulta acontece antes; se não deixar, o pedido não adianta nada e também não dá erro, e a resposta traz a mesma data de antes. Repetir o pedido em laço é inútil. Em simulação, o simulador responde no mesmo pedido, então a nota nova aparece na hora.

Como integrar sem se atrapalhar

  • Prefira o webhook dfe.recebido: o MadNotas avisa quando a nota chega.
  • Se preferir consultar, guarde o maior nsu que você já leu e peça GET /dfe?nsu=ULTIMO. Essa leitura é do banco do MadNotas, não vai à SEFAZ, e pode ser feita com frequência.
  • Use sincronizar só quando um usuário clicar em “buscar agora”, e mostre a proxima_consulta_em se a resposta não adiantar nada.

Ler as notas recebidas

GET /dfe lista em ordem crescente de NSU, com limite de 1 a 100 e cursor como nas outras listas. Filtros: emitente_id, nsu (só os de NSU maior que esse), situacao, manifestacao, tipo (entrada ou saida), chave, desde e ate (data de emissão). Valor fora da lista dá 422 parametro_invalido.

GET /dfe?emitente_id=12&nsu=0 (dados fictícios)
{
    "dados": [
        {
            "id": "dfe_0000004b4484d31a",
            "objeto": "dfe",
            "ambiente": "simulacao",
            "emitente": {
                "id": 130,
                "cnpj": "47670421000193",
                "razao_social": "QA N6 Serviços São Paulo Ltda"
            },
            "nsu": 54,
            "chave": "41261087834655000143550010001841871339683281",
            "modelo": "55",
            "fornecedor": {
                "documento": "87834655000143",
                "nome": "Comercial Teste de Ferragens Ltda",
                "inscricao_estadual": "873093881"
            },
            "data_emissao": "2026-10-31T13:20:14-03:00",
            "tipo_operacao": "saida",
            "valor_total": "3.10",
            "situacao_nfe": "autorizada",
            "xml_completo": false,
            "manifestacao": {
                "tipo": null,
                "status": null,
                "registrada_em": null
            },
            "recebido_em": "2026-10-31T18:46:14-03:00",
            "atualizado_em": "2026-10-31T18:46:14-03:00",
            "links": {
                "self": "https://proj-6e831164-6bc2-4128-8e36-00a304b709f7.test.madbuilder.dev/api/v1/dfe/dfe_0000004b4484d31a",
                "xml": "https://proj-6e831164-6bc2-4128-8e36-00a304b709f7.test.madbuilder.dev/api/v1/dfe/dfe_0000004b4484d31a/xml",
                "eventos": "https://proj-6e831164-6bc2-4128-8e36-00a304b709f7.test.madbuilder.dev/api/v1/dfe/dfe_0000004b4484d31a/eventos"
            }
        },
        {
            "id": "dfe_0000004c6d47f976",
            "objeto": "dfe",
            "ambiente": "simulacao",
            "emitente": {
                "id": 130,
                "cnpj": "47670421000193",
                "razao_social": "QA N6 Serviços São Paulo Ltda"
            },
            "nsu": 55,
            "chave": "31261072385737000180550010005000251876785858",
            "modelo": "55",
            "fornecedor": {
                "documento": "72385737000180",
                "nome": "Indústria Modelo de Embalagens Ltda",
                "inscricao_estadual": "975299550"
            },
            "data_emissao": "2026-10-31T14:08:14-03:00",
            "tipo_operacao": "saida",
            "valor_total": "182.60",
            "situacao_nfe": "autorizada",
            "xml_completo": false,
            "manifestacao": {
                "tipo": null,
                "status": null,
                "registrada_em": null
            },
            "recebido_em": "2026-10-31T18:46:14-03:00",
            "atualizado_em": "2026-10-31T18:46:14-03:00",
            "links": {
                "self": "https://proj-6e831164-6bc2-4128-8e36-00a304b709f7.test.madbuilder.dev/api/v1/dfe/dfe_0000004c6d47f976",
                "xml": "https://proj-6e831164-6bc2-4128-8e36-00a304b709f7.test.madbuilder.dev/api/v1/dfe/dfe_0000004c6d47f976/xml",
                "eventos": "https://proj-6e831164-6bc2-4128-8e36-00a304b709f7.test.madbuilder.dev/api/v1/dfe/dfe_0000004c6d47f976/eventos"
            }
        },
        {
            "id": "dfe_0000004dbe3b6cf8",
            "objeto": "dfe",
            "ambiente": "simulacao",
            "emitente": {
                "id": 130,
                "cnpj": "47670421000193",
                "razao_social": "QA N6 Serviços São Paulo Ltda"
            },
            "nsu": 56,
            "chave": "41261094656763000139550010001477261574930601",
            "modelo": "55",
            "fornecedor": {
                "documento": "94656763000139",
                "nome": "Comercial Teste de Ferragens Ltda",
                "inscricao_estadual": "830784666"
            },
            "data_emissao": "2026-10-31T10:21:14-03:00",
            "tipo_operacao": "saida",
            "valor_total": "162.15",
            "situacao_nfe": "autorizada",
            "xml_completo": false,
            "manifestacao": {
                "tipo": null,
                "status": null,
                "registrada_em": null
            },
            "recebido_em": "2026-10-31T18:46:14-03:00",
            "atualizado_em": "2026-10-31T18:46:14-03:00",
            "links": {
                "self": "https://proj-6e831164-6bc2-4128-8e36-00a304b709f7.test.madbuilder.dev/api/v1/dfe/dfe_0000004dbe3b6cf8",
                "xml": "https://proj-6e831164-6bc2-4128-8e36-00a304b709f7.test.madbuilder.dev/api/v1/dfe/dfe_0000004dbe3b6cf8/xml",
                "eventos": "https://proj-6e831164-6bc2-4128-8e36-00a304b709f7.test.madbuilder.dev/api/v1/dfe/dfe_0000004dbe3b6cf8/eventos"
            }
        }
    ],
    "tem_mais": false,
    "proximo_cursor": null
}
CampoO que é
idIdentificador da nota recebida (dfe_…). Guarde como texto. Há um por chave de NF-e: resumo, XML completo e eventos da mesma nota atualizam o mesmo objeto.
nsuO maior NSU que tocou esta nota.
chaveChave de acesso da NF-e, 44 dígitos.
fornecedorDocumento, nome e inscrição estadual de quem emitiu.
tipo_operacao, valor_total, data_emissaoO que o resumo traz.
situacao_nfeautorizada, cancelada ou denegada. Muda quando o fornecedor cancela.
xml_completofalse enquanto só o resumo chegou; true quando a nota inteira já foi baixada.
manifestacaotipo (nenhuma, ciencia, confirmacao, desconhecimento ou nao_realizada), status (processando, registrado ou rejeitado) e registrada_em.
recebido_em, atualizado_emQuando o MadNotas recebeu e quando mudou pela última vez.

Ciência e XML completo

A SEFAZ só entrega a nota inteira depois que o destinatário dá ciência dela. Por isso o caminho é este:

  1. A nota chega só como resumo (xml_completo: false). Webhook dfe.recebido com motivo: "novo".
  2. Você manifesta ciencia (próxima seção). A ciência não encerra nada.
  3. Na consulta seguinte do MadNotas, chega o XML completo: xml_completo: true e webhook dfe.recebido com motivo: "xml_completo". É a hora de importar.
Nota depois da ciência e da próxima consulta (dados fictícios)
{
    "id": "dfe_0000004b4484d31a",
    "objeto": "dfe",
    "ambiente": "simulacao",
    "emitente": {
        "id": 130,
        "cnpj": "47670421000193",
        "razao_social": "QA N6 Serviços São Paulo Ltda"
    },
    "nsu": 57,
    "chave": "41261087834655000143550010001841871339683281",
    "modelo": "55",
    "fornecedor": {
        "documento": "87834655000143",
        "nome": "Comercial Teste de Ferragens Ltda",
        "inscricao_estadual": "873093881"
    },
    "data_emissao": "2026-10-31T13:20:14-03:00",
    "tipo_operacao": "saida",
    "valor_total": "3.10",
    "situacao_nfe": "autorizada",
    "xml_completo": true,
    "manifestacao": {
        "tipo": "ciencia",
        "status": "registrado",
        "registrada_em": "2026-10-31T18:47:45-03:00"
    },
    "recebido_em": "2026-10-31T18:46:14-03:00",
    "atualizado_em": "2026-10-31T18:47:47-03:00",
    "links": {
        "self": "https://proj-6e831164-6bc2-4128-8e36-00a304b709f7.test.madbuilder.dev/api/v1/dfe/dfe_0000004b4484d31a",
        "xml": "https://proj-6e831164-6bc2-4128-8e36-00a304b709f7.test.madbuilder.dev/api/v1/dfe/dfe_0000004b4484d31a/xml",
        "eventos": "https://proj-6e831164-6bc2-4128-8e36-00a304b709f7.test.madbuilder.dev/api/v1/dfe/dfe_0000004b4484d31a/eventos"
    }
}

GET /dfe/{id}/xml devolve o XML completo quando já chegou e, antes disso, o resumo. O cabeçalho MadNotas-Xml-Tipo diz qual: procNFe (completo) ou resNFe (resumo). Confira o cabeçalho antes de importar.

Manifestar

A manifestação diz à SEFAZ o que aconteceu com a nota. Escolha um dos quatro tipos:

tipoEventoRegra
ciencia210210, Ciência da EmissãoNão encerra. Libera o XML completo.
confirmacao210200, Confirmação da OperaçãoConclusiva.
desconhecimento210220, Desconhecimento da OperaçãoConclusiva.
nao_realizada210240, Operação não RealizadaConclusiva. A justificativa, de 15 a 255 caracteres, é obrigatória.
POST /dfe/{id}/manifestacao
curl -X POST "$MADNOTAS_URL/dfe/dfe_ID/manifestacao" \
  -H "Authorization: Bearer $MADNOTAS_CHAVE" \
  -H "Content-Type: application/json" \
  -d '{"tipo":"ciencia"}'
Resposta 201 (dados fictícios)
{
    "id": "evt_0000005i377b0520",
    "objeto": "evento",
    "origem": "manifestacao",
    "tipo": "ciencia",
    "codigo_evento": "210210",
    "descricao": "Ciência da Emissão",
    "justificativa": null,
    "nsu": null,
    "status": "registrado",
    "sefaz": {
        "cstat": "135",
        "motivo": "Evento registrado e vinculado a NF-e",
        "protocolo": "891267223142628"
    },
    "registrado_em": "2026-10-31T18:47:45-03:00",
    "criado_em": "2026-10-31T18:47:45-03:00",
    "dfe": {
        "id": "dfe_0000004b4484d31a",
        "objeto": "dfe",
        "ambiente": "simulacao",
        "emitente": {
            "id": 130,
            "cnpj": "47670421000193",
            "razao_social": "QA N6 Serviços São Paulo Ltda"
        },
        "nsu": 54,
        "chave": "41261087834655000143550010001841871339683281",
        "modelo": "55",
        "fornecedor": {
            "documento": "87834655000143",
            "nome": "Comercial Teste de Ferragens Ltda",
            "inscricao_estadual": "873093881"
        },
        "data_emissao": "2026-10-31T13:20:14-03:00",
        "tipo_operacao": "saida",
        "valor_total": "3.10",
        "situacao_nfe": "autorizada",
        "xml_completo": false,
        "manifestacao": {
            "tipo": "ciencia",
            "status": "registrado",
            "registrada_em": "2026-10-31T18:47:45-03:00"
        },
        "recebido_em": "2026-10-31T18:46:14-03:00",
        "atualizado_em": "2026-10-31T18:47:45-03:00",
        "links": {
            "self": "https://proj-6e831164-6bc2-4128-8e36-00a304b709f7.test.madbuilder.dev/api/v1/dfe/dfe_0000004b4484d31a",
            "xml": "https://proj-6e831164-6bc2-4128-8e36-00a304b709f7.test.madbuilder.dev/api/v1/dfe/dfe_0000004b4484d31a/xml",
            "eventos": "https://proj-6e831164-6bc2-4128-8e36-00a304b709f7.test.madbuilder.dev/api/v1/dfe/dfe_0000004b4484d31a/eventos"
        }
    }
}

A resposta é 201 com o evento e a nota (ou 202, se a SEFAZ ainda não respondeu; o resultado chega por webhook). Os prazos e a ordem permitida são da SEFAZ: se a SEFAZ recusar, por exemplo uma manifestação conclusiva depois de outra, o evento sai com status: "rejeitado" e o código da recusa, ainda com 201. A API só responde erro HTTP para o que dá para ver aqui: 409 manifestacao_em_andamento (já há uma a caminho) e 422 justificativa_invalida.

Evento recusado pela SEFAZ (dados fictícios)
{
    "id": "evt_0000005kad15776a",
    "objeto": "evento",
    "origem": "manifestacao",
    "tipo": "nao_realizada",
    "codigo_evento": "210240",
    "descricao": "Operação não Realizada",
    "justificativa": "SIM-REJ-596 evento fora do prazo de manifestacao",
    "nsu": null,
    "status": "rejeitado",
    "sefaz": {
        "cstat": "596",
        "motivo": "Rejeição: Evento apresentado fora do prazo: [prazo vigente]",
        "protocolo": null
    },
    "registrado_em": null,
    "criado_em": "2026-10-31T18:47:55-03:00",
    "dfe": {
        "id": "dfe_0000004c6d47f976",
        "objeto": "dfe",
        "ambiente": "simulacao",
        "emitente": {
            "id": 130,
            "cnpj": "47670421000193",
            "razao_social": "QA N6 Serviços São Paulo Ltda"
        },
        "nsu": 55,
        "chave": "31261072385737000180550010005000251876785858",
        "modelo": "55",
        "fornecedor": {
            "documento": "72385737000180",
            "nome": "Indústria Modelo de Embalagens Ltda",
            "inscricao_estadual": "975299550"
        },
        "data_emissao": "2026-10-31T14:08:14-03:00",
        "tipo_operacao": "saida",
        "valor_total": "182.60",
        "situacao_nfe": "autorizada",
        "xml_completo": false,
        "manifestacao": {
            "tipo": "nao_realizada",
            "status": "rejeitado",
            "registrada_em": null
        },
        "recebido_em": "2026-10-31T18:46:14-03:00",
        "atualizado_em": "2026-10-31T18:47:55-03:00",
        "links": {
            "self": "https://proj-6e831164-6bc2-4128-8e36-00a304b709f7.test.madbuilder.dev/api/v1/dfe/dfe_0000004c6d47f976",
            "xml": "https://proj-6e831164-6bc2-4128-8e36-00a304b709f7.test.madbuilder.dev/api/v1/dfe/dfe_0000004c6d47f976/xml",
            "eventos": "https://proj-6e831164-6bc2-4128-8e36-00a304b709f7.test.madbuilder.dev/api/v1/dfe/dfe_0000004c6d47f976/eventos"
        }
    }
}

Eventos da nota

GET /dfe/{id}/eventos lista as suas manifestações e os eventos do fornecedor que chegaram pela distribuição, como o cancelamento. Quando o fornecedor cancela, a situacao_nfe da nota muda para cancelada e sai o webhook dfe.recebido com motivo: "evento_emissor".

Webhooks

Inscreva-se em dfe.*. Formato, assinatura e novas tentativas são os de Webhooks.

EventoQuando
dfe.recebidoUma nota nova (motivo: "novo"), o XML completo que chegou ("xml_completo") ou um evento do fornecedor ("evento_emissor"). Os dados trazem o motivo e a nota.
dfe.manifestacao_registradaA SEFAZ aceitou a sua manifestação.
dfe.manifestacao_rejeitadaA SEFAZ recusou a manifestação. Vem o código.

Simulação

Em simulação, nada chega sozinho: você cria notas fictícias com POST /simulacao/dfe (só com chave mn_sim_; com outra, 403 somente_simulacao). Os fornecedores são fictícios, com CNPJ de dígito verificador válido. A rota cria as notas e já faz a consulta.

POST /simulacao/dfe
{
    "emitente_id": 12,
    "quantidade": 3,
    "cenario": "normal"
}
cenarioO que acontece
normal (padrão)Chegam quantidade notas (1 a 50), primeiro como resumo. O XML completo só vem depois da ciência, na consulta seguinte.
canceladaChegam notas que o fornecedor já cancelou: situacao_nfe vem cancelada e o webhook traz motivo: "evento_emissor".
so_resumoChega só o resumo. Mesmo depois da ciência, o XML completo nunca vem (xml_completo fica false).
cancelamento_posteriorO fornecedor cancela uma nota que você já recebeu. Informe a chave (de nota do mesmo emitente: de outro dá 404, e nota já cancelada dá 409). O cancelamento chega na próxima consulta, na mesma nota.

Para ver a SEFAZ recusar uma manifestação, mande SIM-REJ- seguido do código na justificativa de uma nao_realizada, por exemplo SIM-REJ-596 evento fora do prazo de manifestacao. O Playground do painel (Integração › Playground) monta cada cenário.

Roteiro completo em simulação

  1. PUT /emitentes/{id}/dfe com {"habilitado": true}.
  2. POST /simulacao/dfe com quantidade 3: o corpo da resposta traz as chaves e as notas.
  3. GET /dfe?emitente_id={id}&nsu=0: as 3 notas, só com resumo.
  4. POST /dfe/{id}/manifestacao com ciencia.
  5. POST /dfe/sincronizar e GET /dfe/{id}: agora xml_completo: true.
  6. GET /dfe/{id}/xml: o XML completo (MadNotas-Xml-Tipo: procNFe).
  7. POST /dfe/{id}/manifestacao com confirmacao.
  8. POST /simulacao/dfe com cancelamento_posterior e a chave de uma das notas, depois POST /dfe/sincronizar: a situacao_nfe vira cancelada.
  9. GET /dfe/situacao?emitente_id={id}: o último NSU, o máximo e a próxima consulta.

Permissões e cobrança

A chave precisa de dfe.read para ler (GET) e de dfe.write para ligar o DF-e, manifestar, sincronizar e simular. A chave de acesso completo já cobre as duas; sem a permissão, 403 permissao_negada. Receber nota e manifestar não contam na franquia de notas.

Rotas do DF-e

Esta lista vem do OpenAPI publicado; os detalhes de cada rota estão na referência.

RotaO que faz
GET /dfeListar notas recebidas
GET /dfe/situacaoSituação da distribuição
POST /dfe/sincronizarPedir uma consulta
GET /dfe/{id}Consultar nota recebida
GET /dfe/{id}/xmlXML da nota recebida
POST /dfe/{id}/manifestacaoManifestar
GET /dfe/{id}/eventosEventos da nota recebida
PUT /emitentes/{id}/dfeLigar ou desligar o DF-e do emitente
POST /simulacao/dfeSimular notas recebidas (só simulação)