PDF/UA-2 generation Experimental
PDF_UA2_UNSUPPORTED when content is outside the current mapping support.
Fork PDF can generate a tagged PDF 2.0 candidate with PDF/UA-2 structure metadata. The visual layout is preserved. The structure is derived from your HTML and the spatial layout data captured during rendering, so headings, paragraphs, lists, tables, links, images, and supported figures do not have to be guessed from PDF coordinates.
Scope: PDF/UA-2 generation works from semantic HTML. The structure builder maps headings,
paragraphs, lists, tables, links, images with alt text, and inline emphasis. Layout-only
div and span wrappers are flattened into the surrounding structure. Invoices,
reports, statements, tables, and other HTML documents that use the supported elements below are in scope.
The travel itinerary is the current public stress-test fixture.
This feature is available through the compliance object. It is supported by
forkpdf@1.5.0 and newer. Raw REST clients can use the same object.
For WCAG-specific evidence, see WCAG 2.2 AA checks. That page reports WCAG only; the PDF/UA-2 validation page remains PDF/UA-2 evidence only.
Quick start
curl -X POST "https://api.forkpdf.com/v1/generate-pdf" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "x-project-id: YOUR_PROJECT_ID" \
-H "Content-Type: application/json" \
-d '{
"htmlContent": "<h1>Accessible invoice</h1><p>Total: $450</p>",
"format": "A4",
"compliance": { "pdfUa": 2 }
}'
Response and warnings
Successful PDF/UA-2 responses include the version, font-embedding evidence, and experimental marker:
x-pdf-ua: 2
x-pdf-ua-experimental: true
x-font-embedding: verified
x-font-policy: warn
x-compliance-status: <base64 JSON>
When PDF/A-4 is requested, the response also includes x-pdf-a: 4. Stream-only responses also include x-compliance-status, a base64 JSON capability status. Non-streamed responses, and webhook deliveries, include the same information in JSON:
{
"success": true,
"compliance": { "pdfUa": 2 },
"complianceStatus": {
"fontPolicy": "warn",
"fontEmbedding": "verified",
"pdfA": "stable",
"pdfAFlavor": "4",
"pdfUa": "experimental",
"pdfUaVersion": 2
},
"warnings": [
"PDF/UA generation is experimental. It is machine-validated but has not completed a full human accessibility audit; unsupported layouts may be rejected."
],
"downloadUrl": "https://.../result.pdf",
"sizeBytes": 17547
}
Capability status is reported per capability. Font embedding is verified by a PDF font postflight and does not inherit the PDF/UA-2 experimental status. PDF/A-4 is reported as stable.
The generated PDF also identifies its producer as
Fork PDF Engine PDF/UA-2 (Experimental). There is no visible watermark. The SDK prints one
experimental warning per process; set FORKPDF_DISABLE_EXPERIMENTAL_WARNING=1 to suppress
that console warning. The API warning fields are always returned.
Supported combinations
| Request | Result |
|---|---|
compliance: { pdfUa: 2 } | Tagged PDF 2.0 candidate. |
compliance: { pdfUa: 2, pdfA: "4" } | Combined PDF/A-4 + PDF/UA-2 candidate. PDF/A-4 is stable and machine-validated. |
compliance: { pdfUa: 1 } | Tagged PDF 1.7 PDF/UA-1 candidate. |
compliance: { pdfUa: 1, pdfA: "2b" | "2u" | "2a" | "3b" | "3u" | "3a" } | Combined PDF/A-2 or PDF/A-3 + PDF/UA-1 candidate. PDF/A status is stable and machine-validated. |
compliance: { pdfA: "2b" | "2u" | "2a" | "3b" | "3u" | "3a" } | Standalone PDF/A-2/3 candidate with no PDF/UA claim. |
compliance: { pdfA: "4" } | Standalone PDF/A-4 candidate with no PDF/UA claim. |
+ spatial: true | ZIP with the tagged document.pdf and the original data.pb layout map. |
+ targetLang | Sets the PDF /Lang and XMP dc:language. |
+ webhook: true | Async generation; the webhook payload includes compliance, complianceStatus, and warnings. |
+ streamOnly: true | Raw PDF response with the compliance headers. |
+ pdfForm: true | Rejected with COMPLIANCE_FORM_UNSUPPORTED. AcroForm fields are not tagged in this release. |
fontPolicy: "strict" | Rejects external stylesheets, non-inline fonts, and system-font fallback with FONT_POLICY_STRICT. |
When spatial: true is used, data.pb is the source layout map used during rendering.
It is not a substitute for the PDF/UA structure tree inside the PDF.
Capability discovery
Clients can fetch the current compatibility matrix without authentication:
curl https://api.forkpdf.com/v1/compliance/capabilities
The response lists supported PDF/A flavors, PDF/UA versions, valid combinations, font policies, and the current forms limitation.
What gets tagged
| Content | Support |
|---|---|
| Headings, paragraphs, lists | Yes, from the HTML structure. |
| Tables | Yes, including row/column headers and scope. |
| Links | Yes, including the link annotation. |
Images with alt | Yes, as tagged figures. |
| Inline SVG | Supported when it maps to a tagged figure; the itinerary route-map is the current example. Images with alt text cover other artwork. |
| Letter-spaced or kerning-fragmented labels | Yes, through ActualText replacement. |
| Other artwork | Use an image with alt text for a tagged figure. |
| AcroForm fields | Not supported with compliance. |
| PDF/A-4 | Supported together with PDF/UA-2. Validated with veraPDF PDF/A-4 across the compliance corpus. |
| PDF/A-2/3 | Supported together with PDF/UA-1. All six flavors are validated with veraPDF across the compliance corpus. |
| PDF/UA evidence | Validation and proof of work |
Limitations
- Content outside the current mapping support — for example, meaningful inline SVG outside the supported
figure path — returns
PDF_UA2_UNSUPPORTED, so every returned PDF has a structure tree that matches the supported source. - Inline SVG is supported when it maps to a tagged figure; the itinerary route-map is the current example.
Images with
alttext are the portable option for other artwork. - PDF/UA-1/2 output covers documents without AcroForm fields in this release.
- PDF/A supports standalone PDF/A-2/3/4 and combinations with PDF/UA-1/2. PDF/A-4 uses PDF 2.0; PDF/A-2/3 use PDF 1.7.
- Strict font policy rejects system-font fallback. This is stricter than the default warning mode and can reject otherwise valid non-compliance generation.
- A screen-reader and human accessibility audit is the final step for a formal PDF/UA conformance claim. PDF/A status does not depend on that audit.
Errors
| Code | HTTP | Meaning |
|---|---|---|
INVALID_COMPLIANCE | 400 | The compliance value is not an object. |
EMPTY_COMPLIANCE | 400 | The object does not include pdfUa or pdfA. |
INVALID_COMPLIANCE_PARAMETER | 400 | Unknown key or invalid value type. |
UNSUPPORTED_COMPLIANCE_STANDARD | 400 | Unsupported PDF/A version. |
UNSUPPORTED_COMPLIANCE_COMBINATION | 400 | The PDF/UA and PDF/A versions cannot be combined. |
UNSUPPORTED_PDF_UA_VERSION | 400 | Only PDF/UA-1 and PDF/UA-2 are supported. |
COMPLIANCE_FORM_UNSUPPORTED | 400 | compliance cannot be combined with pdfForm. |
PDF_UA2_UNSUPPORTED | 422 | The source layout could not be tagged safely as PDF/UA-2. The PDF is not returned. |
PDF_UA1_UNSUPPORTED | 422 | The source layout could not be tagged safely as PDF/UA-1. The PDF is not returned. |
Validation and human review
- Machine-validated with veraPDF PDF/UA-2 on the production canary and a 20-page load test.
- PDF/UA-2 evidence only. PDF/UA-1 checker results are intentionally not used for this proof.
- Automated checkers can still produce heuristic warnings, and they do not replace a screen-reader test.
- A full human accessibility audit is still required before using this for a regulated accessibility commitment.
- See the exact artifacts, hashes, and validation results.
Limits and performance
PDF/UA-2 generation uses the same request and output limits as normal generation: 20 MB API requests, 25 MB PDFs, 39 MB spatial ZIPs, and 40 MB combined responses. There is no separate page limit, but conversion adds processing time; very large documents may hit the engine timeout.