Node.js
uvpdftool on npm: a small client with no dependencies for Node.js 18 and later (ES modules; TypeScript types included). It does what the quick start does by hand, with retries on the uploads and a wait that reports progress.
npm install uvpdftoolimport { readFile, writeFile } from 'node:fs/promises';
import { UvPdfTool, JobFailedError } from 'uvpdftool';
const client = new UvPdfTool({ apiKey: process.env.UVPDF_KEY });
try {
const job = await client.run({
tool: 'ocr',
options: { languages: ['eng', 'hin'] },
files: [{ name: 'scan.pdf', data: await readFile('scan.pdf'), contentType: 'application/pdf' }],
onProgress: (fraction) => console.log(`${Math.round(fraction * 100)} %`),
});
await writeFile('scan-searchable.pdf', await client.download(job.outputs[0]));
} catch (error) {
if (error instanceof JobFailedError) console.error(error.job.error);
else throw error;
}| Name | Type | Description |
|---|---|---|
| new UvPdfTool({ apiKey, baseUrl? }) | client | The client. baseUrl defaults to the live API. |
| client.run({ tool, options?, files, retentionHours?, onProgress? }) | Promise<Job> | Creates the job, uploads every file, starts it and waits; resolves with the finished job or throws JobFailedError. Each file is { name, data, contentType } where data is a Buffer, Uint8Array, Blob or ReadableStream. |
| client.download(output) | Promise<Uint8Array> | The bytes of one output of a finished job. |
| client.jobs.create({ tool, options?, files, retentionHours? }) | Promise<{ job, uploads }> | POST /jobs with the files declared ({ name, size, contentType }). |
| client.jobs.upload(upload, data) | Promise<void> | PUT the bytes to one upload link. |
| client.jobs.start(id) · get(id) · cancel(id) | Promise<Job> | The three job calls. |
| client.jobs.wait(id, { intervalMs?, timeoutMs?, onProgress? }) | Promise<Job> | Polls until the job ends; resolves with it, or throws JobFailedError. |
| client.tools() · client.account() | Promise<…> | GET /tools and GET /account. |
| verifyWebhook(rawBody, signatureHeader, secret, toleranceSeconds?) | boolean | Checks a delivery; see Webhooks. |
| ApiError | class | Thrown for a refused request: status, code, message, details, retryAfterSeconds. |
| JobFailedError | class | Thrown when a job ends failed or cancelled: job (with job.error). |
Command line
The Node.js package also installs uvpdftool, a command that does the whole flow for files on your computer and saves the results beside them. It reads the key from --key, UVPDFTOOL_API_KEY or UVPDF_KEY; each --set is one option of the tool, read as JSON where it can be. A result never replaces a file of the same name unless you say --force; a number is added instead. It exits 0 when done, 1 when the API refused or the job failed, and 2 when the command was wrong.
npm install -g uvpdftooluvpdftool compress report.pdf --set method=ghostscript --set preset=ebook
uvpdftool office-to-pdf proposal.docx contract.docx -o pdfs
uvpdftool ocr scan.pdf --set 'languages=["eng","hin"]' --json
uvpdftool tools # what each tool takes, and its options
uvpdftool account # the key in use, and the API tasks leftAI assistants (MCP)
uvpdftool-mcp on npm is a Model Context Protocol server: an assistant such as Claude Desktop can list the tools, run one on files in the folders you allow, and tell you where it saved the results. It reads and writes only inside the folders given with --root (or UVPDFTOOL_MCP_ROOTS), never writes over a file, and uses one API task for each run, as any other call does.
{
"mcpServers": {
"uvpdftool": {
"command": "npx",
"args": ["-y", "uvpdftool-mcp", "--root", "/Users/you/Documents/PDFs"],
"env": { "UVPDFTOOL_API_KEY": "uvp_test_…" }
}
}
}Python
uvpdftool on PyPI: the standard library only, Python 3.9 and later, with type hints.
pip install uvpdftoolfrom uvpdftool import Client, JobFailedError
client = Client(api_key=os.environ["UVPDF_KEY"])
try:
job = client.run("pdf-to-office", files=["contract.pdf"], options={"format": "docx"})
client.download(job.outputs[0], "contract.docx")
except JobFailedError as failed:
print(failed.job.error)| Name | Type | Description |
|---|---|---|
| Client(api_key, base_url=None, timeout=60) | client | The client. Standard library only; no package to install besides this one. |
| client.run(tool, files, options=None, retention_hours=None, timeout=None, on_progress=None) | Job | Creates the job, uploads every file, starts it and waits; returns the finished job or raises JobFailedError. A file is a path, or (name, bytes, content_type). |
| client.download(output, path=None) | bytes | None | The bytes of one output, or written to path. |
| client.create_job(tool, files, options=None, retention_hours=None) | CreatedJob | POST /jobs; .job and .uploads. |
| client.upload(upload, data) | None | PUT the bytes (or a path) to one upload link. |
| client.start_job(id) · get_job(id) · cancel_job(id) | Job | The three job calls. |
| client.wait(id, interval=2.0, timeout=None, on_progress=None) | Job | Polls until the job ends; returns it, or raises JobFailedError. |
| client.tools() · client.account() | dict | GET /tools and GET /account. |
| verify_webhook(raw_body, signature_header, secret, tolerance=300) | bool | Checks a delivery; see Webhooks. |
| ApiError | exception | Raised for a refused request: status, code, message, details, retry_after. |
| JobFailedError | exception | Raised when a job ends failed or cancelled: .job. |
Postman
The collection at https://uvpdftool.com/api/v1/postman.json holds every call. In Postman: Import → paste the address or the file; open the collection’s Variables and set apiKey (a test key does). The requests are in order: Create a job stores the job id and the first upload link in variables, Upload a file sends a file you pick, and the rest use the id.
OpenAPI
The description at https://uvpdftool.com/api/v1/openapi.json is OpenAPI 3.1, written from the definitions the server checks against, with each tool’s options as JSON Schema under components.schemas. It drives generators and viewers:
# Any language openapi-generator supports (Java, C#, Go, Ruby, Swift…)
npx @openapitools/openapi-generator-cli generate \
-i https://uvpdftool.com/api/v1/openapi.json -g go -o ./uvpdftool-go
# Or a typed fetch client for TypeScript
npx openapi-typescript https://uvpdftool.com/api/v1/openapi.json -o uvpdftool.d.tsValidate your requests against it before sending; the server does the same and refuses what the schema refuses.