### RenderRequest (top level)
- version: Literal['v4', 'v5'] | None — default None. Wire version of this request. Omit it: the render task is v5 exactly when the request carries a v5 block, and v4 otherwise. `v5` accepts the v5 blocks (a shape's `geometry`, `frame` and `instance` elements, `operations`, `components`); `v4` refuses them.
- schema_version: Literal['v5'] | None — default None. The document format an editor wrote this request in. Not sent to the renderer; `version` is the wire's.
- width: int | None — default None. Output width in pixels. Must be set together with `height` or both omitted.
- height: int | None — default None. Output height in pixels. Must be set together with `width` or both omitted.
- duration: float | None — default None. Total composition duration in seconds. Inferred from elements when omitted.
- frame_rate: int | None — default None. Frames per second. When set, the output encodes at exactly this rate. Defaults to 30 when omitted.
- output_format: OutputFormat — default 'mp4'. Container and codec for the output file.
- background_color: str — default '#000000ff'. RGBA background color in hex format (#RRGGBBAA).
- background_image_url: HttpUrl | None — default None. URL of an image to use as the composition background.
- alpha: bool — default False. When true, produce an alpha-channel (transparent background) output. Requires `output_format=webm` or `output_format=mov`.
- elements: list[VideoElement | AudioElement | TextElement | ImageElement | ShapeElement | FrameElement | InstanceElement] — default []. Ordered list of timeline elements (video, image, text, audio, etc.).
- transitions: list[Transition] — default []. Transition effects applied between consecutive elements.
- groups: list[Group] — default []. Transform groups over member elements (compose member→group→parent; optional stack layout), the alias of frames (§5). A request with `frame` or `instance` elements carries none.
- design_size: DesignSize | None — default None. The logical root in design px: frames and instances at the root are placed in this box, and the render scales it uniformly to `width` x `height`, whose aspect it must have. Canvas percent at the root is unchanged.
- operations: OperationsBlock | None — default None. Element properties driven over time (GVR §4.3): groups of operations, each counting from an anchor. Schema: `blocks.operations` in GET /v1/capabilities.
- components: list[Component] — default []. Component definitions, which `instance` elements place. Schema of one: `blocks.components` in GET /v1/capabilities.
- motion_blur: MotionBlur | None — default None. Shutter-based motion blur over the whole composition (§5c). Graphics motion smears; video holds its decoded frame within the shutter (as in AE). Opt-in and costly: accumulation is CPU-side, so the render falls back to software encoding — expect roughly `samples`× render time.
- background_gradient: Gradient | None — default None. Canvas-sized gradient fill behind every layer (§6). Rendered for the full output slice. Accepts a Gradient object or a CSS `linear-gradient(...)` string.
- watermark_url: HttpUrl | None — default None. Watermark image overlaid on the output (§6).
- custom_animations: CustomAnimationRegistry | None — default None. Inline custom-animation definitions (§3), registered with the engine before any element is built. Reference an `element` entry by name via `motion[].custom` on any video/image/shape element or group; reference a `text` entry via a text element's `animation_preset` or `motion[].custom`. The catalog stops being a ceiling — anything expressible as keyframes is expressible in the request.
### Transition
- type: TransitionType — REQUIRED. Transition effect applied between two video elements (transitions are video-only).
- duration: float — REQUIRED. Transition duration in seconds.
- from_id: str | None — default None. ID of the outgoing video element (omit for the very first transition).
- to_id: str | None — default None. ID of the incoming video element (omit for the very last transition).
- z_index: int | None — default None. **Deprecated — ignored by the renderer.** The transition draws at its linked videos' position; the engine reads no z key on a transition. Accepted for backward compatibility only.
### VideoElement (type: "video")
- lut_url: HttpUrl | None — default None.
- lut_intensity: float — default 100.
- brightness: float — default 0. Brightness, -100..100, applied as a 0..2 colour multiplier (0 = no change). `-100` multiplies by 0: the element renders pure black while keeping its alpha — a silhouette of the artwork. Combine a `brightness: -100` copy of an image with `blur`, reduced `opacity` and a small offset, stacked beneath the real one, to fake the content-shaped drop shadow `shadow_x`/`shadow_y` cannot produce.
- contrast: float — default 0.
- saturation: float — default 0.
- exposure: float — default 0.
- sharpness: float — default 0.
- blur: float — default 0.
- noise: float — default 0.
- vignette: float — default 0.
- hue_rotate: float — default 0.
- temperature: float — default 0. White balance warm (+) / cool (−), −1..1; 0 = no-op. Applied as a channel matrix, after the classic brightness/contrast chain.
- tint: float — default 0. White balance magenta (+) / green (−), −1..1; 0 = no-op.
- vibrance: float — default 0. Saturation boost weighted toward muted colours, −1..1; 0 = no-op. Boosts flat colour without wrecking skin tones.
- highlights: float — default 0. Luma-masked tone lift of the brightest range, −1..1; 0 = no-op.
- shadows: float — default 0. Luma-masked tone lift of the darkest range, −1..1; 0 = no-op.
- crop_top: float — default 0.
- crop_bottom: float — default 0.
- crop_left: float — default 0.
- crop_right: float — default 0.
- border_radius: int | float | str | CornerRadiiPx — default 0. Corner radius in pixels — a single value, or per-corner `{top_left, top_right, bottom_right, bottom_left}` for asymmetric corners (e.g. a card rounded only on top). The renderer normalizes px to a 0–1 fraction of the element's shorter side (≈ half the shorter side is fully rounded) and clamps to that range. For shape elements use `corner_radius` (already 0–1).
- border_color: str | None — default None.
- border_width: int | float | str — default 0. Border thickness in pixels (converted to the renderer's relative border scale against the element's shorter side, so it survives resizes). The border outlines the element's border_radius-rounded quad — not the image's alpha silhouette.
- shadow_color: str | None — default None.
- shadow_blur: int | float | str — default 0. Shadow softness, 0–100 (renderer blur-strength scale, not pixels): 0 = hard edge, 100 = maximum blur. Values are clamped to that range.
- shadow_x: int | float | str — default 0. Horizontal shadow offset in pixels (converted to the renderer's relative offset scale). The shadow silhouette is the element's border_radius-rounded quad, not the content alpha — a cut-out PNG gets a card shadow, not an outline-shaped one. On a cut-out that reads as a floating rectangle (rotated with the element, which is the tell). For a shadow that follows the artwork, drop these fields and stack a second copy of the same image underneath at `brightness: -100` (a black silhouette, alpha preserved) with `blur` and reduced `opacity`, offset a few percent — see `brightness`.
- shadow_y: int | float | str — default 0. Vertical shadow offset in pixels. See `shadow_x`.
- blend_mode: BlendMode — default 'none'.
- mask_shape: MaskShape | None — default None.
- mask: MaskConfig | None — default None.
- mask_keyframes: list[MaskKeyframe] | None — default None.
- matte: Matte | None — default None.
- backdrop_blur: int | float | str — default 0. Glass: the scene behind the element, Gaussian-blurred, fills its footprint under its translucent content (a shape's own silhouette, a video's or image's box with its corner radius and mask). A Gaussian sigma in canvas px, as CSS `backdrop-filter: blur()` takes it; the renderer caps it at 128. 0 is off.
- backdrop_blur_keyframes: list[BlurKeyframe] | None — default None. Animate `backdrop_blur` over the timeline; replaces the static value while present.
- layer_blur: float — default 0. Blurs the element itself as drawn: a Gaussian sigma in canvas px, as CSS `filter: blur()` takes it, spreading three sigma past its box. At most 128; 0 is off. Not on a shape yet (the editor's preview cannot draw it), and not with `blend_mode`, `backdrop_blur` or `matte`, beside which the renderer would draw the element without it.
- layer_blur_keyframes: list[BlurKeyframe] | None — default None. Animate `layer_blur` over the timeline; replaces the static value while present.
- glass: Glass | None — default None. A refracting glass edge: the scene behind bends inward near the element's outline. Pair it with `backdrop_blur` for frosted glass.
- x: int | float | str — default '50%'.
- y: int | float | str — default '50%'.
- width: int | float | str — default '100%'. Box width. Together with `height` this is a **cover** box, not a fit box: sized media (video, image) scales to fill it and the overflow is **cropped** — it is never letterboxed. A box whose aspect ratio differs from the source's therefore silently cuts the source's edges. To show a source whole, match the box aspect to it: on a `W`x`H` canvas, for a source of aspect `a`, `width% = a * height% * (H/W)` — e.g. a 1024x1536 asset (a=0.667) on 1920x1080 needs `width% = 0.375 * height%`. Percentages are of the canvas, not the parent.
- height: int | float | str — default '100%'. Box height. See `width` — the pair is a cover box and crops rather than letterboxes. Percentages are of the canvas.
- aspect_ratio: float | None — default None. **Accepted but ignored — the renderer never receives this field.** It does NOT constrain or correct the `width`/`height` box, so it cannot be used to stop a mismatched box from cropping the source; size the box per `width` instead. Kept for backward compatibility.
- x_anchor: int | float | str — default '50%'. Horizontal pivot the element **rotates** about, measured across its own box (`0%` = left edge, `50%` = centre, `100%` = right edge; px values are an offset from the left edge). This is a pivot, not an alignment — `x` always places the element's centre, so the anchor changes nothing on an unrotated element. Honored on video, image and shape; text and the generator elements rotate about their centre and reject a non-default anchor.
- y_anchor: int | float | str — default '50%'. Vertical pivot the element **rotates** about, measured across its own box (`0%` = top edge, `50%` = centre, `100%` = bottom edge). Same rules as `x_anchor`: a pivot, not an alignment.
- x_rotation: int | float | str — default '0°'.
- y_rotation: int | float | str — default '0°'.
- z_rotation: int | float | str — default '0°'.
- x_scale: int | float | str — default '100%'.
- y_scale: int | float | str — default '100%'.
- flip_horizontal: bool — default False.
- flip_vertical: bool — default False.
- opacity: float — default 100.
- z_index: int | None — default None. Stacking order (higher = on top). When omitted, elements stack in array order — later elements render above earlier ones (painter's rule); text defaults one layer above non-text. Set explicit values only when array order isn't the order you want.
- clip: bool — default False.
- color_overlay: str | None — default None. **Not supported by the renderer — setting this is rejected.** A strict submit returns `unsupported_feature` (422) and a dry-run reports it as a blocking violation; there is no native tint field to map it onto. To darken an element use `brightness` (`-100` is a black silhouette); to lay a colour over one, stack a `shape` with a flat or gradient `fill` above it.
- type: Literal['video'] — default 'video'.
- id: str | None — default None. Unique identifier for this element. **Required on image elements** — an empty or missing ID causes the image to be silently skipped by the renderer. Recommended on all elements that are referenced by a transition.
- name: str | None — default None. Optional human-readable label. Not used by the renderer.
- track: int | None — default None. Timeline track index (0–255). Informational only; not used by the renderer.
- time: float | None — default None. When this element starts on the output timeline, in seconds. Defaults to `0` when omitted.
- visible: bool — default True. Set to `false` to skip this element without removing it from the request.
- locked: bool — default False. Marks the element locked in editors. Not sent to the renderer.
- source_url: HttpUrl — REQUIRED. URL of the video file — MP4, MOV or WebM only; any other extension is rejected at submit. Must be accessible by the renderer.
- in_point: float | None — default None. In point — seconds into the source file to start playing from. Defaults to `0`.
- out_point: float | None — default None. Out point — seconds into the source file to stop playing. Defaults to end of source when omitted. Controls clip length on the timeline.
- speed: float — default 1.0. Playback speed. `1.0` = normal speed, `2.0` = 2× (half duration), `0.5` = half speed (double duration).
- playback_rate_keyframes: list[RateKeyframe] | None — default None. Speed ramp (§5c): piecewise-linear playback-rate keyframes (absolute timeline seconds; rate 0 = freeze; at most 512 keyframes — the renderer truncates beyond that). Audio keeps the static rate — mute or detach it on ramped clips.
- volume: float — default 100. Embedded audio volume as a percentage (0–100). Affects only the audio track inside this video clip.
- muted: bool — default False. Silence the clip's embedded audio. `volume` is kept, so unmuting restores the level.
- loop: bool — default False. Repeat the source to fill the clip: when playback passes the end of the file it restarts from the file's first frame (not `in_point`). Set `out_point` past the source's length to choose how long the clip runs — its timeline length is still `(out_point − in_point) / speed`. Requires `out_point`.
- fade_in_duration: float — default 0. Duration in seconds of a linear audio fade-in at the clip's start.
- fade_out_duration: float — default 0. Duration in seconds of a linear audio fade-out at the clip's end.
- effects: list[Effect] — default [].
- motion: list[Motion] — default [].
### AudioElement (type: "audio")
- type: Literal['audio'] — default 'audio'.
- id: str | None — default None. Unique identifier for this element. **Required on image elements** — an empty or missing ID causes the image to be silently skipped by the renderer. Recommended on all elements that are referenced by a transition.
- name: str | None — default None. Optional human-readable label. Not used by the renderer.
- track: int | None — default None. Timeline track index (0–255). Informational only; not used by the renderer.
- time: float | None — default None. When this element starts on the output timeline, in seconds. Defaults to `0` when omitted.
- visible: bool — default True. Set to `false` to skip this element. Audio has no picture — `false` drops the whole track from the render, it does not mute or hide it (the linter reports that as `AUDIO_HIDDEN`). To keep the track but silence it, set `muted: true`.
- locked: bool — default False. Marks the element locked in editors. Not sent to the renderer.
- source_url: HttpUrl — REQUIRED. URL of the audio file. Must be accessible by the renderer.
- in_point: float | None — default None. In point — seconds into the source file to start from. Defaults to `0`.
- out_point: float | None — default None. Out point — seconds into the source file to stop. Defaults to end of source when omitted. Controls clip length on the timeline.
- speed: float — default 1.0. Playback speed. `1.0` = normal speed, `2.0` = 2× speed.
- volume: float — default 100. Audio volume as a percentage (1–100). **Must be greater than 0** — the renderer silently drops audio streams with `volume <= 0`. Use `muted` to silence the track.
- muted: bool — default False. Silence this track while keeping it, and its `volume`, in the composition. A muted track is left out of the render's audio.
- fade_in_duration: float — default 0. Duration in seconds of a linear audio fade-in at the clip's start.
- fade_out_duration: float — default 0. Duration in seconds of a linear audio fade-out at the clip's end.
### TextElement (type: "text")
- border_radius: int | float | str | CornerRadiiPx — default 0. Corner radius in pixels — a single value, or per-corner `{top_left, top_right, bottom_right, bottom_left}` for asymmetric corners (e.g. a card rounded only on top). The renderer normalizes px to a 0–1 fraction of the element's shorter side (≈ half the shorter side is fully rounded) and clamps to that range. For shape elements use `corner_radius` (already 0–1).
- border_color: str | None — default None.
- border_width: int | float | str — default 0. Border thickness in pixels (converted to the renderer's relative border scale against the element's shorter side, so it survives resizes). The border outlines the element's border_radius-rounded quad — not the image's alpha silhouette.
- shadow_color: str | None — default None.
- shadow_blur: int | float | str — default 0. Shadow softness, 0–100 (renderer blur-strength scale, not pixels): 0 = hard edge, 100 = maximum blur. Values are clamped to that range.
- shadow_x: int | float | str — default 0. Horizontal shadow offset in pixels (converted to the renderer's relative offset scale). The shadow silhouette is the element's border_radius-rounded quad, not the content alpha — a cut-out PNG gets a card shadow, not an outline-shaped one. On a cut-out that reads as a floating rectangle (rotated with the element, which is the tell). For a shadow that follows the artwork, drop these fields and stack a second copy of the same image underneath at `brightness: -100` (a black silhouette, alpha preserved) with `blur` and reduced `opacity`, offset a few percent — see `brightness`.
- shadow_y: int | float | str — default 0. Vertical shadow offset in pixels. See `shadow_x`.
- x: int | float | str — default '50%'.
- y: int | float | str — default '50%'.
- width: int | float | str — default '100%'. Box width. Together with `height` this is a **cover** box, not a fit box: sized media (video, image) scales to fill it and the overflow is **cropped** — it is never letterboxed. A box whose aspect ratio differs from the source's therefore silently cuts the source's edges. To show a source whole, match the box aspect to it: on a `W`x`H` canvas, for a source of aspect `a`, `width% = a * height% * (H/W)` — e.g. a 1024x1536 asset (a=0.667) on 1920x1080 needs `width% = 0.375 * height%`. Percentages are of the canvas, not the parent.
- height: int | float | str — default '100%'. Box height. See `width` — the pair is a cover box and crops rather than letterboxes. Percentages are of the canvas.
- aspect_ratio: float | None — default None. **Accepted but ignored — the renderer never receives this field.** It does NOT constrain or correct the `width`/`height` box, so it cannot be used to stop a mismatched box from cropping the source; size the box per `width` instead. Kept for backward compatibility.
- x_anchor: int | float | str — default '50%'. Horizontal pivot the element **rotates** about, measured across its own box (`0%` = left edge, `50%` = centre, `100%` = right edge; px values are an offset from the left edge). This is a pivot, not an alignment — `x` always places the element's centre, so the anchor changes nothing on an unrotated element. Honored on video, image and shape; text and the generator elements rotate about their centre and reject a non-default anchor.
- y_anchor: int | float | str — default '50%'. Vertical pivot the element **rotates** about, measured across its own box (`0%` = top edge, `50%` = centre, `100%` = bottom edge). Same rules as `x_anchor`: a pivot, not an alignment.
- x_rotation: int | float | str — default '0°'.
- y_rotation: int | float | str — default '0°'.
- z_rotation: int | float | str — default '0°'.
- x_scale: int | float | str — default '100%'.
- y_scale: int | float | str — default '100%'.
- flip_horizontal: bool — default False.
- flip_vertical: bool — default False.
- opacity: float — default 100.
- z_index: int | None — default None. Stacking order (higher = on top). When omitted, elements stack in array order — later elements render above earlier ones (painter's rule); text defaults one layer above non-text. Set explicit values only when array order isn't the order you want.
- clip: bool — default False.
- color_overlay: str | None — default None. **Not supported by the renderer — setting this is rejected.** A strict submit returns `unsupported_feature` (422) and a dry-run reports it as a blocking violation; there is no native tint field to map it onto. To darken an element use `brightness` (`-100` is a black silhouette); to lay a colour over one, stack a `shape` with a flat or gradient `fill` above it.
- type: Literal['text'] — default 'text'.
- id: str | None — default None. Unique identifier for this element. **Required on image elements** — an empty or missing ID causes the image to be silently skipped by the renderer. Recommended on all elements that are referenced by a transition.
- name: str | None — default None. Optional human-readable label. Not used by the renderer.
- track: int | None — default None. Timeline track index (0–255). Informational only; not used by the renderer.
- time: float | None — default None. When this element starts on the output timeline, in seconds. Defaults to `0` when omitted.
- visible: bool — default True. Set to `false` to skip this element without removing it from the request.
- locked: bool — default False. Marks the element locked in editors. Not sent to the renderer.
- duration: float — REQUIRED. **Required.** Duration in seconds the text is visible. Omitting this field produces a zero-length window and the element will not appear in the render.
- text: str — REQUIRED. The text content to render.
- font_family: str — default 'Inter'. Font family name. Must be available to the renderer.
- font_size: float — default 16. Font size in pixels.
- font_weight: int — default 400. Font weight (100–900). The renderer has no variable weights: `600` and above render **bold**, everything below renders regular. Composes with `font_style` (italic + ≥600 = bold italic).
- font_style: Literal['normal', 'italic', 'bold', 'bolditalic'] — default 'normal'. Font style variant.
- text_color: str — default '#ffffff'. Text fill color as a hex string.
- text_align: Literal['left', 'center', 'right'] — default 'center'. Horizontal text alignment.
- text_direction: Literal['ltr', 'rtl'] — default 'ltr'. Text direction. `rtl` for right-to-left scripts (§4).
- text_decoration: Literal['none', 'underline', 'strikethrough'] — default 'none'. Text decoration. Only `none` renders. `underline` is reachable only per word — `words[].style.underline` — and `strikethrough` has no renderer path at all; both are rejected here (422) rather than silently dropped. Draw a strike-through as a thin `shape` rectangle over the text.
- tracking: float — default 0. Letter spacing (tracking) in pixels (converted to the renderer's width-relative unit on the wire). Positive values add space between characters.
- tabular_numbers: bool — default False. Tabular (monospaced) figures: every digit takes the same advance, so columns of numbers align across lines and a `counter` does not jitter as its value changes. The renderer's baked fonts carry the OpenType alternates; a font whose face lacks the feature gets synthesised tabular digits in the export only. Default `false` = the font's proportional figures.
- leading: float — default 1.2. Line height (leading) as a multiplier of font size. `1.2` = 20% taller than the font size.
- stroke_color: str | None — default None. Outline color. Set together with `stroke_width` to enable text outlines.
- stroke_width: float — default 0. Outline width, em-relative (fraction of `font_size` — e.g. `0.05` = 5% of the font size). Has no effect unless `stroke_color` is also set.
- background_color: str | None — default None. Secondary colour. Fills the box behind the text when `background` is `true`, **and** is the highlight colour for `word_animation.style` `color` (the active word) and `box` (the box) — those two styles require it.
- background_opacity: float — default 100.
- x_padding: int | float | str — default 0.
- y_padding: int | float | str — default 0.
- background: bool — default False. Solid color box behind the full text block. Set `background_color` to choose the color.
- background_style: Literal['block', 'line_hard', 'line_round'] — default 'block'. Shape of the `background` plate: `block` — one box behind the whole text; `line_hard` — a square-cornered box behind each line; `line_round` — a rounded box behind each line. Requires `background: true`. An animation that centres its words draws the `block` plate whichever style is set.
- stroke: bool — default False. Outline-only mode — draws the glyph stroke with no fill. Requires `stroke_color` and `stroke_width`. When `false`, setting `stroke_color` + `stroke_width` gives fill + stroke (outlined).
- shadow: bool — default False. Built-in drop shadow.
- motion: list[Motion] — default [].
- word_animation: WordAnimation | None — default None. Word-level animation style with per-word timestamps. When provided, this takes precedence over the `animation_preset` field.
- words: list[WordSpec] | None — default None. Per-word timing and optional per-word style overrides (§4). Emitted as a top-level `words[]` array; use alongside `motion`/`animation_preset` for the animation. Editorial-emphasis captions = word timings + a styled keyword.
- counter: ValueCounter | None — default None. Rewrite this text from an eased numeric sweep (§4). Takes precedence over countdown on the same element.
- glow: TextGlow | None — default None. Soft glow around the glyphs (§4).
- text_wrap: Literal['wrap', 'nowrap'] — default 'wrap'.
- animation_preset: str | None — default None. Renderer text-animation name (e.g. `'typewriter'`) — a catalog text animation or a `custom_animations.text` entry. Runs for the whole element window with per-glyph timings computed by the renderer. Use `motion[]` (with `type`, `preset` or `custom`) for structured timing control — but not both. Ignored when `word_animation` is set.
### ImageElement (type: "image")
- lut_url: HttpUrl | None — default None.
- lut_intensity: float — default 100.
- brightness: float — default 0. Brightness, -100..100, applied as a 0..2 colour multiplier (0 = no change). `-100` multiplies by 0: the element renders pure black while keeping its alpha — a silhouette of the artwork. Combine a `brightness: -100` copy of an image with `blur`, reduced `opacity` and a small offset, stacked beneath the real one, to fake the content-shaped drop shadow `shadow_x`/`shadow_y` cannot produce.
- contrast: float — default 0.
- saturation: float — default 0.
- exposure: float — default 0.
- sharpness: float — default 0.
- blur: float — default 0.
- noise: float — default 0.
- vignette: float — default 0.
- hue_rotate: float — default 0.
- temperature: float — default 0. White balance warm (+) / cool (−), −1..1; 0 = no-op. Applied as a channel matrix, after the classic brightness/contrast chain.
- tint: float — default 0. White balance magenta (+) / green (−), −1..1; 0 = no-op.
- vibrance: float — default 0. Saturation boost weighted toward muted colours, −1..1; 0 = no-op. Boosts flat colour without wrecking skin tones.
- highlights: float — default 0. Luma-masked tone lift of the brightest range, −1..1; 0 = no-op.
- shadows: float — default 0. Luma-masked tone lift of the darkest range, −1..1; 0 = no-op.
- crop_top: float — default 0.
- crop_bottom: float — default 0.
- crop_left: float — default 0.
- crop_right: float — default 0.
- border_radius: int | float | str | CornerRadiiPx — default 0. Corner radius in pixels — a single value, or per-corner `{top_left, top_right, bottom_right, bottom_left}` for asymmetric corners (e.g. a card rounded only on top). The renderer normalizes px to a 0–1 fraction of the element's shorter side (≈ half the shorter side is fully rounded) and clamps to that range. For shape elements use `corner_radius` (already 0–1).
- border_color: str | None — default None.
- border_width: int | float | str — default 0. Border thickness in pixels (converted to the renderer's relative border scale against the element's shorter side, so it survives resizes). The border outlines the element's border_radius-rounded quad — not the image's alpha silhouette.
- shadow_color: str | None — default None.
- shadow_blur: int | float | str — default 0. Shadow softness, 0–100 (renderer blur-strength scale, not pixels): 0 = hard edge, 100 = maximum blur. Values are clamped to that range.
- shadow_x: int | float | str — default 0. Horizontal shadow offset in pixels (converted to the renderer's relative offset scale). The shadow silhouette is the element's border_radius-rounded quad, not the content alpha — a cut-out PNG gets a card shadow, not an outline-shaped one. On a cut-out that reads as a floating rectangle (rotated with the element, which is the tell). For a shadow that follows the artwork, drop these fields and stack a second copy of the same image underneath at `brightness: -100` (a black silhouette, alpha preserved) with `blur` and reduced `opacity`, offset a few percent — see `brightness`.
- shadow_y: int | float | str — default 0. Vertical shadow offset in pixels. See `shadow_x`.
- blend_mode: BlendMode — default 'none'.
- mask_shape: MaskShape | None — default None.
- mask: MaskConfig | None — default None.
- mask_keyframes: list[MaskKeyframe] | None — default None.
- matte: Matte | None — default None.
- backdrop_blur: int | float | str — default 0. Glass: the scene behind the element, Gaussian-blurred, fills its footprint under its translucent content (a shape's own silhouette, a video's or image's box with its corner radius and mask). A Gaussian sigma in canvas px, as CSS `backdrop-filter: blur()` takes it; the renderer caps it at 128. 0 is off.
- backdrop_blur_keyframes: list[BlurKeyframe] | None — default None. Animate `backdrop_blur` over the timeline; replaces the static value while present.
- layer_blur: float — default 0. Blurs the element itself as drawn: a Gaussian sigma in canvas px, as CSS `filter: blur()` takes it, spreading three sigma past its box. At most 128; 0 is off. Not on a shape yet (the editor's preview cannot draw it), and not with `blend_mode`, `backdrop_blur` or `matte`, beside which the renderer would draw the element without it.
- layer_blur_keyframes: list[BlurKeyframe] | None — default None. Animate `layer_blur` over the timeline; replaces the static value while present.
- glass: Glass | None — default None. A refracting glass edge: the scene behind bends inward near the element's outline. Pair it with `backdrop_blur` for frosted glass.
- x: int | float | str — default '50%'.
- y: int | float | str — default '50%'.
- width: int | float | str — default '100%'. Box width. Together with `height` this is a **cover** box, not a fit box: sized media (video, image) scales to fill it and the overflow is **cropped** — it is never letterboxed. A box whose aspect ratio differs from the source's therefore silently cuts the source's edges. To show a source whole, match the box aspect to it: on a `W`x`H` canvas, for a source of aspect `a`, `width% = a * height% * (H/W)` — e.g. a 1024x1536 asset (a=0.667) on 1920x1080 needs `width% = 0.375 * height%`. Percentages are of the canvas, not the parent.
- height: int | float | str — default '100%'. Box height. See `width` — the pair is a cover box and crops rather than letterboxes. Percentages are of the canvas.
- aspect_ratio: float | None — default None. **Accepted but ignored — the renderer never receives this field.** It does NOT constrain or correct the `width`/`height` box, so it cannot be used to stop a mismatched box from cropping the source; size the box per `width` instead. Kept for backward compatibility.
- x_anchor: int | float | str — default '50%'. Horizontal pivot the element **rotates** about, measured across its own box (`0%` = left edge, `50%` = centre, `100%` = right edge; px values are an offset from the left edge). This is a pivot, not an alignment — `x` always places the element's centre, so the anchor changes nothing on an unrotated element. Honored on video, image and shape; text and the generator elements rotate about their centre and reject a non-default anchor.
- y_anchor: int | float | str — default '50%'. Vertical pivot the element **rotates** about, measured across its own box (`0%` = top edge, `50%` = centre, `100%` = bottom edge). Same rules as `x_anchor`: a pivot, not an alignment.
- x_rotation: int | float | str — default '0°'.
- y_rotation: int | float | str — default '0°'.
- z_rotation: int | float | str — default '0°'.
- x_scale: int | float | str — default '100%'.
- y_scale: int | float | str — default '100%'.
- flip_horizontal: bool — default False.
- flip_vertical: bool — default False.
- opacity: float — default 100.
- z_index: int | None — default None. Stacking order (higher = on top). When omitted, elements stack in array order — later elements render above earlier ones (painter's rule); text defaults one layer above non-text. Set explicit values only when array order isn't the order you want.
- clip: bool — default False.
- color_overlay: str | None — default None. **Not supported by the renderer — setting this is rejected.** A strict submit returns `unsupported_feature` (422) and a dry-run reports it as a blocking violation; there is no native tint field to map it onto. To darken an element use `brightness` (`-100` is a black silhouette); to lay a colour over one, stack a `shape` with a flat or gradient `fill` above it.
- type: Literal['image'] — default 'image'.
- id: str — REQUIRED. **Required.** Unique identifier for this image. An empty or missing ID causes the image to be silently skipped by the renderer.
- name: str | None — default None. Optional human-readable label. Not used by the renderer.
- track: int | None — default None. Timeline track index (0–255). Informational only; not used by the renderer.
- time: float | None — default None. When this element starts on the output timeline, in seconds. Defaults to `0` when omitted.
- visible: bool — default True. Set to `false` to skip this element without removing it from the request.
- locked: bool — default False. Marks the element locked in editors. Not sent to the renderer.
- duration: float — REQUIRED. **Required.** Duration in seconds the image is visible. Omitting this field produces a zero-length window and the image will not appear in the render.
- source_url: HttpUrl — REQUIRED. URL of the image file (PNG, JPG, WebP, GIF, SVG). A `.svg` draws a subset: groups and the basic shapes and paths, filled and stroked with flat colours. An element that uses anything else (a `style` attribute, `clip-path`, `mask`, `filter`, `stroke-dasharray`, a gradient or `currentColor` paint, `<text>`, `<use>`, `<image>`) is not drawn, nor anything inside it; an SVG that would draw nothing at all is refused at submit. Set explicit colours and presentation attributes, or pre-rasterize to PNG.
- effects: list[Effect] — default [].
- motion: list[Motion] — default [].
### ShapeElement (type: "shape")
- blend_mode: BlendMode — default 'none'.
- mask_shape: MaskShape | None — default None.
- mask: MaskConfig | None — default None.
- mask_keyframes: list[MaskKeyframe] | None — default None.
- matte: Matte | None — default None.
- backdrop_blur: int | float | str — default 0. Glass: the scene behind the element, Gaussian-blurred, fills its footprint under its translucent content (a shape's own silhouette, a video's or image's box with its corner radius and mask). A Gaussian sigma in canvas px, as CSS `backdrop-filter: blur()` takes it; the renderer caps it at 128. 0 is off.
- backdrop_blur_keyframes: list[BlurKeyframe] | None — default None. Animate `backdrop_blur` over the timeline; replaces the static value while present.
- layer_blur: float — default 0. Blurs the element itself as drawn: a Gaussian sigma in canvas px, as CSS `filter: blur()` takes it, spreading three sigma past its box. At most 128; 0 is off. Not on a shape yet (the editor's preview cannot draw it), and not with `blend_mode`, `backdrop_blur` or `matte`, beside which the renderer would draw the element without it.
- layer_blur_keyframes: list[BlurKeyframe] | None — default None. Animate `layer_blur` over the timeline; replaces the static value while present.
- glass: Glass | None — default None. A refracting glass edge: the scene behind bends inward near the element's outline. Pair it with `backdrop_blur` for frosted glass.
- x: int | float | str — default '50%'.
- y: int | float | str — default '50%'.
- width: int | float | str — default '100%'. Box width. Together with `height` this is a **cover** box, not a fit box: sized media (video, image) scales to fill it and the overflow is **cropped** — it is never letterboxed. A box whose aspect ratio differs from the source's therefore silently cuts the source's edges. To show a source whole, match the box aspect to it: on a `W`x`H` canvas, for a source of aspect `a`, `width% = a * height% * (H/W)` — e.g. a 1024x1536 asset (a=0.667) on 1920x1080 needs `width% = 0.375 * height%`. Percentages are of the canvas, not the parent.
- height: int | float | str — default '100%'. Box height. See `width` — the pair is a cover box and crops rather than letterboxes. Percentages are of the canvas.
- aspect_ratio: float | None — default None. **Accepted but ignored — the renderer never receives this field.** It does NOT constrain or correct the `width`/`height` box, so it cannot be used to stop a mismatched box from cropping the source; size the box per `width` instead. Kept for backward compatibility.
- x_anchor: int | float | str — default '50%'. Horizontal pivot the element **rotates** about, measured across its own box (`0%` = left edge, `50%` = centre, `100%` = right edge; px values are an offset from the left edge). This is a pivot, not an alignment — `x` always places the element's centre, so the anchor changes nothing on an unrotated element. Honored on video, image and shape; text and the generator elements rotate about their centre and reject a non-default anchor.
- y_anchor: int | float | str — default '50%'. Vertical pivot the element **rotates** about, measured across its own box (`0%` = top edge, `50%` = centre, `100%` = bottom edge). Same rules as `x_anchor`: a pivot, not an alignment.
- x_rotation: int | float | str — default '0°'.
- y_rotation: int | float | str — default '0°'.
- z_rotation: int | float | str — default '0°'.
- x_scale: int | float | str — default '100%'.
- y_scale: int | float | str — default '100%'.
- flip_horizontal: bool — default False.
- flip_vertical: bool — default False.
- opacity: float — default 100.
- z_index: int | None — default None. Stacking order (higher = on top). When omitted, elements stack in array order — later elements render above earlier ones (painter's rule); text defaults one layer above non-text. Set explicit values only when array order isn't the order you want.
- clip: bool — default False.
- color_overlay: str | None — default None. **Not supported by the renderer — setting this is rejected.** A strict submit returns `unsupported_feature` (422) and a dry-run reports it as a blocking violation; there is no native tint field to map it onto. To darken an element use `brightness` (`-100` is a black silhouette); to lay a colour over one, stack a `shape` with a flat or gradient `fill` above it.
- type: Literal['shape'] — default 'shape'.
- id: str — REQUIRED. **Required.** Unique identifier.
- name: str | None — default None. Optional human-readable label. Not used by the renderer.
- track: int | None — default None. Timeline track index (0–255). Informational only; not used by the renderer.
- time: float | None — default None. When this element starts on the output timeline, in seconds. Defaults to `0` when omitted.
- visible: bool — default True. Set to `false` to skip this element without removing it from the request.
- locked: bool — default False. Marks the element locked in editors. Not sent to the renderer.
- duration: float — REQUIRED. **Required.** Seconds the shape is visible.
- path: str | None — default None. SVG path `d` (M L H V C S Q T A Z; elliptical arcs render as arcs). **Required** unless `geometry` is set.
- geometry: ShapeGeometry | None — default None. Draw a closed-form shape instead of a `path`: exactly one of `rect` (`corner_radius` per corner, `smoothing`), `ellipse`, `line`, `ring` or `arc` (`inner_ratio`, `start_angle`, `sweep`, `cap`, `segments`), `polygon` (`sides`, `corner_radius`) or `star` (`points`, `inner_ratio`, `corner_radius`), plus `stroke_align` and `shadows`. Lengths are px, angles degrees clockwise from 3 o'clock. The box, `fill`, `stroke`, `stroke_width`, `stroke_dash`, motion, masks, mattes, blend modes and effects work as on any shape; `path`, `path_keyframes`, `trim`, `corner_radius` and `shadow` do not apply.
- view_box: list[float] — default [0.0, 0.0, 100.0, 100.0]. `[x, y, width, height]` path coordinate space.
- fill: str | Literal['none'] | Gradient — default '#000000'. Fill: a hex colour (alpha ok), `"none"` for outline-only, a Gradient object (`{kind, angle_degrees, center, stops}`, ≥2 stops), or a CSS `linear-gradient(...)` / `radial-gradient(...)` string, which is normalised to the Gradient object at validation — read back, the composition holds the object. A gradient fill on a rectangular path is how you draw a gradient card, bar or pill — there is no separate `gradient` element. The gradient paints the shape's own path, so it fills any silhouette — a triangle, a blob, an icon outline, a morphing path — and layers on the same element with `stroke` / `stroke_width` / `stroke_dash`, `path_keyframes` (morph), `trim` / `trim_keyframes` (draw-on), `blend_mode`, `mask_shape` / `mask` / `mask_keyframes`, `matte` and `backdrop_blur`. `fill_rule`, `corner_radius` and `opacity` behave with a gradient exactly as they do with a flat colour.
- fill_rule: Literal['nonzero', 'evenodd'] — default 'nonzero'.
- stroke: str | None — default None. Stroke colour.
- stroke_width: float | None — default None. Stroke width in viewBox units, at most 100000 (absent = SVG 1.0; 0 disables).
- stroke_linecap: Literal['butt', 'round', 'square'] — default 'round'. Cap on the open ends of a stroked path (SVG `stroke-linecap`): `butt` stops at the endpoint, `round` and `square` extend it by half the stroke width. Closed paths have joins, not caps.
- stroke_linejoin: Literal['miter', 'round', 'bevel'] — default 'round'. Corner join of a stroked path (SVG `stroke-linejoin`): `miter` is the sharp corner (subject to `stroke_miter_limit`), `bevel` cuts it flat.
- stroke_miter_limit: float — default 4.0. SVG `stroke-miterlimit`: miter length over stroke width. A `miter` join sharper than this falls back to `bevel`.
- stroke_dash: list[float] | None — default None. Dash pattern in viewBox units, SVG `stroke-dasharray` semantics: `[on, off, ...]` of any length — an odd-length array repeats so on/off alternate (`[4]` is 4 on, 4 off). Trim applies before dash, so a dashed path can draw itself on without the pattern re-flowing.
- stroke_dash_offset: float — default 0.0. Where the dash pattern starts along the path, in viewBox units (SVG `stroke-dashoffset`): positive shifts the pattern forward, negative backward.
- stroke_dash_offset_keyframes: list[DashOffsetKeyframe] | None — default None. Animate the dash offset (timeline seconds) — marching ants: keyframe `offset` linearly by one dash period (the pattern's sum) per second. Needs a `stroke_dash`; while present it drives the offset in place of the static `stroke_dash_offset`.
- stroke_marker_start: Literal['none', 'triangle', 'open_chevron', 'dot'] — default 'none'. A head at the start of each open subpath, in the stroke's colour (render-node V2.6): `triangle` is filled, its tip on the endpoint (the shaft shortens to meet it); `open_chevron` is an open head stroked like the path; `dot` is a disc. Placed after the trim, so a draw-on keeps its head at the visible end, and left out of the dash. A closed subpath takes none. Needs a `stroke`; path shapes only.
- stroke_marker_end: Literal['none', 'triangle', 'open_chevron', 'dot'] — default 'none'. A head at the end of each open subpath; see `stroke_marker_start`.
- stroke_marker_size: float — default 4.0. Marker length in stroke widths, 1–32 (4 is four times `stroke_width`).
- corner_radius: float | CornerRadii — default 0. Corner radius, normalized 0–1 — a single value or per-corner `{top_left, top_right, bottom_right, bottom_left}`.
- shadow: DropShadow | None — default None. Optional drop shadow. `distance`/`blur` are the renderer's 0–100 strength scale, not pixels — see DropShadow.
- path_keyframes: list[PathKeyframe] | None — default None. Morph the path between keyframes (timeline seconds).
- trim: TrimPath | None — default None. Static trim window: keep only this arc-length fraction of each subpath.
- trim_keyframes: list[TrimKeyframe] | None — default None. Animate the trim window (timeline seconds) — the draw-on: animate `end` 0→1 on a stroked path to draw a signature, underline or chart line. Absent `start`/`end` inherit the static `trim`.
- effects: list[Effect] — default []. Shader effect chain (§6 W3).
- motion: list[Motion] — default [].
### FrameElement (type: "frame")
- x: float | None — default None. Left edge in design px from its parent's left edge (at the root, the `design_size` box's, else the output's). Omitted: 0.
- y: float | None — default None. Top edge in design px from its parent's top edge. Omitted: 0.
- x_anchor: int | float | str | None — default None. Pivot it turns and scales about, across its own box: a percent, or design px from its left edge. Omitted: the centre.
- y_anchor: int | float | str | None — default None. Pivot across its own box's height: a percent, or design px from its top edge. Omitted: the centre.
- z_rotation: int | float | str | None — default None. Rotation in degrees. Omitted: 0.
- x_rotation: int | float | str | None — default None. Perspective tilt (X axis) each element inside takes about its own centre, as a group's does. Omitted: 0.
- y_rotation: int | float | str | None — default None. Perspective tilt (Y axis); see `x_rotation`. Omitted: 0.
- scale: float | None — default None. Uniform scale about the anchor. Omitted: 1.
- opacity: float | None — default None. Opacity 0 to 100 of everything inside. Omitted: 100.
- z_index: int | None — default None. Stacking order among its siblings (higher on top); ties draw in array order. Everything inside draws together at its place.
- duration: float | None — default None. Seconds active. Omitted: until its parent ends.
- motion: list[Motion] — default []. Animations of the whole, about its anchor.
- clip: bool | None — default None. Crop what is inside to its box.
- corner_radius: float | list[float] | GeometryCornerRadii | None — default None. Corner radius of the clip in design px: a number, `[top_left, top_right, bottom_right, bottom_left]` or `{top_left, ...}`. Applies with `clip`.
- blend_mode: BlendMode | None — default None. Blend of its content over what is below. Omitted: normal.
- mask_shape: MaskShape | None — default None. Analytic mask over its box.
- mask: MaskConfig | None — default None. Feather, scale and centre of `mask_shape`.
- matte: Matte | None — default None. Track matte: another element's render drives its coverage.
- effects: list[Effect] — default []. Shader effects run over its content.
- render: Literal['flatten', 'composite'] | None — default None. `composite` makes it a nested composition whose content runs on `time_map`'s clock; its content is graphics only (no video). Omitted: `flatten`.
- time_map: TimeMap | None — default None. A composite's clock: `offset`, `speed`, `loop` and `freeze`. Needs `render: "composite"`.
- type: Literal['frame'] — default 'frame'.
- id: str — REQUIRED. **Required.** Unique in the request; operations, mattes and anchors name it.
- name: str | None — default None. Optional human-readable label. Not used by the renderer.
- track: int | None — default None. Timeline track index (0–255). Informational only; not used by the renderer.
- time: float | None — default None. Start in seconds on its parent's clock (the composition's at the root). Omitted: its parent's start.
- visible: bool — default True. Set to `false` to skip this element without removing it from the request.
- locked: bool — default False. Marks the element locked in editors. Not sent to the renderer.
- width: float | None — default None. Width in design px. Omitted: its parent's width.
- height: float | None — default None. Height in design px. Omitted: its parent's height.
- slot: str | None — default None. In a component body: the slot name an instance's `slots` fill in place of this frame's own children.
- children: list[ChildVideoElement | ChildTextElement | ChildImageElement | ChildShapeElement | FrameElement | InstanceElement] — default []. The elements inside, in design px from this frame's top-left corner; frames and instances nest. Audio stays at the root.
### InstanceElement (type: "instance")
- x: float | None — default None. Left edge in design px from its parent's left edge (at the root, the `design_size` box's, else the output's). Omitted: 0.
- y: float | None — default None. Top edge in design px from its parent's top edge. Omitted: 0.
- x_anchor: int | float | str | None — default None. Pivot it turns and scales about, across its own box: a percent, or design px from its left edge. Omitted: the centre.
- y_anchor: int | float | str | None — default None. Pivot across its own box's height: a percent, or design px from its top edge. Omitted: the centre.
- z_rotation: int | float | str | None — default None. Rotation in degrees. Omitted: 0.
- x_rotation: int | float | str | None — default None. Perspective tilt (X axis) each element inside takes about its own centre, as a group's does. Omitted: 0.
- y_rotation: int | float | str | None — default None. Perspective tilt (Y axis); see `x_rotation`. Omitted: 0.
- scale: float | None — default None. Uniform scale about the anchor. Omitted: 1.
- opacity: float | None — default None. Opacity 0 to 100 of everything inside. Omitted: 100.
- z_index: int | None — default None. Stacking order among its siblings (higher on top); ties draw in array order. Everything inside draws together at its place.
- duration: float | None — default None. Seconds active. Omitted: until its parent ends.
- motion: list[Motion] — default []. Animations of the whole, about its anchor.
- clip: bool | None — default None. Crop what is inside to its box.
- corner_radius: float | list[float] | GeometryCornerRadii | None — default None. Corner radius of the clip in design px: a number, `[top_left, top_right, bottom_right, bottom_left]` or `{top_left, ...}`. Applies with `clip`.
- blend_mode: BlendMode | None — default None. Blend of its content over what is below. Omitted: normal.
- mask_shape: MaskShape | None — default None. Analytic mask over its box.
- mask: MaskConfig | None — default None. Feather, scale and centre of `mask_shape`.
- matte: Matte | None — default None. Track matte: another element's render drives its coverage.
- effects: list[Effect] — default []. Shader effects run over its content.
- render: Literal['flatten', 'composite'] | None — default None. `composite` makes it a nested composition whose content runs on `time_map`'s clock; its content is graphics only (no video). Omitted: `flatten`.
- time_map: TimeMap | None — default None. A composite's clock: `offset`, `speed`, `loop` and `freeze`. Needs `render: "composite"`.
- type: Literal['instance'] — default 'instance'.
- id: str — REQUIRED. **Required.** Its content's ids become `<id>/<child id>`.
- name: str | None — default None. Optional human-readable label. Not used by the renderer.
- track: int | None — default None. Timeline track index (0–255). Informational only; not used by the renderer.
- time: float — REQUIRED. **Required.** Start in seconds on its parent's clock; every time inside the component counts from it.
- visible: bool — default True. Set to `false` to skip this element without removing it from the request.
- locked: bool — default False. Marks the element locked in editors. Not sent to the renderer.
- component: str — REQUIRED. The `components` entry it places.
- variant: str | None — default None. The variant by name. Omitted: the first.
- properties: dict[str, bool | int | float | str] — default {}. Values of the component's declared properties, by name, each of its type.
- slots: dict[str, list[ChildVideoElement | ChildTextElement | ChildImageElement | ChildShapeElement | FrameElement | InstanceElement]] — default {}. Content for the component's slots, by slot name, in place of the slot frame's own children.
### AnimationKeyframe
- time: float — REQUIRED. Fraction of the animation (0–1).
- easing: str | None — default None. Easing into this keyframe — any `easings` catalog name (`quad_out`, `expo_in_out`, `hold`, …). Unknown names are rejected. A `bezier`/`spring`/`back`/`elastic` sub-object overrides it.
- bezier: BezierEasing | None — default None.
- spring: SpringEasing | None — default None.
- back: BackEasing | None — default None.
- elastic: ElasticEasing | None — default None.
- translate: Point | None — default None.
- path: SpatialPath | None — default None. Curve the translate into this keyframe along a cubic bezier (`c1`/`c2` control points).
- scale: float | ScaleXY | None — default None. Uniform scale factor, or `{x, y}` for non-uniform scale.
- rotate: float | None — default None. In-plane (z) rotation, degrees.
- rotation: RotationXYZ | None — default None. Full 3D rotation `{x, y, z}` (degrees); overrides `rotate`. Non-zero x/y = animated perspective tilt.
- opacity: float | None — default None.
- color: str | None — default None. Colour tint at this keyframe (multiplied with the element). An 8-digit hex alpha composes with `opacity` — when both are set, `opacity` wins for the alpha channel.
- blur: float | None — default None. Per-glyph blur amount (fraction of the em). Text registries only.
### AudioGenerator
- feature: Literal['amplitude', 'bass', 'mid', 'high', 'beat'] — default 'amplitude'.
- scale: float — default 0. Scale offset per unit feature.
- opacity: float — default 0. Opacity offset per unit feature.
- translate: Point | None — default None. Translate offset per unit feature.
- rotate: float — default 0. Rotation offset (degrees) per unit feature.
### BackEasing
- overshoot: float — default 1.70158. Overshoot amount; AE default 1.70158.
- dir: Literal['in', 'out'] — default 'out'. 'in' anticipates, 'out' overshoots.
### BezierEasing
- x1: float — default 0.0.
- y1: float — default 0.0.
- x2: float — default 1.0.
- y2: float — default 1.0.
### BlurKeyframe
- time: float — REQUIRED. Timeline seconds.
- value: float — REQUIRED. Gaussian sigma in canvas px at `time`, at most 128.
### ChildImageElement
- lut_url: HttpUrl | None — default None.
- lut_intensity: float — default 100.
- brightness: float — default 0. Brightness, -100..100, applied as a 0..2 colour multiplier (0 = no change). `-100` multiplies by 0: the element renders pure black while keeping its alpha — a silhouette of the artwork. Combine a `brightness: -100` copy of an image with `blur`, reduced `opacity` and a small offset, stacked beneath the real one, to fake the content-shaped drop shadow `shadow_x`/`shadow_y` cannot produce.
- contrast: float — default 0.
- saturation: float — default 0.
- exposure: float — default 0.
- sharpness: float — default 0.
- blur: float — default 0.
- noise: float — default 0.
- vignette: float — default 0.
- hue_rotate: float — default 0.
- temperature: float — default 0. White balance warm (+) / cool (−), −1..1; 0 = no-op. Applied as a channel matrix, after the classic brightness/contrast chain.
- tint: float — default 0. White balance magenta (+) / green (−), −1..1; 0 = no-op.
- vibrance: float — default 0. Saturation boost weighted toward muted colours, −1..1; 0 = no-op. Boosts flat colour without wrecking skin tones.
- highlights: float — default 0. Luma-masked tone lift of the brightest range, −1..1; 0 = no-op.
- shadows: float — default 0. Luma-masked tone lift of the darkest range, −1..1; 0 = no-op.
- crop_top: float — default 0.
- crop_bottom: float — default 0.
- crop_left: float — default 0.
- crop_right: float — default 0.
- border_radius: int | float | str | CornerRadiiPx — default 0. Corner radius in pixels — a single value, or per-corner `{top_left, top_right, bottom_right, bottom_left}` for asymmetric corners (e.g. a card rounded only on top). The renderer normalizes px to a 0–1 fraction of the element's shorter side (≈ half the shorter side is fully rounded) and clamps to that range. For shape elements use `corner_radius` (already 0–1).
- border_color: str | None — default None.
- border_width: int | float | str — default 0. Border thickness in pixels (converted to the renderer's relative border scale against the element's shorter side, so it survives resizes). The border outlines the element's border_radius-rounded quad — not the image's alpha silhouette.
- shadow_color: str | None — default None.
- shadow_blur: int | float | str — default 0. Shadow softness, 0–100 (renderer blur-strength scale, not pixels): 0 = hard edge, 100 = maximum blur. Values are clamped to that range.
- shadow_x: int | float | str — default 0. Horizontal shadow offset in pixels (converted to the renderer's relative offset scale). The shadow silhouette is the element's border_radius-rounded quad, not the content alpha — a cut-out PNG gets a card shadow, not an outline-shaped one. On a cut-out that reads as a floating rectangle (rotated with the element, which is the tell). For a shadow that follows the artwork, drop these fields and stack a second copy of the same image underneath at `brightness: -100` (a black silhouette, alpha preserved) with `blur` and reduced `opacity`, offset a few percent — see `brightness`.
- shadow_y: int | float | str — default 0. Vertical shadow offset in pixels. See `shadow_x`.
- blend_mode: BlendMode — default 'none'.
- mask_shape: MaskShape | None — default None.
- mask: MaskConfig | None — default None.
- mask_keyframes: list[MaskKeyframe] | None — default None.
- matte: Matte | None — default None.
- backdrop_blur: int | float | str — default 0. Glass: the scene behind the element, Gaussian-blurred, fills its footprint under its translucent content (a shape's own silhouette, a video's or image's box with its corner radius and mask). A Gaussian sigma in canvas px, as CSS `backdrop-filter: blur()` takes it; the renderer caps it at 128. 0 is off.
- backdrop_blur_keyframes: list[BlurKeyframe] | None — default None. Animate `backdrop_blur` over the timeline; replaces the static value while present.
- layer_blur: float — default 0. Blurs the element itself as drawn: a Gaussian sigma in canvas px, as CSS `filter: blur()` takes it, spreading three sigma past its box. At most 128; 0 is off. Not on a shape yet (the editor's preview cannot draw it), and not with `blend_mode`, `backdrop_blur` or `matte`, beside which the renderer would draw the element without it.
- layer_blur_keyframes: list[BlurKeyframe] | None — default None. Animate `layer_blur` over the timeline; replaces the static value while present.
- glass: Glass | None — default None. A refracting glass edge: the scene behind bends inward near the element's outline. Pair it with `backdrop_blur` for frosted glass.
- x: float | None — default None. Left edge in design px from the frame's left edge. Omitted: 0.
- y: float | None — default None. Top edge in design px from the frame's top edge. Omitted: 0.
- width: float | None — default None. Width in design px. Omitted: the frame's width.
- height: float | None — default None. Height in design px. Omitted: the frame's height (a text's: twice its `font_size`).
- aspect_ratio: float | None — default None. **Accepted but ignored — the renderer never receives this field.** It does NOT constrain or correct the `width`/`height` box, so it cannot be used to stop a mismatched box from cropping the source; size the box per `width` instead. Kept for backward compatibility.
- x_anchor: int | float | str — default '50%'. Pivot the element turns and scales about, across its own box: a percent, or design px from its left edge.
- y_anchor: int | float | str — default '50%'. Pivot across its own box's height: a percent, or design px from its top edge.
- x_rotation: int | float | str — default '0°'.
- y_rotation: int | float | str — default '0°'.
- z_rotation: int | float | str — default '0°'.
- x_scale: int | float | str — default '100%'.
- y_scale: int | float | str — default '100%'.
- flip_horizontal: bool — default False.
- flip_vertical: bool — default False.
- opacity: float — default 100.
- z_index: int | None — default None. Stacking order among the frame's children (higher on top); ties draw in array order.
- clip: bool — default False.
- color_overlay: str | None — default None. **Not supported by the renderer — setting this is rejected.** A strict submit returns `unsupported_feature` (422) and a dry-run reports it as a blocking violation; there is no native tint field to map it onto. To darken an element use `brightness` (`-100` is a black silhouette); to lay a colour over one, stack a `shape` with a flat or gradient `fill` above it.
- type: Literal['image'] — default 'image'.
- id: str — REQUIRED. **Required.** Unique identifier for this image. An empty or missing ID causes the image to be silently skipped by the renderer.
- name: str | None — default None. Optional human-readable label. Not used by the renderer.
- track: int | None — default None. Timeline track index (0–255). Informational only; not used by the renderer.
- time: float | None — default None. Start in seconds on the clock the frame gives its children (the composition's, unless a composite frame maps it; inside a component, 0 is the instance's start). Omitted: the frame's start.
- visible: bool — default True. Set to `false` to skip this element without removing it from the request.
- locked: bool — default False. Marks the element locked in editors. Not sent to the renderer.
- duration: float | None — default None. Seconds visible. Omitted: until the frame ends.
- source_url: HttpUrl — REQUIRED. URL of the image file (PNG, JPG, WebP, GIF, SVG). A `.svg` draws a subset: groups and the basic shapes and paths, filled and stroked with flat colours. An element that uses anything else (a `style` attribute, `clip-path`, `mask`, `filter`, `stroke-dasharray`, a gradient or `currentColor` paint, `<text>`, `<use>`, `<image>`) is not drawn, nor anything inside it; an SVG that would draw nothing at all is refused at submit. Set explicit colours and presentation attributes, or pre-rasterize to PNG.
- effects: list[Effect] — default [].
- motion: list[Motion] — default [].
### ChildShapeElement
- blend_mode: BlendMode — default 'none'.
- mask_shape: MaskShape | None — default None.
- mask: MaskConfig | None — default None.
- mask_keyframes: list[MaskKeyframe] | None — default None.
- matte: Matte | None — default None.
- backdrop_blur: int | float | str — default 0. Glass: the scene behind the element, Gaussian-blurred, fills its footprint under its translucent content (a shape's own silhouette, a video's or image's box with its corner radius and mask). A Gaussian sigma in canvas px, as CSS `backdrop-filter: blur()` takes it; the renderer caps it at 128. 0 is off.
- backdrop_blur_keyframes: list[BlurKeyframe] | None — default None. Animate `backdrop_blur` over the timeline; replaces the static value while present.
- layer_blur: float — default 0. Blurs the element itself as drawn: a Gaussian sigma in canvas px, as CSS `filter: blur()` takes it, spreading three sigma past its box. At most 128; 0 is off. Not on a shape yet (the editor's preview cannot draw it), and not with `blend_mode`, `backdrop_blur` or `matte`, beside which the renderer would draw the element without it.
- layer_blur_keyframes: list[BlurKeyframe] | None — default None. Animate `layer_blur` over the timeline; replaces the static value while present.
- glass: Glass | None — default None. A refracting glass edge: the scene behind bends inward near the element's outline. Pair it with `backdrop_blur` for frosted glass.
- x: float | None — default None. Left edge in design px from the frame's left edge. Omitted: 0.
- y: float | None — default None. Top edge in design px from the frame's top edge. Omitted: 0.
- width: float | None — default None. Width in design px. Omitted: the frame's width.
- height: float | None — default None. Height in design px. Omitted: the frame's height (a text's: twice its `font_size`).
- aspect_ratio: float | None — default None. **Accepted but ignored — the renderer never receives this field.** It does NOT constrain or correct the `width`/`height` box, so it cannot be used to stop a mismatched box from cropping the source; size the box per `width` instead. Kept for backward compatibility.
- x_anchor: int | float | str — default '50%'. Pivot the element turns and scales about, across its own box: a percent, or design px from its left edge.
- y_anchor: int | float | str — default '50%'. Pivot across its own box's height: a percent, or design px from its top edge.
- x_rotation: int | float | str — default '0°'.
- y_rotation: int | float | str — default '0°'.
- z_rotation: int | float | str — default '0°'.
- x_scale: int | float | str — default '100%'.
- y_scale: int | float | str — default '100%'.
- flip_horizontal: bool — default False.
- flip_vertical: bool — default False.
- opacity: float — default 100.
- z_index: int | None — default None. Stacking order among the frame's children (higher on top); ties draw in array order.
- clip: bool — default False.
- color_overlay: str | None — default None. **Not supported by the renderer — setting this is rejected.** A strict submit returns `unsupported_feature` (422) and a dry-run reports it as a blocking violation; there is no native tint field to map it onto. To darken an element use `brightness` (`-100` is a black silhouette); to lay a colour over one, stack a `shape` with a flat or gradient `fill` above it.
- type: Literal['shape'] — default 'shape'.
- id: str — REQUIRED. **Required.** Unique identifier.
- name: str | None — default None. Optional human-readable label. Not used by the renderer.
- track: int | None — default None. Timeline track index (0–255). Informational only; not used by the renderer.
- time: float | None — default None. Start in seconds on the clock the frame gives its children (the composition's, unless a composite frame maps it; inside a component, 0 is the instance's start). Omitted: the frame's start.
- visible: bool — default True. Set to `false` to skip this element without removing it from the request.
- locked: bool — default False. Marks the element locked in editors. Not sent to the renderer.
- duration: float | None — default None. Seconds visible. Omitted: until the frame ends.
- path: str | None — default None. SVG path `d` (M L H V C S Q T A Z; elliptical arcs render as arcs). **Required** unless `geometry` is set.
- geometry: ShapeGeometry | None — default None. Draw a closed-form shape instead of a `path`: exactly one of `rect` (`corner_radius` per corner, `smoothing`), `ellipse`, `line`, `ring` or `arc` (`inner_ratio`, `start_angle`, `sweep`, `cap`, `segments`), `polygon` (`sides`, `corner_radius`) or `star` (`points`, `inner_ratio`, `corner_radius`), plus `stroke_align` and `shadows`. Lengths are px, angles degrees clockwise from 3 o'clock. The box, `fill`, `stroke`, `stroke_width`, `stroke_dash`, motion, masks, mattes, blend modes and effects work as on any shape; `path`, `path_keyframes`, `trim`, `corner_radius` and `shadow` do not apply.
- view_box: list[float] — default [0.0, 0.0, 100.0, 100.0]. `[x, y, width, height]` path coordinate space.
- fill: str | Literal['none'] | Gradient — default '#000000'. Fill: a hex colour (alpha ok), `"none"` for outline-only, a Gradient object (`{kind, angle_degrees, center, stops}`, ≥2 stops), or a CSS `linear-gradient(...)` / `radial-gradient(...)` string, which is normalised to the Gradient object at validation — read back, the composition holds the object. A gradient fill on a rectangular path is how you draw a gradient card, bar or pill — there is no separate `gradient` element. The gradient paints the shape's own path, so it fills any silhouette — a triangle, a blob, an icon outline, a morphing path — and layers on the same element with `stroke` / `stroke_width` / `stroke_dash`, `path_keyframes` (morph), `trim` / `trim_keyframes` (draw-on), `blend_mode`, `mask_shape` / `mask` / `mask_keyframes`, `matte` and `backdrop_blur`. `fill_rule`, `corner_radius` and `opacity` behave with a gradient exactly as they do with a flat colour.
- fill_rule: Literal['nonzero', 'evenodd'] — default 'nonzero'.
- stroke: str | None — default None. Stroke colour.
- stroke_width: float | None — default None. Stroke width in viewBox units, at most 100000 (absent = SVG 1.0; 0 disables).
- stroke_linecap: Literal['butt', 'round', 'square'] — default 'round'. Cap on the open ends of a stroked path (SVG `stroke-linecap`): `butt` stops at the endpoint, `round` and `square` extend it by half the stroke width. Closed paths have joins, not caps.
- stroke_linejoin: Literal['miter', 'round', 'bevel'] — default 'round'. Corner join of a stroked path (SVG `stroke-linejoin`): `miter` is the sharp corner (subject to `stroke_miter_limit`), `bevel` cuts it flat.
- stroke_miter_limit: float — default 4.0. SVG `stroke-miterlimit`: miter length over stroke width. A `miter` join sharper than this falls back to `bevel`.
- stroke_dash: list[float] | None — default None. Dash pattern in viewBox units, SVG `stroke-dasharray` semantics: `[on, off, ...]` of any length — an odd-length array repeats so on/off alternate (`[4]` is 4 on, 4 off). Trim applies before dash, so a dashed path can draw itself on without the pattern re-flowing.
- stroke_dash_offset: float — default 0.0. Where the dash pattern starts along the path, in viewBox units (SVG `stroke-dashoffset`): positive shifts the pattern forward, negative backward.
- stroke_dash_offset_keyframes: list[DashOffsetKeyframe] | None — default None. Animate the dash offset (timeline seconds) — marching ants: keyframe `offset` linearly by one dash period (the pattern's sum) per second. Needs a `stroke_dash`; while present it drives the offset in place of the static `stroke_dash_offset`.
- stroke_marker_start: Literal['none', 'triangle', 'open_chevron', 'dot'] — default 'none'. A head at the start of each open subpath, in the stroke's colour (render-node V2.6): `triangle` is filled, its tip on the endpoint (the shaft shortens to meet it); `open_chevron` is an open head stroked like the path; `dot` is a disc. Placed after the trim, so a draw-on keeps its head at the visible end, and left out of the dash. A closed subpath takes none. Needs a `stroke`; path shapes only.
- stroke_marker_end: Literal['none', 'triangle', 'open_chevron', 'dot'] — default 'none'. A head at the end of each open subpath; see `stroke_marker_start`.
- stroke_marker_size: float — default 4.0. Marker length in stroke widths, 1–32 (4 is four times `stroke_width`).
- corner_radius: float | CornerRadii — default 0. Corner radius, normalized 0–1 — a single value or per-corner `{top_left, top_right, bottom_right, bottom_left}`.
- shadow: DropShadow | None — default None. Optional drop shadow. `distance`/`blur` are the renderer's 0–100 strength scale, not pixels — see DropShadow.
- path_keyframes: list[PathKeyframe] | None — default None. Morph the path between keyframes (timeline seconds).
- trim: TrimPath | None — default None. Static trim window: keep only this arc-length fraction of each subpath.
- trim_keyframes: list[TrimKeyframe] | None — default None. Animate the trim window (timeline seconds) — the draw-on: animate `end` 0→1 on a stroked path to draw a signature, underline or chart line. Absent `start`/`end` inherit the static `trim`.
- effects: list[Effect] — default []. Shader effect chain (§6 W3).
- motion: list[Motion] — default [].
### ChildTextElement
- border_radius: int | float | str | CornerRadiiPx — default 0. Corner radius in pixels — a single value, or per-corner `{top_left, top_right, bottom_right, bottom_left}` for asymmetric corners (e.g. a card rounded only on top). The renderer normalizes px to a 0–1 fraction of the element's shorter side (≈ half the shorter side is fully rounded) and clamps to that range. For shape elements use `corner_radius` (already 0–1).
- border_color: str | None — default None.
- border_width: int | float | str — default 0. Border thickness in pixels (converted to the renderer's relative border scale against the element's shorter side, so it survives resizes). The border outlines the element's border_radius-rounded quad — not the image's alpha silhouette.
- shadow_color: str | None — default None.
- shadow_blur: int | float | str — default 0. Shadow softness, 0–100 (renderer blur-strength scale, not pixels): 0 = hard edge, 100 = maximum blur. Values are clamped to that range.
- shadow_x: int | float | str — default 0. Horizontal shadow offset in pixels (converted to the renderer's relative offset scale). The shadow silhouette is the element's border_radius-rounded quad, not the content alpha — a cut-out PNG gets a card shadow, not an outline-shaped one. On a cut-out that reads as a floating rectangle (rotated with the element, which is the tell). For a shadow that follows the artwork, drop these fields and stack a second copy of the same image underneath at `brightness: -100` (a black silhouette, alpha preserved) with `blur` and reduced `opacity`, offset a few percent — see `brightness`.
- shadow_y: int | float | str — default 0. Vertical shadow offset in pixels. See `shadow_x`.
- x: float | None — default None. Left edge in design px from the frame's left edge. Omitted: 0.
- y: float | None — default None. Top edge in design px from the frame's top edge. Omitted: 0.
- width: float | None — default None. Width in design px. Omitted: the frame's width.
- height: float | None — default None. Height in design px. Omitted: the frame's height (a text's: twice its `font_size`).
- aspect_ratio: float | None — default None. **Accepted but ignored — the renderer never receives this field.** It does NOT constrain or correct the `width`/`height` box, so it cannot be used to stop a mismatched box from cropping the source; size the box per `width` instead. Kept for backward compatibility.
- x_anchor: int | float | str — default '50%'. Pivot the element turns and scales about, across its own box: a percent, or design px from its left edge.
- y_anchor: int | float | str — default '50%'. Pivot across its own box's height: a percent, or design px from its top edge.
- x_rotation: int | float | str — default '0°'.
- y_rotation: int | float | str — default '0°'.
- z_rotation: int | float | str — default '0°'.
- x_scale: int | float | str — default '100%'.
- y_scale: int | float | str — default '100%'.
- flip_horizontal: bool — default False.
- flip_vertical: bool — default False.
- opacity: float — default 100.
- z_index: int | None — default None. Stacking order among the frame's children (higher on top); ties draw in array order.
- clip: bool — default False.
- color_overlay: str | None — default None. **Not supported by the renderer — setting this is rejected.** A strict submit returns `unsupported_feature` (422) and a dry-run reports it as a blocking violation; there is no native tint field to map it onto. To darken an element use `brightness` (`-100` is a black silhouette); to lay a colour over one, stack a `shape` with a flat or gradient `fill` above it.
- type: Literal['text'] — default 'text'.
- id: str | None — default None. Unique identifier for this element. **Required on image elements** — an empty or missing ID causes the image to be silently skipped by the renderer. Recommended on all elements that are referenced by a transition.
- name: str | None — default None. Optional human-readable label. Not used by the renderer.
- track: int | None — default None. Timeline track index (0–255). Informational only; not used by the renderer.
- time: float | None — default None. Start in seconds on the clock the frame gives its children (the composition's, unless a composite frame maps it; inside a component, 0 is the instance's start). Omitted: the frame's start.
- visible: bool — default True. Set to `false` to skip this element without removing it from the request.
- locked: bool — default False. Marks the element locked in editors. Not sent to the renderer.
- duration: float | None — default None. Seconds visible. Omitted: until the frame ends.
- text: str — REQUIRED. The text content to render.
- font_family: str — default 'Inter'. Font family name. Must be available to the renderer.
- font_size: float — default 16. Font size in pixels.
- font_weight: int — default 400. Font weight (100–900). The renderer has no variable weights: `600` and above render **bold**, everything below renders regular. Composes with `font_style` (italic + ≥600 = bold italic).
- font_style: Literal['normal', 'italic', 'bold', 'bolditalic'] — default 'normal'. Font style variant.
- text_color: str — default '#ffffff'. Text fill color as a hex string.
- text_align: Literal['left', 'center', 'right'] — default 'center'. Horizontal text alignment.
- text_direction: Literal['ltr', 'rtl'] — default 'ltr'. Text direction. `rtl` for right-to-left scripts (§4).
- text_decoration: Literal['none', 'underline', 'strikethrough'] — default 'none'. Text decoration. Only `none` renders. `underline` is reachable only per word — `words[].style.underline` — and `strikethrough` has no renderer path at all; both are rejected here (422) rather than silently dropped. Draw a strike-through as a thin `shape` rectangle over the text.
- tracking: float — default 0. Letter spacing (tracking) in pixels (converted to the renderer's width-relative unit on the wire). Positive values add space between characters.
- tabular_numbers: bool — default False. Tabular (monospaced) figures: every digit takes the same advance, so columns of numbers align across lines and a `counter` does not jitter as its value changes. The renderer's baked fonts carry the OpenType alternates; a font whose face lacks the feature gets synthesised tabular digits in the export only. Default `false` = the font's proportional figures.
- leading: float — default 1.2. Line height (leading) as a multiplier of font size. `1.2` = 20% taller than the font size.
- stroke_color: str | None — default None. Outline color. Set together with `stroke_width` to enable text outlines.
- stroke_width: float — default 0. Outline width, em-relative (fraction of `font_size` — e.g. `0.05` = 5% of the font size). Has no effect unless `stroke_color` is also set.
- background_color: str | None — default None. Secondary colour. Fills the box behind the text when `background` is `true`, **and** is the highlight colour for `word_animation.style` `color` (the active word) and `box` (the box) — those two styles require it.
- background_opacity: float — default 100.
- x_padding: int | float | str — default 0.
- y_padding: int | float | str — default 0.
- background: bool — default False. Solid color box behind the full text block. Set `background_color` to choose the color.
- background_style: Literal['block', 'line_hard', 'line_round'] — default 'block'. Shape of the `background` plate: `block` — one box behind the whole text; `line_hard` — a square-cornered box behind each line; `line_round` — a rounded box behind each line. Requires `background: true`. An animation that centres its words draws the `block` plate whichever style is set.
- stroke: bool — default False. Outline-only mode — draws the glyph stroke with no fill. Requires `stroke_color` and `stroke_width`. When `false`, setting `stroke_color` + `stroke_width` gives fill + stroke (outlined).
- shadow: bool — default False. Built-in drop shadow.
- motion: list[Motion] — default [].
- word_animation: WordAnimation | None — default None. Word-level animation style with per-word timestamps. When provided, this takes precedence over the `animation_preset` field.
- words: list[WordSpec] | None — default None. Per-word timing and optional per-word style overrides (§4). Emitted as a top-level `words[]` array; use alongside `motion`/`animation_preset` for the animation. Editorial-emphasis captions = word timings + a styled keyword.
- counter: ValueCounter | None — default None. Rewrite this text from an eased numeric sweep (§4). Takes precedence over countdown on the same element.
- glow: TextGlow | None — default None. Soft glow around the glyphs (§4).
- text_wrap: Literal['wrap', 'nowrap'] — default 'wrap'.
- animation_preset: str | None — default None. Renderer text-animation name (e.g. `'typewriter'`) — a catalog text animation or a `custom_animations.text` entry. Runs for the whole element window with per-glyph timings computed by the renderer. Use `motion[]` (with `type`, `preset` or `custom`) for structured timing control — but not both. Ignored when `word_animation` is set.
### ChildVideoElement
- lut_url: HttpUrl | None — default None.
- lut_intensity: float — default 100.
- brightness: float — default 0. Brightness, -100..100, applied as a 0..2 colour multiplier (0 = no change). `-100` multiplies by 0: the element renders pure black while keeping its alpha — a silhouette of the artwork. Combine a `brightness: -100` copy of an image with `blur`, reduced `opacity` and a small offset, stacked beneath the real one, to fake the content-shaped drop shadow `shadow_x`/`shadow_y` cannot produce.
- contrast: float — default 0.
- saturation: float — default 0.
- exposure: float — default 0.
- sharpness: float — default 0.
- blur: float — default 0.
- noise: float — default 0.
- vignette: float — default 0.
- hue_rotate: float — default 0.
- temperature: float — default 0. White balance warm (+) / cool (−), −1..1; 0 = no-op. Applied as a channel matrix, after the classic brightness/contrast chain.
- tint: float — default 0. White balance magenta (+) / green (−), −1..1; 0 = no-op.
- vibrance: float — default 0. Saturation boost weighted toward muted colours, −1..1; 0 = no-op. Boosts flat colour without wrecking skin tones.
- highlights: float — default 0. Luma-masked tone lift of the brightest range, −1..1; 0 = no-op.
- shadows: float — default 0. Luma-masked tone lift of the darkest range, −1..1; 0 = no-op.
- crop_top: float — default 0.
- crop_bottom: float — default 0.
- crop_left: float — default 0.
- crop_right: float — default 0.
- border_radius: int | float | str | CornerRadiiPx — default 0. Corner radius in pixels — a single value, or per-corner `{top_left, top_right, bottom_right, bottom_left}` for asymmetric corners (e.g. a card rounded only on top). The renderer normalizes px to a 0–1 fraction of the element's shorter side (≈ half the shorter side is fully rounded) and clamps to that range. For shape elements use `corner_radius` (already 0–1).
- border_color: str | None — default None.
- border_width: int | float | str — default 0. Border thickness in pixels (converted to the renderer's relative border scale against the element's shorter side, so it survives resizes). The border outlines the element's border_radius-rounded quad — not the image's alpha silhouette.
- shadow_color: str | None — default None.
- shadow_blur: int | float | str — default 0. Shadow softness, 0–100 (renderer blur-strength scale, not pixels): 0 = hard edge, 100 = maximum blur. Values are clamped to that range.
- shadow_x: int | float | str — default 0. Horizontal shadow offset in pixels (converted to the renderer's relative offset scale). The shadow silhouette is the element's border_radius-rounded quad, not the content alpha — a cut-out PNG gets a card shadow, not an outline-shaped one. On a cut-out that reads as a floating rectangle (rotated with the element, which is the tell). For a shadow that follows the artwork, drop these fields and stack a second copy of the same image underneath at `brightness: -100` (a black silhouette, alpha preserved) with `blur` and reduced `opacity`, offset a few percent — see `brightness`.
- shadow_y: int | float | str — default 0. Vertical shadow offset in pixels. See `shadow_x`.
- blend_mode: BlendMode — default 'none'.
- mask_shape: MaskShape | None — default None.
- mask: MaskConfig | None — default None.
- mask_keyframes: list[MaskKeyframe] | None — default None.
- matte: Matte | None — default None.
- backdrop_blur: int | float | str — default 0. Glass: the scene behind the element, Gaussian-blurred, fills its footprint under its translucent content (a shape's own silhouette, a video's or image's box with its corner radius and mask). A Gaussian sigma in canvas px, as CSS `backdrop-filter: blur()` takes it; the renderer caps it at 128. 0 is off.
- backdrop_blur_keyframes: list[BlurKeyframe] | None — default None. Animate `backdrop_blur` over the timeline; replaces the static value while present.
- layer_blur: float — default 0. Blurs the element itself as drawn: a Gaussian sigma in canvas px, as CSS `filter: blur()` takes it, spreading three sigma past its box. At most 128; 0 is off. Not on a shape yet (the editor's preview cannot draw it), and not with `blend_mode`, `backdrop_blur` or `matte`, beside which the renderer would draw the element without it.
- layer_blur_keyframes: list[BlurKeyframe] | None — default None. Animate `layer_blur` over the timeline; replaces the static value while present.
- glass: Glass | None — default None. A refracting glass edge: the scene behind bends inward near the element's outline. Pair it with `backdrop_blur` for frosted glass.
- x: float | None — default None. Left edge in design px from the frame's left edge. Omitted: 0.
- y: float | None — default None. Top edge in design px from the frame's top edge. Omitted: 0.
- width: float | None — default None. Width in design px. Omitted: the frame's width.
- height: float | None — default None. Height in design px. Omitted: the frame's height (a text's: twice its `font_size`).
- aspect_ratio: float | None — default None. **Accepted but ignored — the renderer never receives this field.** It does NOT constrain or correct the `width`/`height` box, so it cannot be used to stop a mismatched box from cropping the source; size the box per `width` instead. Kept for backward compatibility.
- x_anchor: int | float | str — default '50%'. Pivot the element turns and scales about, across its own box: a percent, or design px from its left edge.
- y_anchor: int | float | str — default '50%'. Pivot across its own box's height: a percent, or design px from its top edge.
- x_rotation: int | float | str — default '0°'.
- y_rotation: int | float | str — default '0°'.
- z_rotation: int | float | str — default '0°'.
- x_scale: int | float | str — default '100%'.
- y_scale: int | float | str — default '100%'.
- flip_horizontal: bool — default False.
- flip_vertical: bool — default False.
- opacity: float — default 100.
- z_index: int | None — default None. Stacking order among the frame's children (higher on top); ties draw in array order.
- clip: bool — default False.
- color_overlay: str | None — default None. **Not supported by the renderer — setting this is rejected.** A strict submit returns `unsupported_feature` (422) and a dry-run reports it as a blocking violation; there is no native tint field to map it onto. To darken an element use `brightness` (`-100` is a black silhouette); to lay a colour over one, stack a `shape` with a flat or gradient `fill` above it.
- type: Literal['video'] — default 'video'.
- id: str | None — default None. Unique identifier for this element. **Required on image elements** — an empty or missing ID causes the image to be silently skipped by the renderer. Recommended on all elements that are referenced by a transition.
- name: str | None — default None. Optional human-readable label. Not used by the renderer.
- track: int | None — default None. Timeline track index (0–255). Informational only; not used by the renderer.
- time: float | None — default None. Start in seconds on the clock the frame gives its children (the composition's, unless a composite frame maps it; inside a component, 0 is the instance's start). Omitted: the frame's start.
- visible: bool — default True. Set to `false` to skip this element without removing it from the request.
- locked: bool — default False. Marks the element locked in editors. Not sent to the renderer.
- source_url: HttpUrl — REQUIRED. URL of the video file — MP4, MOV or WebM only; any other extension is rejected at submit. Must be accessible by the renderer.
- in_point: float | None — default None. In point — seconds into the source file to start playing from. Defaults to `0`.
- out_point: float | None — default None. Out point — seconds into the source file to stop playing. Defaults to end of source when omitted. Controls clip length on the timeline.
- speed: float — default 1.0. Playback speed. `1.0` = normal speed, `2.0` = 2× (half duration), `0.5` = half speed (double duration).
- playback_rate_keyframes: list[RateKeyframe] | None — default None. Speed ramp (§5c): piecewise-linear playback-rate keyframes (absolute timeline seconds; rate 0 = freeze; at most 512 keyframes — the renderer truncates beyond that). Audio keeps the static rate — mute or detach it on ramped clips.
- volume: float — default 100. Embedded audio volume as a percentage (0–100). Affects only the audio track inside this video clip.
- muted: bool — default False. Silence the clip's embedded audio. `volume` is kept, so unmuting restores the level.
- loop: bool — default False. Repeat the source to fill the clip: when playback passes the end of the file it restarts from the file's first frame (not `in_point`). Set `out_point` past the source's length to choose how long the clip runs — its timeline length is still `(out_point − in_point) / speed`. Requires `out_point`.
- fade_in_duration: float — default 0. Duration in seconds of a linear audio fade-in at the clip's start.
- fade_out_duration: float — default 0. Duration in seconds of a linear audio fade-out at the clip's end.
- effects: list[Effect] — default [].
- motion: list[Motion] — default [].
### ChromaKeyProps
- key_color: str — default '#00FF00'. The colour to key out. Green-screen green by default.
- threshold: float — default 0.1. Chroma distance from `key_color` below which a pixel is fully transparent. Raise it if fringes of the screen survive.
- smoothness: float — default 0.15. Width of the ramp from transparent to opaque, starting at `threshold`. Raise it to soften hard edges; 0 gives a hard cut.
- spill_suppress: float — default 0.5. How strongly surviving pixels near the key colour are pulled toward their own luma, removing green spill on hair and edges. 0 disables.
### Component
- id: str — REQUIRED. What an instance's `component` names.
- width: float — REQUIRED. Box width in design px.
- height: float — REQUIRED. Box height in design px.
- clip: bool | None — default None. Its instances clip to the box unless they say otherwise.
- corner_radius: float | list[float] | GeometryCornerRadii | None — default None. Its instances' clip corner radius in design px.
- properties: list[ComponentProperty] — default []. What an instance can set.
- children: list[ChildVideoElement | ChildTextElement | ChildImageElement | ChildShapeElement | FrameElement | InstanceElement] | None — default None. The body of a single-variant component, in design px from the box's top-left corner. Give this or `variants`.
- operations: OperationsBlock | None — default None. The body's operations (beside `children`); groups count from `instance.start` unless they say otherwise.
- variants: list[ComponentVariant] | None — default None. Named bodies, the first the default. Give this or `children`.
### ComponentProperty
- name: str — REQUIRED. A letter, then letters, digits or `_`.
- type: Literal['text', 'colour', 'number', 'boolean', 'media', 'component', 'variant'] — REQUIRED. `text`, `colour` (`#RRGGBB` or `#RRGGBBAA`), `number`, `boolean`, `media` (a URL), `component` (an id from `allowed`) or `variant` (a nested instance's).
- bind: list[str] — REQUIRED. Body fields it writes, as `<child id>.<field>` in this API's field names: any element's `x`, `y`, `z_rotation`, `opacity` and `visible`; a frame's or instance's `scale` and `clip`; a text's `text`, `text_color` and `font_size`; a shape's `fill`, `stroke` and `stroke_width`; an image's or video's `source_url`; an instance's `component`, `variant` and `properties.<name>`.
- default: bool | int | float | str | None — default None. Its value when an instance sets none. Omitted: the body's own.
- min: float | None — default None. A `number` property's lowest value.
- max: float | None — default None. A `number` property's highest value.
- allowed: list[str] | None — default None. The component ids a `component` property may swap in. Required on one.
### ComponentVariant
- name: str — REQUIRED.
- width: float | None — default None. Its box width in design px. Omitted: the component's.
- height: float | None — default None. Its box height in design px. Omitted: the component's.
- children: list[ChildVideoElement | ChildTextElement | ChildImageElement | ChildShapeElement | FrameElement | InstanceElement] — default []. Its body, in design px from the box's top-left corner.
- operations: OperationsBlock | None — default None. Its operations; groups count from `instance.start` unless they say otherwise.
### CornerRadii
- top_left: float — default 0.
- top_right: float — default 0.
- bottom_right: float — default 0.
- bottom_left: float — default 0.
### CornerRadiiPx
- top_left: int | float | str — default 0.
- top_right: int | float | str — default 0.
- bottom_right: int | float | str — default 0.
- bottom_left: int | float | str — default 0.
### CustomAnimation
- name: str — REQUIRED. Reference name (reserved/catalog-shadowing names are rejected).
- keyframes: list[AnimationKeyframe] — REQUIRED.
- group: Literal['block', 'word', 'glyph'] — default 'block'. What the animation repeats over: the whole text block, each word, or each glyph. Required for `selector` to shape anything — a selector over a single block has nothing to range across. Text registries only.
- selector: RangeSelector | None — default None. AE-style range selector: shape this animation's amount by position along the text (§4, W2). Set `group` to `word` or `glyph` alongside it. Text registries only.
### CustomAnimationRegistry
- element: list[CustomAnimation] — default [].
- text: list[CustomAnimation] — default [].
### DashOffsetKeyframe
- time: float — REQUIRED. Timeline seconds.
- offset: float — REQUIRED. Dash offset at this time, in viewBox units (SVG `stroke-dashoffset`).
- easing: Easing | None — default None. Ease into this keyframe.
- spring: SpringEasing | None — default None.
- back: BackEasing | None — default None.
- elastic: ElasticEasing | None — default None.
- bezier: BezierEasing | None — default None.
### DesignSize
- width: float — REQUIRED. Width in design px.
- height: float — REQUIRED. Height in design px.
### DropShadow
- color: str — REQUIRED.
- distance: float — default 0. Shadow offset **strength**, 0–100 on the renderer's own scale — **not pixels**. The rendered offset is `distance × 0.0005 × the element's shorter side`, so on a 400px-tall card `60` drops the shadow 12px while a px-looking `8` drops it 1.6px, and on a 200px chip that same `8` is 0.8px — invisible. Author 60–70 (what the reference scenes use) and it scales with the element; for a specific N px offset use `distance = N ÷ (0.0005 × shorter_side_px)`. Must be > 0: distance 0 is skipped by the renderer entirely. For pixel-unit shadows use `shadow_x`/`shadow_y` on video/image elements.
- direction: float — default 90. Shadow direction in degrees (polar; 90 = down).
- blur: float — default 0. Shadow softness, 0–100 on the renderer's blur-strength scale — **not** a pixel radius, and unlike `distance` it does not scale with the element. `0` is a hard-edged offset copy (a legitimate poster look); 60–70 is the soft card shadow the reference scenes author. A px-looking `8` is a near-hard edge, not an 8px feather.
### EaseBack
- back: BackEasing — REQUIRED.
### EaseBezier
- bezier: list[float] — REQUIRED. `[x1, y1, x2, y2]`, as CSS `cubic-bezier`.
### EaseElastic
- elastic: ElasticEasing — REQUIRED.
### EaseFamily
- family: Literal['smooth', 'natural', 'slowdown', 'accelerate', 'overshoot', 'anticipate', 'anticipate_overshoot', 'spring', 'elastic', 'bounce', 'impulse', 'throw'] — REQUIRED. The curve's character.
- intensity: float — REQUIRED. How strongly, 0 to 100.
### EaseSpring
- spring: SpringEasing — REQUIRED.
### Effect
- type: EffectType | None — default None. The effect from the vocabulary (`effects` in GET /v1/capabilities). Omit it beside `shader`.
- intensity: float | None — default 50. Effect strength, 0 to 100. On a shader effect it is null unless set: the shader then runs at the engine's own full intensity rather than the effect-wide 50.
- intensity_keyframes: list[IntensityKeyframe] | None — default None. Animate intensity over time (§2): piecewise-linear `[{time, value}]` in timeline seconds. Overrides the static `intensity` when set.
- props: dict[str, float] | None — default None. Per-shader scalar props (§2), bound as `u_prop_<key>` (e.g. `{"speed": 0.6}` for aurora). Ignored for chroma_key (use `chroma_settings`).
- chroma_settings: ChromaKeyProps | None — default None.
- shader: EffectShader | None — default None. A runtime shader in place of `type` (render-node AEC §2): `{id, params}`, with `intensity` beside it and nothing else. Authoring: `shaders` in GET /v1/capabilities.
### EffectShader
- id: str — REQUIRED. The shader's id (`sh_...`): one of this workspace's or a shared one (GET /v1/shaders).
- params: dict[str, float | str | list[float] | list[ShaderParamKeyframe]] — default {}. Values of the shader's declared params by name: a number (`float`), "#RRGGBBAA" (`color`) or [x, y] (`vec2`), or keyframes `[{time, value}]` in timeline seconds. A param left out takes its declared default.
### ElasticEasing
- amplitude: float — default 1.0. Ring amplitude.
- period: float — default 0.3. Ring period as a fraction of the segment.
- dir: Literal['in', 'out'] — default 'out'. 'in' rings before, 'out' after.
### GeometryCornerRadii
- top_left: float | None — default None.
- top_right: float | None — default None.
- bottom_right: float | None — default None.
- bottom_left: float | None — default None.
### GeometryEllipse
### GeometryLine
- x1: float | None — default None.
- y1: float | None — default None.
- x2: float | None — default None.
- y2: float | None — default None.
### GeometryPolygon
- sides: int | None — default None. Vertices. Omitted: 5.
- corner_radius: float | None — default None. Rounds every vertex with an arc of this radius in px. Omitted: 0.
### GeometryRect
- corner_radius: float | list[float] | GeometryCornerRadii | None — default None. Corner radius in px: one number for all four corners, `[top_left, top_right, bottom_right, bottom_left]`, or `{top_left, top_right, bottom_right, bottom_left}` (missing corners 0). Omitted: square corners.
- smoothing: float | None — default None. Figma's corner smoothing, 0 to 1: above 0 the corners ease into the edges (a squircle at 1). Omitted: 0, the plain rounded rect.
### GeometryRing
- inner_ratio: float | None — default None. The hole's share of the radius, 0–1 (0 is a pie). Omitted: 0.
- inner_ratio_percent: float | None — default None. `inner_ratio` as a percent (85 is 0.85).
- start_angle: float | None — default None. Where the sweep starts, degrees, 0 at 3 o'clock, clockwise. Omitted: 0.
- sweep: float | None — default None. Degrees drawn clockwise from `start_angle`. Omitted: 360. With `segments` the sweep is theirs, so leave it out.
- sweep_percent: float | None — default None. `sweep` as a percent of the full circle (100 = 360°).
- cap: Literal['butt', 'round'] | None — default None. Ends of a partial sweep. Omitted: `butt`.
- segments: list[GeometrySegment] | None — default None. Consecutive solid slices (at most 32, together at most 360°) drawn as one shape, so abutting slices leave no seam.
### GeometrySegment
- sweep: float | None — default None. Slice angle in degrees.
- sweep_percent: float | None — default None. Slice as a percent of the full circle (100 = 360°).
- fill: str — REQUIRED. The slice's solid colour.
### GeometryShadow
- type: Literal['drop', 'inner'] | None — default None. Omitted: `drop`.
- x: float | None — default None. Horizontal offset in px.
- y: float | None — default None. Vertical offset in px, down positive.
- blur: float | None — default None. CSS blur radius in px (sigma = blur / 2).
- spread: float | None — default None. Spread in px.
- color: str — REQUIRED.
### GeometryStar
- points: int | None — default None. Outer vertices. Omitted: 5.
- inner_ratio: float | None — default None. The inner vertices' share of the outer ellipse. Omitted: 0.382, a regular pentagram's.
- corner_radius: float | None — default None. Rounds every vertex with an arc of this radius in px. Omitted: 0.
### Glass
- bevel: float | None — default None. Width of the bent band at the edge in canvas px, at most 256. Omitted: 16.
- refraction: float | None — default None. How far the edge bends the scene inward, 0–1. Omitted: 0.5.
- dispersion: float | None — default None. How far red and blue split apart at the edge, 0–1. Omitted: 0.
### Gradient
- kind: Literal['linear', 'radial', 'conic'] — default 'linear'. `conic` sweeps the stops clockwise once round `center`, starting at `angle_degrees`.
- angle_degrees: float — default 0. Linear gradient angle in degrees, measured clockwise on the screen (y down): 0 = left→right (offset 0 at the left), 90 = top→bottom, 45 = top-left→bottom-right, 315 = bottom-left→top-right, and the same convention governs a shape's gradient `fill`. A numeric CSS angle is box-relative: `135deg` behaves as `to bottom right` whatever the card's shape; only 0/90/180/270 are pixel-exact. On a conic gradient: where the sweep starts, degrees clockwise from 3 o'clock.
- center: Point | None — default None. Radial focus point as fractions of the fill's box — the element box for a shape's gradient fill, the canvas for the background. `y` runs down the screen, as CSS `at` does: `{x: 0.5, y: 0}` is the top edge and `{x: 0.5, y: 1}` the bottom (CSS `at 50% 100%`). Defaults to the centre; ignored for linear gradients. The renderer's radial is an ellipse inscribed in the box, reaching the last stop at the corners: it keeps that centred radius when the focus moves, rather than re-deriving it from the focus the way CSS `farthest-corner` does, so an off-centre focus imported from CSS completes its ramp earlier than a browser shows it. A CSS `circle` is drawn as that same ellipse, so it only comes out round on a square box. A conic gradient sweeps round this point.
- stops: list[GradientStop] — REQUIRED. Two or more colour stops.
### GradientStop
- offset: float — REQUIRED. Position along the gradient, 0–1.
- color: str — REQUIRED. Stop colour (hex, alpha supported).
### Group
- id: str — REQUIRED. **Required.** Unique group id.
- parent: str | None — default None. Parent group id for nesting.
- pivot: Point — default Point(x=0.5, y=0.5). Rotation/scale pivot.
- translate: Point | None — default None. Group translation (normalized).
- scale: float — default 1.0. Group scale.
- rotation_degrees: float — default 0.0. In-plane (z) rotation of the group.
- x_rotation: int | float | str — default '0°'. Perspective tilt (X axis) applied to each member's orientation about its own centre — the tilted card-gallery look.
- y_rotation: int | float | str — default '0°'. Perspective tilt (Y axis). See `x_rotation`.
- opacity: float — default 1.0. Group opacity.
- members: list[str] — default []. Member element uuids.
- animations: list[Motion] — default []. Animations driving the whole group about `pivot`. Translate, scale, rotation and colour all compose — that is how you move or resize a whole scene as one unit. Two channels do NOT: a preset that animates **clip** (`wipe_left/right/up/down`) or **crop** (`ken_burns_*`) is a silent no-op on a group, doing nothing at all rather than erroring — put those on a member element instead. Non-uniform scale is also flattened here: only the x component of a `custom_animations` `scale` keyframe is used, so `{x:2,y:1}` scales uniformly. Note `zoom_out` barely moves (scale 1.0->0.9 under a full fade), so it reads as a pure fade; for a real shrink use a `custom` entry with the scale travel you want, or the group's static `scale`.
- layout: StackLayout | None — default None. Optional stack layout.
### IntensityKeyframe
- time: float — REQUIRED. Absolute timeline seconds.
- value: float — REQUIRED. Effect intensity 0–1 at this time.
### MaskConfig
- feather: float — default 0. Soften the mask's SDF edge.
- scale: float — default 1.0. Mask scale (iris reveals).
- center: Point | None — default None. Mask centre (wipes).
### MaskKeyframe
- time: float — REQUIRED. Timeline seconds.
- feather: float | None — default None.
- scale: float | None — default None.
- center: Point | None — default None.
- easing: str | None — default None. Easing curve name — any `easings` catalog value (`linear`, `hold`, `ease_in_out`, `quad_out`, `expo_in_out`, `square_in_out` = step, …). Unknown names are rejected: the engine would silently fall back to linear. For spring/back/elastic/bezier use the sub-objects instead.
- spring: SpringEasing | None — default None.
- back: BackEasing | None — default None.
- elastic: ElasticEasing | None — default None.
- bezier: BezierEasing | None — default None.
### Matte
- source: str — REQUIRED. uuid of the source layer (auto-hidden). Text sources supported.
- mode: Literal['alpha', 'luma'] — default 'alpha'.
- invert: bool — default False.
### Motion
- type: MotionType | None — default None. Catalog preset. Exactly one of `type`, `preset` or `custom` must be set.
- preset: str | None — default None. Renderer animation name, used verbatim — any element animation on video/image/shape/group (e.g. `'pop'`, `'floatUp'`, `'out-slideBounceLeft'`, `'loop-heartBeat'`), any text animation on text (e.g. `'typewriter'`, `'roll'`, `'out-sink'`, `'loop-wavey'`). Reaches the presets `type` has no name for. The name carries its own direction: `out-*` names are exits, `loop-*` names loop with `duration` as one cycle, so `reversed` and `scope` do not apply. Exactly one of `type`, `preset` or `custom` must be set.
- custom: str | None — default None. Name of a `custom_animations` entry to run instead of a catalog preset — the `element` registry for video/image/shape/group animations, the `text` registry for text. Exactly one of `type`, `preset` or `custom` must be set.
- time: float — REQUIRED. Absolute start time on the output timeline in seconds. For entrances and loops set this to the element's `time`. For exits set this to element `time + duration − motion duration`. An entrance timed later than the element's own `time` leaves it fully rendered on screen until the entrance fires; the linter reports that as `ENTRANCE_AFTER_ELEMENT_START`.
- duration: float — REQUIRED. How long the animation runs in seconds.
- easing: Easing — default 'ease_in_out'. **Ignored by the renderer** — animation curves are baked into the preset's keyframes (or your `custom_animations` keyframes' `easing`). Kept for backward compatibility only.
- reversed: bool — default False. Run the preset's exit form instead of its entrance. Only presets that ship both forms accept it — `fade`, `slide_*`, `wipe_*`, `rotate_*`, `bounce`. Entrance-only presets have a separate exit-only type instead: use `zoom_out` (not `zoom_in` reversed), `evaporate` (not `blur`), `whip_down`, `drift_out`, `swing_out`, `elastic_drop` — those six set this flag for you. See `GET /v1/capabilities` `motion[].element_exit` for the per-preset truth.
- scope: MotionScope — default 'element'.
- delay: float — default 0. Seconds to wait before the animation starts (folded into the animation's start time on the wire — the engine has no standalone pre-start delay). On loop presets it spaces the repeats instead.
- spacing: float | None — default None. Stagger multiplier between per-glyph/word windows on text animations (engine default 1 = fully sequential; smaller values overlap the windows). Ignored by block animations.
- loop: bool — default False.
- audio: AudioGenerator | None — default None. Audio-reactive offsets (§3). Element animations only (video/image/shape/group) — the engine does not run the generator on text animations; put the text in an audio-reactive group instead. For a pure generator with no visible motion, use `type: "identity"`, the engine's no-op carrier.
### MotionBlur
- samples: int — REQUIRED. Temporal samples per frame (2–32).
- shutter: float — default 0.5. Shutter fraction of the frame interval, (0–1]. (Exactly 0 is rejected: it renders N identical samples — full cost, zero blur.)
### Operation
- id: str | None — default None. A stable id for editors.
- target: str — REQUIRED. The element id it drives; with a `child` split, a frame's.
- start: float — REQUIRED. Seconds after the group's anchor.
- end: float — REQUIRED. Seconds after the group's anchor; equal to `start` switches at once.
- property: str — REQUIRED. A property registry path: `position.x`, `size.y`, `scale`, `rotation`, `opacity`, `fill`, `geometry.ring.segments[0].sweep`, `text.value`, …; a colour takes `.r`/`.g`/`.b`/`.a`. GET /v1/capabilities lists every path, its unit and range under `registry.properties`.
- from: float | str | None — default None. Value at `start` (a string on `text.value`). Omitted on a replace: the value below it at `start`; on an add or multiply: the identity.
- to: float | str | None — default None. Value at `end`, held after it. Omitted on a replace: the live base value; on an add or multiply: the identity.
- easing: Easing | EaseFamily | EaseBezier | EaseSpring | EaseBack | EaseElastic | None — default None. A curve name (`ease_in_out`, `hold`, …), `{family, intensity}`, or one of `{bezier: [x1, y1, x2, y2]}`, `{spring}`, `{back}`, `{elastic}`. Omitted: linear.
- composite: Literal['replace', 'add', 'multiply'] | None — default None. `replace` overrides what is below it from `start`; `add` and `multiply` stack on it (multiply on scale, opacity and colours). Omitted: `replace`.
- split: OperationSplit | None — default None. Run it per child, letter, word or line, staggered.
- takeover: Literal['velocity'] | None — default None. On a replace without `from`: start at the speed of what it replaces.
### OperationAnchor
- ref: Literal['composition', 'element.start', 'element.end', 'marker', 'instance.start'] — REQUIRED. `composition` (0 s), `element.start` or `element.end` of `target`, a marker by `name`, or `instance.start` of `target` (in a component, its own instance).
- target: str | None — default None. The element or instance an element or instance anchor reads.
- name: str | None — default None. The marker a `marker` anchor reads.
- offset: float | None — default None. Seconds added to the anchor. Omitted: 0.
### OperationGroup
- id: str | None — default None. A stable id for editors.
- name: str | None — default None. A label, e.g. `Animate in`.
- role: str | None — default None. What the group is for in editors (`in`, `out`, `loop`, …). Not sent to the renderer.
- anchor: OperationAnchor | None — default None. Where its times count from. Required in the request's `operations`; a component's groups default to `instance.start`.
- ops: list[Operation | PresetOperation] — REQUIRED. Operations and presets in document order: at equal starts the later replace wins.
### OperationMarker
- name: str — REQUIRED.
- time: float — REQUIRED. Seconds on the composition clock.
### OperationSplit
- unit: Literal['element', 'child', 'letter', 'word', 'line'] — REQUIRED. `child` runs over a frame's children; `letter`, `word` and `line` over a text's.
- stagger: float | None — default None. Seconds between units. Omitted: 0.
- order: Literal['forward', 'reverse', 'centre', 'edges', 'seeded'] | None — default None. The order the units take their turns in. Omitted: `forward`.
### OperationsBlock
- markers: list[OperationMarker] — default []. Named times `marker` anchors read.
- groups: list[OperationGroup] — default []. At most 1000 groups and 10000 operations.
### PathKeyframe
- time: float — REQUIRED. Timeline seconds for this path.
- d: str — REQUIRED. SVG path `d` at this time.
- easing: Easing | None — default None. Ease into this keyframe. A spring/back/elastic/bezier sub-object overrides it — overshooting eases visibly overshoot the *geometry* and settle back.
- spring: SpringEasing | None — default None.
- back: BackEasing | None — default None.
- elastic: ElasticEasing | None — default None.
- bezier: BezierEasing | None — default None.
### Point
- x: float — default 0.5.
- y: float — default 0.5.
### PresetOperation
- id: str | None — default None. A stable id for editors.
- target: str — REQUIRED. The element id it drives; with a `child` split, a frame's.
- start: float — REQUIRED. Seconds after the group's anchor.
- end: float — REQUIRED. Seconds after the group's anchor; equal to `start` switches at once.
- preset: Literal['arcRise', 'bounceIn', 'drop', 'elasticRise', 'fade', 'floatDown', 'floatLeft', 'floatRight', 'floatUp', 'gentleFloatDown', 'gentleFloatLeft', 'gentleFloatRight', 'gentleFloatUp', 'identity', 'kenBurnsIn', 'kenBurnsInOut', 'kenBurnsOut', 'loop-3DSpin', 'loop-3DSway', 'loop-bounce', 'loop-heartBeat', 'loop-jiggle', 'loop-orbit', 'loop-rotateBasic', 'loop-rotateSmooth', 'loop-squeezy', 'loop-sway', 'out-bounceOut', 'out-dropOut', 'out-elasticDrop', 'out-fade', 'out-floatDown', 'out-floatLeft', 'out-floatRight', 'out-floatUp', 'out-gentleFloatDown', 'out-gentleFloatLeft', 'out-gentleFloatRight', 'out-gentleFloatUp', 'out-pop', 'out-slideBounceDown', 'out-slideBounceLeft', 'out-slideBounceRight', 'out-slideBounceUp', 'out-slideDown', 'out-slideLeft', 'out-slideRight', 'out-slideUp', 'out-spinAntiClockwise', 'out-spinClockwise', 'out-swingOut', 'out-wipeDown', 'out-wipeLeft', 'out-wipeRight', 'out-wipeUp', 'out-zoomOut', 'pop', 'slideBounceDown', 'slideBounceLeft', 'slideBounceRight', 'slideBounceUp', 'slideDown', 'slideLeft', 'slideRight', 'slideUp', 'smoothPop', 'spinAntiClockwise', 'spinClockwise', 'springPop', 'swingIn', 'tiltZoom', 'wipeDown', 'wipeLeft', 'wipeRight', 'wipeUp', 'zoomIn'] — REQUIRED. An element preset by the engine's name (`slideUp`, `zoomIn`, `fade`, …). Text presets stay on a text's `motion`.
### RangeSelector
- based_on: Literal['glyph', 'word'] — default 'glyph'.
- start: float — default 0.0. Range start, fraction along the text.
- end: float — default 1.0. Range end, fraction along the text.
- falloff: float — default 0.0. Ease to zero over this fraction beyond each edge.
- ease: str | None — default None. Easing curve name for the falloff.
- invert: bool — default False.
### RateKeyframe
- time: float — REQUIRED. Timeline seconds.
- rate: float — REQUIRED. Playback rate (0 = freeze-frame).
### RotationXYZ
- x: float — default 0.0.
- y: float — default 0.0.
- z: float — default 0.0.
### ScaleXY
- x: float — default 1.0.
- y: float — default 1.0.
### ShaderParamKeyframe
- time: float — REQUIRED. Absolute timeline seconds.
- value: float | str | list[float] — REQUIRED. The param's value at this time, of its type.
### ShapeGeometry
- rect: GeometryRect | None — default None.
- ellipse: GeometryEllipse | None — default None.
- line: GeometryLine | None — default None.
- ring: GeometryRing | None — default None.
- arc: GeometryRing | None — default None. The same parameters as `ring`.
- polygon: GeometryPolygon | None — default None.
- star: GeometryStar | None — default None.
- stroke_align: Literal['inside', 'center', 'outside'] | None — default None. Where the stroke sits on the outline (`centre` is read as `center`). Omitted: `center`. A polygon, a star and a smoothed rect stroke centred.
- shadows: list[GeometryShadow] | None — default None. Up to 4 shadows, the first on top, on a rect or an ellipse drawn as a circle.
### SpatialPath
- c1: Point — REQUIRED.
- c2: Point — REQUIRED.
### SpringEasing
- stiffness: float — default 100.0. Stiffness; higher lowers zeta, so the spring rings more.
- damping: float — default 10.0. Damping; higher raises zeta (less overshoot), lower rings longer.
- mass: float — default 1.0. Mass; like stiffness, higher lowers zeta, so the spring rings more. It does not swing slower: the segment's duration sets the timing.
### StackLayout
- type: Literal['stack'] — default 'stack'.
- direction: Literal['row', 'column'] — default 'row'.
- gap: float — default 0. Gap between members, normalized along the main axis.
- align: Literal['start', 'center', 'end'] — default 'center'.
- origin: Point | None — default None. Centre of the whole stack.
### TextGlow
- color: str — REQUIRED.
- size: float — default 0.15. Glow size, em-relative.
- intensity: float — default 1.0. Glow intensity.
### TimeMap
- offset: float | None — default None. Seconds into the children's timeline at the frame's start. Omitted: 0.
- speed: float | None — default None. Rate of the children's timeline: 0 holds, below 0 plays backwards. Omitted: 1.
- loop: float | None — default None. Seconds after which the children's timeline repeats. Omitted: no loop.
- freeze: float | None — default None. Hold the children at this many seconds into their timeline; overrides `offset` and `speed`.
### TrimKeyframe
- time: float — REQUIRED. Timeline seconds.
- start: float | None — default None.
- end: float | None — default None.
- easing: Easing | None — default None. Ease into this keyframe.
- spring: SpringEasing | None — default None.
- back: BackEasing | None — default None.
- elastic: ElasticEasing | None — default None.
- bezier: BezierEasing | None — default None.
### TrimPath
- start: float — default 0. Trim start, 0–1 along the path.
- end: float — default 1. Trim end, 0–1 along the path.
### ValueCounter
- from_value: float — default 0. Start value.
- to_value: float — default 100. End value.
- decimals: int — default 0. Decimal places (0–6).
- prefix: str — default ''. Text prepended to the number.
- suffix: str — default ''. Text appended to the number, e.g. '%'.
- easing: str | None — default None. Easing curve name from the `easings` catalog (e.g. 'quad_out', 'expo_out'). Only named curves apply here — the parameterized spring/back/elastic families are not available on the counter.
- start_time: float — default 0. Seconds into the element to start the sweep.
- length: float | None — default None. Sweep duration; defaults to the element's remaining life.
### Word
- text: str — REQUIRED.
- start: float — REQUIRED. ABSOLUTE output-timeline seconds (not element-relative).
- end: float — REQUIRED. ABSOLUTE output-timeline seconds (not element-relative).
### WordAnimation
- style: WordAnimationStyle — REQUIRED.
- words: list[Word] — REQUIRED.
### WordSpec
- word: str — REQUIRED. The word (whole-word match; UTF-8).
- start: float — REQUIRED. Word reveal start, seconds — drives a word-group animation; ignored without one.
- end: float — REQUIRED. Word reveal end, seconds — drives a word-group animation; ignored without one.
- style: WordStyle | None — default None. Optional per-word style override (static for the element's life).
### WordStyle
- color: str | None — default None.
- bold: bool | None — default None.
- italic: bool | None — default None.
- underline: bool | None — default None.
### Enums
- BlendMode: none, multiply, screen, overlay, darken, lighten, color_dodge, color_burn, hard_light, soft_light, difference, add, exclusion, hue, saturation, color, luminosity
- Easing: linear, hold, ease_in, ease_out, ease_in_out, sin_in, sin_out, sin_in_out, square_in, square_out, square_in_out, expo_in, expo_out, expo_in_out, quad_in, quad_out, quad_in_out, cubic_in, cubic_out, cubic_in_out, quart_in, quart_out, quart_in_out, quint_in, quint_out, quint_in_out
- EffectType: vintage, polaroid, portra, super8, filmic, add_grain, rgb_split, ghosting, displacement_map, posterize, mosaic, mosaic_blur, mosaic_posterize, cc_halftone, cc_halftone_blue, cc_halftone_green, cc_halftone_red, invert, optics_compensation, viewfinder, night_vision, thermal, camera_lens_blur, camera_lens_blur_bg, box_blur, lens_flare, strobe_light, snow, glow, sepia, echo, chromatic_aberration, vhs, vhs_overlay, crt, television, glitch, compression_glitch, scanlines, prism, light_leaks, film_burn, duotone, cross_process, bleach_bypass, chroma_key, aurora
- MaskShape: circle, diamond, hexagon, star, heart, triangle
- MotionScope: element, character
- MotionType: identity, fade, slide_up, slide_down, slide_left, slide_right, zoom_in, zoom_out, rotate_cw, rotate_ccw, bounce, wipe_left, wipe_right, wipe_up, wipe_down, ken_burns_in, ken_burns_out, ken_burns_in_out, loop_wiggle, loop_rotate, loop_rotate_smooth, loop_3d_spin, loop_3d_sway, blur, evaporate, overlay, difference, rubber_in, whip_up, whip_down, glitch_pop, drift_in, drift_out, loop_breathe, loop_shimmer, swing_in, swing_out, elastic_rise, elastic_drop, tilt_zoom, loop_orbit, smooth_pop
- OutputFormat: mp4, webm, mov, gif, png, jpg
- TransitionType: cross_dissolve, dip_to_black, dip_to_white, wipe_left, wipe_right, wipe_up, wipe_down, diagonal_wipe, barn_doors_horizontal, barn_doors_vertical, iris, page_turn, cross_zoom, gradient_wipe, band_wipe, box_wipe, swirl, glitch_memories, window_slice, cube, doorway, pinwheel, water_drop, crosshatch, dreamy, angular, burn, heart, circle_open, color_phase, squares_wire, whip_pan, cinematic_zoom, burn_edge, shatter, domain_warp, circle_crop, cross_warp, fold_horizontal, fold_vertical, linear_blur, minimise_bottom_left, minimise_bottom_right, minimise_top_left, minimise_top_right, ripple, rotate, splice, three_stripes
- WordAnimationStyle: glow, box, scale_pop, slide_up, fly_in, color