/v1/images
Request a render
createImage
Asynchronous by default: you get a 202 and an id, then collect the result from GET /images/{id}. With ?wait=true we hold the connection until the image is ready and return 200 — or 503 sync_overloaded if we run out of time. format, quality and scale are part of the cache key: the same fields as PNG and as JPEG are two files and two renders, while a parameter the format ignores (quality for PNG) never makes a second one.
Sizes. One design, every size: og 1200×630, square 1080×1080, portrait 1080×1350, story 1080×1920, pinterest 1000×1500, youtube 1280×720. size renders one of them; sizes renders several at once and returns {"renders": [...]}. Every size is an ordinary render — its own id, one render of quota (a size already rendered with the same fields is free), its own cache entry, refund and webhook. All or nothing: when the quota does not cover every new size, you get a 402 and nothing is queued. A size equal to the template's own dimensions is the same image as no size at all (same cache entry). Built-in templates lay themselves out for every size; your own templates get the classes shape-landscape|shape-square|shape-tall and size-{name} on <html> to do the same.
Animated GIF and MP4. format: gif or mp4 records the template's CSS animations and transitions frame by frame (paused and seeked, so the same fields always give the same file), plus a window.shareglintFrame(t, duration) hook (seconds) that built-in templates use for counting and typing — your own templates have no scripts (removed on save), so animate them with CSS. duration (0.5–5 s, default 3) and fps (10–30) set the clip. The long edge is capped at 1080 px with even dimensions (og 1200×630 gives a 1080×566 file); quality and scale are ignored. GIF loops forever; MP4 is H.264 (yuv420p, faststart, no audio) and much smaller. Each animated render costs 5 renders of quota (per size with sizes); an identical file you already have is free and a failed one refunds all 5. ?wait=true holds up to 45 s for them. During a gif/mp4 render <html> has the class motion and the CSS variable --clip (e.g. 3s); a still render of the same template has no motion class, so put animations under .motion … with animation-duration: var(--clip) and the still formats show the finished design. Built-in animated templates: GET /templates/library, slugs starting with animated-. Batches take still formats only.
Parameters
| Name | In | Type | Description |
|---|---|---|---|
wait |
query | boolean | Wait for the result instead of polling. |
Idempotency-Key |
header | string | The same Idempotency-Key with the same body returns the same response, with no second render. An empty or whitespace-only header counts as no key. |
Request bodyapplication/json
| Name | Type | Description |
|---|---|---|
templaterequired |
string | Template slug: one of yours or a built-in one from GET /templates/library. |
modifications |
object | Values for the template fields. A field you leave out takes the template's defaults value, or stays empty — omitting modifications altogether renders the defaults. |
locale |
string | Language for text the template adds itself (date, reading time).one of en pl de es fr |
webhook_url |
string | We call this URL when the render finishes. Private-network addresses are rejected with a 422 at request time, so a webhook that could never fire never costs you a render. |
format |
string | Output file. pdf is a single page exactly the template size in CSS px (1200×630 for the built-in templates), no margins, backgrounds printed, text kept as vector. gif and mp4 are animated: 5 renders of quota each, long edge 1080 px. The Free plan watermark applies to every format.one of png jpeg webp pdf gif mp4 · default png |
quality |
integer | Compression quality for jpeg and webp. Ignored for png (lossless) and pdf.default 85 · 1–100 |
scale |
integer | Pixel density for png, jpeg and webp: 2 gives 2400×1260 for a 1200×630 template, 1 gives exactly 1200×630. Ignored for pdf, gif and mp4.one of 1 2 · default 2 |
duration |
number | gif and mp4 only: clip length in seconds, rounded to 0.1 s. With a still format: 422.default 3 · 0.5–5 |
fps |
integer | gif and mp4 only: frames per second. Default 15 for gif, 30 for mp4. With a still format: 422.10–30 |
size |
string | Render the template in this size preset instead of its own dimensions: og 1200×630, square 1080×1080, portrait 1080×1350, story 1080×1920, pinterest 1000×1500, youtube 1280×720. Cannot be combined with sizes.one of og square portrait story pinterest youtube |
sizes |
array of string | Several presets at once. The response is {"renders": [...]} with one render per size, in this order; each costs one render of quota (5 for gif/mp4; sizes already rendered are free).one of og square portrait story pinterest youtube · max items 6 · min items 1 |
Example
{
"template": "blog-og",
"locale": "en",
"modifications": {
"eyebrow": "Health",
"title": "Ten things that ruin your sleep",
"author": "Anna Kowalska",
"site": "yourblog.com",
"accent": "#f97316",
"date": "2026-08-17",
"reading_time": 7
}
}
Responses
| Status | Description | Returns |
|---|---|---|
| 200 | Finished (only with ?wait=true). With sizes: {"renders": [...]} once every size is done. |
Render | RenderList |
| 202 | Accepted into the queue. With sizes: {"renders": [...]}, one entry per size. |
|
| 402 | Monthly quota exhausted (quota_exceeded). With sizes, also when the quota covers only some of the sizes — then none is queued. |
Error |
| 422 | Validation error (including an unknown format, quality outside 1–100, scale other than 1 or 2, duration outside 0.5–5 s or fps outside 10–30, duration/fps with a still format, an unknown or repeated size, or size together with sizes), or the same Idempotency-Key with a different body. |
|
| 500 | With ?wait=true and sizes: at least one size failed. The body still lists every render; failed ones use no quota. |
|
| 503 | Sync mode ran out of time (sync_overloaded). The body carries id (with sizes: renders) — nothing is lost. |
202 · single — Example
{
"id": "img_01m08…",
"status": "queued",
"format": "png",
"size": null,
"url": "…/v1/images/img_01m08…"
}
202 · sizes — Example
{
"renders": [
{
"id": "img_01m08…",
"status": "queued",
"format": "png",
"size": "og",
"url": "…/v1/images/img_01m08…"
},
{
"id": "img_01m09…",
"status": "queued",
"format": "png",
"size": "square",
"url": "…/v1/images/img_01m09…"
}
]
}