API documentation

Integrate EqualDoX into your own systems: upload a PDF, poll the status, download the accessible PDF and its diagnostics.

Overview

The REST API v1 automates what you know from the web interface: you send a PDF, EqualDoX remediates it for accessibility asynchronously, and you download the result together with structured diagnostics.

The API is available to organisation accounts. Every request belongs to one person and one group of your organisation. The rules of the web interface apply: the same upload checks, the same page quotas and prices, the same retention. API jobs appear in the dashboard under the person and group that submitted them.

  • JSON over HTTPS, the PDF as the request body
  • Asynchronous: poll the status, no webhooks
  • Diagnostics per job: outcome, pages, findings
  • Safe retries with an Idempotency-Key
  • Page usage of web interface and API together

Authentication

Create a key in the dashboard under Account › API keys: one for each group in which you may submit PDFs. The key is shown only once, so store it securely.

Base URL
https://equaldox.de/api/v1
Header
Authorization: Bearer eqx_…
Test your key: page usage of the current month
curl -sS --fail-with-body https://equaldox.de/api/v1/usage \
  -H "Authorization: Bearer $EQUALDOX_API_KEY"

Key rules

  • A key belongs to you and one group: jobs are submitted under that group, and the key sees only your jobs in it. For another group, use that group's key.
  • Regenerating or revoking a key takes effect immediately. Each person can create at most five new keys within 24 hours.
  • A key stops working when your membership ends, you leave the group or the organisation is no longer active.
  • Use the key on your server only, never in browser code, apps or repositories. Calls from web pages on other domains are not supported.
  • Accept new terms of service in the dashboard first; until then the API answers 403.

Quickstart

Processing is asynchronous: the upload creates a job, which you poll until job.status is DONE or FAILED. Do not wait for diagnostics.outcome.final; it only shows whether the diagnostics can still change.

Bash script: upload, poll, download, delete
#!/usr/bin/env bash
# Requires curl 7.76+ and jq; first: export EQUALDOX_API_KEY="eqx_…"
set -euo pipefail
BASE="https://equaldox.de/api/v1"
AUTH="Authorization: Bearer $EQUALDOX_API_KEY"
FILE="annual-report-2026.pdf"
IDEM_KEY="annual-report-2026-$(date +%Y%m%d%H%M%S)"         # your own ID for this upload
NAME=$(jq -rn --arg f "$(basename "$FILE")" '$f|@uri')    # percent-encode the file name

# 1. Upload; after a lost connection, repeat the same request with the same IDEM_KEY
JOB=$(curl -sS --fail-with-body -X POST "$BASE/jobs" -H "$AUTH" \
  -H "Content-Type: application/pdf" \
  -H "X-Upload-Filename: $NAME" \
  -H "Idempotency-Key: $IDEM_KEY" \
  --data-binary "@$FILE") || { echo "$JOB" >&2; exit 1; }
JOB_ID=$(jq -r '.job.id' <<< "$JOB")

# 2. Poll until job.status is DONE or FAILED
while :; do
  JOB=$(curl -sS --fail-with-body "$BASE/jobs/$JOB_ID" -H "$AUTH") || { echo "$JOB" >&2; exit 1; }
  STATUS=$(jq -r '.job.status' <<< "$JOB")
  echo "Status: $STATUS"
  case "$STATUS" in DONE|FAILED) break ;; esac
  sleep 10
done

# 3. Download the result (--fail never writes an error response into the file)
if [ "$(jq -r '.job.result_available' <<< "$JOB")" = true ]; then
  curl -sS --fail -o "${FILE%.pdf}_accessible.pdf" "$BASE/jobs/$JOB_ID/result" -H "$AUTH"
else
  jq '.job.diagnostics.failure' <<< "$JOB"   # FAILED: error_code and action
fi

# 4. Optional: delete the job and its documents now (otherwise after 7 days)
curl -sS --fail-with-body -X DELETE "$BASE/jobs/$JOB_ID" -H "$AUTH"
  • 1. Upload The PDF as the request body, the file name percent-encoded in X-Upload-Filename (ending in .pdf).
  • 2. Poll Every 10 seconds; 60 requests per minute and person are allowed.
  • 3. Download Only with result_available: true; --fail never saves an error response as a PDF.
  • 4. Delete Optional; otherwise automatically 7 days after upload.

API reference

All paths are relative to https://equaldox.de. Responses are JSON with "status": "ok", except the PDF download. All fields and schemas are described in the OpenAPI 3.1 specification (JSON).

Endpoints of API v1
Endpoint Purpose Key parameters Response
POST /api/v1/jobs Upload a PDF, start the conversion Body: PDF; headers Content-Type, X-Upload-Filename, optional Idempotency-Key 201 job (repeat 200)
GET /api/v1/jobs List jobs, newest first limit 1–100 (default 50), offset jobs, total
GET /api/v1/jobs/{id} Status, pages, billing, diagnostics summary none job
GET /api/v1/jobs/{id}/diagnostics Diagnostics with findings per page none job_id, diagnostics
GET /api/v1/jobs/{id}/result Download the accessible PDF none application/pdf
DELETE /api/v1/jobs/{id} Delete the job and its documents none job_id, deleted
GET /api/v1/usage Charged pages per period from, to (YYYY-MM-DD, both or neither; default: current month) usage

A key sees only your own jobs in its group, including those you uploaded there in the web interface; any other job answers 404. Timestamps are UTC in ISO 8601 format.

