Blog

PDF/A e Factur-X / NF-e explicados para engenheiros (sem o jargão jurídico)

O que perfis PDF/A realmente restringem, por que Factur-X torna-se obrigatório na UE em 2026, e o pipeline mais prático para emitir compliant a partir de um renderer JSON.

Se você é engenheiro a quem acabaram de dizer «as faturas precisam ser PDF/A-3 com Factur-X até o próximo trimestre», e seu único contexto é que alguém do jurídico pronunciou essas palavras, este post é para você.

Cortamos o tom dos documentos de padronização e explicamos o que esses perfis realmente restringem, por que governos começaram a obrigá-los, e o pipeline prático mais pequeno para emitir um PDF compliant a partir de um renderer de dados estruturados.

PDF/A em dois parágrafos

PDF é um formato flexível. Demais flexível — a mesma especificação PDF deixa você embedar JavaScript, linkar a recursos externos que podem não existir em 50 anos, criptografar conteúdo com criptografia reversível, referenciar fontes externas, e cem outras coisas que tornam um documento não-autocontido.

PDF/A («A» de Archival) é um perfil de PDF que proíbe as partes que impediriam o documento de renderizar identicamente em 50 anos. As regras de alto nível:

  • Todas as fontes devem estar embedded.
  • Sem JavaScript, sem links externos, sem áudio/vídeo.
  • Sem criptografia.
  • Toda transparência deve ser achatada ou suportada pela versão do perfil.
  • Cores devem ser independentes do dispositivo (perfil ICC necessário).
  • Todo conteúdo deve estar dentro do arquivo — sem referências que dependem da rede.

Existem várias versões, cada uma adicionando tolerância para features mais recentes:

PerfilAnoO que adiciona
PDF/A-1b2005Baseline original — o mais estrito
PDF/A-2b2011Permite JPEG2000, transparência, layers
PDF/A-3b2012Permite anexos arbitrários de arquivo (a fundação do Factur-X)
PDF/A-42020Base ISO 32000-2 (PDF 2.0), níveis de conformidade simplificados

O sufixo «b» significa conformidade «basic» (fidelidade visual). Há também variantes «u» (unicode-mapped) e «a» (accessibility-tagged) — para a maioria dos workflows fatura/recibo, «b» é o que você quer, porque arquivamento fiscal se preocupa com reprodutibilidade visual, não semântica de leitor de tela.

Conclusão prática: se seu renderer diz suportar PDF/A-3b, deve ser uma única flag de configuração ({ profile: "PDF/A-3b" } ou equivalente). Se você precisa rodar uma segunda ferramenta (Ghostscript, qpdf, Acrobat) para converter depois, isso é uma lacuna de workflow para fatorar nas suas ops.

Por que PDF/A-3 importa especificamente: é o portador de notas fiscais eletrônicas

PDF/A-3 adicionou uma capacidade que se mostrou mudança-de-mundo: anexos de arquivo arbitrários dentro do PDF.

Soa entediante. Não é. É a fundação técnica inteira dos mandatos de fatura eletrônica rolando pela Europa neste momento.

A arquitetura: um único arquivo PDF que é tanto

  1. Uma fatura legível por humanos (layout visual, totais, branding) — a parte que humanos leem.
  2. Uma fatura XML legível por máquina — a parte que software de autoridade fiscal parsa.

Ambos dentro de um arquivo, ambos representando a mesma fatura, e o wrapper PDF/A-3 garante que o arquivo permanecerá parseable por décadas.

Os dois principais formatos XML:

  • Factur-X (França) — perfil XML baseado em UN/CEFACT Cross Industry Invoice
  • ZUGFeRD (Alemanha) — substancialmente idêntico a Factur-X (os dois padrões fundiram-se tecnicamente em 2018)
  • EN 16931 — a norma europeia à qual ambas implementações conformam
  • NF-e (Brasil) — formato XML brasileiro estruturado transmitido via SEFAZ; conceitualmente equivalente mas com schema próprio

Para a maioria dos workflows, «Factur-X» e «ZUGFeRD» são termos intercambiáveis — compartilham um schema, compartilham o mecanismo de embedding, e um único PDF compliant com um geralmente é compliant com o outro.

O que é obrigatório, onde, quando

Snapshot não-exaustivo para engenheiros planejando rollouts Q2/Q3 2026:

PaísStatusFormato requerido
BrasilNF-e B2B obrigatória desde 2008 (B2C NFC-e desde 2014)XML NF-e via SEFAZ + DANFE PDF
AlemanhaB2B obrigatório para recepção desde 2025-01-01; emissão a partir de 2027EN 16931 (ZUGFeRD / Factur-X / XRechnung)
FrançaEmissão obrigatória para grandes empresas 2026-09; PMEs 2027-09Factur-X via Chorus Pro
ItáliaB2B obrigatório desde 2019FatturaPA via SDI
PolôniaObrigatório desde 2024-07KSeF
EspanhaObrigatório a partir de 2026 (B2B)Facturae via FACe
PortugalObrigatório B2G; B2B em rollout 2025-2026Modelo SAFT-PT + UBL Peppol

O padrão: cada estado-membro UE está implementando alguma variante de e-faturação compliant EN 16931 em uma timeline 2024–2027. Se seus clientes operam em qualquer desses mercados, seu gerador PDF precisará emitir XML anexo junto à fatura visual.

