Skip to main content

quirepdf (Python)

Send JSON, get back a polished PDF. Python 3.9+, standard library only, synchronous.

Install

pip install quirepdf

Quickstart

Any JSON object renders. Quire picks the best-matching template, or a clean generic layout:

from quirepdf import Quire

client = Quire()  # reads QUIRE_API_KEY (and QUIRE_API_URL)

order = {
    "order_id": "ORD-88213",
    "customer": {"name": "Lena Fischer", "email": "lena@example.de"},
    "lines": [{"sku": "TS-BLK-M", "name": "Organic tee", "qty": 2, "price": 29.0}],
    "currency": "€",
}
result = client.render(order)
result.save("order.pdf")
print(result.template, result.template_source, result.pages)  # document fallback 1
if result.hint:
    print("almost matched:", result.hint)  # e.g. "invoice (seller is required)"

Name a template and use the generated types so your editor checks the fields:

from quirepdf.types import InvoiceData

invoice: InvoiceData = {
    "number": "INV-2026-0142",
    "issued": "1 Oct 2026",
    "due": "15 Oct 2026",
    "seller": {"name": "Northwind Studio", "address": ["221 Market Street", "San Francisco, CA 94105"]},
    "customer": {"name": "Ravi Kumar", "address": ["14 Residency Road", "Bengaluru 560025"]},
    "items": [{"description": "Pro plan", "qty": 1, "unit_price": 49}],
    "status": "due",  # Literal["draft", "due", "paid", "overdue", "void"]
}

pdf = client.render(invoice, template="invoice")
png = client.render(invoice, template="invoice", format="png", page=1)  # preview one page
print(pdf.content[:5], len(png.content), pdf.render_ms, pdf.quota)    # Quota(limit=100, remaining=97)

RenderResult fields: content (the file as bytes), content_type, pages, template, template_source (explicit | detected | fallback), hint, render_ms, quota, and save(path).

Other calls:

check = client.validate(invoice, template="invoice")   # free, nothing rendered
check.valid, check.errors                               # False, [{"path": "...", "message": "..."}]

client.templates.list()            # [{"name": "invoice", "title": "Invoice", ...}, ...]
client.templates.get("invoice")    # {"template": {...}, "schema": {...}, "sample": {...}}
client.usage()                     # {"plan": "free", "used": 3, "limit": 100, "remaining": 97, ...}

new = client.keys.create(name="ci")   # new["api_key"] is shown only once
client.keys.list()                    # [{"id", "prefix", "name", "current": bool, ...}]
client.keys.revoke(new["key"]["id"])

Errors

Every failure raises QuireError with status, type, message and fields:

from quirepdf import QuireError

try:
    client.render({"number": "INV-1"}, template="invoice")
except QuireError as err:
    print(err.status, err.type)  # 422 invalid_data
    print(err)                   # data has 5 problems
                                 #   - issued is required
                                 #   - due is required ...
    for f in err.fields:
        print(f["path"], f["message"])

Common types: invalid_data, unknown_template, unauthorized, quota_exceeded, bad_request, payload_too_large, timeout. Client-side failures have status == 0: type == "network" (can't connect) or type == "timeout" (no reply within timeout seconds). The SDK never retries.

Configuration

Argument Environment Default
api_key QUIRE_API_KEY none (no Authorization header is sent)
base_url QUIRE_API_URL https://api.quirepdf.dev
timeout 30.0 seconds
client = Quire(api_key="qk_...", base_url="http://127.0.0.1:8787", timeout=10)

A local engine in open mode (make serve) needs no key.

Development

python3 scripts/gen_types.py          # regenerate src/quirepdf/types.py after a schema change
python3 scripts/gen_types.py --check  # fail if it is stale
PYTHONPATH=src python3 -m unittest discover -s tests -v   # runs against engine/target/release/quire-engine (make build)

Metadata

Release files for quirepdf 0.2.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 quirepdf 0.2.0
File Size Uploaded
quirepdf-0.2.0.tar.gz 12.4 kB Details

Built distribution (wheel)

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

Total release size: 26.5 kB

Release files / quirepdf-0.2.0.tar.gz

Download URL quirepdf-0.2.0.tar.gz
Size 12.4 kB
Tags Source
SHA-256 checksum
How to use checksums
f52c6d0ce804730947de1ab168ef81c1ac8ca911b61411da8cb011a61f5ed964
BLAKE2b-256 checksum
How to use checksums
7e8ddf3c7e47fddf7470e6bc744184a7caf0c763b3c806f3bcb9930f5770f059
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.12.13

Release files / quirepdf-0.2.0-py3-none-any.whl

Download URL quirepdf-0.2.0-py3-none-any.whl
Size 14.1 kB
Tags Python 3
SHA-256 checksum
How to use checksums
80f97f095486e84c33966bfdd8f7521ce6ea6b6d17a4e3933dea4b68cdfe760b
BLAKE2b-256 checksum
How to use checksums
2380cf239d79fd7f1290cf16eef59a7eb19469e940ac8c8dddef5dd1d84b152f
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.12.13

Release history Release notifications | RSS feed

This release

0.2.0 This release

2 release files

0.1.0

2 release files

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