Official Python SDK for html2pdf service - convert HTML to PDF with ease
Project description
html2pdf-sdk
Official Python SDK for the html2pdf service - convert HTML to PDF with ease.
Features
- 🚀 Simple & Intuitive API - Easy to use, powerful capabilities
- 🐍 Python 3.9+ - Full type hints and modern Python features
- ⚡ Async/Await Support - Both sync and async clients available
- 🔄 Sync & Async Rendering - Choose based on your needs
- 📦 Batch Processing - Render multiple PDFs efficiently
- 🎨 Template Support - Use pre-built templates (invoices, reports, etc.)
- 🔐 Webhook Integration - Get notified when jobs complete
- ✅ Compliance - PDF/A, PDF/UA, WCAG, PDF/X validation
- 🔄 Automatic Retries - Built-in retry logic for resilience
- 📊 Progress Tracking - Monitor long-running jobs
- 🎯 Type Safe - Comprehensive type hints with Pydantic models
Installation
pip install html2pdf-sdk
poetry add html2pdf-sdk
uv add html2pdf-sdk
Quick Start
Synchronous Usage
from html2pdf import Html2PdfClient
from html2pdf.types import RenderRequest, RenderOptions, Margins
# Initialize the client
client = Html2PdfClient(
base_url="https://api.rendly.cloud",
api_key="your-api-key"
)
# Render HTML to PDF (synchronous)
result = client.render.create(RenderRequest(
html="<h1>Hello World</h1>",
options=RenderOptions(
page_size="A4",
margins=Margins(
top="1in",
right="1in",
bottom="1in",
left="1in"
)
)
))
# Save the PDF
with open("output.pdf", "wb") as f:
f.write(result.pdf)
print(f"Generated {result.metadata.pages} pages in {result.metadata.duration_ms}ms")
Asynchronous Usage
from html2pdf import AsyncHtml2PdfClient
from html2pdf.types import RenderRequest, RenderOptions
import asyncio
async def main():
async with AsyncHtml2PdfClient(
base_url="https://api.rendly.cloud",
api_key="your-api-key"
) as client:
result = await client.render.acreate(RenderRequest(
html="<h1>Hello World</h1>",
options=RenderOptions(page_size="A4")
))
with open("output.pdf", "wb") as f:
f.write(result.pdf)
print(f"Generated {result.metadata.pages} pages")
asyncio.run(main())
Authentication
The SDK supports two authentication methods:
API Key Authentication
client = Html2PdfClient(
base_url="https://api.rendly.cloud",
api_key="your-api-key"
)
JWT Token Authentication
client = Html2PdfClient(
base_url="https://api.rendly.cloud",
access_token="your-jwt-token"
)
Core Features
Synchronous Rendering
For quick rendering (max 5MB HTML, 30s timeout):
result = client.render.create(RenderRequest(
html="<h1>Invoice</h1><p>Total: $100</p>",
options=RenderOptions(
page_size="A4",
print_background=True,
margins=Margins(top="1in", right="1in", bottom="1in", left="1in")
)
))
with open("invoice.pdf", "wb") as f:
f.write(result.pdf)
Asynchronous Rendering
For large documents or complex pages:
# Submit the job
job = client.render.create_async(RenderRequest(
url="https://example.com/large-report",
options=RenderOptions(
page_size="Letter",
display_header_footer=True,
header_template='<div style="font-size: 10px;">Report Header</div>',
footer_template='<div style="font-size: 10px;">Page <span class="pageNumber"></span></div>'
)
))
print(f"Job created: {job.job_id}")
# Poll for status
import time
while True:
status = client.render.get_status(job.job_id)
if status.status == "succeeded":
pdf = client.render.download(job.job_id)
with open("output.pdf", "wb") as f:
f.write(pdf)
break
elif status.status == "failed":
print(f"Render failed: {status.error.message}")
break
time.sleep(1)
Render and Wait (Simplified Async)
result = client.render.render_and_wait(
RenderRequest(
url="https://example.com",
options=RenderOptions(page_size="A4")
),
poll_interval=1.0,
max_wait_time=300.0,
on_progress=lambda status: print(f"Status: {status.status}")
)
with open("output.pdf", "wb") as f:
f.write(result.pdf)
Batch Processing
Process multiple PDFs in parallel:
from html2pdf.types import BatchRequest, BatchItem
# Create a batch
batch = client.batch.create(BatchRequest(
items=[
BatchItem(
mode="html",
html="<h1>Document 1</h1>",
item_id="doc1",
options=RenderOptions(page_size="A4")
),
BatchItem(
mode="url",
url="https://example.com/page1",
item_id="doc2",
options=RenderOptions(page_size="Letter")
),
BatchItem(
mode="html",
html="<h1>Document 3</h1>",
item_id="doc3"
)
]
))
print(f"Batch created: {batch.batch_id}")
# Wait for completion
result = client.batch.wait_for_completion(
batch.batch_id,
on_progress=lambda status: print(f"Progress: {status.completed}/{status.total}")
)
# Download all PDFs as a ZIP
if result.status == "completed":
zip_data = client.batch.download_zip(batch.batch_id)
with open("batch-results.zip", "wb") as f:
f.write(zip_data)
Batch from CSV
csv_data = """
mode,html,url,itemId
html,"<h1>Doc 1</h1>",,doc1
url,,https://example.com,doc2
html,"<h1>Doc 3</h1>",,doc3
"""
batch = client.batch.create_from_csv(csv_data)
Bulk Status Check
from html2pdf.types import BulkStatusRequest
statuses = client.batch.bulk_status(BulkStatusRequest(
job_ids=["job_1", "job_2", "job_3"]
))
for job_id, status in statuses.jobs.items():
print(f"{job_id}: {status.status}")
Template Rendering
Use pre-built templates for common documents:
from html2pdf.types import TemplateRenderRequest
result = client.templates.render(TemplateRenderRequest(
template="invoice",
data={
"invoiceNumber": "INV-001",
"date": "2024-01-15",
"customerName": "John Doe",
"items": [
{
"description": "Consulting Services",
"quantity": 10,
"price": 150,
"total": 1500
},
{
"description": "Software License",
"quantity": 1,
"price": 500,
"total": 500
}
],
"subtotal": 2000,
"tax": 200,
"total": 2200
},
options=RenderOptions(
page_size="A4",
print_background=True
)
))
with open("invoice.pdf", "wb") as f:
f.write(result.pdf)
Validate Template Data
from html2pdf.types import TemplateValidateRequest
validation = client.templates.validate(TemplateValidateRequest(
template="invoice",
data={"invoiceNumber": "INV-001"}
))
if not validation.valid:
print("Validation errors:", validation.errors)
Preview Template
html = client.templates.preview(
template="certificate",
data={
"name": "John Doe",
"achievement": "Course Completion",
"date": "2024-01-15"
}
)
print(html)
Webhooks
Get notified when rendering jobs complete:
from html2pdf.types import WebhookConfig
# Register a webhook
client.webhooks.create(WebhookConfig(
url="https://myapp.com/webhooks/html2pdf",
secret="your-secret-key-min-16-chars",
events=["job.completed", "job.failed", "batch.completed"],
enabled=True
))
# Get webhook config
webhook = client.webhooks.get()
print(f"Webhook: {webhook.url}")
# Update webhook
client.webhooks.update(WebhookConfig(
url="https://myapp.com/webhooks/html2pdf",
secret="your-secret-key",
events=["job.completed", "batch.completed"],
enabled=False
))
# Delete webhook
client.webhooks.delete()
Verify Webhook Signatures
In your webhook endpoint (Flask example):
from flask import Flask, request
from html2pdf.resources.webhooks import WebhooksResource
app = Flask(__name__)
@app.route("/webhooks/html2pdf", methods=["POST"])
def handle_webhook():
signature = request.headers.get("x-webhook-signature")
body = request.get_data(as_text=True)
secret = "your-secret-key"
is_valid = WebhooksResource.verify_signature_local(body, signature, secret)
if not is_valid:
return {"error": "Invalid signature"}, 401
# Process webhook event
event = request.get_json()
print(f"Event: {event['type']}, Job: {event['jobId']}")
return {"status": "ok"}
FastAPI example:
from fastapi import FastAPI, Request, HTTPException
from html2pdf.resources.webhooks import WebhooksResource
app = FastAPI()
@app.post("/webhooks/html2pdf")
async def handle_webhook(request: Request):
signature = request.headers.get("x-webhook-signature")
body = await request.body()
secret = "your-secret-key"
is_valid = WebhooksResource.verify_signature_local(
body.decode(), signature, secret
)
if not is_valid:
raise HTTPException(status_code=401, detail="Invalid signature")
event = await request.json()
print(f"Event: {event['type']}, Job: {event['jobId']}")
return {"status": "ok"}
Compliance & Validation
Validate PDFs against compliance standards:
from html2pdf.types import ComplianceCertificateRequest
with open("document.pdf", "rb") as f:
pdf_data = f.read()
# Generate compliance certificate
certificate = client.compliance.generate_certificate(
ComplianceCertificateRequest(
pdf=pdf_data,
standards=["pdfa", "pdfua", "wcag"],
format="json"
)
)
print(f"Certificate ID: {certificate.certificate_id}")
for result in certificate.results:
print(f"{result.standard}: {'PASS' if result.compliant else 'FAIL'}")
print(f"Score: {result.score}/100")
if not result.compliant:
print("Issues:")
for issue in result.issues:
print(f" [{issue.severity}] {issue.message}")
if issue.recommendation:
print(f" → {issue.recommendation}")
Specific Validations
# PDF/A validation
pdfa_result = client.compliance.validate_pdfa(pdf_data)
# PDF/UA (accessibility) validation
pdfua_result = client.compliance.validate_pdfua(pdf_data)
# WCAG compliance
wcag_result = client.compliance.validate_wcag(pdf_data)
# PDF/X (print production)
pdfx_result = client.compliance.validate_pdfx(pdf_data)
Advanced Options
Page Size Options
# Preset sizes
result = client.render.create(RenderRequest(
html="<h1>Test</h1>",
options=RenderOptions(
page_size="A4" # 'A4', 'Letter', 'Legal', 'A3', 'A5', 'Tabloid'
)
))
# Custom dimensions
from html2pdf.types import CustomPageSize
result = client.render.create(RenderRequest(
html="<h1>Test</h1>",
options=RenderOptions(
page_size=CustomPageSize(width="8.5in", height="11in")
)
))
Headers and Footers
result = client.render.create(RenderRequest(
html="<h1>Report</h1>",
options=RenderOptions(
display_header_footer=True,
header_template="""
<div style="font-size: 10px; width: 100%; text-align: center;">
Company Report
</div>
""",
footer_template="""
<div style="font-size: 10px; width: 100%; text-align: center;">
Page <span class="pageNumber"></span> of <span class="totalPages"></span>
</div>
""",
margins=Margins(
top="1in",
bottom="1in",
left="0.5in",
right="0.5in"
)
)
))
PDF/A Compliance with Attachments
from html2pdf.types import PDFAttachment
import base64
with open("invoice.xml", "rb") as f:
xml_content = f.read()
result = client.render.create(RenderRequest(
html="<h1>Invoice</h1>",
options=RenderOptions(
compliance="pdfa-3",
attachments=[
PDFAttachment(
filename="invoice.xml",
content=base64.b64encode(xml_content).decode(),
description="Structured invoice data (ZUGFeRD)",
mime_type="text/xml",
relationship="Data"
)
]
)
))
Digital Signatures
from html2pdf.types import DigitalSignature
import base64
with open("certificate.p12", "rb") as f:
cert_data = f.read()
result = client.render.create(RenderRequest(
html="<h1>Signed Document</h1>",
options=RenderOptions(
signature=DigitalSignature(
certificate=base64.b64encode(cert_data).decode(),
password="cert-password",
reason="Document approval",
contact_info="signer@example.com",
location="New York, USA",
name="John Doe"
)
)
))
Debug Mode
job = client.render.create_async(RenderRequest(
html="<h1>Debug Test</h1>",
options=RenderOptions(debug=True)
))
# Wait for completion
import time
while True:
status = client.render.get_status(job.job_id)
if status.status in ("succeeded", "failed"):
break
time.sleep(1)
# Download debug bundle (includes HTML, console logs, network errors, metadata)
if status.status == "succeeded":
debug_zip = client.render.download_debug(job.job_id)
with open("debug.zip", "wb") as f:
f.write(debug_zip)
Error Handling
The SDK provides typed errors for better error handling:
from html2pdf import (
Html2PdfError,
ValidationError,
AuthenticationError,
RateLimitError,
TimeoutError,
NetworkError
)
try:
result = client.render.create(RenderRequest(html="<h1>Test</h1>"))
except AuthenticationError as e:
print(f"Authentication failed: {e.message}")
except RateLimitError as e:
print(f"Rate limit exceeded: {e.message}")
except ValidationError as e:
print(f"Validation error: {e.message}")
print(f"Details: {e.details}")
except TimeoutError as e:
print(f"Request timeout: {e.message}")
except NetworkError as e:
print(f"Network error: {e.message}")
except Html2PdfError as e:
print(f"Error [{e.status_code}]: {e.message}")
except Exception as e:
print(f"Unknown error: {e}")
Configuration Options
client = Html2PdfClient(
# Required
base_url="https://api.rendly.cloud",
# Authentication (choose one)
api_key="your-api-key",
# OR
# access_token="your-jwt-token",
# Optional
timeout=60.0, # Request timeout in seconds (default: 30.0)
max_retries=5, # Max retry attempts (default: 3)
headers={ # Custom headers for all requests
"X-Custom-Header": "value"
}
)
Type Safety
The SDK is fully typed using Pydantic models:
from html2pdf import Html2PdfClient
from html2pdf.types import (
RenderRequest,
RenderOptions,
PageSizeEnum,
ComplianceStandard,
Margins
)
# IDE autocomplete and type checking work seamlessly
options = RenderOptions(
page_size=PageSizeEnum.A4,
compliance=ComplianceStandard.PDFA_2,
print_background=True,
margins=Margins(
top="1in",
right="1in",
bottom="1in",
left="1in"
)
)
request = RenderRequest(
html="<h1>Test</h1>",
options=options
)
Health Check
Check if the service is available:
is_healthy = client.health_check()
print(f"Service healthy: {is_healthy}")
Metrics
Get Prometheus metrics:
metrics = client.get_metrics()
print(metrics)
Context Managers
Both sync and async clients support context managers:
# Synchronous
with Html2PdfClient(...) as client:
result = client.render.create(...)
# Asynchronous
async with AsyncHtml2PdfClient(...) as client:
result = await client.render.acreate(...)
Requirements
- Python 3.9 or higher
- httpx >= 0.27.0
- pydantic >= 2.0.0
Development
Setup
# Clone the repository
git clone https://github.com/nixbit-maker/Rendly.git
cd html2pdf/sdk-python
# Install dependencies
pip install -e ".[dev]"
Running Tests
pytest
Type Checking
mypy html2pdf
Linting and Formatting
ruff check html2pdf
ruff format html2pdf
License
MIT
Support
Contributing
Contributions are welcome! Please see CONTRIBUTING.md for details.
Changelog
See CHANGELOG.md for release notes.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file html2pdf_sdk-1.0.0.tar.gz.
File metadata
- Download URL: html2pdf_sdk-1.0.0.tar.gz
- Upload date:
- Size: 23.1 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
f551044f62baa3d0b1308237cf01d85cf5fee1b9b1af32577050b3a6c31d1e54
|
|
| MD5 |
5e149a8ef9158078bd43e5056eaec34b
|
|
| BLAKE2b-256 |
5026b245d55d7a934bad0408a1c68b9b48b3b0ec125caa868af043d5630716f6
|
File details
Details for the file html2pdf_sdk-1.0.0-py3-none-any.whl.
File metadata
- Download URL: html2pdf_sdk-1.0.0-py3-none-any.whl
- Upload date:
- Size: 28.7 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
72ffb3b4c76ecffff911f3950961f0780190e71fc920e960828184d83a1ca46c
|
|
| MD5 |
9ff14665526aaa29c9f0c77c79e96b9c
|
|
| BLAKE2b-256 |
71f218dfaab83b3b0f596e006eba6a5fdaba626a43d61d4e048122684299b529
|