API documentation

Base URL https://api.pagesmith.eu/api · every request is processed in memory and shredded. Nothing is stored.

Authentication

All requests to the pagesmith API require an API key passed via the Authorization header:

Authorization: Bearer psk_live_...

Generate your API key in the dashboard. Keys require an active subscription.

POST /v1/fill

Fill AcroForm fields in a PDF from JSON data. Fields are optional; missing fields are skipped. Optionally flatten the form to bake the values into the page and remove the interactive fields.

Parameters

NameTypeDescription
file PDF file The PDF to fill (multipart/form-data)
data JSON object Field names and values, e.g. {"name":"Jesper","subscribed":true}
flatten boolean (optional) Bake field values into the page and remove the interactive form. Default: false
Flatten is one-way

Flattening renders each field's value into the page content and removes the interactive form. The result has no fillable fields left. It cannot be un-flattened, so keep your source PDF if you need to edit the fields again.

Example

curl -s https://api.pagesmith.example/api/v1/fill \
  -H "Authorization: Bearer psk_live_..." \
  -F file=@contract.pdf \
  -F 'data={"name":"Jesper","subscribed":true}' \
  -F flatten=true -o filled.pdf

Response

HTTP 200 with the filled PDF file as binary content. Content-Type: application/pdf

POST /v1/pdfa/validate

Validate a PDF against PDF/A compliance standards using the veraPDF engine. Returns detailed rule-level results for archival readiness assessment.

Parameters

NameTypeDescription
file PDF file The PDF to validate (multipart/form-data)
profile string (optional) PDF/A profile: 2b (default) or 3b

Example

curl -s https://api.pagesmith.example/api/v1/pdfa/validate \
  -H "Authorization: Bearer psk_live_..." \
  -F file=@archive.pdf -F profile=2b

Response

HTTP 200 with JSON:

{
  "compliant": true,
  "profile": "2b",
  "passedRules": 58,
  "failedRules": 0,
  "ruleSummaries": [
    {
      "ruleId": "6.1.2-1",
      "specification": "ISO 19005-1:2005",
      "description": "Font program embedded",
      "status": "failed",
      "failedChecks": 3
    }
  ]
}

POST /v1/pdfa/convert

Convert any PDF to archival PDF/A using Ghostscript. The output must pass pagesmith's own PDF/A-validate engine for the requested profile before it's ever returned.

Parameters

NameTypeDescription
file PDF file The PDF to convert (multipart/form-data)
profile string (optional) Target PDF/A profile: 2b (default) or 3b

Example

curl -s https://api.pagesmith.example/api/v1/pdfa/convert \
  -H "Authorization: Bearer psk_live_..." \
  -F file=@scan.pdf -F profile=2b -o converted.pdf

Response

HTTP 200 with the converted PDF as binary content. Content-Type: application/pdf, X-Pagesmith-Units: 3 (3 units per call).

Convert fails differently than validate

Unparseable or otherwise unconvertible input returns 422 pdfa.not_convertible, not pdf.corrupt. Convert's engine (Ghostscript) and validate's engine (veraPDF) fail on different inputs in different ways; this is the one place that distinction surfaces as a different error code.

POST /v1/seal

Apply a PAdES digital signature with your own PKCS#12 certificate. No signing authority, no pagesmith-issued identity. An invisible signature field is added to the PDF automatically, so it works on any PDF, not just one with an existing signature field.

Parameters

NameTypeDescription
file PDF file The PDF to seal (multipart/form-data)
certificate PKCS#12 file Your signing certificate (.p12/.pfx). Provide this or certificate_id, never both.
certificate_id integer A certificate previously uploaded to your dashboard vault. Provide this or certificate, never both.
passphrase string Required. The certificate's PKCS#12 passphrase. Never stored, never logged, never passed on a command line.
tsa_url string (optional) RFC 3161 timestamp authority URL, for a timestamped signature
reason string (optional) Signing reason embedded in the signature, 120 characters or fewer
Certificates can live in your vault

Upload a PKCS#12 certificate once in the dashboard (it's stored encrypted at rest) and reference it by certificate_id on every call instead of re-uploading the file with every request. Passphrases are never stored, either way.

Example

curl -s https://api.pagesmith.example/api/v1/seal \
  -H "Authorization: Bearer psk_live_..." \
  -F file=@contract.pdf \
  -F certificate_id=4 \
  -F passphrase="correct horse battery staple" \
  -F reason="Approved by finance" -o sealed.pdf

Response

HTTP 200 with the sealed PDF as binary content. Content-Type: application/pdf, X-Pagesmith-Units: 3 (3 units per call).

