pennypdf

Developer API

PDF generation API

Most 'PDF generation' workloads in production are one of four things: an invoice per customer transaction, a receipt per order, a monthly report per account, or a per-user export of some dashboard. All four look alike programmatically: render an HTML template with data, save the result as a PDF.

PennyPDF's /v1/html-to-pdf is the generation primitive. Combine it with your favorite templating engine (Jinja2, Handlebars, Mustache, React SSR, whatever) and you have a full generation pipeline at 1 coin per doc. At the Pro pack ($14.99 / 500 coins), that's 3 cents per invoice — indistinguishable from the marginal cost of the outbound email that delivers it.

For templated workflows without wanting to run your own templating: pass JSON variables alongside the HTML, and PennyPDF substitutes `{{ variable_name }}` placeholders server-side. Zero dependencies on your end. See the 'templated invoice' sample below.

Copy, paste, ship

Same bearer-token auth across every endpoint. Set PENNYPDF_API_KEY in your environment first.

curlPOST /v1/html-to-pdf (templated)
curl -X POST https://api.pennypdf.com/v1/html-to-pdf \
  -H "Authorization: Bearer $PENNYPDF_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "html": "<h1>Invoice {{ invoice_number }}</h1><p>Customer: {{ customer }}</p><p>Total: {{ total }}</p>",
    "variables": {
      "invoice_number": "INV-1042",
      "customer": "Acme Co.",
      "total": "$1,200.00"
    }
  }' \
  -o invoice.pdf
PythonJinja2 + PennyPDF (full pipeline)
from jinja2 import Template
import os, requests

tmpl = Template(open("invoice.html").read())
html = tmpl.render(customer="Acme Co.", total=1200.00, invoice="INV-1042")

r = requests.post(
    "https://api.pennypdf.com/v1/html-to-pdf",
    headers={"Authorization": f"Bearer {os.environ['PENNYPDF_API_KEY']}"},
    json={"html": html, "page_size": "Letter"},
)
open("invoice.pdf", "wb").write(r.content)
# Spent 1 coin. At Pro pack prices: 3¢ per invoice.

PennyPDF vs DocRaptor

 PennyPDFDocRaptor
Price per doc1 coin (~$0.04)$0.12/doc overage
Monthly minimum$0$15/mo for 125 docs
TemplatingServer-side var substitution, or bring-your-ownClient-side only
Test rendersFree with welcome coinsUnlimited but watermarked
EngineChromium printPrinceXML
Pay-as-you-goYes, alwaysNo

How it works

  1. 1Write an HTML template — yours or ours.
  2. 2POST to /v1/html-to-pdf with `html` + `variables` (or `url` for URL-based rendering).
  3. 3Receive the rendered PDF in the response body. Serve to customer, email, archive.

Frequently asked

Should I use the server-side variable substitution or my own templating?+

Bring your own for anything non-trivial (loops, conditionals, filters). Our server-side substitution is deliberately minimal — it's for quick prototypes and the trivial 'replace 5 values' case. For real invoicing pipelines, Jinja2/Handlebars/React-SSR on your end is the right call.

Can I generate 10,000 invoices in a run?+

Yes. Use the async endpoint /v1/jobs/html-to-pdf to queue them, or parallelize at the client (200 rpm rate limit per API key handles 12k/hr). For month-end bulk runs, email api@pennypdf.com for higher QPS.

Latency?+

p50 = 1.1 s per invoice-sized doc, p90 = 3.2 s. Variable-substitution doesn't add measurable latency (happens in ~1 ms before the Chromium render).

Headers and footers with page numbers?+

Yes — `header_template` and `footer_template` fields accept Chromium's template syntax: `<span class="pageNumber"></span>`, `<span class="totalPages"></span>`, `<span class="date"></span>`.

PDF/A compliance for archival generation?+

Chain /v1/pdf-a (3 coins) after generation. Total: 4 coins per archival-compliant invoice. Still cheaper than a single DocRaptor doc.

Rate limits?+

200 rpm per API key on the sync endpoint, unlimited on async (coin-only cap). For bulk month-end runs at 5,000+ docs, set up webhook delivery so you don't poll.

Why PennyPDF

  • No subscription. Ever.
  • Coins never expire — use them in 5 years.
  • Client-side processing for 14 of 22 tools.
  • No watermarks at any tier.
  • Per-operation pricing, shown before you click.
  • Same coins for web + public API.