How preview works
Preview reuses the exact same render pipeline and renderer asPOST /v1/renders —
same engine, same JSON schema — just restricted to a slice of the timeline and
downscaled. What you see in a preview is exactly what the full render produces at
that timestamp.
- Submit
POST /v1/previewwith arender_requestcomposition. - Choose what you want:
dry_run: true— validate only, no render, returns instantly.at: <seconds>— a single frame.window: { from, to }— a short clip, with audio.contact_sheet: { ... }— a grid of frames sampled across the timeline.
- Get a response immediately —
200for a dry run, no job (a contact-sheet dry run also includes the sampling plan, still with no job). Any non-dry-run preview — frame, window, or contact sheet — returns202with a job queued. - Poll like any render —
job.id(prefixrender_) works withGET /v1/renders/{id}. Preview jobs are free: excluded from your usage totals and fromGET /v1/renders.
Free validation (dry_run)
Set dry_run: true to run Framelane’s linter without spending a render: duplicate
element IDs, dangling or self-referencing transitions, an empty timeline, an
element or caption that starts after the composition ends, and — if you pass
target_duration_sec — a timeline that misses your target length.
ok is false only when a violation is severity: "error" — a missed
target_duration_sec, for example, is a "warning" and never blocks you.
Frame and window previews
Passat for a single frame, or window: { from, to } for a short clip (audio
trimmed and muxed for free). Both render at a small draft width by default (480
px; raise width up to 3840 for a sharper look) and dispatch a real, cheap render
job.
job.id via GET /v1/renders/{id} exactly like a full render.
at and window are mutually exclusive. A window.to past the end of the
composition is clamped down to the composition’s duration rather than rejected —
you may get a shorter clip than requested, never an error. A window.from at or
past the composition’s duration is rejected, with 422 invalid_request.Contact sheets: see the whole edit in one image
Setcontact_sheet to get back a single grid PNG sampling frames across the
timeline — enough to check an entire edit in one glance (or one vision call),
without downloading and scrubbing a video.
{ "detail": "balanced" } on a 10-second
composition budgets ~10 cells; max_cells caps that, shown here at 4 to keep the
example short). The sheet field describes the plan immediately (even on a
dry_run, before any render happens):
Combine with
window to sample only part of the timeline instead of the whole
thing. Once the render completes, job.output.url is a single PNG —
columns × cellWidth pixels wide, rows × cellHeight tall — with each cell’s
frame and burned-in label ("0:04 element_start") matching sheet.cells[i] in
order.
Request reference
Endpoints
Good to know
- Preview jobs cost nothing and are excluded from
GET /v1/rendersandGET /v1/workspace/usage— build as many as you need while iterating. - A preview is pixel-identical to the equivalent full render at the same timestamp, modulo resolution — the renderer takes no different code path for a preview, so what you approve (once scaled up) is what you’ll get.
- Preview requests never accept
Idempotency-Key— every call creates a new job. - If an element references media you haven’t finished uploading yet, a real
preview (
dry_run: false) returns422 asset_not_ready; adry_run: truevalidation tolerates it and lints the rest of the composition anyway.

