Dev Server API
The HTTP API behind studio dev — script it, or wire it into an agent.
studio dev starts an HTTP server (the same one the Live Studio UI talks to) at http://localhost:3030 by default. Every endpoint below is plain JSON/HTTP no auth, no client library needed so you can script renders, build your own UI on top, or give an agent direct render/measure tool calls.
studio dev --port 3030Render a template
POST /render
Content-Type: application/json{
"templateId": "stat-card",
"props": { "title": "Weekly Active Users", "stat": "124.5K" },
"preset": "instagram-square",
"locale": "en"
}Prop
Type
Response is the raw image bytes (Content-Type: image/png), with:
| Header | Meaning |
|---|---|
X-Cache | hit or miss |
Cache-Control | public, max-age=31536000, immutable |
curl -X POST http://localhost:3030/render \
-H "Content-Type: application/json" \
-d '{"templateId":"stat-card","props":{"title":"Hello","stat":"10K"}}' \
-o out.pngMeasure a template
Same request shape as /render (minus preset, since no image is produced), returns just the natural dimensions instead of pixels useful for auto-sizing UI or checking a layout without paying for a full render.
POST /measure{ "templateId": "stat-card", "props": { "title": "Hello" } }{ "width": 1080, "height": 640 }List templates, presets, and locales
GET /templates → every registered template, with its JSON-Schema propsSchema and load status
GET /presets → the configured presets array
GET /locales → the configured locale codes
GET /config → { defaultPreset, locales, outDir, presets }/templates is the one to poll (or subscribe to via /events, below) if you're building a prop-editing UI it gives you everything needed to render a form per template:
[
{
"id": "stat-card",
"description": "A milestone or stat card for social media.",
"status": "ok",
"propsSchema": { "type": "object", "properties": { "...": "..." } }
}
]A template that failed to load still appears, with "status": "error" and an errorMessage other templates keep working.
Live reload events
GET /eventsA Server-Sent Events stream. The studio UI uses this to hot-reload the canvas when you edit a template, config, or locale file — subscribe to it yourself to trigger your own rebuilds/refreshes on the same changes:
const events = new EventSource("http://localhost:3030/events");
events.addEventListener("reload", (e) => {
const event = JSON.parse(e.data);
// event.type: "template" (one template changed) or "full" (config/shared file changed)
});A connected event fires once on open; a keepalive comment is sent every 15s so the connection doesn't idle-timeout behind a proxy.
Cache management
GET /cache/stats → { compiled: { entries }, pixels: { entries, sizeBytes, maxSizeBytes }, cacheDir }
POST /cache/clean → evicts everything, returns a summary of what was freedSame cache the CLI's studio cache stats/studio cache clean report on — see Caching.
Errors
Validation and render/measure errors come back as JSON with a 4xx status, not a generic 500:
| Status | Body | When |
|---|---|---|
400 | { "error": "Invalid request body", "issues": [...] } | Malformed request (missing templateId, etc.) |
400 | { "error": "Invalid props", "issues": [...] } | Props failed the template's Zod schema issues is the same structured shape as PropValidationError in the core API |
404 | { "error": "Template \"x\" not found" } | Unknown templateId |
404 | { "error": "Preset \"x\" not found" } | Unknown preset |
422 | { "error": "Template \"x\" failed to load: ..." } | Template exists but has a load error (bad export, syntax error) |
issues entries include a human-readable message and often a suggestion designed to be useful directly in an agent's retry loop, not just for display.