Endpoints#
Base URL: https://api.htmlpix.com
All endpoints except GET /v1/image require authentication.
POST /v1/url#
Mint a signed public URL for a single image. Each successful response consumes 1 quota unit.
Request body#
{
"templateId": "k57k8w9n7n9r8b6r2x6f2q9v1h7p4y0c",
"variables": { "title": "Launch Day" }
}| Field | Type | Required | Description |
|---|---|---|---|
templateId | string | Yes | Template ID |
variables | object | No | Key-value pairs for template variables |
width | number | No | 1–4096 (default from template or 1200) |
height | number | No | 1–4096 (default from template or 630) |
format | string | No | png, jpeg, or webp (default webp) |
quality | number | No | 0–100, applies to jpeg and webp |
devicePixelRatio | number | No | Positive number for HiDPI (e.g. 2) |
tv | string | No | Template version override for cache busting |
Response 200#
{
"url": "https://image.htmlpix.com/v1/image?templateId=...&sig=...",
"expiresAt": 1914998400000
}POST /v1/urls#
Batch mint multiple signed URLs in one call. Each item in the response consumes 1 quota unit.
Request body#
{
"items": [
{ "templateId": "tmpl_a", "variables": { "title": "Page A" } },
{ "templateId": "tmpl_b", "variables": { "title": "Page B" } }
]
}Each entry in items accepts the same fields as POST /v1/url. Maximum 25 items per request.
Response 200#
{
"urls": [
{
"templateId": "tmpl_a",
"url": "https://image.htmlpix.com/v1/image?...&sig=...",
"expiresAt": 1914998400000
}
]
}GET /v1/templates#
List templates available to your account.
Query parameters#
| Parameter | Type | Required | Description |
|---|---|---|---|
scope | string | No | all (default), mine, or starter |
all— your templates plus public starter templatesmine— only templates you createdstarter— only public starter templates
Response 200#
{
"scope": "all",
"templates": [
{
"_id": "k57k8w9n7n9r8b6r2x6f2q9v1h7p4y0c",
"name": "Blog Post OG",
"description": "Card layout for blog posts",
"variables": [{ "name": "title", "defaultValue": "Hello" }],
"width": 1200,
"height": 630,
"format": "webp",
"devicePixelRatio": 1,
"signedPreviewUrl": "https://image.htmlpix.com/v1/image?...",
"isPublic": false
}
]
}POST /v1/templates#
Create a new template from JSX code.
Request body#
{
"name": "Launch Card",
"description": "Marketing launch visual",
"code": "export default function Template({ title = \"Launch Day\" }) {\n return <div style={{ ... }}>{title}</div>;\n}\n\nexport const options = { width: 1200, height: 630, format: \"webp\" };"
}| Field | Type | Required | Description |
|---|---|---|---|
name | string | Yes | Template name (max 120 chars) |
description | string | No | Template description (max 2000 chars) |
code | string | Yes | JSX template source (max 180K chars) |
Templates are compiled server-side after creation. Export an options object from your code to set default width, height, format, quality, and devicePixelRatio.
Response 201#
{
"templateId": "k57k8w9n7n9r8b6r2x6f2q9v1h7p4y0c",
"template": { "..." }
}POST /v1/templates/generate#
Generate templates using AI. Sends a batch of prompts and returns generated templates. Each successful generation consumes 1 AI quota unit.
Request body#
{
"items": [
{
"prompt": "A professional blog post OG image with title and author",
"width": 1200,
"height": 630
}
]
}| Field | Type | Required | Description |
|---|---|---|---|
items | array | Yes | Array of generation requests (max 5) |
items[].prompt | string | Yes | Description of the template to generate (max 2000 chars) |
items[].width | number | No | Image width, 1–4096 |
items[].height | number | No | Image height, 1–4096 |
items[].imageDataUrl | string | No | Base64 data URL of a reference image (e.g. data:image/png;base64,...). The image is sent to the AI alongside your prompt — no predefined instructions are added. |
Response 200#
{
"results": [
{
"ok": true,
"result": { "templateId": "...", "template": { "..." } }
}
]
}Individual items can fail independently:
{
"results": [
{
"ok": false,
"error": { "code": "GENERATION_FAILED", "message": "..." }
}
]
}GET /v1/templates/:templateId#
Fetch a single template by ID. Returns templates you own or public starter templates.
Response 200#
{
"template": {
"_id": "k57k8w9n7n9r8b6r2x6f2q9v1h7p4y0c",
"name": "Blog Post OG",
"code": "export default function Template({ title }) { ... }",
"variables": [{ "name": "title", "defaultValue": "Hello" }],
"width": 1200,
"height": 630,
"format": "webp"
}
}PATCH /v1/templates/:templateId#
Update a template you own. Only include the fields you want to change.
Request body#
{
"name": "Launch Card v2",
"code": "export default function Template({ title = \"Updated\" }) { ... }"
}| Field | Type | Required | Description |
|---|---|---|---|
name | string | No | New template name (max 120 chars) |
description | string | No | New description (max 2000 chars) |
code | string | No | New JSX source (max 180K chars) |
At least one field must be provided.
Response 200#
{
"templateId": "k57k8w9n7n9r8b6r2x6f2q9v1h7p4y0c",
"template": { "..." }
}GET /v1/image#
Public image delivery endpoint. This is the URL you put in your meta tags. Not billable — fetches are free and cached.
This endpoint is served from image.htmlpix.com via Cloudflare's edge network.
How it works#
The signed URL returned by POST /v1/url points here. When a crawler or browser requests it, the image is rendered (or served from cache) and returned as binary data.
Signed query parameters#
These parameters are set automatically when you mint a URL. Do not modify them.
| Parameter | Description |
|---|---|
templateId | Template to render |
uid | User ID |
exp | Expiration timestamp |
sig | HMAC signature |
rv | Render version |
tv | Template version |
width | Image width |
height | Image height |
format | Output format |
quality | Compression quality |
dpr | Device pixel ratio |
Template variables are passed with a v_ prefix (e.g. v_title=Launch+Day).
Response#
- 200 — image bytes (
image/png,image/jpeg, orimage/webp) - 304 — not modified (when
If-None-Matchmatches the ETag)
Cache headers#
| Header | Value |
|---|---|
Cache-Control | public, max-age=86400 |
ETag | Content hash |
X-Cache | r2 (cached) or render (fresh) |
Server-Timing | Render duration (fresh renders only) |