Skip to main content
This page is the field-by-field reference for the elements[] array in POST /v1/renders. For full request body examples see the Render Examples section.

How to read this page

Dimension fields accept a pixel number (960), a percentage string ("50%"), or an angle string ("90°" / "90deg") depending on context.

Common fields

These fields are present on every element type.
GET /v1/capabilities lists four further element types with supported: falsecomposition, progress_bar, audio_visualization and countdown. None of them are accepted: sending one returns 422 from the discriminated union (Input tag 'composition' found using 'type' does not match any of the expected tags), which does not explain itself. composition has no engine concept at all — the render task is a flat set of per-type arrays with no nesting — so use groups[] to transform several elements as one. progress_bar, audio_visualization and countdown are broken on the renderer and have no direct replacement; build a progress bar from a stroked shape whose trim_keyframes animate end 0→1, and a countdown from a text element with a counter sweeping from_valueto_value (a plain number, not mm:ss).
gradient has been REMOVED as an element type. {"type": "gradient", …} now returns a 422 naming the replacement and carrying the JSON to send instead. A gradient is a fill value now, not a type of element, so it paints any silhouette rather than only a box: write a gradient card as a shape with a gradient fill — the same picture, plus a free path, stroke, trim, morph and the compositing family. Nothing you have saved needs editing: stored compositions, their version history and queued job bodies were all rewritten to the shape form, which renders identically. See The removed gradient element for the field-by-field mapping.

Advanced transform & looks

Transform fields (position/rotation/anchor/opacity) apply to every visual element. The compositing family (blend_mode, mask_shape, mask, mask_keyframes, matte, backdrop_blur) applies to video, image, and shape elements only — the renderer does not read those keys on text, so the API rejects them there. (Text overlay/difference blends exist as motion presets.)
video and image also accept the extended colour grade — temperature, tint, vibrance, highlights, shadows — alongside brightness/contrast/etc. Those five run −1 to 1, where 0 is a no-op, and the schema does not clamp them.

video

Plays a video clip on the timeline.

Source and trim

Video elements do not have a duration field. Clip length on the output timeline is determined by out_point − in_point (accounting for speed). To fix the output to a specific length, set a top-level duration on the request.

Position and size

Audio

Color adjustments

Cropping

Border and shadow

A shadow needs an offset. Setting shadow_color with shadow_x and shadow_y both 0 returns 422 on video and image — the renderer skips the entire shadow pass at zero offset, so there is no ambient/no-offset shadow. Give it at least 1px.Percentage strings are also rejected on border_radius, border_width, shadow_x, shadow_y and backdrop_blur — those are pixel-unit fields, and a "%" value would silently become 0. Use a number or an "Npx" string.

Effects, motion


audio

Plays an audio clip or background music track.

text

Renders a text layer on screen.
duration is required on text elements. Omitting it produces a zero-length window — the text will not appear in the render.
background, stroke and shadow are mutually exclusive — they select one renderer display mode, so setting two returns 422. Pick one.
On text, animation_preset, word_animation and motion[] are three routes to the same slot — combining motion[] with either of the other two returns 422. Also rejected: an animation_preset naming no catalog text animation and no custom_animations.text entry (the renderer would drop it silently); any loop-* preset name (use motion[] with the matching loop_* type and duration = one cycle); and any per-glyph preset — or scope: "character" motion — on an element that has a counter, because glyph timings are computed once against the placeholder text and later glyphs of longer values never render (use a block animation like fade).

image

Renders a static image on screen.
Both id and duration are required on image elements. An empty or missing id causes the image to be silently skipped by the renderer. A missing duration produces a zero-length window.

The removed gradient element

{"type": "gradient", …} is gone. A body carrying one returns a 422 — and, unlike an ordinary unknown-tag error, it says so in words and hands you the replacement:
GET /v1/capabilities no longer lists gradient among element_types and no longer publishes a schema for it. shape is the type to check a gradient card against. Nothing you have saved needs editing. Every stored composition — project heads, their version history and queued job bodies — was rewritten to the shape form before this change shipped, and the two forms render identically, so old projects keep working untouched. Only request bodies your own code still builds need changing.

Write this instead

A gradient card, bar or pill is a shape whose path covers its whole view_box and whose fill is the gradient. Field for field: Before — a gradient card as the removed element (now a 422):
After — the same card, in the spelling the API accepts. Two keys change: type, and gradient becomes fill; one key is added: path:
The fill also takes the CSS shorthand — "fill": "linear-gradient(45deg, #e07a4f 0%, #7c3aed 100%)" is the same card in one line. See Gradient fills for the full treatment, and What a gradient fill composes with for everything the shape spelling gives you that the removed element could not.
Only the element went. The word gradient is untouched everywhere else in the API: a shape’s gradient fill, the request-level background_gradient, the Gradient object and the CSS linear-gradient(...) / radial-gradient(...) shorthand all work exactly as before.

shape

A first-class vector primitive: SVG path fill + stroke, morphing, trim paths. The fill is a hex colour, "none", a Gradient object or a CSS gradient string — so a gradient card, bar or pill is a shape with a rectangular path, a corner_radius and a gradient fill (Gradient fills).