POST /v1/merge

Merge 2–10 PDFs into a single document, in the order submitted.

Parameters

NameTypeDescription
files[] PDF files (2–10) The PDFs to merge, in order (multipart/form-data)

Example

curl -s https://api.pagesmith.example/api/v1/merge \
  -H "Authorization: Bearer psk_live_..." \
  -F files[]=@cover.pdf -F files[]=@contract.pdf -F files[]=@appendix.pdf \
  -o merged.pdf

Response

HTTP 200 with the merged PDF as binary content. Content-Type: application/pdf, X-Pagesmith-Units: 1 (1 unit per call, regardless of file count).

POST /v1/stamp

Stamp text onto every page of a PDF: page numbers, watermarks, draft marks.

Parameters

NameTypeDescription
file PDF file The PDF to stamp (multipart/form-data)
text string Required. Stamp text, 200 characters or fewer
position string (optional) One of center, top, bottom. Default: bottom
opacity float (optional) 0.05–1. Default: 0.3

Example

curl -s https://api.pagesmith.example/api/v1/stamp \
  -H "Authorization: Bearer psk_live_..." \
  -F file=@draft.pdf -F text="DRAFT internal review" -F position=top -F opacity=0.4 \
  -o stamped.pdf

Response

HTTP 200 with the stamped PDF as binary content. Content-Type: application/pdf, X-Pagesmith-Units: 1 (1 unit per call).

Async processing

Add async=1 to any of /v1/fill, /v1/pdfa/convert, /v1/seal, /v1/merge, or /v1/stamp to run the same operation as a background job instead of waiting for the response inline. Useful for large files or slower operations like convert and seal.

Parameters

NameTypeDescription
async boolean Set to 1 to run the operation asynchronously
webhook_url string (optional) URL pagesmith POSTs {"id": "...", "status": "..."} to once the job reaches a terminal state (done or failed). Best-effort; never retried.

Example

curl -s https://api.pagesmith.example/api/v1/seal \
  -H "Authorization: Bearer psk_live_..." \
  -F file=@contract.pdf -F certificate_id=4 -F passphrase="..." \
  -F async=1 -F webhook_url=https://example.com/hooks/pagesmith

{"id": "01j...", "status": "queued", "status_url": "https://api.pagesmith.example/api/v1/jobs/01j..."}

GET /v1/jobs/{id}

Poll (or wait for the webhook, then call) the job's status_url:

  • HTTP 200 {"id": "...", "status": "queued"} or "status": "processing" while the job is still running.
  • application/problem+json, at the operation's original error status, if the job failed: the same body the synchronous call would have returned.
  • HTTP 200 with the result file as binary content (Content-Type: application/pdf) once the job is done.
  • HTTP 404 job.not_found for an unknown job id, or one belonging to another account.
The one zero-retention exception, and it's tight

Async inputs and results are encrypted at rest and expire after 1 hour. A done result is deleted the instant you fetch it via GET /v1/jobs/{id}; you can only collect it once. Nothing else about a document is ever persisted: job rows carry no filenames.

Error responses

All errors are returned as application/problem+json with a stable code field for programmatic handling.

Error codes

CodeStatusMeaning
auth.invalid_key401API key is missing or invalid
subscription.required402Account has no active subscription
subscription.past_due402Subscription payment is past due
request.too_large413File exceeds maximum size (20 MB)
request.unsupported_media_type415Request content type is not supported
request.validation422Request validation failed (missing or invalid parameters)
form.no_acroform422PDF has no form fields (AcroForm)
form.field_unknown422A requested field does not exist in the PDF
pdf.encrypted422PDF is password-protected or encrypted
pdf.corrupt422PDF structure is invalid or corrupt
pdfa.not_convertible422PDF could not be converted to PDF/A
seal.cert_invalid422Certificate could not be read, or the passphrase is wrong
seal.cert_expired422Certificate has expired
seal.tsa_unreachable422Timestamp authority could not be reached
job.not_found404Async job does not exist, or belongs to another account
rate_limit.exceeded429Too many requests; rate limit exceeded
internal.engine_timeout504Processing engine timed out (try again)
internal.engine_failure500the validation engine returned no usable result (rare; retry or contact support)
internal.error500Unexpected server error

Example error response

HTTP/1.1 422 Unprocessable Entity
Content-Type: application/problem+json

{
  "type": "https://pagesmith.example/problems/form.field_unknown",
  "title": "Field not found",
  "status": 422,
  "detail": "Field 'employer' does not exist in this PDF",
  "code": "form.field_unknown"
}