Nutrient Remediate PDF
Remediate an existing PDF by auto-tagging it with PDF/UA semantic structure — headings (H1–H6),
lists, tables (TR/TD/TH), reading order, and artifact marking — via the dedicated Nutrient DWS
Accessibility API. The script uploads a PDF and writes back the remediated, tagged PDF.
This skill ships auto-tag only. The DWS Accessibility API does not currently expose a
separate accessibility conformance validation endpoint (confirmed by live probe — see
references/accessibility-api-reference.md). To check tagged output today, use the bundled
standalone verifier — uv run scripts/verify-pdf.py --input doc-tagged.pdf --profile pdfua —
which checks structural PDF/UA-1 signals and escalates to a full veraPDF audit when veraPDF is
installed. It is not a certification. (The same verifier ships with the make-pdf skill.)
When to use
- "Make this PDF accessible" / "auto-tag for screen readers"
- "Tag this PDF for PDF/UA" / "remediate accessibility"
- "Prepare this document for Section 508" (the tagging step)
Disambiguation from sibling skills
Existing PDF vs. new PDF is the first fork:
- Use this skill (
remediate-pdf) to fix a PDF that already exists — auto-tag it for
accessibility.
- Use
make-pdf (its own plugin: /plugin install make-pdf@nutrient-skills) to generate a
NEW compliant PDF from Markdown or HTML (PDF/UA or PDF/A output with built-in verification).
This plugin bundles the same verify-pdf.py for checking tagged output.
Both document-processor-api and this skill perform PDF/UA auto-tagging using the same
underlying engine (the pdf_to_pdfua capability — confirmed from the live response's build
stats). The distinction is product and account surface, not capability:
- Use this skill (
remediate-pdf) when the user wants the dedicated DWS Accessibility
product: its own API key (NUTRIENT_ACCESSIBILITY_API_KEY), its own monthly auto-tagged-pages
quota and dashboard.
- Use
document-processor-api when the user is already doing /build work and wants PDF/UA
as one of several output targets with their Processor key, or wants convert to PDF/A, produce PDF/UA via /build, merge, or sign.
Do not claim the Processor "cannot auto-tag" — it can. Route on which product/key/quota the
user wants, not on a capability difference. Cross-link the Processor's pdfua output target.
Setup
The DWS Accessibility API is a separate product with its own API key (distinct from the
Processor key NUTRIENT_API_KEY and the Extraction key NUTRIENT_EXTRACT_API_KEY). Calling the
Accessibility endpoint with the wrong product key returns 401 (malformed/unknown key) or 403
(valid key for a different DWS product — observed live).
Operations
autotag.py — remediate a PDF with PDF/UA tags
uv run scripts/autotag.py --input doc.pdf --output doc-tagged.pdf
uv run scripts/autotag.py --url https://example.com/doc.pdf --output doc-tagged.pdf
POST https://api.nutrient.io/accessibility/autotag, Authorization: Bearer <key>, always as
multipart/form-data (field file). --url is validated (https-only, must resolve to a public
address) then downloaded client-side and uploaded as bytes — the Nutrient backend never
fetches the URL, so there is no backend SSRF surface (redirects are not followed).
- On success the remediated PDF is written to
--output (default <input-stem>-tagged.pdf).
- The script prints the pages-processed and quota-unit count from the response build stats.
Decision rules
- Quota gate. Auto-tagging consumes from the monthly auto-tagged-pages quota (Free tier = 20
pages/month; quotas do not roll over and the API blocks at the limit).
autotag.py estimates
the page count and requires confirmation before any run exceeding remaining quota (when the
account surfaces it) or exceeding --confirm-over (default 20) when remaining is unknown.
Pass --yes to bypass for known-safe runs.
- Max file size is 150 MiB per request; the script enforces this client-side before upload.
For larger documents, split first with
document-processor-api/split.py.
- Do not auto-retry on a 2xx response — each call consumes quota.
Anti-patterns
- Do not represent auto-tagged output as guaranteed PDF/UA-compliant. Auto-tagging improves
but does not guarantee conformance (Nutrient's benchmark cites ~96.5% PDF/UA conformance, not
100%). Check output with the bundled
verify-pdf.py (and veraPDF for a full
audit); treat the output as remediated, not certified.
- Do not route
convert to PDF/A, produce PDF/UA via /build, merge, or sign here —
those belong to document-processor-api.
- Do not use a Processor or Extraction key against this endpoint — it returns
401.
Security Hardening Addendum
- Never store
NUTRIENT_ACCESSIBILITY_API_KEY in committed files. Use process env injection at
runtime (shell/export, secrets manager, or host env).
- The script never prints or logs the API key, and redacts the key from any error response body
before printing it.
--url inputs are validated (https-only; the host must resolve to a globally-routable public
address) and then fetched client-side with redirects disabled, so the Nutrient backend never
fetches the URL — there is no backend SSRF surface. The client fetch is still operator-scoped
egress: do not pass unsanitized user-controlled strings to --url.
Reference map
references/accessibility-api-reference.md — confirmed endpoint, request/response shape, quota
model, error envelope, and the validation-endpoint probe findings.
references/pdf-ua-wcag-compliance-notes.md — what PDF/UA auto-tagging does, PDF/UA vs WCAG,
Section 508 relationship.
- Sibling
document-processor-api/SKILL.md — /build PDF/UA output target and the same
underlying auto-tagging engine.
scripts/verify-pdf.py — the bundled standalone structural checker for tagged output (the
identical file ships in the make-pdf plugin; keep them in sync).
- The
make-pdf skill (separate plugin: make-pdf@nutrient-skills) — generate NEW compliant
PDFs from Markdown/HTML.
1---2name: remediate-pdf3description: Auto-tag existing PDFs with PDF/UA semantic structure (headings, lists, tables, reading order) for accessibility remediation via the Nutrient DWS Accessibility API. Use when the user wants to make an existing PDF accessible, auto-tag for screen readers, remediate for PDF/UA, or prepare a document for Section 508. Triggers include auto-tag PDF, make this PDF accessible, tag for screen readers, remediate accessibility, PDF/UA remediation, or Section 508 remediation. Auto-tag only: check tagged output with the bundled verify-pdf.py. To generate a NEW accessible PDF from Markdown or HTML, use make-pdf instead. Converting to PDF/A, producing a PDF/UA output target via /build, merging, or signing go to document-processor-api.4license: MIT5---67# Nutrient Remediate PDF89Remediate an existing PDF by auto-tagging it with PDF/UA semantic structure — headings (H1–H6),10lists, tables (TR/TD/TH), reading order, and artifact marking — via the dedicated Nutrient DWS11Accessibility API. The script uploads a PDF and writes back the remediated, tagged PDF.1213> **This skill ships auto-tag only.** The DWS Accessibility API does not currently expose a14> separate accessibility conformance *validation* endpoint (confirmed by live probe — see15> `references/accessibility-api-reference.md`). To check tagged output today, use the bundled16> standalone verifier — `uv run scripts/verify-pdf.py --input doc-tagged.pdf --profile pdfua` —17> which checks structural PDF/UA-1 signals and escalates to a full veraPDF audit when veraPDF is18> installed. It is not a certification. (The same verifier ships with the `make-pdf` skill.)1920## When to use2122- "Make this PDF accessible" / "auto-tag for screen readers"23- "Tag this PDF for PDF/UA" / "remediate accessibility"24- "Prepare this document for Section 508" (the tagging step)2526## Disambiguation from sibling skills2728Existing PDF vs. new PDF is the first fork:2930- **Use this skill (`remediate-pdf`)** to fix a PDF that already exists — auto-tag it for31 accessibility.32- **Use `make-pdf`** (its own plugin: `/plugin install make-pdf@nutrient-skills`) to generate a33 NEW compliant PDF from Markdown or HTML (PDF/UA or PDF/A output with built-in verification).34 This plugin bundles the same `verify-pdf.py` for checking tagged output.3536Both `document-processor-api` and this skill perform **PDF/UA auto-tagging using the same37underlying engine** (the `pdf_to_pdfua` capability — confirmed from the live response's build38stats). The distinction is **product and account surface, not capability**:3940- **Use this skill (`remediate-pdf`)** when the user wants the dedicated DWS **Accessibility41 product**: its own API key (`NUTRIENT_ACCESSIBILITY_API_KEY`), its own monthly auto-tagged-pages42 quota and dashboard.43- **Use `document-processor-api`** when the user is already doing `/build` work and wants PDF/UA44 as one of several output targets with their Processor key, or wants `convert to PDF/A`, `produce45 PDF/UA` via `/build`, `merge`, or `sign`.4647Do **not** claim the Processor "cannot auto-tag" — it can. Route on which product/key/quota the48user wants, not on a capability difference. Cross-link the Processor's `pdfua` output target.4950## Setup5152The DWS Accessibility API is a **separate product** with its own API key (distinct from the53Processor key `NUTRIENT_API_KEY` and the Extraction key `NUTRIENT_EXTRACT_API_KEY`). Calling the54Accessibility endpoint with the wrong product key returns `401` (malformed/unknown key) or `403`55(valid key for a different DWS product — observed live).5657- Get a DWS Accessibility API key at <https://dashboard.nutrient.io/>.58- Export it as `NUTRIENT_ACCESSIBILITY_API_KEY` (the key uses the `pdf_live_` prefix):59 ```bash60 export NUTRIENT_ACCESSIBILITY_API_KEY="pdf_live_..."61 ```62- Run from the directory containing this SKILL.md:63 ```bash64 cd <directory containing this SKILL.md> && uv run scripts/autotag.py --help65 ```6667## Operations6869### `autotag.py` — remediate a PDF with PDF/UA tags7071```bash72uv run scripts/autotag.py --input doc.pdf --output doc-tagged.pdf73uv run scripts/autotag.py --url https://example.com/doc.pdf --output doc-tagged.pdf74```7576- `POST https://api.nutrient.io/accessibility/autotag`, `Authorization: Bearer <key>`, always as77 `multipart/form-data` (field `file`). `--url` is validated (https-only, must resolve to a public78 address) then **downloaded client-side** and uploaded as bytes — the Nutrient backend never79 fetches the URL, so there is no backend SSRF surface (redirects are not followed).80- On success the remediated PDF is written to `--output` (default `<input-stem>-tagged.pdf`).81- The script prints the pages-processed and quota-unit count from the response build stats.8283## Decision rules8485- **Quota gate.** Auto-tagging consumes from the monthly auto-tagged-pages quota (Free tier = 2086 pages/month; quotas do not roll over and the API blocks at the limit). `autotag.py` estimates87 the page count and **requires confirmation before any run exceeding remaining quota** (when the88 account surfaces it) **or exceeding `--confirm-over` (default 20)** when remaining is unknown.89 Pass `--yes` to bypass for known-safe runs.90- **Max file size** is 150 MiB per request; the script enforces this client-side before upload.91 For larger documents, split first with `document-processor-api/split.py`.92- **Do not auto-retry on a 2xx response** — each call consumes quota.9394## Anti-patterns9596- Do **not** represent auto-tagged output as guaranteed PDF/UA-compliant. Auto-tagging improves97 but does not guarantee conformance (Nutrient's benchmark cites ~96.5% PDF/UA conformance, not98 100%). Check output with the bundled `verify-pdf.py` (and veraPDF for a full99 audit); treat the output as remediated, not certified.100- Do **not** route `convert to PDF/A`, `produce PDF/UA` via `/build`, `merge`, or `sign` here —101 those belong to `document-processor-api`.102- Do **not** use a Processor or Extraction key against this endpoint — it returns `401`.103104## Security Hardening Addendum105106- Never store `NUTRIENT_ACCESSIBILITY_API_KEY` in committed files. Use process env injection at107 runtime (shell/export, secrets manager, or host env).108- The script never prints or logs the API key, and redacts the key from any error response body109 before printing it.110- `--url` inputs are validated (https-only; the host must resolve to a globally-routable public111 address) and then fetched **client-side** with redirects disabled, so the Nutrient backend never112 fetches the URL — there is no backend SSRF surface. The client fetch is still operator-scoped113 egress: do not pass unsanitized user-controlled strings to `--url`.114115## Reference map116117- `references/accessibility-api-reference.md` — confirmed endpoint, request/response shape, quota118 model, error envelope, and the validation-endpoint probe findings.119- `references/pdf-ua-wcag-compliance-notes.md` — what PDF/UA auto-tagging does, PDF/UA vs WCAG,120 Section 508 relationship.121- Sibling `document-processor-api/SKILL.md` — `/build` PDF/UA output target and the same122 underlying auto-tagging engine.123- `scripts/verify-pdf.py` — the bundled standalone structural checker for tagged output (the124 identical file ships in the `make-pdf` plugin; keep them in sync).125- The `make-pdf` skill (separate plugin: `make-pdf@nutrient-skills`) — generate NEW compliant126 PDFs from Markdown/HTML.