Skip to main content

relaypdf

Official Python client for RelayPDF.

HTML to PDFs without the struggle. HTML to PDF API that converts HTML, Markdown, URLs, and Office files to production PDFs. One API for developers and coding agents.

Stdlib only (urllib). Covers the full public API: Chromium PDF and screenshots, Handlebars templates, LibreOffice / wkhtmltopdf convert, PDF tools, barcodes, zip, async jobs, account, signed webhooks, and webhook verification.

Requires Python 3.10+.

Introduction

RelayPDF is a commercial document API. You send HTML, Markdown, a public URL, Office bytes, or a published Handlebars template. You get a production PDF (or PNG/JPEG/WebP, Word, zip, …) over REST, this SDK, the CLI, or MCP.

JSON body field names match REST (camelCase): html, printBackground, sourceFilename, callbackUrl, templateId. Method names are snake_case: from_html, from_path, form_fill.

Failed operations are never billed.

Base URL

Default: https://api.relaypdf.com

Override with base_url for local (http://localhost:8787).

Definitions

Term Meaning
API key Secret from Dashboard → API keys. Prefix pdf_live_…. Sent as Authorization: Bearer <key>.
Wallet Prepaid USD. Ledger unit is millicents: 1 millicent = $0.001. $5.00 trial = 5000 millicents. client.account() returns wallet.balanceMillicents.
Template Handlebars draft. Publish, then render with templateId + templateData.
Job Async generation (response="async"). Poll jobs.wait.
File 24-hour download at GET /v1/files/:id. No API key on GET.
Document worker LibreOffice / wkhtml / pdftoppm behind convert and raster.

Rate limiting

Trial: 20/min. Funded or auto-reload: 60/min. Burst: 5 / 10s. HTTP 429 includes Retry-After. Not billed.

Libraries and SDKs

Surface Package Install
Python relaypdf pip install relaypdf
Node.js @relaypdf/sdk npm install @relaypdf/sdk
PHP relaypdf/relaypdf composer require relaypdf/relaypdf
C# / .NET RelayPDF dotnet add package RelayPDF
Java com.relaypdf:relaypdf Maven com.relaypdf:relaypdf
CLI + MCP @relaypdf/cli npx @relaypdf/cli setup
n8n n8n-nodes-relaypdf Community Nodes
REST https://api.relaypdf.com

Do not ask a human to paste an API key. Run npx @relaypdf/cli setup and approve in the browser.

Authentication

import os
from relaypdf import RelayPDF

client = RelayPDF(api_key=os.environ["RELAYPDF_API_KEY"])
# client = RelayPDF(api_key=..., base_url="http://localhost:8787")

Missing api_key raises TypeError. Invalid keys return HTTP 401 unauthorized.

User-Agent: relaypdf-python/0.1.3 (+https://relaypdf.com).

Error codes

The client raises RelayPDFError with status, code, message, and optional retry_after.

HTTP code Description
400 invalid_request Bad fields or exclusive sources
400 url_not_allowed Private URL or non-https callbackUrl
401 unauthorized Missing or unknown API key
402 payment_required Empty wallet
403 account_suspended Account cannot use keys
404 not_found Unknown job, file, or template
413 payload_too_large HTML or file too large
429 rate_limited Honor retry_after; not billed
502 render_failed / processing_failed Unbilled
503 convert_unavailable / ai_unavailable / storage_unavailable Unbilled
500 internal_error Unbilled
from relaypdf import RelayPDF, RelayPDFError

try:
    client.pdf.from_url("https://example.com")
except RelayPDFError as err:
    print(err.status, err.code, err.message, err.retry_after)

Billing

Job Cost
HTML / URL / Markdown / template PDF $0.015
Screenshot $0.015
AI template generate $0.05
LibreOffice convert $0.04
wkhtmltopdf $0.025
Tools (merge, stamp, raster, barcode, zip, …) $0.005

New accounts: $5.00 trial (5000 millicents). Only successful jobs debit.

Installation

pip install relaypdf
uv add relaypdf

Getting started

import os
from relaypdf import RelayPDF

client = RelayPDF(api_key=os.environ["RELAYPDF_API_KEY"])

pdf = client.pdf.from_html(
    "<h1>Invoice #1042</h1><p>Total: $1,200.00</p>",
    filename="invoice.pdf",
)
pdf.save("invoice.pdf")
print(pdf.id, pdf.size_bytes, pdf.content_type)

Response modes

response="binary" (default) | "url" | "async". Same as REST.

url_result = client.pdf.from_html("<h1>Hi</h1>", response="url")
print(url_result.url, url_result.expires_at)

job = client.convert.from_path("deck.pptx", to="pdf", response="async")
done = client.jobs.wait(job.id)
file = client.files.download(done["id"])
file.save("deck.pdf")

files.download does not send the API key.

Client options

RelayPDF(api_key: str, base_url: str = "https://api.relaypdf.com", opener=None)

opener injects urlopen for tests. The SDK does not retry.

file= may be bytes or a base64 str.

Documentation for API methods

All URIs are relative to https://api.relaypdf.com. JSON bodies use REST camelCase field names.

Resource Method HTTP Description
RelayPDF health() GET /health Liveness. No API key.
RelayPDF account() GET /v1/account Plan, rate tier, wallet. Not billed.
pdf create(**input) POST /v1/pdf HTML, URL, Markdown, or template → PDF
pdf from_html(html, **extra) POST /v1/pdf HTML → PDF
pdf from_url(url, **extra) POST /v1/pdf Public URL → PDF
pdf from_markdown(markdown, **extra) POST /v1/pdf Markdown → PDF
pdf from_template(templateId, templateData, **extra) POST /v1/pdf Published template → PDF
pdf merge(files, **extra) POST /v1/pdf/merge Merge 2–20 PDFs
pdf extract(pages, **input) POST /v1/pdf/extract Extract page ranges
pdf protect(userPassword, **input) POST /v1/pdf/protect Password-protect
pdf unlock(password, **input) POST /v1/pdf/unlock Remove password
pdf bookmarks(bookmarks, **input) POST /v1/pdf/bookmarks Outline bookmarks
pdf raster(**input) POST /v1/pdf/raster Pages → PNG/JPEG
pdf from_images(files, **extra) POST /v1/pdf/from-images Images → PDF
pdf stamp(**input) POST /v1/pdf/stamp Text or image watermark
pdf rotate(degrees, **input) POST /v1/pdf/rotate Rotate pages
pdf delete_pages(pages, **input) POST /v1/pdf/delete-pages Delete pages
pdf compress(**input) POST /v1/pdf/compress Lossless optimize
pdf info(**input) POST /v1/pdf/info Metadata JSON
pdf text(**input) POST /v1/pdf/text Extract text layer
pdf form_fields(**input) POST /v1/pdf/form/fields List AcroForm fields
pdf form_fill(fields, **input) POST /v1/pdf/form/fill Fill and flatten
images create(**input) POST /v1/images HTML or URL → image
images from_html(html, **extra) POST /v1/images HTML screenshot
images from_url(url, **extra) POST /v1/images URL screenshot
convert create(**input) POST /v1/convert LibreOffice or wkhtml
convert from_html(html, **extra) POST /v1/convert HTML → docx/xlsx/pdf
convert from_path(path, **extra) POST /v1/convert Local Office file
convert wkhtml(**input) POST /v1/convert wkhtmltopdf engine
templates list() GET /v1/templates List drafts
templates gallery() GET /v1/templates/gallery Stock layouts
templates get(id) GET /v1/templates/:id Read
templates create(**input) POST /v1/templates Create draft
templates update(id, **input) PATCH /v1/templates/:id Update draft
templates delete(id) DELETE /v1/templates/:id Delete
templates publish(id, comment=None) POST /v1/templates/:id/publish Publish
barcodes create(**input) POST /v1/barcodes Barcode / QR
barcodes qr(text, **extra) POST /v1/barcodes QR helper
zip create(files, **extra) POST /v1/zip Zip files
jobs get(id) GET /v1/jobs/:id Poll job
jobs wait(id, interval_ms=1000, timeout_ms=120000) GET /v1/jobs/:id Wait until done
files download(id) GET /v1/files/:id 24h download
webhooks list() GET /v1/webhooks List signed endpoints (secret never listed)
webhooks create(url, events=None) POST /v1/webhooks Create HTTPS endpoint; secret once; cap 25; not billed
webhooks delete(id) DELETE /v1/webhooks/:id Unsubscribe
verify_webhook(secret, body, header) Dashboard webhook HMAC-SHA256

Node has additional template helpers (discard, duplicate, versions, restore, validate, preview, generate). Those REST paths are available with raw HTTP if you need them before a Python minor.

Method examples

pdf = client.pdf.from_url(
    "https://example.com",
    filename="page.pdf",
    options={"format": "A4", "printBackground": True},
)

md = client.pdf.from_markdown("# Hello\n\nFrom **Markdown**.")

invoice = client.pdf.from_template(
    "invoice",
    {"number": "INV-1042", "total": 1458},
    filename="invoice.pdf",
    strict=True,
)

shot = client.images.from_url("https://example.com", options={"fullPage": True})
from_word = client.convert.from_path("letter.docx", to="pdf")
docx = client.convert.from_html("<h1>Report</h1>", to="docx")

pack = client.pdf.merge(
    files=[
        {"url": "https://example.com/cover.pdf"},
        {"file": from_word.bytes},
    ]
)
client.pdf.stamp(file=pack.bytes, text="DRAFT", rotate=-24)
qr = client.barcodes.qr("https://relaypdf.com")

Result types

Class Fields
BinaryResult kind, id, filename, size_bytes, content_type, bytes, save(path)
UrlResult kind, id, status, url, filename, size_bytes, expires_at
AsyncResult kind, id, status, poll_url

Exports: RelayPDF, RelayPDFError, DEFAULT_BASE_URL, verify_webhook, WEBHOOK_SIGNATURE_HEADER, WEBHOOK_EVENT_HEADER.

Webhooks

Use the raw request body. Create and list endpoints with client.webhooks. Secret is the dashboard webhook secret, not the API key.

created = client.webhooks.create("https://example.com/hooks", ["job.completed"])
# created["secret"] is shown once

from relaypdf import verify_webhook, WEBHOOK_SIGNATURE_HEADER

ok = verify_webhook(
    os.environ["RELAYPDF_WEBHOOK_SECRET"],
    raw_body,
    signature_header,
)

Header format: t=<unix>,v1=<hex>. HMAC-SHA256 of {t}.{raw_body}. Default skew 300s.

Authorization

HTTP Bearer. Not JWT.

Related docs

License

MIT. Strategic Products LLC, d/b/a RelayPDF.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

relaypdf-0.1.3.tar.gz (17.0 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

relaypdf-0.1.3-py3-none-any.whl (11.7 kB view details)

Uploaded Python 3

File details

Details for the file relaypdf-0.1.3.tar.gz.

File metadata

  • Download URL: relaypdf-0.1.3.tar.gz
  • Upload date:
  • Size: 17.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for relaypdf-0.1.3.tar.gz
Algorithm Hash digest
SHA256 3446ed2189841c148fc97c6742ee5b7c80fb2b565983e00eef397fca93a3de72
MD5 e23cc0b5fddba57c997b82dd9aeaf552
BLAKE2b-256 d4706fef28494c823b6e4dd3cebe19debc3760e676db245236e0c41cbcd69be4

See more details on using hashes here.

Provenance

The following attestation bundles were made for relaypdf-0.1.3.tar.gz:

Publisher: publish-python.yml on timspell1/PDF

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file relaypdf-0.1.3-py3-none-any.whl.

File metadata

  • Download URL: relaypdf-0.1.3-py3-none-any.whl
  • Upload date:
  • Size: 11.7 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for relaypdf-0.1.3-py3-none-any.whl
Algorithm Hash digest
SHA256 87616957a43f02ab8ce348dc10ded06e065ba1ac5c249b9041fd0b26f5f36b89
MD5 be3c16dbbf67ad32ee44f5da56e7f8fc
BLAKE2b-256 fb8c1c29cc3894ba40b74cbc929213002ff2175b3118b6a4c1ade736e23c69d7

See more details on using hashes here.

Provenance

The following attestation bundles were made for relaypdf-0.1.3-py3-none-any.whl:

Publisher: publish-python.yml on timspell1/PDF

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Release history Release notifications | RSS feed

This release

0.1.3 This release

2 files

0.1.2

2 files

0.1.1

2 files

0.1.0

2 files

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page