Size az önce “gelecek çeyreğe kadar faturalar PDF/A-3 with Factur-X olmalı” dendiyse ve tek bağlamınız hukuk ekibinden bu kelimeleri duymaksa, bu yazı sizin için.
Standart belgelerinin tonunu kenara koyup bu profillerin gerçekte neyi kısıtladığını, hükümetlerin neden bunları zorunlu kılmaya başladığını ve yapılandırılmış veri renderer’ından uyumlu PDF üretmenin en küçük pratik pipeline’ını anlatacağız.
PDF/A iki paragrafta
PDF esnek bir formattır. Fazla esnek — aynı PDF spec JavaScript embed etmeye, 50 yıl sonra var olmayabilecek dış kaynaklara link vermeye, içeriği geri döndürülebilir kriptografiyle şifrelemeye, dış fontlara referans vermeye ve belgeyi self-contained olmaktan çıkaran yüzlerce şeye izin verir.
PDF/A içindeki “A”, Archival anlamına gelir. PDF’in, belgenin 50 yıl sonra aynı şekilde render edilmesini engelleyecek parçaları yasaklayan bir profilidir. Üst düzey kurallar:
- Tüm fontlar embedded olmalı.
- JavaScript yok, dış link yok, audio/video yok.
- Şifreleme yok.
- Tüm transparency flatten edilmeli veya profil sürümü tarafından desteklenmeli.
- Renkler device-independent olmalı; ICC profile gerekli.
- Tüm içerik file içinde olmalı; network’e bağlı referans yok.
Birkaç version vardır; her biri daha yeni features için tolerans ekler:
| Profil | Yıl | Ne ekler |
|---|---|---|
| PDF/A-1b | 2005 | Orijinal baseline, en katı |
| PDF/A-2b | 2011 | JPEG2000, transparency, layers izinleri |
| PDF/A-3b | 2012 | Arbitrary file attachments, Factur-X’in temeli |
| PDF/A-4 | 2020 | ISO 32000-2 (PDF 2.0) tabanı, sadeleştirilmiş conformance levels |
“b” suffix’i “basic” conformance, yani visual fidelity demektir. “u” unicode-mapped ve “a” accessibility-tagged variants da vardır. Çoğu invoice/receipt workflow’u için istediğiniz “b”dir, çünkü vergi arşivleme screen-reader semantiğiyle değil, görselin yeniden üretilebilirliğiyle ilgilenir.
Pratik sonuç: Renderer PDF/A-3b desteklediğini söylüyorsa bu tek bir config flag olmalı: { profile: "PDF/A-3b" } veya eşdeğeri. Sonradan dönüştürmek için Ghostscript, qpdf ya da Acrobat gibi ikinci bir araç çalıştırmanız gerekiyorsa, bu ops’a yansıtmanız gereken bir workflow boşluğudur.
PDF/A-3 neden özellikle önemli: e-faturanın taşıyıcısıdır
PDF/A-3 basit görünen ama dünyayı değiştiren bir capability ekledi: PDF içinde arbitrary file attachments.
Kulağa sıkıcı geliyor. Değil. Avrupa’da şu anda yayılan e-invoice mandates’in tüm teknik temeli bu.
Mimari: tek bir PDF file, hem:
- İnsan tarafından okunabilir fatura; görsel layout, totals, branding.
- Makine tarafından okunabilir XML fatura; vergi otoritesinin yazılımının parse ettiği bölüm.
İkisi de aynı file içinde, ikisi de aynı faturayı temsil eder, ve PDF/A-3 wrapper file’ın onlarca yıl sonra da parseable kalmasını garanti eder.
Başlıca XML formatları:
- Factur-X (Fransa), UN/CEFACT Cross Industry Invoice tabanlı XML profile.
- ZUGFeRD (Almanya), Factur-X ile özünde aynı; iki standard 2018’de teknik olarak birleşti.
- EN 16931, iki implementation’ın uyduğu Avrupa normu.
Çoğu workflow’da “Factur-X” ve “ZUGFeRD” birbirinin yerine geçer. Aynı schema’yı ve embedding mechanism’i paylaşırlar; biriyle compliant olan tek bir PDF genelde diğeriyle de compliant olur.
Ne zorunlu, nerede, ne zaman
Q2/Q3 2026 rollout planlayan engineers için non-exhaustive snapshot:
| Country | Status | Required format |
|---|---|---|
| Germany | invoice receipt için B2B mandatory from 2025-01-01; 2027’den itibaren issuing de | EN 16931 (Factur-X / ZUGFeRD / XRechnung) |
| France | large enterprises için mandatory issuing 2026-09; SMEs 2027-09 | Factur-X via Chorus Pro |
| Italy | B2B mandatory since 2019 | FatturaPA via SDI |
| Poland | Mandatory since 2024-07 | KSeF |
| Spain | Mandatory from 2026 (B2B) | Facturae via FACe |
| Belgium | Mandatory from 2026-01 | Peppol BIS 3 |
Pattern açık: Her EU member state 2024-2027 timeline’ında EN 16931-compliant e-invoicing’in bir çeşidini implement ediyor. Customers bu markets’in herhangi birinde operate ediyorsa, PDF generator’ınız visual invoice’ın yanında attached XML de emit etmek zorunda kalacak.
En küçük pratik pipeline
Standards documents’ın ne buyurduğunu unutun. Engineering view:
┌─────────────────────┐
│ Your invoice data │ (zaten bir yerde JSON object)
└─────────┬───────────┘
│
▼
┌─────────────────────┐
│ Build EN 16931 XML │ (deterministic mapping; tested libs var)
└─────────┬───────────┘
│
▼
┌─────────────────────┐
│ Render PDF/A-3b + │
│ attach the XML │ (gPdf'e single API call, elsewhere two-step)
└─────────┬───────────┘
│
▼
┌─────────────────────┐
│ Hand off to │
│ Chorus Pro / SDI / │
│ Peppol / etc │
└─────────────────────┘
İki non-trivial step:
Step 1: XML’i build edin
Bu can sıkıcı ama mekanik. Invoice data’nızı, yani lines, taxes, totals ve parties alanlarını EN 16931 XML field names’e map edersiniz. Java/Node/Python için bunu yapan birkaç library var; kendi language’inizde “factur-x library” arayın. XML schema specs gerçekten hoşunuza gitmiyorsa baştan yazmayın.
Step 2: PDF/A-3 render edin ve XML’i attach edin
Renderer seçimi burada önemlidir.
Built-in support yoksa: ordinary PDF render edersiniz, sonra PDF/A-3’e convert eden ve XML’i embedded file olarak attach eden bir tool ile post-process edersiniz. Common stacks: Ghostscript + qpdf veya Aspose gibi paid tool. İki extra step, iki extra failure point, ayrıca post-processing’in visual layout’u drift ettirmediğinden emin olmanız gerekir.
Built-in support varsa (gPdf approach): one call.
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 invoice-with-einvoice.pdf
Pipeline’ın tamamı bu. Renderer PDF/A-3b emit eder, XML’inizi factur-x.xml veya zugferd-invoice.xml olarak attach eder ve bytes döner. İki filename de consumers tarafından tanınır.
Yaygın tuzaklar
İnsanların zor yoldan öğrendiği birkaç şey:
“PDF/A” ve “PDF/A-compliant fontlarla” aynı şey değildir
PDF/A-3 file, kullanılan glyphs için full character coverage ile tüm fontların embedded olmasını gerektirir. Invoice içinde Japanese customer name varsa ve renderer fully embeddable olmayan bir fallback font’a düşerse, validation tools file’ı reject eder. Renderer’ınızın PDF/A mode’da CJK fonts embed ettiğini kontrol edin; çoğu default olarak yapmaz.
Visual + XML aynı olmalı
XML invoice ve visual invoice aynı invoice’ı temsil etmelidir. Tax auditors bunları diff eder. Code XML’de total: 119.00 emit ederken visual PDF Total: 120.00 gösteriyorsa, rounding bug veya stale template yüzünden file içinde tax discrepancy oluşur. İkisini aynı source-of-truth’tan, ideally aynı code path içinde generate edin.
EN 16931’de “profile” seviyeleri
Factur-X profiles: MINIMUM, BASIC, EN 16931, EXTENDED. Fark, XML’deki data miktarıdır. Customer specifically daha fazlasını istemedikçe BASIC kullanın; tax codes, line items, parties ve totals kapsar, bu da B2B invoicing’in yaklaşık %95’i için yeterlidir. EN 16931 profile edge cases için daha fazla detail ekler.
Submission öncesi validation
Generated PDF’i her zaman bir PDF/A validator ile validate edin; veraPDF open-source standard’dır. XML’i de tax authority’ye ship etmeden önce EN 16931 schema’ya karşı validate edin. Chorus Pro / SDI failed submissions regulator tarafındaki reliability metrics’inizi etkiler.
TL;DR
PDF/A self-contained-document profile’dır. PDF/A-3 files attach etmeye izin verir. Factur-X / ZUGFeRD, “PDF/A-3 içine attached EN 16931 XML” demektir. EU e-invoice mandates 2025-2027 arasında bu kombinasyonu de facto B2B invoice formatı yapıyor.
Renderer’ınız PDF/A-3 + Factur-X’i single config flag gibi ele alıyorsa migration mekaniktir. Değilse multi-step ops pipeline kuruyorsunuz. gPdf’in /api/v1/e-invoice/render endpoint’i single-flag version’dır; full schema API reference içinde, sample render için Playground’ı deneyin.