HTML & URL input
Send a fully-formed HTML document or a URL. Chromium loads and prints it with the PDFOptions you pass.
An honest HTML-to-PDF rendering API. Send HTML or a URL to
POST /v1/convert,
poll the job, download the PDF. Chromium under the hood —
no legacy wkhtmltopdf path, no six-language SDK surface we don't
actually ship.
The whole API is POST /v1/convert plus two job
endpoints. No webhooks yet, no direct-to-S3 yet — just a
bounded worker pool and an object store the client picks up from.
# Convert a URL to a PDF — async job model curl -X POST https://login.21pdf.com/v1/convert \ -H "Authorization: Bearer $QPDF_KEY" \ -H "Content-Type: application/json" \ -d '{ "url": "https://example.com/invoice/8412", "options": { "page_size": "A4", "orientation": "portrait", "margin_top": "20mm", "wait_for_network_idle": true } }' # → { "job_id": "5f1c3e2a-...", "status": "pending" } # Then: GET /v1/jobs/{job_id}/download once status == "completed"
{
"url": "https://example.com/invoice/8412",
"options": {
"page_size": "A4",
"orientation": "portrait",
"margin_top": "20mm",
"margin_bottom": "15mm",
"wait_for_network_idle": true
}
}
// Response
{
"job_id": "5f1c3e2a-9b4d-4c8a-9e2f-1a2b3c4d5e6f",
"status": "pending",
"message": "enqueued"
}
Bill to: Northwind Trading Co. · 221 Baker St, Portland OR
| Item | Qty | Total |
|---|---|---|
| API calls — Apr 2026 | 412,900 | ₹ 28,903 |
| Overage renders | 8,412 | ₹ 2,104 |
| Priority support | 1 | ₹ 5,000 |
No roadmap tiles. Everything below is live on
https://login.21pdf.com/v1 today. Things that aren't
shipped are listed as "Roadmap" in the docs, not promoted here.
Send a fully-formed HTML document or a URL. Chromium loads and prints it with the PDFOptions you pass.
page_size, orientation, four-sided margins, and wait_for_network_idle for SPA-heavy sources.
Every submission returns a job_id. Poll status, download when completed. No long-held HTTP connections.
Per-tenant API keys with rotation. Bearer tokens for your dashboard sessions. Keys never leave the dashboard in plaintext.
Razorpay-backed subscriptions. Quota + concurrency are enforced server-side; 402 returns when you hit the cap.
Card declines drop you to a 7-day grace window instead of immediate cut-off. Dunning emails hit SMTP on day 1, 3, 5.
RFC1918, link-local, and loopback targets are refused — at the HTTP boundary and inside Chromium's request interceptor.
Hardened launch flags, supervised relaunch on crash, renders short-circuited to a pool so a bad page can't starve the next.
Rendered files auto-expire after PDF_RETENTION_DAYS (default 7). No stale PDFs accumulating in object storage forever.
Every convert returns a job ID immediately. The worker pool
renders in the background and stores the output; your client
polls /v1/jobs/{id} and fetches
/download when status == "completed".
Perfect for queue-backed pipelines; no HTTP timeout-tuning.
{
"job_id": "5f1c3e2a-...",
"status": "running",
"progress": 0.7
}
When you pass a url, we reject RFC 1918,
link-local and loopback targets at the HTTP handler. Then the
Chromium request interceptor re-runs the same allowlist on
every subresource and redirect hop — so a 302
that lands on 169.254.169.254 still fails closed.
Both layers must fail-open for a leak to land. Neither does.