Para times no Brasil especificamente: a NF-e (Nota Fiscal Eletrônica) é gerenciada pela SEFAZ via SPED. Cada NF-e brasileira deve ser transmitida via SEFAZ em formato XML estruturado, com o DANFE (Documento Auxiliar da NF-e) como representação visual em PDF impressa para acompanhar mercadorias. Embora o schema seja específico do Brasil (não EN 16931), o conceito é idêntico ao Factur-X / ZUGFeRD: XML estruturado + visual humana. Para integração internacional, o mesmo endpoint gPdf gera Factur-X conforme padrões EU.

O pipeline mais pequeno prático

Esqueça o que documentos de padronização prescrevem. Aqui a visão de engenheiro:

   ┌─────────────────────┐
   │  Dados da sua       │  (já um objeto JSON em algum lugar)
   │      fatura         │
   └─────────┬───────────┘


   ┌─────────────────────┐
   │ Construir XML       │  (mapeamento determinístico; libs testadas existem)
   │   EN 16931 / NF-e   │
   └─────────┬───────────┘


   ┌─────────────────────┐
   │ Renderizar          │
   │ PDF/A-3b + anexar   │  (uma única chamada API ao gPdf — ou dois passos noutros)
   │       XML           │
   └─────────┬───────────┘


   ┌─────────────────────┐
   │  Entregar a         │
   │  SEFAZ / Chorus Pro/│
   │  Peppol / SDI / etc │
   └─────────────────────┘

Os dois passos não-triviais:

Passo 1: construir o XML

Isso é chato mas mecânico. Você mapeia seus dados de fatura (linhas, impostos, totais, partes) para nomes de campo XML EN 16931 (ou NF-e para Brasil). Várias bibliotecas Java/Node/Python fazem isso para você — busque por «factur-x library» ou «nfe library» na sua linguagem. Não escreva do zero a menos que você genuinamente goste de specs de schema XML.

Passo 2: renderizar PDF/A-3 e anexar o XML

Aqui a escolha do renderer importa.

Sem suporte embutido: você renderiza um PDF comum, depois pós-processa com uma ferramenta que converte para PDF/A-3 e anexa o XML como arquivo embedded. Stacks comuns: Ghostscript + qpdf, ou ferramenta paga como Aspose. Dois passos extras, dois pontos de falha extras, e você precisa garantir que o pós-processamento não derive o layout visual.

Com suporte embutido (a abordagem do gPdf): uma chamada.

curl -X POST https://gpdf.com/api/v1/e-invoice/render \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  --data '{
    "document": {
      "pages": [{ "size": "a4", "elements": [...] }]
    },
    "einvoice": {
      "format": "factur-x",
      "profile": "BASIC",
      "xml": "<rsm:CrossIndustryInvoice>...</rsm:CrossIndustryInvoice>"
    }
  }' \
  --output fatura-com-factur-x.pdf

Isso é o pipeline inteiro. O renderer emite PDF/A-3b, anexa seu XML como factur-x.xml (ou zugferd-invoice.xml, ambos reconhecidos por todo consumidor), e retorna os bytes.

Pegadinhas comuns

Algumas coisas que pessoas aprendem do jeito difícil:

«PDF/A» e «com fontes compliant PDF/A» não são a mesma coisa

Um arquivo PDF/A-3 requer que todas as fontes estejam embedded com cobertura completa de glyphs usados. Se sua fatura tem nome de cliente estrangeiro e o renderer faz fallback para uma fonte que não é completamente embedável, ferramentas de validação rejeitarão. Verifique se seu renderer embeda fontes CJK em modo PDF/A — muitos não o fazem por padrão.

Visual + XML devem coincidir

A fatura XML e a fatura visual deveriam representar a mesma fatura. Auditores fiscais vão diff-las. Se seu código emite XML com total: 119,00 e o PDF visual mostra Total: 120,00 (por causa de bug de arredondamento ou template antigo), você tem uma discrepância fiscal nos arquivos. Gere ambos da mesma source-of-truth, idealmente no mesmo path de código.

Níveis de «perfil» em EN 16931

Factur-X tem perfis: MINIMUM, BASIC, EN 16931, EXTENDED. Diferem em quantos dados estão no XML. Use BASIC a menos que seu cliente requeira especificamente mais — cobre códigos fiscais, linhas, partes, totais, o que é suficiente para ~95% de faturação B2B.

Validação antes de submissão

Sempre valide o PDF gerado contra um validador PDF/A (veraPDF é o padrão open-source) e valide o XML contra o schema EN 16931 / NF-e antes de enviar à autoridade fiscal. Submissões falhas a SEFAZ / Chorus Pro / SDI contam contra suas métricas de confiabilidade com o regulador.

TL;DR

PDF/A é um perfil de documento autocontido. PDF/A-3 deixa você anexar arquivos. Factur-X / ZUGFeRD é «um XML EN 16931 anexo dentro de um PDF/A-3». Mandatos de e-faturação pela UE fazem essa combinação o formato de fato B2B de 2025–2027.

Se seu renderer trata PDF/A-3 + Factur-X como uma única flag de configuração, a migração é mecânica. Se não, você está construindo um pipeline ops multi-passo. O /api/v1/e-invoice/render do gPdf é a versão single-flag — a referência API tem o schema completo, ou tente um render exemplo no Playground.