Quick Start

Get rendering in under 5 minutes:

  1. Create a free account
  2. Add funds to your wallet (minimum ₹100)
  3. Create an API key in the dashboard
  4. Make your first API call:
curl
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.

http
POST /v1/render HTTP/1.1
Host: api.html2dochub.com
X-API-Key: sk_live_xxxxxxxxxxxxxxxx
Content-Type: application/json

JWT (Dashboard)

Dashboard API calls use JWT Bearer tokens from the /v1/auth/login endpoint.

http
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...

Endpoints

POST /v1/render

Render HTML to PDF or image. Requires API key authentication.

Request Body

json
{
  "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.

json
{
  "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"
}
Completed jobs may also include extra numeric fields for exports and reconciliation (for example 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.

http
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.

json
{
  "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.

json
// 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.

json
// 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_pages and final_cost for 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

CodeMeaning
400Bad Request — Invalid parameters
401Unauthorized — Invalid or missing API key
402Payment Required — Insufficient wallet balance
403Forbidden — Admin access required
404Not Found — Job or resource not found
429Too Many Requests — Rate limit or daily spend limit exceeded
500Internal Server Error — Rendering failed