Client libraries
Official SDKs for Python and Node.js. Both are thin wrappers around the REST API with automatic retries on 429 and 5xx, a typed exception hierarchy, and idempotency-key pass-through. Zero or one dependency each — nothing bloats your deploy.
Python
Works with any Python framework (FastAPI, Django, Flask, Celery workers, Lambda) on Python 3.9+. Ships sync and async clients.
from html2dochub import Client
client = Client(api_key="sk_live_YOUR_KEY")
pdf_bytes = client.render(
html="<h1>Hello from Python</h1>",
options={"format": "A4", "margin": "18mm"},
)
with open("out.pdf", "wb") as f:
f.write(pdf_bytes)For asyncio code (FastAPI, Django-async, aiohttp workers):
from html2dochub import AsyncClient
async with AsyncClient(api_key="sk_live_YOUR_KEY") as client:
pdf = await client.render(html="<h1>Hello</h1>", options={"format": "A4"})Node.js / TypeScript
Node 18+. Zero runtime dependencies — uses built-in fetch. Ships dual ESM + CJS builds and full TypeScript declarations.
import { Client } from "@html2dochub/client";
const client = new Client({ apiKey: "sk_live_YOUR_KEY" });
const pdf = await client.render({
html: "<h1>Hello from Node</h1>",
options: { format: "A4", margin: "18mm" },
});
await fs.writeFile("out.pdf", pdf);Common features across both SDKs
- Automatic retries on
429and5xxwith exponential backoff + jitter, honouringRetry-After. - Typed exceptions —
AuthenticationError,RateLimitError(withretry_after),InsufficientFundsError,ValidationError,APIError. - Idempotency keys on any render so queue retries never double-bill.
- Async mode with
render_async/renderAsyncfor large reports; completion POSTs to your webhook. - Per-job metadata via
render_job/renderJob— get page count, cost, render duration.
Quick Start
Get rendering in under 5 minutes:
- Create a free account
- Add funds to your wallet (minimum ₹100)
- Create an API key in the dashboard
- Make your first API call:
curl -X POST https://api.html2dochub.com/v1/render \
-H "X-API-Key: sk_live_YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{
"type": "pdf",
"html": "<h1>Hello World</h1>",
"options": { "format": "A4" }
}'Authentication
API Keys
Pass your API key in the X-API-Key header. Create and manage keys in the dashboard.
POST /v1/render HTTP/1.1
Host: api.html2dochub.com
X-API-Key: sk_live_xxxxxxxxxxxxxxxx
Content-Type: application/jsonJWT (Dashboard)
Dashboard API calls use JWT Bearer tokens from the /v1/auth/login endpoint.
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...Endpoints
POST /v1/render
Render HTML to PDF or image. Requires API key authentication.
Request Body
{
"type": "pdf" | "image", // required
"mode": "sync" | "async", // default: sync
"html": "<h1>Hello</h1>", // required if no url
"url": "https://example.com", // required if no html
"options": {
"format": "A4", // A3, A4, A5, Letter, Legal, Tabloid
"landscape": false,
"print_background": true,
"margin_top": "2cm",
"margin_bottom": "2cm",
"margin_left": "1.5cm",
"margin_right": "1.5cm",
"header_template": "<span>Header</span>",
"footer_template": "<span class=\"pageNumber\"></span>",
"scale": 1, // image: DPR multiplier
"width": 1280, // image: viewport width
"height": 800, // image: viewport height
"full_page": true, // image: full-page screenshot
"format": "png" | "jpeg", // image format
"quality": 90 // jpeg quality
},
"webhook_url": "https://yourapp.com/webhook",
"idempotency_key": "invoice-2042",
"tag": "invoices"
}Response (sync)
Completed jobs always include output_pages, final_cost (amount charged to your wallet), and download_url. While a job is running you may see estimated_cost. For typical rates, see the pricing page.
{
"id": "550e8400-e29b-41d4-a716-446655440000",
"status": "completed",
"type": "pdf",
"mode": "sync",
"output_pages": 2,
"output_size_bytes": 145382,
"render_duration_ms": 847,
"estimated_cost": 0.00082,
"final_cost": 0.00076,
"download_url": "https://cdn.html2dochub.com/...",
"created_at": "2026-02-26T10:00:00Z",
"completed_at": "2026-02-26T10:00:01Z"
}compute_cost, storage_cost, bandwidth_cost, shared_cost, margin_applied). Use final_cost as the billable total.GET /v1/jobs
List your rendering jobs with pagination and filters.
GET /v1/jobs?page=1&page_size=20&status=completed&type=pdf
Authorization: Bearer <token>GET /v1/jobs/:id
Get a single job by ID.
GET /v1/wallet
Get wallet balance and totals.
{
"balance": 4.732100,
"reserved_balance": 0.001200,
"total_deposited": 10.000000,
"total_spent": 5.267900
}POST /v1/wallet/add-funds
Create a Razorpay Order for a wallet top-up. The response gives you the payload the frontend needs to open Razorpay Checkout.js. After the user pays, Checkout.js calls your handler, which POSTs the three razorpay_* fields to /v1/wallet/razorpay/verify.
// Request
{ "amount": 500 }
// Response
{
"order_id": "order_abc123...",
"amount": 51180, // paise (gross, includes 2% Razorpay fee + 18% GST on fee)
"currency": "INR",
"key_id": "rzp_live_...",
"wallet_credit": 500.0, // what your wallet gets on success
"gateway_fee": 10.00,
"gst_on_fee": 1.80,
"total_charged": 511.80
}
// POST /v1/wallet/razorpay/verify — body from Checkout.js handler
{
"razorpay_order_id": "order_abc123...",
"razorpay_payment_id": "pay_xyz456...",
"razorpay_signature": "..."
}Webhooks
For async jobs, set webhook_url in your request. We'll POST the job result when complete.
// Webhook payload (POST to your URL)
{
"event": "job.completed",
"job": {
"id": "550e8400-...",
"status": "completed",
"download_url": "https://cdn.html2dochub.com/...",
"final_cost": 0.00076,
"output_pages": 2,
"render_duration_ms": 847
}
}We retry failed webhook deliveries 5 times with exponential backoff (30s, 60s, 120s, 240s, 480s). View all delivery attempts via GET /v1/jobs/:id/webhooks.
Billing & Wallet
HTML2DocHub uses prepaid wallet billing: add funds, then each successful render deducts the job's final_cost. There are no subscriptions. Typical per-page rates and examples are on the Pricing page.
- Per page — usage scales with pages in the output PDF or image.
- ₹0.10 minimum per successful job — each completed render is charged at least this amount.
- No charge on failure — failed jobs are not billed.
- Receipts — the API and dashboard show
output_pagesandfinal_costfor every completed job.
Export all transactions as CSV: GET /v1/wallet/export/csv
Export all jobs as CSV: GET /v1/wallet/export/jobs-csv
Security
- API Keys — stored as SHA-256 hash, never in plaintext
- SSRF Protection — private IP ranges blocked when rendering URLs
- Rate Limiting — configurable per API key (default 60 req/min)
- 2FA — TOTP-based two-factor authentication available
- Daily Spend Limit — configurable wallet guard
- Signed URLs — all downloads via signed S3 URLs (1h expiry)
Error codes
| Code | Meaning |
|---|---|
| 400 | Bad Request — Invalid parameters |
| 401 | Unauthorized — Invalid or missing API key |
| 402 | Payment Required — Insufficient wallet balance |
| 403 | Forbidden — Admin access required |
| 404 | Not Found — Job or resource not found |
| 429 | Too Many Requests — Rate limit or daily spend limit exceeded |
| 500 | Internal Server Error — Rendering failed |