# Html2Pdf - Full Technical Documentation & LLM Guide > High-performance developer API and TypeScript SDK for converting HTML and CSS to pixel-perfect PDF documents with native Indian language typography. Html2Pdf provides a headless Chromium rendering pipeline built on Fastify, designed for mission-critical document generation (invoices, legal agreements, executive reports, tax filings). It bundles OpenType font rasterizers for 21 Indian languages across 12 scripts, validates all network sub-resources via a strict SSRF-filtering proxy, stores PDFs in S3-compatible cloud storage, and issues expiring presigned download URLs. --- ## 1. Quick Start ### Installation ```bash npm install @akcraft/html2pdf-sdk ``` ### Basic TypeScript Example ```typescript import { Html2PdfClient, PaperFormat, PdfOrientation } from '@akcraft/html2pdf-sdk'; // Initialize with your API key from https://html2pdf.akcraft.app/dashboard const client = new Html2PdfClient('your_api_key_here'); async function generateInvoice() { const response = await client.sendHtmlRequest({ userId: 'your_user_id_uuid', // Shown in dashboard Settings content: `

Invoice #1042

Billed to: Acme Corp

Total: $1,250.00

`, options: { format: PaperFormat.A4, orientation: PdfOrientation.PORTRAIT, printBackground: true, margin: { top: '15mm', bottom: '15mm', left: '12mm', right: '12mm', }, }, }); console.log('PDF generated successfully!'); console.log('Job ID:', response.jobId); console.log('Download URL:', response.pdfUrl); console.log('File Name:', response.fileName); } generateInvoice().catch(console.error); ``` --- ## 2. Architecture & Security 1. **Authentication & Authorization**: - API keys are created in the authenticated web dashboard (`/dashboard`). - Keys are stored exclusively as one-way SHA-256 hashes (`api_key_info` table). Raw keys are shown only once upon creation. - Keys are transmitted via the `x-api-key` HTTP header. - Every request verifies that the `x-api-key` is active (`revoked_at IS NULL`) and matches the `userId` in the payload. 2. **Isolated Headless Chromium Engine**: - Renders in-memory buffers using headless Chromium (Puppeteer). - Tini process reaper prevents zombie processes (`PID 1`). - Runs with `--no-sandbox --disable-setuid-sandbox` inside a non-root Linux container (`uid 997`). 3. **SSRF & Private Network Firewall**: - Chromium routes all network traffic through a local validating proxy (`--proxy-server`). - All requests to private IPv4 ranges (`10.0.0.0/8`, `172.16.0.0/12`, `192.168.0.0/16`, `127.0.0.0/8`, `169.254.0.0/16`) and local IPv6 literals are immediately aborted. - Local filesystem access (`file://`) is blocked. 4. **Storage & Lifecycle**: - Rendered PDFs are saved to S3-compatible cloud storage. - Presigned download URLs are generated with a 1-hour expiration time. - Automated cron workers delete PDFs older than the retention window (`PDF_RETENTION_HOURS`). Users can also delete PDFs on-demand. --- ## 3. TypeScript SDK Reference (`@akcraft/html2pdf-sdk`) ### `Html2PdfClient` Class #### Constructor ```typescript new Html2PdfClient(apiKey?: string) ``` - `apiKey` (optional): Default API key included in the `x-api-key` header on all requests. #### Methods ##### `sendHtmlRequest(request: SendHTMLRequest): Promise` Renders HTML into a PDF document. - **Request Properties**: - `userId` (string, required): Supabase user UUID owning the API key. - `content` (string, required): Full HTML string to render. - `apikey` (string, optional): Overrides constructor key if supplied. - `options` (PdfOptions, optional): Print and formatting parameters. - **Response Properties**: - `status` (`Html2PdfStatus.COMPLETED` = 2) - `jobId` (string, UUID): Unique conversion identifier. - `pdfUrl` (string, URL): Presigned S3 URL valid for 1 hour. - `fileName` (string): S3 file name format `{jobId}.pdf`. ##### `getPdfUrl(fileName: string): Promise` Generates a fresh presigned download URL for an existing, unexpired PDF. - `fileName` (string): The filename returned by `sendHtmlRequest`. ##### `getHealthStatus(): Promise<{ message: string }>` Checks API server availability. Returns `{ message: "Server is running!" }`. ### Enumerations & Types ```typescript export enum PaperFormat { A0 = 'A0', A1 = 'A1', A2 = 'A2', A3 = 'A3', A4 = 'A4', A5 = 'A5', A6 = 'A6', LETTER = 'Letter', LEGAL = 'Legal', TABLOID = 'Tabloid', LEDGER = 'Ledger', } export enum PdfOrientation { PORTRAIT = 'portrait', LANDSCAPE = 'landscape', } export interface PdfMargin { top?: string | number; // e.g. '10mm', '0.5in', '20px', or number bottom?: string | number; left?: string | number; right?: string | number; } export interface PdfOptions { format?: PaperFormat; // Defaults to 'A4' orientation?: PdfOrientation; // Defaults to 'portrait' margin?: PdfMargin; preferCSSPageSize?: boolean; // Gives CSS @page priority over format printBackground?: boolean; // Defaults to true (renders colors/images) pageRanges?: string; // e.g. '1-5, 8' scale?: number; // 0.1 to 2.0 (defaults to 1.0) headerTemplate?: string; // HTML template for page headers footerTemplate?: string; // HTML template for page footers } ``` ### Error Handling The SDK throws `Html2PdfError`: ```typescript try { await client.sendHtmlRequest({ ... }); } catch (error) { if (error instanceof Html2PdfError) { console.error('HTTP Status:', error.statusCode); console.error('API Error:', error.apiError); if (error.statusCode === 429) { console.warn('Rate limit hit. Retry after seconds:', error.retryAfter); } } } ``` --- ## 4. HTTP REST API Reference - **Base URL**: `https://api.html2pdf.akcraft.app` - **Default Headers**: - `x-api-key: ` - `Content-Type: application/json` ### `POST /api/send-html` Converts submitted HTML into a PDF file. #### Request Body (JSON) ```json { "userId": "3fa85f64-5717-4562-b3fc-2c963f66afa6", "content": "

