முதன்மை உள்ளடக்கத்துக்குச் செல்லவும்
UV pdfTool
Contents

Developer API

Developer API

The tools that run on our servers, for your own software: create a job, upload the files, start it, download the result.

Last updated 2026-10-29 · Written in English

What it is

The tools that run on our servers, for your own software: the same engines the UV pdfTool site uses, reached with a key instead of a browser. You create a job, upload the files straight to our storage, start it, and download the result, or let a webhook tell you when it is ready. Everything is JSON over HTTPS at https://uvpdftool.com/api/v1.

Make a key on the API keys page (a test key is free), then run the quick start below.

Quick start

One script that compresses report.pdf and writes report-compressed.pdf beside it (results are named by the API). Put your key in the UVPDF_KEY environment variable first; a test key works, and marks the result.

The whole flow
#!/usr/bin/env bash
set -euo pipefail
BASE="https://uvpdftool.com/api/v1"
AUTH="Authorization: Bearer $UVPDF_KEY"
FILE="report.pdf"
SIZE=$(stat -c %s "$FILE" 2>/dev/null || stat -f %z "$FILE")

# 1. Create the job: the tool, its options, and each file's name, size and type.
CREATED=$(curl -sS -X POST "$BASE/jobs" -H "$AUTH" -H "Content-Type: application/json" \
  -d "{\"tool\":\"compress\",\"options\":{\"method\":\"ghostscript\",\"preset\":\"ebook\"},
       \"files\":[{\"name\":\"$FILE\",\"size\":$SIZE,\"contentType\":\"application/pdf\"}]}")
JOB_ID=$(echo "$CREATED" | jq -r .job.id)
UPLOAD_URL=$(echo "$CREATED" | jq -r '.uploads[0].url')

# 2. Upload the file, as it is, to the link the job gave.
curl -sS -X PUT --upload-file "$FILE" -H "Content-Type: application/pdf" "$UPLOAD_URL"

# 3. Start it.
curl -sS -X POST "$BASE/jobs/$JOB_ID/start" -H "$AUTH" > /dev/null

# 4. Wait for it (or let a webhook tell you).
while :; do
  sleep 2
  JOB=$(curl -sS "$BASE/jobs/$JOB_ID" -H "$AUTH")
  STATE=$(echo "$JOB" | jq -r .job.state)
  if [ "$STATE" = done ]; then break; fi
  if [ "$STATE" = failed ] || [ "$STATE" = cancelled ]; then echo "$JOB" | jq .job.error; exit 1; fi
done

# 5. Download the result.
OUT=$(echo "$JOB" | jq -r '.job.outputs[0].name')
curl -sS -o "$OUT" "$(echo "$JOB" | jq -r '.job.outputs[0].url')"
echo "Done: $OUT"

Needs: cURL curl and jq · Node.js Node.js 18 or later; nothing to install · Python Python 3.9 or later and requests · PHP PHP 8 with the curl extension · Node.js SDK npm install uvpdftool (Node.js 18 or later) · Python SDK pip install uvpdftool (Python 3.9 or later).

The reference has each call on its own with its parameters and answers, and the tools page every option.

Authentication

Every call except GET /tools carries your key as a bearer token:

Authorization: Bearer uvp_live_k3JdQ…
  • A key is shown once, when it is made; we keep only a fingerprint of it. Lose it and you make another.
  • A key is live (uvp_live_…) or test (uvp_test_…), and may be read-only: then it can read jobs and the account but not make, start or cancel one.
  • A key can be limited to address ranges, such as 203.0.113.0/24; a call from elsewhere answers 403 API_ADDRESS.
  • Send the key from your server only. Never put it in a web page, a mobile app or a repository: anyone who reads it can spend your tasks.
  • Revoking a key refuses it at once, on every request.

Keys, test mode and pricing

Live and test keys
NameTypeDescription
uvp_live_…liveSpends one API task for each job that succeeds. A job that fails, is cancelled or never gets its files gives its task back. Tasks come in packs of 1,000 for €19 (priced in your currency at checkout), good for 365 days, on any account: Pro is not needed.
uvp_test_…testFree: 50 jobs a day, files up to 10 MB, and every result is marked TEST across its pages (conversions out of PDF carry the mark from the input; the PDF/A check says it was a test). The same code runs unchanged against a live key.

Live and test keys share one account; GET /account says how many tasks and test jobs are left, and we mail you when a pack is four fifths spent and when it is gone. Up to 20 keys per account.

How a job runs

  1. Create it with POST /jobs: the tool, its options, and each file’s name, size and content type. The answer carries the job and an upload link per file.
  2. Upload each file with a PUT to its link, as it is, within 20 minutes. The link goes straight to our storage; the bytes never pass through the API.
  3. Start it with POST /jobs/{id}/start. Every file is checked for size and presence, and the job joins the queue.
  4. Wait: ask GET /jobs/{id} every few seconds, or set a webhook and be told. A server picks a job up within seconds; after a quiet spell one is started first, which takes up to half a minute.
  5. Download each output from the url the job carries once it is done; a link lasts 15 minutes, and reading the job again gives a fresh one.
A job's states
created ──start──▶ queued ──▶ running ──▶ done
   │                                   └──▶ failed   (job.error says why)
   └── 20 minutes without its files ──▶ cancelled   (the task comes back)
DELETE /jobs/{id} at any point ─────────▶ cancelled

A job’s files and results are deleted 2 hours after it ran, or when you delete the job; retentionHours on creation keeps them up to 24 hours. The job record itself stays readable after that, without its files.

Limits

Limits
NameTypeDescription
requests120 / minPer key. Over it, 429 TOO_MANY_REQUESTS with a Retry-After header.
open jobs10Unfinished jobs per account at once: created, queued or running.
files per job20Declared together; each tool says what it does with several.
file sizeper toolUp to 2 GB for Compress and Repair, 500 MB for OCR and PDF/A, 200 MB for the conversions; each tool's page says. 10 MB with a test key.
upload window20 minFrom creation to start. A job left without its files is cancelled and its task returned.
run timeper toolFrom 3 minutes (web pages) to 60 (OCR); a job over it fails with TIMEOUT.
keys20Per account, live and test together.

Your files

Files sent to the API are handled as the privacy policy describes for the server tools: processed on our servers in the European Union, stored in a bucket restricted to the European Union, never read by a person in the ordinary course of things, never used to train anything, and deleted when the job’s retention ends or when you delete the job. The job record keeps the file names and sizes, not the files.

Webhook bodies carry the outputs’ names and sizes but no download links: read the job for those, with your key, so a leaked webhook body gives nobody your documents.