1) Single file check
curl -sS -X POST "https://api.ua1.dev/api/validate?format=compact" \ -F "file=@document.pdf"
Add &profile=ua2 to validate against PDF/UA-2 (ISO 14289-2).
2) Validate a PDF by URL
curl -sS -X POST "https://api.ua1.dev/api/validate?format=compact&url=https://example.com/report.pdf"
Handy when the file already lives in object storage. Private network addresses are refused.
3) What compact mode returns
{
"ok": true,
"mode": "compact",
"profile": "PDF/UA-1",
"verdict": "fail",
"errors": 17,
"failed_rules": 7,
"rules": [
{
"rule_id": "7.1-3",
"count": 6,
"title": "Untagged content on the page",
"fix": "Open Accessibility > Reading Order in Acrobat Pro and assign a tag to each untagged region.",
"pages": [1, 2]
}
]
}
errors is the true number of failed checks. rules is ordered most frequent first: fix the top entry for the biggest win.
4) CI / release gate
# exit non-zero when the document fails verdict=$(curl -sS -X POST "https://api.ua1.dev/api/validate?format=compact" \ -F "file=@docs/final.pdf" | jq -r .verdict) [ "$verdict" = "pass" ] || exit 1
Or use the GitHub Action, which annotates failing rules directly on the job:
- uses: hajekt2/ua1-validate-action@v1
with:
files: "docs/**/*.pdf"
profile: ua1
5) README badge

The badge validates the linked PDF and caches the verdict for 15 minutes.
6) Batch remediation loop
1. Validate all PDFs in compact mode 2. Group by rule_id across documents (the API already groups per document) 3. Fix the most frequent rule first: it usually has one root cause in the source template 4. Re-validate and diff the counts
Rule explanations and fixes are also available as data: GET /api/rules?profile=ua1.
7) Error codes
Stable codes, returned as { "ok": false, "error": { "code", "message" } }:
400 FILE_REQUIRED, AMBIGUOUS_INPUT, URL_REQUIRED, PARAMETER_REQUIRED 403 URL_NOT_ALLOWED, URL_FETCH_DISABLED 413 FILE_TOO_LARGE 415 UNSUPPORTED_TYPE 422 PDF_ENCRYPTED, PDF_MALFORMED, UNSUPPORTED_PROFILE, URL_FETCH_FAILED 429 RATE_LIMITED 503 SERVER_BUSY 504 VALIDATION_TIMEOUT, URL_FETCH_TIMEOUT
Rate limit headers on every response: X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset.