Skip to main content

Tailprint Python SDK

PyPI version Python versions License: MIT

Official Python client for Tailprint (tailprint.com) — the developer-first programmable PDF and document engine.

Turns Tailwind CSS HTML, dynamic data, and AI prompts into pixel-perfect vector PDFs, European Factur-X / ZUGFeRD e-invoices, and provides full PDF manipulation operations (merge, split, fill forms, stamp, compress, validate).

  • Zero dependencies: Built entirely with standard library modules (urllib, json, base64, hmac). Installs in < 1 second with 0 dependency conflicts.
  • Async & Batch: Native support for asynchronous background rendering and concurrent multi-document batch runs.
  • Enterprise-Ready: Cryptographic webhook signature verification and zero-retention GDPR mode.

📦 Installation

pip install tailprint

🚀 Quickstart

import os
from tailprint import Tailprint

# Initialize with your API key (or set TAILPRINT_API_KEY environment variable)
tp = Tailprint(api_key=os.environ.get("TAILPRINT_API_KEY", "sec_live_..."))

# 1. Render Tailwind HTML to Vector PDF
pdf_bytes = tp.render_pdf(
    html="""
    <div class="p-12 bg-slate-900 text-white font-sans">
        <h1 class="text-3xl font-bold text-indigo-400">Quarterly Invoice</h1>
        <p class="text-slate-400 mt-2">Styled dynamically with Tailwind CSS.</p>
    </div>
    """,
    format="A4",
    smart_pagination=True,
)

with open("invoice.pdf", "wb") as f:
    f.write(pdf_bytes)

⚡ Asynchronous Rendering & Webhooks

For heavy 100+ page reports or async pipelines:

# Submit rendering job in background
job = tp.render_pdf_async(
    html="<h1>Heavy 200-page Annual Financial Report</h1>",
    webhook_url="https://your-api.com/webhooks/pdf",
    webhook_headers={"X-Secret": "your_webhook_secret"},
)

print("Job queued:", job["job_id"])

# Optionally poll until finished:
completed_job = tp.wait_for_job(job["job_id"], poll_interval=1.0, timeout=60.0)
print("Download URL:", completed_job["results"][0]["download_url"])

📦 Concurrent Batch Rendering with Auto-Merge

Render up to 100 documents concurrently and optionally merge them into a single multi-page PDF:

batch = tp.render_batch(
    items=[
        {"html": "<h1>Invoice #101</h1>", "filename": "inv-101.pdf"},
        {"html": "<h1>Invoice #102</h1>", "filename": "inv-102.pdf"},
        {"html": "<h1>Invoice #103</h1>", "filename": "inv-103.pdf"},
    ],
    merge_output=True,
    merged_filename="all-invoices.pdf",
    webhook_url="https://your-api.com/webhooks/pdf",
)

completed = tp.wait_for_job(batch["job_id"])
print("Merged PDF link:", completed["merged_output"]["download_url"])

🇪🇺 European Factur-X / ZUGFeRD E-Invoicing

Generate Compliant Hybrid PDF/A-3

invoice_pdf = tp.generate_einvoice(
    invoice_number="INV-2026-0042",
    currency="EUR",
    seller={"name": "Acme Nordic ApS", "country": "DK", "vat_id": "DK12345678"},
    buyer={"name": "Global Logistics GmbH", "country": "DE", "vat_id": "DE987654321"},
    line_items=[
        {"name": "Consulting Services", "quantity": 10, "unit_price": 150.0, "vat_rate": 25.0}
    ],
    payment_iban="DK001234567890",
)

Validate E-Invoice Compliance (EN 16931)

report = tp.validate_einvoice(pdf=invoice_pdf)
print("Compliant:", report["is_valid"])
print("Profile:", report["profile"])
print("Totals:", report["invoice_details"]["totals"])

🛠 Complete PDF Operations

# 1. Merge multiple PDFs
merged_pdf = tp.merge_pdfs([doc1_bytes, doc2_bytes])

# 2. Extract pages (e.g. pages 1 to 3, and page 5)
split_pdf = tp.split_pdf(doc_bytes, pages="1-3, 5")

# 3. Fill interactive AcroForms
filled_pdf = tp.fill_pdf_form(doc_bytes, fields={"customer_name": "Alice", "opt_in": True})

# 4. Stamp watermark or compliance mark
stamped_pdf = tp.stamp_pdf(doc_bytes, watermark_text="CONFIDENTIAL", opacity=0.2)

# 5. Compress PDF file size
compressed_pdf = tp.compress_pdf(doc_bytes)

🔐 Webhook Signature Verification

Verify HMAC-SHA256 signatures in FastAPI, Flask, or Django:

from fastapi import FastAPI, Request, HTTPException

app = FastAPI()

@app.post("/webhooks/pdf")
async def handle_webhook(request: Request):
    payload = await request.body()
    sig_header = request.headers.get("x-tailprint-signature", "")
    
    if not tp.verify_webhook_signature(payload, sig_header):
        raise HTTPException(status_code=401, detail="Invalid signature")
        
    data = await request.json()
    print("PDF rendered:", data["data"]["download_url"])
    return {"status": "ok"}

📄 License

MIT © Tailprint

Metadata

Release files for tailprint 1.3.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 tailprint 1.3.0
File Size Uploaded Provenance Actions
tailprint-1.3.0.tar.gz 11.5 kB Without provenance Details for tailprint-1.3.0.tar.gz

Built distribution (wheel)

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

Total release size: 20.6 kB

Release files / tailprint-1.3.0.tar.gz

Download URL tailprint-1.3.0.tar.gz
Size 11.5 kB
Tags Source
SHA-256 checksum
How to use checksums
fbc8e71ef15acc3cec9fa19e43c5f22d269b57b331b203b100103f97506517b5
BLAKE2b-256 checksum
How to use checksums
a0cb5e0247b0278117ae6af830dbaae0548ec9bd53d763e0b534b18bba8ed600
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.15.2

Release files / tailprint-1.3.0-py3-none-any.whl

Download URL tailprint-1.3.0-py3-none-any.whl
Size 9.1 kB
Tags Python 3
SHA-256 checksum
How to use checksums
93d64c2bac5d360e7f6d0bdf0a9695dd43961c7f2fe29392c8913e7bc3c15935
BLAKE2b-256 checksum
How to use checksums
30619b730300513fa176aac23480ad686be663524ce8f931edd145e1d5db0569
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.15.2

Security for tailprint 1.3.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.

No provenance found

None of the files in this release were uploaded with provenance metadata.

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

1.3.0 This release

2 release files No 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