PDFZippy

PDFZippy API

Send a PDF, get the result back. Keys are issued personally during the pilot, so email us to get one.

Getting started

  1. Ask us for a key. We create it for you and send it privately. It is shown once, so save it straight away.
  2. Store it as a secret on your server, for example an environment variable named PDFZIPPY_KEY. The examples below read it from there.
  3. Call the API from your server, never from a web page or an app that users can inspect.
  4. Check your usage any time with the usage call at the bottom of this page.

Authentication

Send your key in the Authorization header on every request. Keep it secret and call the API from your server, never from a web page.

Authorization: Bearer pz_live_xxxxxxxxxxxxxxxxxxxxxxxx

Merge PDFs

POST /api/v1/merge as multipart/form-data. files: 2 to 20 PDF files.

curl -X POST https://pdfzippy.me/api/v1/merge \
  -H "Authorization: Bearer $PDFZIPPY_KEY" \
  -F [email protected] -F [email protected] \
  -o merged.pdf

Compress a PDF

POST /api/v1/compress as multipart/form-data. file: one PDF. level (optional): low, medium (default) or high.

curl -X POST https://pdfzippy.me/api/v1/compress \
  -H "Authorization: Bearer $PDFZIPPY_KEY" \
  -F [email protected] -F level=medium \
  -o compressed.pdf

Convert a PDF to Word

POST /api/v1/pdf-to-word as multipart/form-data. file: one PDF. Works best on text-based PDFs, not scanned pages.

curl -X POST https://pdfzippy.me/api/v1/pdf-to-word \
  -H "Authorization: Bearer $PDFZIPPY_KEY" \
  -F [email protected] \
  -o paper.docx

Use it from your code

Node.js (version 18 or newer):

import { readFile, writeFile } from 'node:fs/promises'

const form = new FormData()
form.append('file', new Blob([await readFile('paper.pdf')], { type: 'application/pdf' }), 'paper.pdf')

const res = await fetch('https://pdfzippy.me/api/v1/pdf-to-word', {
  method: 'POST',
  headers: { Authorization: `Bearer ${process.env.PDFZIPPY_KEY}` },
  body: form,
})
if (!res.ok) throw new Error((await res.json()).error.message)
await writeFile('paper.docx', Buffer.from(await res.arrayBuffer()))
console.log('documents left:', res.headers.get('x-quota-remaining'))

Python:

import os, requests

res = requests.post(
    "https://pdfzippy.me/api/v1/pdf-to-word",
    headers={"Authorization": "Bearer " + os.environ["PDFZIPPY_KEY"]},
    files={"file": open("paper.pdf", "rb")},
)
res.raise_for_status()
open("paper.docx", "wb").write(res.content)
print("documents left:", res.headers["X-Quota-Remaining"])

Check your usage

GET /api/v1/usage does not count against your limit.

curl https://pdfzippy.me/api/v1/usage -H "Authorization: Bearer $PDFZIPPY_KEY"

{ "name": "Your company", "period": "2026-10", "limit": 250, "used": 12, "remaining": 238 }

A machine-readable description of the API is at /api/v1/openapi.json (OpenAPI 3).

Limits

  • Each request can be up to 4 MB in total.
  • Every successful call counts as one document. Failed calls are not counted.
  • Your monthly limit resets on the 1st (UTC). Each response shows it in X-Quota-Limit and X-Quota-Remaining.
  • Up to 30 requests a minute per key.
  • PDF to Word accepts up to 150 pages per file.
  • Every response carries an X-Request-Id. Quote it if you contact us about a problem.

Errors

Errors return JSON with a stable code and a readable message.

{ "error": { "code": "quota_exceeded", "message": "Your monthly limit of 100 documents is used up." } }
  • 401 unauthorized: missing, wrong or revoked key.
  • 400 invalid_request or invalid_pdf: the upload was not what the endpoint expects.
  • 413 payload_too_large: over 4 MB.
  • 422 processing_failed: we could not process that file.
  • 429 rate_limited or quota_exceeded: slow down, or wait for the monthly reset.

Your files

Files are processed in memory and returned in the response. We do not save them, and we do not log their contents. Do not send files you are not allowed to share with a third-party service, such as patient records.

Search tools and files

Find a PDF tool or recent file