Skip to content

Image render API

POST /api/framekit/images/render

When FRAMEKIT_AUTH_ENABLED is missing or false, the route is credential-free. When it is true, the route accepts either a same-origin framekit_session cookie or an API token in Authorization: Bearer <token>. It accepts no other authentication scheme. In both modes, the handler validates the image-render configuration and retains its request, image, browser, capacity, timeout, and cleanup defenses before rendering.

When authentication is enabled and an Authorization header is present, it takes precedence. A malformed or invalid Bearer value returns 401; the handler does not fall back to a valid session cookie in that request. In open mode no credential is required.

Send JSON with a body no larger than 12,000,000 bytes:

{
"template": "example",
"variant": "default",
"data": {
"title": "Launch"
}
}

The object accepts exactly these keys:

Key Required Meaning
template Yes A non-empty slug from the generated template registry.
variant No A non-empty content variant. When omitted, the template’s default variant is used.
data No A plain object containing edits for declared fields. When omitted, it is treated as an empty object.

Unknown keys, empty template or variant values, arrays, and prototype-pollution keys are rejected. A template must exist in the registry, and a supplied variant must exist in that template’s content.

Use Content-Type: application/json. The endpoint rejects other content types and content encodings other than identity.

For field values and image sources, see Image inputs. See Security and reverse proxies for deployment restrictions and Image API errors for failure codes.

Success returns 200 with the PNG bytes produced at the template’s declared width and height:

Content-Type: image/png
Cache-Control: no-store
Content-Disposition: inline; filename="example.png"
Content-Length: <PNG byte length>
X-Content-Type-Options: nosniff

The filename replaces / in a template slug with -. The response is always PNG in the current contract. There is no format, DPI, or asynchronous job parameter.

For an authenticated deployment, create an API token in Studio, keep the full secret in a server-side environment variable, and replace example with a slug from your generated registry:

import { writeFile } from 'node:fs/promises'
const origin = process.env.FRAMEKIT_ORIGIN ?? 'http://localhost:3000'
const token = process.env.FRAMEKIT_TOKEN
if (!token) throw new Error('FRAMEKIT_TOKEN is required')
const response = await fetch(`${origin}/api/framekit/images/render`, {
method: 'POST',
headers: {
Authorization: `Bearer ${token}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({ template: 'example' })
})
if (!response.ok) throw new Error(`Render failed: ${response.status}`)
await writeFile('example.png', Buffer.from(await response.arrayBuffer()))

Do not put the token in the URL or send it from an untrusted browser. The render images guide adds a request workflow and failure handling.

For open mode, leave FRAMEKIT_AUTH_ENABLED unset or set it to false and omit the Authorization header. The image endpoint remains protected by its renderer defenses even though it does not require credentials.