Image render API
Endpoint
Section titled “Endpoint”POST /api/framekit/images/renderWhen 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.
Request
Section titled “Request”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 response
Section titled “Success response”Success returns 200 with the PNG bytes produced at the template’s declared width and height:
Content-Type: image/pngCache-Control: no-storeContent-Disposition: inline; filename="example.png"Content-Length: <PNG byte length>X-Content-Type-Options: nosniffThe 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.
Example
Section titled “Example”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_TOKENif (!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()))export FRAMEKIT_ORIGIN=http://localhost:3000export FRAMEKIT_AUTH_ENABLED=trueexport FRAMEKIT_TOKEN='fk_replace_with_the_full_secret'
curl --fail-with-body \ --request POST "$FRAMEKIT_ORIGIN/api/framekit/images/render" \ --header "Authorization: Bearer $FRAMEKIT_TOKEN" \ --header 'Content-Type: application/json' \ --data '{"template":"example"}' \ --output example.pngDo 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.