Fiscal
NF-e (modelo 55), Declaração de Conteúdo, registro de XML e download de DANFE/PDF. Um documento fiscal por pedido.
Pré-requisitos: leia primeiro Pedidos: visão geral. O pedido precisa estar em estado fiscal-elegível (
preparingem diante — ou, em pedidos de produção, qualquer estado da fábrica) antes de qualquer operação aqui.
Conceitos
O objeto que GET /orders/{id}/fiscal devolve — o(s) documento(s) já registrado(s) e a disponibilidade da Declaração:
{
"invoices": [ // 0 ou 1 documento por pedido
{
"id": "5b4f…",
"type": "nfe", // ← nfe | declaration
"status": "completed", // ← pending | validating | valid | invalid | processing | completed | error
"invoice_key": "3526…", // chave de acesso (44 dígitos, NF-e)
"invoice_number": "1234", // só display
"invoice_value": 249.9, // só display
"has_pdf": true, // ← DANFE/PDF pronto p/ download (olhe aqui, não no status)
"error_message": null, // motivo quando a validação fiscal falha (status error/invalid)
"created_at": "2026-04-26T15:10:00Z"
}
],
"declaration_available": true // loja pode emitir Declaração de Conteúdo
}Quem emite o quê
Quem emite a NF-e é a sua loja, não a plataforma — e isso faz sentido: a nota nasce dos seus dados fiscais, do seu CNPJ e do seu regime tributário, então ela sai do seu ERP e é autorizada pela SEFAZ no seu nome. O papel da plataforma vem depois que a nota existe: guardar a chave (e, idealmente, o XML), gerar o DANFE a partir do XML, e disponibilizar para download quando o cliente ou o transportador precisar. Ou seja, você cuida da emissão; a gente cuida de hospedar e entregar.
A Declaração de Conteúdo é diferente: a plataforma gera o PDF dela para você, em background, a partir dos dados do pedido. É uma alternativa à NF-e para casos onde a loja não emite nota fiscal (típico em PF, MEI sem inscrição estadual, ou em pedidos de baixo valor).
Você usa um ou outro por pedido:
Pré-condições
O pedido precisa estar num estado fiscal-elegível: qualquer estado de produção (production_started, awaiting_materials, production_in_progress, production_finished) ou preparing em diante (ready_to_ship, shipped, delivered, ready_for_pickup, picked_up). Tentar emitir em paid retorna 422:
{
"success": false,
"code": 422,
"message_code": "VALIDATION_ERROR",
"errors": {
"status": ["O pedido precisa estar em preparação antes de emitir documentos fiscais. Status atual: paid"]
}
}Declaração de Conteúdo exige feature da loja. A primeira chamada que você deve fazer é a consulta:
GET/api/v1/sellers/orders/{id}/fiscal
{
"data": {
"invoices": [],
"declaration_available": true
}
}invoices[]: documentos já emitidos para esse pedido (vazio se for o primeiro).declaration_available: se sua loja tem a featurefiscal_declarationativa. Se vierfalse, só resta NF-e.
NF-e: dois caminhos
A NF-e nasce no seu ERP. O que muda é o que você tem em mãos quando vai registrar:
Caminho 1: XML completo em string
Se o seu ERP devolveu o XML autorizado junto com a chave, mande tudo de uma vez:
POST/api/v1/sellers/orders/{id}/fiscal/nfe/key
{
"type": "nfe",
"invoice_key": "35260411222333000144550010000012341123456789",
"invoice_number": "1234",
"invoice_value": 249.90,
"invoice_xml": "<?xml version=\"1.0\"?><nfeProc>...</nfeProc>"
}| Campo | Obrigatório | O que é |
|---|---|---|
type | sim | Sempre nfe por enquanto. |
invoice_key | sim | Chave de acesso de 44 caracteres (aqui a validação é só de tamanho; o dígito mod-11 é conferido nos fluxos de lookup/upload de XML). |
invoice_xml | sim | XML autorizado. A partir dele a plataforma gera o DANFE em background. |
invoice_number | não | Número da nota, só para exibição. |
invoice_value | não | Valor total, só para exibição. |
Retorno 201 Created. O DANFE entra na fila e fica pronto em alguns segundos.
Caminho 2: upload manual do XML
Quando você tem o arquivo .xml em mãos mas não tem ainda a chave registrada na plataforma (cenário típico: XML salvo do email do contador, exportado de outro sistema). Mande o arquivo direto:
POST/api/v1/sellers/orders/{id}/invoice/upload-xml
multipart/form-data com o campo xml contendo o arquivo (máx 1 MB, extensão .xml):
POST /api/v1/sellers/orders/ORD-000123/invoice/upload-xml
Content-Type: multipart/form-data; boundary=----X
------X
Content-Disposition: form-data; name="xml"; filename="nfe.xml"
Content-Type: application/xml
<?xml version="1.0"?>...
------X--A chave é extraída do próprio XML (atributo Id="NFe..." em infNFe) e validada por mod-11. Resposta igual ao caminho 1.
Erros típicos:
- 422: XML sem chave, chave inválida, arquivo vazio, extensão errada.
- 409
chave_already_used: essa NF-e já está vinculada a outro pedido. - 409
invoice_already_validated: refaça o invoice antes de reenviar.
Declaração de Conteúdo
Para lojas sem NF-e. A plataforma gera o PDF a partir dos dados do pedido; você só dispara:
POST/api/v1/sellers/orders/{id}/fiscal/declaration
Sem body. Resposta 202 Accepted:
{
"success": true,
"code": 202,
"data": {
"invoice": { "id": "8c7e...", "type": "declaration", "status": "pending", "has_pdf": false }
}
}A partir daí, polling até has_pdf=true no GET /fiscal.
Erros típicos:
- 403:
declaration_available=falsena sua loja. Peça ativação da featurefiscal_declaration. - 422: pedido em status que não permite emissão fiscal (típico:
paid).
Polling do PDF
NF-e (com XML) e Declaração geram PDF em background. O padrão é o mesmo para os dois:
Cadência recomendada: primeiros 30 segundos a cada 3s, depois a cada 10s, com timeout em 2 minutos. PDFs simples ficam prontos em ~5s; declarações com muitos itens podem levar mais.
Baixar o PDF
GET/api/v1/sellers/orders/{id}/fiscal/{invoiceId}/pdf
{invoiceId} é o id que veio em invoices[] na resposta de /fiscal. A rota é a mesma para DANFE e Declaração; o filename já vem com o prefixo certo (danfe_ ou declaracao_).
Quando o PDF está pronto:
{
"success": true,
"code": 200,
"data": {
"url": "https://s3.amazonaws.com/.../danfe_ORD-000123.pdf?X-Amz-Signature=...",
"filename": "danfe_ORD-000123.pdf",
"expires_in": "15 minutos"
}
}A url é S3 assinada, válida por 15 minutos. Se expirar, chame a rota de novo, que gera uma nova URL. Não armazene a URL.
Quando ainda não está pronto, retorna 202 Accepted com o status atual (não é um erro, é só sinal de "tente de novo").
Consulta de dados (sem PDF)
GET/api/v1/sellers/orders/{id}/fiscal/{invoiceId}/view
Devolve os dados completos do invoice (chave, número, valor, status, metadata da declaração) sem o PDF. Útil para telas de detalhe fiscal no painel.
Cenários comuns
"Acabei de emitir a NF-e no ERP, quero registrar agora"
ERP devolveu chave + XML:
POST /api/v1/sellers/orders/ORD-000123/fiscal/nfe/key
{ "type": "nfe", "invoice_key": "...", "invoice_xml": "<?xml...?>" }Depois faça polling do /fiscal até has_pdf=true e baixe.
"Loja é MEI, vai usar Declaração"
Confirme primeiro:
GET /api/v1/sellers/orders/ORD-000123/fiscalSe declaration_available=true, dispara:
POST /api/v1/sellers/orders/ORD-000123/fiscal/declarationPolling → download.
"O cliente está reclamando que não recebeu o DANFE, quero reenviar"
A URL expirou. Faça GET /fiscal/{invoiceId}/pdf de novo, que vai gerar uma URL nova.
"Errei a NF-e, emiti outra no ERP, quero corrigir"
A rota /fiscal/nfe/key aceita ser chamada de novo no mesmo pedido se o invoice ainda não foi validado. Se já foi validado, vai bater 409 invoice_already_validated; nesse caso é caso de operação (contate suporte para reabrir o invoice).
Cuidados
Não chame /fiscal em loop curto. Para acompanhar geração de PDF, cadência de 3–10 segundos é suficiente. Loop em ms gasta quota sem benefício.
invoice_xml é obrigatório. Esquecer o XML no /fiscal/nfe/key retorna 422. Se você ainda não tem o XML registrado na plataforma, use /invoice/upload-xml para enviar o arquivo.
Um pedido carrega um único documento fiscal — NF-e ou Declaração, nunca os dois. Isso é proposital: o documento fiscal é o que acompanha a mercadoria, e ter dois competindo pelo mesmo pedido só geraria ambiguidade na hora de imprimir, despachar e mostrar pro cliente. Por isso você escolhe um caminho no começo. Se emitiu um e precisa trocar, não é algo que você desfaz pela API — é caso de operação (contate o suporte).
Não armazene as URLs S3. Elas têm assinatura curta. Sempre chame /fiscal/{invoiceId}/pdf na hora de servir o download, pois a URL anterior pode estar expirada.

