Skip to main content

pdfops

Python client for the PDFops API: fill AcroForm PDFs, merge PDFs, inspect form fields, and generate invoices with one HTTP call. No native dependencies, no headless browser, nothing to install but this package.

Built for the moment pypdf / PyPDFForm stop cooperating — appearance streams that never render, NeedAppearances flags, encrypted government blanks, checkboxes that will not tick — and for runtimes where a PDF toolchain does not fit: Lambda, Cloud Functions, Airflow tasks, notebooks.

pip install pdfops

Zero dependencies (standard-library urllib), Python 3.9+, fully typed.

Quick start

from pdfops import PdfOps

client = PdfOps(api_key="pdfops_live_...")   # or PdfOps() for the keyless trial (100 req/IP/month)

# 1. Discover the field names — you cannot fill fields you cannot name.
info = client.inspect("blank-w9.pdf")
print(info["count"], "fields")
fields = info["fillTemplate"]                  # paste-ready {name: ""} dict

# 2. Fill, optionally flattening so the result is no longer editable.
fields["Name"] = "Ada Lovelace"
fields["Agree"] = "true"                       # checkboxes take "true" / "false"
pdf_bytes = client.fill_form("blank-w9.pdf", fields, flatten=True)
open("w9-filled.pdf", "wb").write(pdf_bytes)

# 3. Merge, in order.
packet = client.merge(["cover.pdf", pdf_bytes, "terms.pdf"])

# 4. Invoice from data — deterministic, safe to re-render from a webhook.
invoice = client.invoice({
    "from": "Acme Ltd",
    "to": {"name": "Ada Lovelace", "lines": ["12 Analytical Way", "London"]},
    "items": [{"description": "Consulting", "quantity": 3, "unit_price": 120.0}],
    "invoice_number": "2026-0042",
    "date": "2026-09-05",
    "currency": "GBP",
})

PDF inputs may be bytes, a path (str / pathlib.Path), or a binary file object. Every PDF-producing call returns bytes.

API

Method Endpoint Returns
inspect(pdf) POST /api/inspect dict — count, hasXFA, fields[], fillTemplate
fill_form(pdf, fields, *, flatten=False) POST /api/fill-form filled PDF bytes
merge([pdf, pdf, ...]) POST /api/merge merged PDF bytes
invoice(request) POST /api/invoice invoice PDF bytes
usage() GET /api/usage dict — tier, limit, used, remaining, resets_at
signup(email) POST /api/signup None — the key is emailed

Full request/response schemas: pdfops.dev/docs · OpenAPI.

Errors

Every non-2xx response raises PdfOpsError carrying the API's stable error slug:

from pdfops import PdfOps, PdfOpsError

try:
    client.fill_form("form.pdf", {"Nmae": "typo"})
except PdfOpsError as e:
    print(e.status, e.code, e.details)   # 422 unknown_field No field named Nmae

Common codes: unknown_field, exceeds_max_length, invalid_option, encrypted_pdf, rate_limited, invalid_api_key.

Configuration

  • PdfOps(api_key=...) or the PDFOPS_API_KEY environment variable. A free key (250 req/month, no card) is one field at pdfops.dev/pricing.
  • client_tag="..." sets the X-Pdfops-Client header for anonymous usage attribution when you embed this client in another tool. Defaults to "py".
  • timeout=60.0 seconds per request; base_url= overrides the API origin for testing.
  • transport= injects a (method, url, headers, body) -> (status, headers, body) callable — the test suite uses this; no network needed.

Why an API instead of a library

pdf-lib and pypdf are excellent when the PDF is well-behaved. PDFops exists for the other ones: it renders appearance streams server-side so every viewer shows the values, handles the encrypted-with-empty-password blanks governments publish, flattens deterministically, and is byte-for-byte reproducible — the same request yields the same file. The compatibility registry records which public forms fill cleanly with which toolchain.

Fill a PDF in Python · Docs · MCP server for AI agents · TypeScript SDK · n8n node · hello@pdfops.dev

MIT © PDFops

Metadata

Release files for pdfops 0.1.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for pdfops 0.1.0
File Size Uploaded Provenance
pdfops-0.1.0.tar.gz 9.0 kB With provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for pdfops 0.1.0
File Interpreter ABI Platform
pdfops-0.1.0-py3-none-any.whl Python 3 none any Details

Total release size: 17.0 kB

Release files / pdfops-0.1.0.tar.gz

Download URL pdfops-0.1.0.tar.gz
Size 9.0 kB
Tags Source
SHA-256 checksum
How to use checksums
514cd822ae88ff72aa1f34010ae77f09f0146b4256fb9dacdeb7e83c901516cb
BLAKE2b-256 checksum
How to use checksums
156b3cc910b244eaf9a8e5292b64c4948afcad9541f1ca544c4f9bb3aa4581aa
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 5, 2026.

Transparency log

Release files / pdfops-0.1.0-py3-none-any.whl

Download URL pdfops-0.1.0-py3-none-any.whl
Size 8.0 kB
Tags Python 3
SHA-256 checksum
How to use checksums
b8bd90fac5e25b9f0ad60190cc1c55931daadcfadea5f3c333814106d03b64df
BLAKE2b-256 checksum
How to use checksums
19936be5ca99c144efb7ff7623831cab3f545cae46b70bce213b674b27a29f0d
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 5, 2026.

Transparency log

Security for pdfops 0.1.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

Full provenance

All 2 files in this release have been uploaded with provenance metadata.

Select from 2 files

Attestation for pdfops-0.1.0.tar.gz

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 5, 2026.

Transparency log

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Release history Release notifications | RSS feed

This release

0.1.0 This release

2 release files Full provenance

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page