Skip to content

Produce PDF/A-4 output and gate it with the veraPDF oracle

This how-to creates Portable Document Format/Archive (PDF/A-4) output with the Premium PdfAManager, runs veraPDF, and uses its verdict as the build gate. NextPDF writes the artifacts; the validator decides conformance. The flow follows examples/32-pdfa4-icc.php.

  • Core installed: composer require nextpdf/core:^3.
  • Premium installed: composer require nextpdf/pro. PDF/A-4 is a Premium-tier feature (Architecture Decision Record ADR-011). Without Premium, enablePdfA() throws InvalidConfigException with an upgrade path.
  • veraPDF on PATH for the gate step.
  1. Probe the capability registry for security.pdfa so a Core-only install shows a clear message instead of a stack trace.
  2. Create the document, then call enablePdfA() before you add content.
  3. Set metadata and write content. Do not call setEncryption(); PDF/A prohibits the Encrypt key.
  4. Save the document. During save(), the PdfAManager schedules the OutputIntent, the embedded International Color Consortium (ICC) profile, and the Extensible Metadata Platform (XMP) extension schemas.
  5. Run verapdf --flavour 4 on the output. Fail the build if it exits non-zero. The validator verdict is the gate.
<?php
declare(strict_types=1);
require_once __DIR__ . '/vendor/autoload.php';
use NextPDF\Core\Document;
use NextPDF\Exception\InvalidConfigException;
use NextPDF\Support\CapabilityRegistry;
$out = __DIR__ . '/archival.pdf';
// Step 1 — probe before activating a Premium-gated feature.
$registry = CapabilityRegistry::getInstance();
if (!$registry->get('security.pdfa')->isAvailable()) {
fwrite(STDERR, "PDF/A-4 requires nextpdf/pro. Run: composer require nextpdf/pro\n");
exit(1);
}
try {
$doc = Document::createStandalone();
// Step 2 — enable PDF/A-4 before content. Defaults to PdfA4.
$doc->enablePdfA();
// Step 3 — metadata and content. No setEncryption() on a PDF/A document.
$doc->setTitle('Archival Record 2026-0042');
$doc->setLanguage('en');
$doc->addPage();
$doc->setFont('helvetica', '', 12);
$doc->cell(0, 10, 'This document targets PDF/A-4.', newLine: true);
// Step 4 — save. PdfAManager emits OutputIntent + ICC + XMP here.
$doc->save($out);
} catch (InvalidConfigException $e) {
fwrite(STDERR, "PDF/A-4 activation failed: {$e->getMessage()}\n");
exit(1);
}
// Step 5 — the gate. veraPDF, not the library, asserts conformance.
$exitCode = 0;
$output = [];
exec('verapdf --flavour 4 ' . escapeshellarg($out), $output, $exitCode);
if ($exitCode !== 0) {
fwrite(STDERR, "veraPDF FAILED — output is not PDF/A-4 conforming\n");
fwrite(STDERR, implode("\n", $output) . "\n");
exit(1);
}
echo "veraPDF PASS — archival.pdf is reported PDF/A-4 conforming by veraPDF\n";

When veraPDF passes:

veraPDF PASS — archival.pdf is reported PDF/A-4 conforming by veraPDF

When the Premium package is missing, the script exits non-zero with an actionable message and does not write a file.

  • Premium gate. In a Core-only install, enablePdfA() throws InvalidConfigException that names security.pdfa and gives the composer require nextpdf/pro remedy. Probe the registry first.
  • Encryption conflict. Calling setEncryption(), useAesGcm(), or setPublicKeyEncryption() on a PDF/A document raises an incompatibility exception in either call order. PDF/A prohibits the Encrypt trailer key.
  • Conformance variant. Pass a PdfAVersion to enablePdfA() for 4e or 4f. The default is 4.
  • The gate is the validator, not the engine. A successful save() means NextPDF emitted the artifacts that PDF/A-4 requires. It does not, by itself, prove conformance. veraPDF asserts conformance; this recipe makes its verdict the gate. Do not state that a file is PDF/A-4 conforming until the validator passes.
StatementSpecClausereference_id
A PDF/A-4 file may specify its color characteristics with a PDF/A OutputIntent that references an embedded International Color Consortium (ICC) profile. Device-independent color can instead be specified directly; §6.2.4.1.ISO 19005-4§6.2.3
Encryption is prohibited in PDF/A-4.ISO 19005-4§6.6.4
PDF/A-4 carries pdfaid identification in Extensible Metadata Platform (XMP) metadata.ISO 19005-4§6.7.5

The validator asserts conformance. The library produces output intended to conform; the validator decides.