HTML → PDF¶
POST /pdf/v1/html renders an HTML string to a PDF with full fidelity — your CSS, web fonts, and
JavaScript (including charts) all render. If it looks right in a browser, it looks right in the PDF.
Request body¶
{
"html": "<h1>Hello</h1>",
"data": { "name": "Ada" },
"options": {
"format": "A4",
"orientation": "portrait",
"margins": { "top": "20mm", "right": "15mm", "bottom": "20mm", "left": "15mm" },
"include_page_numbers": false
},
"security": null,
"delivery": "inline"
}
Only html is required; everything else has sensible defaults.
| Field | Type | Default | Notes |
|---|---|---|---|
html |
string | — | required. Your HTML. May contain {{ variables }}. |
data |
object | {} |
Values for the {{ variables }} in html (sandboxed Jinja2). |
options.format |
string | A4 |
A3 · A4 · Letter · Legal · Tabloid |
options.orientation |
string | portrait |
portrait · landscape |
options.margins |
object | all 0 |
CSS lengths as strings: "20mm", "1in", "0" |
options.include_page_numbers |
bool | false |
Adds page numbers in the footer |
security |
object | null | null |
Password + permissions — see below |
delivery |
string | inline |
inline (PDF bytes) or url (signed URL) |
Page layout¶
curl -X POST https://api.kikidoc.dev/pdf/v1/html \
-H "X-API-Key: $KIKIDOC_API_KEY" -H "Content-Type: application/json" \
-d '{
"html": "<h1>Landscape report</h1>",
"options": {
"format": "Letter",
"orientation": "landscape",
"margins": { "top": "10mm", "right": "10mm", "bottom": "10mm", "left": "10mm" },
"include_page_numbers": true
}
}' --output report.pdf
Delivery: bytes vs a signed URL¶
"delivery": "inline"(default) — the response body is the PDF."delivery": "url"— KikiDoc uploads the PDF and returns a time-limited signed URL instead:
Use url when you'd rather hand a link to a downstream step than move bytes around (great in no-code
flows). The link expires (default 1 hour).
PDF security (password + permissions)¶
Add a security block to encrypt the PDF (AES-256):
{
"html": "<h1>Confidential</h1>",
"security": {
"user_password": "open-sesame",
"owner_password": "admin-only",
"print": false,
"extract_content": false
}
}
user_password(required whensecurityis present) — needed to open the document.owner_password— gates permission changes (auto-generated if you set flags but omit it).- Permission flags (omit = allowed):
annotations,extract_content,modify,assemble,print,print_high_res.
Other inputs¶
- Render a URL instead of an HTML body:
POST /pdf/v1/urlwith{ "url": "https://…" }(SSRF-guarded; optionalcredentialsfor basic-auth pages). - Screenshot instead of a PDF:
POST /pdf/v1/screenshot→ PNG/JPEG/WebP.
See the API reference for the full schema of every endpoint.