Response of GET /api/v1/jobs/{id} (shortened)
{
  "status": "ok",
  "job": {
    "id": "3f6c2a1e-8b0d-4c55-9a77-1d2e3f4a5b6c",
    "status": "DONE",
    "filename": "annual-report-2026.pdf",
    "page_count": 24,
    "expires_at": "2026-11-16T09:00:00Z",
    "result_available": true,
    "error_code": null,
    "billing": {"pages_reserved": 24, "pages_charged": 24,
                "settled": true, "failed_pages": []},
    "links": {"result": "/api/v1/jobs/3f6c2a1e-…/result"},
    "diagnostics": {
      "outcome": {"state": "succeeded", "final": true},
      "pages": {"total": 24, "converted": 24, "failed": []},
      "failure": null
    }
  }
}

Key job fields

status
UPLOADED, PROCESSING, DONE or FAILED
result_available, links.result
The PDF can be downloaded
expires_at
When the documents are deleted automatically
error_code
Reason for FAILED
billing
Reserved and charged pages
diagnostics
Diagnostics summary, only in GET /api/v1/jobs/{id}

Important integration details

  • File format and size

    PDF only, up to 50 MB (52,428,800 bytes), as the request body with Content-Type: application/pdf. File name percent-encoded in X-Upload-Filename, ending in .pdf, at most 255 characters. Empty, damaged and password-protected PDFs: 422.

  • Rate limit

    60 requests per minute per person, across all keys. Above that: 429 with Retry-After (seconds); wait that long, then repeat. Poll single jobs at most every 5 seconds, many jobs together via GET /api/v1/jobs.

  • Idempotency and retries

    Send your own Idempotency-Key with each upload (1–255 visible ASCII characters). The identical repeat returns the same job (200, Idempotency-Replayed: true), with no second charge. Valid for 24 hours per person; another file or name: 409. After FAILED, use a new key.

  • Status and result

    UPLOADED, PROCESSING, then finally DONE or FAILED. The PDF is ready as soon as result_available is true. The API delivers the remediated PDF; a version corrected later in the inspection view is available in the dashboard.

  • Retention and deletion

    Automatic deletion 7 days after upload (expires_at), then 404. DELETE removes a job earlier, also while it is being processed; then no pages are charged. Extension to 30 days in the dashboard.

  • Page quota and billing

    Your organisation's quota and prices, as in the web interface, with no API surcharge. Pages are reserved on upload and charged when the job finishes, failed pages and FAILED jobs not. Not enough pages: 409. Usage per day: GET /api/v1/usage.

Diagnostics

Every job carries a summary in diagnostics: outcome (overall result), pages (total, converted, failed) and, for FAILED, failure with action. GET …/diagnostics adds the individual findings: errors, warnings and notes with page and code.

The findings come from the automatic check of the remediated PDF, which the inspection view in the dashboard shows as well. EqualDoX uses its own accessibility validator for it. The validator is designed to detect all accessibility violations that veraPDF and PAC can detect. The diagnostics are a technical check result, not a certification and not a legal assessment.

Values of outcome.state

pending
The job is still being processed
checking
Converted; the check is still running
succeeded
Converted without reported errors or warnings
succeeded_with_warnings
Converted; review the warnings
review_required
At least one error; review it in the inspection view
failed
Conversion failed; see failure.action

outcome.final only shows whether the diagnostics can still change. Whether a job is finished is decided by job.status.

Error handling

Errors are JSON: {"status": "error", "error": "<code>"}, for invalid input also fields with field and reason. Repeat a request unchanged only after idempotency_request_in_progress, 429 and 5xx; all other errors need a changed request or an action in the dashboard.

HTTP status, error codes and what to do
Status Error codes What to do
401 api_key_required, invalid_api_key Send exactly one Authorization: Bearer … header. Key invalid, revoked or regenerated: create a new one in the dashboard.
403 terms_acceptance_required, processing_restricted Accept the new terms of service in the dashboard. If processing is restricted, contact us.
404 not_found, result_not_available Job unknown, deleted, expired or not visible. No result: wait for DONE; FAILED has none.
405, 413, 415, 422 method_not_allowed, payload_too_large, unsupported_media_type, validation_failed Fix the request. For 422, fields names the reason, e.g. file: password_protected or filename: not_pdf_extension.
409 page_quota_exceeded, member_page_limit_exceeded Not enough pages (pages_required, pages_remaining): buy pages or ask your organisation's administrators.
409 dpa_required, dpa_update_required, organization_not_active, upload_group_unavailable Account not ready for uploads: accept the data processing agreement (DPA) or its update in the dashboard, check the organisation and group.
409 idempotency_key_reused, idempotency_request_in_progress Key used for another request: use a new one. First request still running: repeat after Retry-After.
429 rate_limited Wait Retry-After seconds, then repeat.
500, 503 server_error, processing_unavailable, storage_unavailable, storage_locked, uploads_disabled Temporary: repeat later with growing intervals, uploads with the same Idempotency-Key.

A failed conversion is not an HTTP error: the job ends with FAILED, and diagnostics.failure.action says what to do: retry_later (upload again later with a new Idempotency-Key), fix_input (the file is not a usable PDF), contact_support (contact us) or resubmit (submit again). FAILED jobs are not charged.

Want to integrate EqualDoX into your workflows?

With an organisation account you create your API key in the dashboard. We are happy to help with questions about the integration.