API Documentation
pdfkitt converts HTML to PDF via a single HTTP endpoint. No SDK required.
Quick Start
1. Sign up and create an API key
Create a free account then go to Dashboard → API Keys to generate your key. Keys look like
pdfk_live_...2. Make your first request
curl -X POST https://api.pdfkitt.dev/v1/convert \ -H "Authorization: Bearer pdfk_live_YOUR_KEY" \ -H "Content-Type: application/json" \ -d '{"html":"<h1>Hello PDF</h1>"}' \ --output hello.pdf3. Check your usage
curl https://api.pdfkitt.dev/v1/usage \ -H "Authorization: Bearer pdfk_live_YOUR_KEY"
Authentication
Every request must include your API key in the Authorization header.
Authorization: Bearer pdfk_live_YOUR_KEYKeep your key secret. If it is compromised, revoke it from the dashboard and create a new one. Keys are hashed in the database — we cannot recover a lost key.
POST /v1/convert
https://api.pdfkitt.dev/v1/convertConverts HTML to a PDF binary. Returns application/pdf.
Request body
{
"html": "<h1>Hello</h1><p>World</p>", // required
"options": {
"page_size": "A4", // "A4" | "Letter" | "Legal" (default: "A4")
"landscape": false, // boolean (default: false)
"print_background": true, // boolean (default: true)
"scale": 1, // 0.1–2 (default: 1)
"margins": {
"top": "20mm",
"right": "15mm",
"bottom": "20mm",
"left": "15mm"
}
}
}Response
200 OK — PDF binary with Content-Type: application/pdf. On error, returns JSON (see Error Codes).
Examples
curl
curl -X POST https://api.pdfkitt.dev/v1/convert \
-H "Authorization: Bearer pdfk_live_YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{
"html": "<h1>Invoice #1001</h1><p>Due: 2026-05-01</p>",
"options": {
"page_size": "Letter",
"margins": { "top": "20mm", "right": "15mm", "bottom": "20mm", "left": "15mm" }
}
}' \
--output invoice.pdfNode.js
const res = await fetch("https://api.pdfkitt.dev/v1/convert", {
method: "POST",
headers: {
"Authorization": "Bearer pdfk_live_YOUR_KEY",
"Content-Type": "application/json",
},
body: JSON.stringify({
html: "<h1>Hello PDF</h1>",
options: { page_size: "A4", margins: { top: "20mm", bottom: "20mm" } },
}),
});
if (!res.ok) throw new Error(await res.text());
const pdf = Buffer.from(await res.arrayBuffer());
fs.writeFileSync("output.pdf", pdf);Python
import requests
response = requests.post(
"https://api.pdfkitt.dev/v1/convert",
headers={
"Authorization": "Bearer pdfk_live_YOUR_KEY",
"Content-Type": "application/json",
},
json={
"html": "<h1>Hello PDF</h1>",
"options": {"page_size": "A4"},
},
)
response.raise_for_status()
with open("output.pdf", "wb") as f:
f.write(response.content)GET /v1/usage
https://api.pdfkitt.dev/v1/usageReturns your current quota consumption for the billing period.
Response
{
"used": 142,
"limit": 1000,
"resets_at": "2026-05-01T00:00:00.000Z",
"plan": "free"
}Example
curl https://api.pdfkitt.dev/v1/usage \
-H "Authorization: Bearer pdfk_live_YOUR_KEY"Error Codes
All errors return JSON in this shape:
{
"error": {
"code": "quota_exceeded",
"message": "Monthly quota exceeded",
"request_id": "550e8400-e29b-41d4-a716-446655440000",
"docs_url": "https://pdfkitt.dev/docs/errors#quota_exceeded"
}
}| Code | HTTP | Meaning |
|---|---|---|
invalid_html | 400 | The html field is missing or empty |
unauthorized | 401 | API key is missing or invalid |
quota_exceeded | 429 | Monthly PDF quota exhausted — upgrade plan or wait for reset |
rate_limit_exceeded | 429 | Too many requests per minute — back off and retry |
render_timeout | 408 | HTML took longer than 30 s to render — simplify the document |
render_failed | 500 | Internal rendering error — contact support with request_id |
Limits
Monthly quota
| Plan | PDFs / mo |
|---|---|
| Free | 1,000 |
| Starter | 10,000 |
| Growth | 50,000 |
| Scale | 200,000 |
Rate limits
| Plan | Req / min |
|---|---|
| Free | 30 |
| Starter | 60 |
| Growth | 120 |
| Scale | 300 |
Quota resets on the 1st of each month. Rate limits apply per API key per minute. Exceeding either returns a 429 response.