PDF Optimization API reference

Base URL: https://api.justapi.tech (alias: https://pdf.justapi.tech)

MethodPathDescriptionModes
POST /v1/pdf/compress Compress a PDF sync, async (sync: input under 10 MB)

options for POST /v1/pdf/compress

"options": {
  "profile": "auto",           // auto (default) | screen | email | ebook | print | prepress | custom
  "intent": "email",           // optional hint for auto: email | archive | print | web
  "password": null,            // for PDFs encrypted with a user password
  "allow_signature_break": false,   // signed PDF → 422 unless true
  "allow_conformance_break": false, // PDF/A or PDF/X → 422 unless true
  "max_dpi": null,              // hard ceiling, not a target. null = no ceiling, placement decides
  "max_size_mb": 5,             // target output file size
  "max_base64_bytes": 28000000, // target output size in base64 CHARACTERS (e.g. the SendGrid limit)
  "min_quality": 60,            // floor for the search; never goes below this
  "image_quality": 76,          // 1..100, MozJPEG
  "grayscale": false,
  "strip": {
    "metadata": true, "thumbnails": true, "javascript": true,
    "embedded_files": true, "annotations": false, "structure_tree": false
  },
  "fonts": { "subset": true, "dedupe": true },
  "dedupe_images": true,
  "jbig2": "auto",              // auto | off | lossless (bilevel scans)
  "zopfli": false,              // +3-8% smaller, ~4x more CPU
  "linearize": false,           // "fast web view"
  "verify_quality": false,      // render + SSIM check; retries at higher quality if it fails (+$0.005)
  "ssim_threshold": 0.97,
  "output": "url"               // url (default) | base64 | both
}

There is no target_dpi. The DPI each image gets resampled to is derived from how large that image is actually placed on the page in the document that was sent — not from a number you pick in advance. max_dpi is a ceiling for the rare case you need to cap it externally; null (the default) means placement decides. See the PDF Optimization API page for why, with a real example.

strip.structure_tree: true removes bytes but breaks PDF accessibility, so it defaults to false.

POST /v1/pdf/analyze — free, no options that cost anything

Parses only, does not re-encode. Same source envelope, no options required. Returns composition, per-image filters/colorspaces/estimated_jpeg_quality, and a projection per profile with a quality_risk (none | low | medium | high) so you know what a number cost before you spend anything on it.

Example

curl https://api.justapi.tech/v1/pdf/compress \
  -H "Authorization: Bearer ak_live_..." \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: 8f14e45f-..." \
  -d '{
    "source": { "url": "https://example.com/report.pdf" },
    "options": { "profile": "email", "max_base64_bytes": 28000000 }
  }'

Full envelope (source, mode, webhook, result, metadata), error catalog and billing rule are the same across every JustAPI service — see the API reference index and error codes.