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: false — composition, 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_value → to_value (a plain number, not mm:ss).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
Effects, motion
audio
Plays an audio clip or background music track.text
Renders a text layer on screen.background, stroke and shadow are mutually exclusive — they select one renderer display mode, so setting two returns 422. Pick one.image
Renders a static image on screen.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 ashape 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):
type, and gradient
becomes fill; one key is added: path:
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. Thefill 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 ashape 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.)
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:
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 (45 → 45deg) and pixel stop positions
(40px → 25%).
What a gradient fill composes with
A gradientfill 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 eitherfill_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,matteandbackdrop_blurread a gradient-filledshapethe 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.
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 ofelements), not on individual elements:
Sub-objects
Motion
Used inmotion[] 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/capabilities → motions[] 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 ineffects[] on video, image, and shape elements.
ChromaKeyProps
Used aschroma_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 asword_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 inword_animation.words[]. Timestamps are absolute timeline seconds — the same clock as the element’s time, motion time, and everything else.
WordSpec
Used inwords[] on text. Per-word timing with an optional style override (whole-word matches only).
ValueCounter
Used ascounter on text. Rewrites the text from an eased numeric sweep.
TextGlow
Used asglow on text.
Gradient object
Used asfill 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 asshadow on shape elements.
Matte
Used asmatte on visual elements. Drives coverage from another layer’s isolated render (the source auto-hides).
MaskConfig
Used asmask on visual elements (layered on the analytic mask_shape).
AudioGenerator
Used asaudio in a motion[] entry. Each frame the soundtrack FFT reduces to the feature and offsets the element’s properties by amount × feature.
RangeSelector
Used asselector 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 ascustom_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-levelgroups[]. Composes member → group → parent (pixel-space, aspect-correct).

