Enterprise edition
NextPDF Enterprise quick start
At a glance
Section titled “At a glance”This tutorial takes you from an empty project to two working Enterprise results. First you verify an existing signed PDF and read its MainIndication. Then you raise a signed document to PAdES B-LT with the long-term producer. Every step shows the exact output or exception you should expect.
This capability ships in NextPDF Enterprise (nextpdf/enterprise) and activates with an Enterprise-tier license envelope. A deployment without that entitlement does not load the capability’s classes. Compare editions and get a license.
Prerequisites
Section titled “Prerequisites”- Composer is configured for the private NextPDF repository. Follow Install and authenticate first.
- You have your Enterprise license envelope, downloaded from your account at app.getnextpdf.com. Licensing and activation explains what the envelope is and where it goes.
- For step 3 you need a signed PDF to verify. For the B-LT part you also need your signer certificate and network access to OCSP/CRL responders.
1. Install and activate
Section titled “1. Install and activate”Require the Enterprise package. It depends on nextpdf/core and nextpdf/pro, so Composer brings the whole stack:
composer require nextpdf/enterprisecomposer show nextpdf/enterpriseIf composer show prints the package and its version, the install worked. Now place the signed license envelope where your deployment loads it, exactly as Licensing and activation describes. Installing the package alone does not grant Enterprise capabilities; the activated license selects the edition.
2. Verify your entitlement
Section titled “2. Verify your entitlement”Ask the entitlement evaluator what your license grants. Your bootstrap obtains the verified NextPDF\Enterprise\Licensing\LicenseKey during activation; pass it in:
<?phprequire __DIR__ . '/vendor/autoload.php';
use NextPDF\Enterprise\Licensing\EntitlementEvaluator;use NextPDF\Enterprise\Licensing\LicenseKey;
/** @var LicenseKey|null $license The verified license from activation. */$result = (new EntitlementEvaluator())->evaluate($license);
echo 'status: ' . $result->status->value . PHP_EOL;echo 'edition: ' . ($result->edition?->value ?? 'none') . PHP_EOL;echo 'runtime: ' . ($result->runtimeAllowed ? 'allowed' : 'disabled') . PHP_EOL;With an active Enterprise license you see:
status: activeedition: enterpriseruntime: allowedThe method behind this step:
public function evaluate(?LicenseKey $license, ?DateTimeImmutable $now = null): EntitlementResultThrows or fails with: it never throws. A missing license returns a fail-closed EntitlementResult with EntitlementStatus::NoLicense and runtimeAllowed false (see step 4).
3. First result
Section titled “3. First result”Verify an existing signed PDF
Section titled “Verify an existing signed PDF”Extract the signature from a signed PDF, then run basic AdES validation. The engine implements the validation levels of ETSI EN 319 102-1; validateBasic() is the clause 5.2 flow — structure, digest, signature crypto, and the certificate chain:
<?phprequire __DIR__ . '/vendor/autoload.php';
use NextPDF\Enterprise\Security\Validation\AdESValidationEngine;use NextPDF\Enterprise\Security\Validation\CmsSignatureDataExtractor;use NextPDF\Enterprise\Signature\SignatureExtractor;
$pdf = file_get_contents(__DIR__ . '/contract-signed.pdf');if ($pdf === false) { throw new RuntimeException('Could not read contract-signed.pdf');}
$signatures = (new SignatureExtractor())->extract($pdf);if ($signatures === []) { throw new RuntimeException('The PDF carries no signature dictionary.');}
$engine = new AdESValidationEngine(extractor: new CmsSignatureDataExtractor());$report = $engine->validateBasic( $signatures[0]['signedBytes'], // the exact /ByteRange-covered bytes $signatures[0]['contents'], // the DER CMS SignedData from /Contents);
echo $report->mainIndication->name . PHP_EOL;echo ($report->subIndication?->name ?? '(none)') . PHP_EOL;For a well-formed signature that passes the basic structural, digest, cryptographic, and chain checks configured in this example, you see:
TOTAL_PASSED(none)MainIndication has exactly three cases: TOTAL_PASSED, TOTAL_FAILED, and INDETERMINATE. The engine is fail-closed: a check it cannot positively establish yields INDETERMINATE, never a silent pass. A pass here is a validation outcome under this engine’s checks; trust anchors and long-term evidence belong to the deeper levels on the verification page.
public function extract(string $pdfData): arrayThrows or fails with: InvalidArgumentException if the input is not a valid PDF. A malformed /ByteRange or /Contents yields empty strings (fail-closed), never a positive result.
public function validateBasic(string $signedData, string $signature): ValidationReportThrows or fails with: it never throws on a verification failure. Every defect maps to a ValidationReport indication, e.g. HASH_FAILURE or SIG_CRYPTO_FAILURE.
Produce a PAdES B-LT
Section titled “Produce a PAdES B-LT”Now upgrade a freshly signed document to B-LT. The long-term producer collects the certificate chain plus OCSP/CRL evidence and writes the Document Security Store (DSS). It continues the signing pass described on the Signature page, which gives you the output buffer, the object registry, and the signature /Contents hex:
use NextPDF\Enterprise\Security\Ltv\LtvManager;use NextPDF\Security\Signature\CertificateInfo;use NextPDF\Security\Signature\SignatureLevel;
$certInfo = CertificateInfo::fromPkcs12('/secure/signer.p12', $p12Password);
// $httpClient is any PSR-18 client; it fetches OCSP responses and CRLs.$ltv = new LtvManager($certInfo, $httpClient, level: SignatureLevel::PAdES_B_LT);
// $buffer, $registry, and $signatureContentsHex come from the signing pass.$dssObjectNumber = $ltv->enableLtv($buffer, $registry, $signatureContentsHex);The return value is the DSS object number for the document catalog’s /DSS entry. The producer defaults to strict revocation enforcement: missing revocation material raises an exception instead of silently emitting a hollow “B-LT” file.
public function enableLtv(BinaryBuffer $buffer, ObjectRegistry $registry, string $signatureContentsHex): intThrows or fails with: NextPDF\Enterprise\Security\Ltv\LtvException when chain validation fails, when the certificate is revoked, or when revocation material is missing under the strict default.
4. When something fails
Section titled “4. When something fails”status: no_license — the envelope is not loaded
Section titled “status: no_license — the envelope is not loaded”Step 2 prints status: no_license and runtime: disabled, and the result carries the warning No license configured. Enterprise runtime is disabled. Install a license or purchase one at https://nextpdf.dev/pricing. An entitlement-gated call then throws NextPDF\Accelerator\Exception\SpectrumAuthenticationException with code SPEC-LIC-001, e.g. Capability '...' requires a valid license. Fix: place and activate the envelope per Licensing and activation, then rerun step 2.
InvalidArgumentException: Input does not start with %PDF header
Section titled “InvalidArgumentException: Input does not start with %PDF header”SignatureExtractor::extract() received something that is not a PDF — a wrong path, an empty read, or a compressed download. Check the file you loaded. An empty $signatures list is different: the file is a PDF, but it carries no /Type /Sig dictionary, so there is nothing to verify.
LtvException: Strict revocation: LTV warning: no revocation data for certificate at chain position 0
Section titled “LtvException: Strict revocation: LTV warning: no revocation data for certificate at chain position 0”enableLtv() could not obtain an OCSP response or a CRL for a chain certificate, and the strict default refuses to write a B-LT claim without evidence. Check responder reachability from the host, or pass enforcementMode: RevocationEnforcementMode::PERMISSIVE only if you explicitly accept a warn-only run — never label such output as B-LT for production or compliance workflows unless the missing revocation evidence is explicitly accepted and documented. Related: requesting B-LTA without a TSA client fails with LtvException: TSA client required for document timestamps.
Where to go next
Section titled “Where to go next”- Signature: PAdES B-LT / B-LTA, DSS, document timestamps — the full producer behavior, ordering rules, and the archival loop.
- Signature verification — time-based and long-term validation, trust anchors, archival chains.
- Licensing — NextPDF Enterprise — entitlement states, grace, capability gating.
- NextPDF Enterprise module index — everything else the edition ships.