Title

", "options": { "format": "A4", "orientation": "portrait", "printBackground": true, "margin": { "top": "10mm", "bottom": "10mm", "left": "10mm", "right": "10mm" }, "scale": 1.0, "headerTemplate": "
", "footerTemplate": "
Page of
" } } ``` #### Success Response (`200 OK`) ```json { "status": 2, "jobId": "8b9e6f12-3456-42bc-9d0a-112233445566", "fileName": "8b9e6f12-3456-42bc-9d0a-112233445566.pdf", "pdfUrl": "https:////8b9e6f12-3456-42bc-9d0a-112233445566.pdf?X-Amz-Signature=..." } ``` #### Error Responses - **`400 Bad Request`**: Validation error in request schema. - **`401 Unauthorized`**: Missing or invalid API key (`Invalid API key`). - **`403 Forbidden`**: API key does not belong to the provided `userId`. - **`413 Payload Too Large`**: Payload exceeds 10MB limit. - **`429 Too Many Requests`**: Rate limit exceeded (per-minute or monthly limit). Returns `Retry-After` header. - **`500 Internal Server Error`**: Chromium rendering failure. ### `GET /pdfs/:fileName` Generates a fresh presigned URL for an existing file. - **Headers**: `x-api-key: ` - **Response**: `{ "pdfUrl": "https://..." }` ### `GET /health` Health check endpoint. - **Response**: `{ "message": "Server is running!" }` --- ## 5. cURL Example ```bash curl -X POST https://api.html2pdf.akcraft.app/api/send-html \ -H "Content-Type: application/json" \ -H "x-api-key: YOUR_API_KEY" \ -d '{ "userId": "YOUR_USER_ID", "content": "

Executive Summary

Generated via Html2Pdf API

", "options": { "format": "Letter", "orientation": "portrait", "printBackground": true } }' ``` --- ## 6. Indian Language Typography Support Html2Pdf solves the non-Latin conjunct rendering problem ("tofu" boxes `□□□`) by pre-bundling official Noto OpenType fonts directly inside the rendering runtime: | Script | Languages Supported | Bundled Noto Font | |---|---|---| | **Devanagari** | Hindi, Marathi, Sanskrit, Nepali, Konkani, Maithili, Bodo, Dogri | `Noto Sans Devanagari` | | **Bengali** | Bengali, Assamese, Bishnupriya | `Noto Sans Bengali` | | **Tamil** | Tamil | `Noto Sans Tamil` | | **Telugu** | Telugu | `Noto Sans Telugu` | | **Gujarati** | Gujarati | `Noto Sans Gujarati` | | **Gurmukhi** | Punjabi | `Noto Sans Gurmukhi` | | **Kannada** | Kannada | `Noto Sans Kannada` | | **Malayalam** | Malayalam | `Noto Sans Malayalam` | | **Odia** | Odia (Oriya) | `Noto Sans Oriya` | | **Nastaliq** | Urdu, Kashmiri, Sindhi | `Noto Nastaliq Urdu` | | **Ol Chiki** | Santali | `Noto Sans Ol Chiki` | | **Meetei Mayek** | Manipuri | `Noto Sans Meetei Mayek` | No extra font loading, link tags, or CSS imports are required in your HTML payloads for these languages; the fontconfig engine automatically applies the appropriate Noto typeface. --- ## 7. Dynamic Headers and Footers When `headerTemplate` or `footerTemplate` are provided, Chromium's print subsystem automatically injects document metadata into the following HTML class names: - ``: Formatted print date - ``: Document title - ``: Document location - ``: Current page number (1-based) - ``: Total page count *Tip*: Ensure your templates include `font-size` (minimum 8px) in inline styles; Chromium's default font size for headers and footers is 0px.