reference

API reference

Every route lives at the root, unversioned, so placeholder URLs stay as short as possible. Synth-at-edge GETs are public; AI writes need an API key.

Conventions

Synth-at-edge (public, SVG)

Pure functions of the URL. No auth, instant, free.

MethodRouteQuery paramsAccess
GET/{w}x{h}
Boring dimension-labelled placeholder.
text, bg, fgpublic
GET/color/{hex}/{w}x{h}
Solid color fill.
public
GET/gradient/{w}x{h}
Linear (with angle) or radial gradient.
from, to, angle, type=linear|radialpublic
GET/seed/{seed}/{w}x{h}
Deterministic, stable variation derived from the seed string.
public
GET/glyph/{w}x{h}
Wireframe icon placeholder.
as=avatar|photo|video|product|map|documentpublic

Examples

GET /400x300
GET /600x240?text=hero+banner&bg=111827&fg=9aa0b4
GET /color/7c9cff/400x300
GET /gradient/600x400?from=7c9cff&to=59e3c5&angle=120
GET /gradient/600x400?from=7c9cff&to=59e3c5&type=radial
GET /seed/precious-tide/400x300
GET /glyph/300x300?as=avatar

Async AI

A job pipeline. Submitting a prompt returns a stable URL immediately; the image fills in later via a provider webhook. The URL never changes.

MethodRouteNotesAccess
POST/ai
Submit a prompt. Returns {id, url, status_url}.
API key
GET/ai/{w}x{h}/{id}.png
Placeholder while pending, final PNG once ready. Stable across the job's lifetime.
public
GET/ai/{id}/status
Job state JSON: pending | generating | ready | failed.
public
POST/ai/replicate-webhook
Provider → service. Signature-verified. Not called by clients.
API key

Submit a job

POST /ai
Authorization: Bearer YOUR_API_KEY
Content-Type: application/json

{
  "prompt": "a red fox in snow, cinematic lighting",
  "w": 512,
  "h": 512,
  "seed": 42,        // optional
  "model": "..."     // optional, defaults to flux-schnell
}

→ 200 OK
{
  "id": "a1b2c3d4e5f6g7h8",
  "url": "/ai/512x512/a1b2c3d4e5f6g7h8.png",
  "status_url": "/ai/a1b2c3d4e5f6g7h8/status"
}

Poll for completion

GET /ai/a1b2c3d4e5f6g7h8/status

→ { "state": "pending" }                                  // queued
→ { "state": "generating" }                               // prediction running
→ { "state": "ready", "url": "/ai/512x512/{id}.png" }     // done
→ { "state": "failed", "error": "..." }                   // gave up

Re-submitting the same prompt + dimensions + model + seed returns the same id and does not start a second generation. A blocked prompt returns 422 with a "blocked" glyph rather than a broken image.

Drop-in <ai-img> component

A framework-agnostic custom element. It renders a placeholder immediately, polls status_url with exponential backoff (500ms → cap 5s), and swaps in the final image on ready — no manual refresh. The raw URL stays usable without it.

<script type="module">
  import { registerAiImg } from '/components/ai-img.js'
  registerAiImg()
</script>

<!-- Prompt mode: POSTs to /ai, then polls -->
<ai-img prompt="a red fox in snow" w="512" h="512" api-key="YOUR_KEY"></ai-img>

<!-- URL mode: you already have a stable URL + status URL -->
<ai-img
  src="/ai/512x512/{id}.png"
  status="/ai/{id}/status">
</ai-img>
AttributeDescription
promptPrompt text. Triggers POST /ai unless src is set.
w, hDimensions (default 400×300).
srcExplicit image URL; skips POST.
statusExplicit status_url to poll (used with src).
endpointService base URL (default: same origin).
api-keyBearer token for POST /ai (prompt mode only).
seed, modelOptional overrides forwarded to POST /ai.
altAlt text for the rendered image.

Events: ai-img:ready and ai-img:failed bubble from the element. The current state is also reflected on the data-state attribute.

Health

MethodRouteResponse
GET/healthz{ "ok": true }

Try it in the playground →