Gradient fills

A gradient card, bar or pill is a shape whose path covers its whole view_box and whose fill is a gradient — the rectangle is what makes it a card, not something the gradient itself asks for (what a gradient fill composes with). Both spellings are accepted — the Gradient object, or the CSS shorthand, which is parsed API-side into exactly the same object. (This replaces the gradient element, which was removed.)
The same card written with the CSS shorthand. It is accepted anywhere the object is — a shape’s fill and the request-level background_gradient — and it is normalized at validation, so the stored composition and every read-back hold the object, never the string:
CSS angles are converted to the engine’s convention — angle_degrees = (90 − css_deg) mod 360, so to right is 0 and to top is 90 — and a radial at 30% 70% is converted to the engine’s bottom-up center. A numeric CSS angle is box-relative: 135deg behaves as to bottom right whatever the card’s aspect, so only 0/90/180/270 are pixel-exact on a non-square box. What the parser cannot represent is a 422 carrying the fix: repeating-* and conic-gradient(...), var()/calc(), vendor prefixes, a unitless angle (4545deg) and pixel stop positions (40px25%).

What a gradient fill composes with

A gradient fill is a paint on the shape’s own path, sitting where a flat hex colour would sit. Everything else on the element keeps working around it:
  • Any path. A triangle ("M50 0 L100 100 L0 100 Z"), a blob, an icon outline, a multi-subpath glyph under either fill_rule — a gradient fills each of them the way it fills the card above. The rectangle is a card’s shape, not a gradient’s requirement.
  • stroke / stroke_width / stroke_dash. Outline a gradient-filled path in a flat colour, dashed or solid, on the one element.
  • path_keyframes. Morph a gradient-filled path between keyframes.
  • trim / trim_keyframes. The draw-on works on a gradient-filled path; trim still applies before dash.
  • The compositing family. blend_mode, mask_shape / mask / mask_keyframes, matte and backdrop_blur read a gradient-filled shape the same way they read a flat-filled one — a screen-blended gradient sweep, a gradient card behind a frosted panel, a gradient held inside a luma matte are all one element each.
  • fill_rule, corner_radius, opacity. Identical behaviour to a flat fill.
Stacking a gradient-filled shape behind a flat-filled one is still a fine way to build a layered look — two shapes when you want two shapes, not a workaround. This is the spelling to write, and now the only one. The gradient element that used to draw the same card was removed: it had no channel for a path, a stroke, a trim or the compositing family, and everything it could draw a shape draws too.

Composition-level features

Set on the render request itself (siblings of elements), not on individual elements:

Sub-objects

Motion

Used in motion[] on video, text, image, and shape elements, and in animations[] on groups. Each entry runs either a pre-built catalog preset (type) or one of your custom_animations definitions (custom).

Preset surfaces

Presets are surface-specific. Text animations and element animations come from two different renderer directories, so a preset used on the wrong surface returns 422, not a silent no-op — blur and evaporate are text-only; identity, swing_in, tilt_zoom, loop_orbit and the ken_burns_* family are element-only. GET /v1/capabilitiesmotions[] is authoritative: every entry carries the same four booleans shown here. See Motion examples. scope: "character" needs a preset with a ✅ in the character column — a text-block preset at character scope is a 422 too.

Effect

Used in effects[] on video, image, and shape elements.

ChromaKeyProps

Used as chroma_settings on a chroma_key effect. Omitting the object entirely applies the defaults below — not the shader’s own zero defaults, which would key black rather than green.

WordAnimation

Used as word_animation on text. Drives word-by-word animated text synchronized to timestamps.
style: "color" and style: "box" paint the active word with the text element’s background_color. It is required for those two styles (422 otherwise) — the renderer resolves an absent value to opaque black, which is an invisible highlight on dark footage.

Word

Used in word_animation.words[]. Timestamps are absolute timeline seconds — the same clock as the element’s time, motion time, and everything else.

WordSpec

Used in words[] on text. Per-word timing with an optional style override (whole-word matches only).

ValueCounter

Used as counter on text. Rewrites the text from an eased numeric sweep.

TextGlow

Used as glow on text.

Gradient object

Used as fill on shape elements and as background_gradient on the request. Everywhere this object is accepted a CSS linear-gradient(...) / radial-gradient(...) string is accepted too, and is normalized into this object at validation.

DropShadow

Used as shadow on shape elements.

Matte

Used as matte on visual elements. Drives coverage from another layer’s isolated render (the source auto-hides).

MaskConfig

Used as mask on visual elements (layered on the analytic mask_shape).

AudioGenerator

Used as audio in a motion[] entry. Each frame the soundtrack FFT reduces to the feature and offsets the element’s properties by amount × feature.

RangeSelector

Used as selector on a custom_animations definition (the engine reads it off the animation definition, never off a motion[] entry). Shapes the animation amount by position along the text; set the definition’s group to glyph or word so there is something to range across.

CustomAnimationRegistry

Set as custom_animations on the request. Two registries, because the engine builds element animations and text animations from two different code paths:

CustomAnimation

AnimationKeyframe

Group

Used in the request-level groups[]. Composes member → group → parent (pixel-space, aspect-correct).