add_text_layer
Create a new text layer — a first-class leaf that animates, groups, and z-orders exactly like an image or shape. The renderer draws live typeset text (multi-line, auto-fit to the box). Defaults: x/y = canvas centre, width 900, height 320, font_family "Anton", text_size derived from existing text layers (or ~10% of canvas height). Also accepts full type styling: font_weight (100-900), font_style (italic), text_transform, letter_spacing, line_height, text_align, text_autofit ("hug" default = box shrink-wraps the text at the fixed text_size, honouring literal newlines, so it can't re-wrap between preview and export — bake your own "\n" line breaks / "wrap"=fixed size + word-wrap to the box / "fit"=auto-size to fill the box, grows and shrinks / "shrink"=legacy shrink-only), text_valign (top/middle/bottom), an outline (stroke_width + stroke_color), and text_shadow. Returns the new layer's id + element id (text.).
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| x | No | Centre x in canvas px. Defaults to canvas centre. | |
| y | No | Centre y in canvas px. Defaults to canvas centre. | |
| text | No | The text to render. Newlines are honoured as hard line breaks. | |
| block | No | OPTIONAL timeline window — {start, duration} in composition frames. OMIT IT (the default) and the layer is ALWAYS PRESENT: a persistent overlay that holds for the whole composition, which is what an agent-placed watermark / lower-third almost always wants. Pass it to place a bounded CLIP instead (what the editor's own add does: 5 s at the playhead). Keyframes on a blocked layer are sampled RELATIVE to `start`. | |
| curve | No | Curve the text onto an arc, in degrees of total sweep. 0 = straight (default). POSITIVE = a SMILE (⌣, ends rise); NEGATIVE = an ARCH (⌒, rainbow). Clamped ±135. A tasteful smile is ~+60. Single line only (multi-line is joined while curved). | |
| width | No | Box width in px (> 0). Default 900. | |
| height | No | Box height in px (> 0). Default 320. | |
| projectId | Yes | Opaque project id (a v4 UUID, from list_projects/create_project). Selects which existing project this call mutates. | |
| text_size | No | Font size in px. Omit to derive from existing text layers (median) or the canvas height. | |
| font_style | No | Italic toggle. Default normal. | |
| text_align | No | Horizontal alignment of each line. Default center. | |
| text_color | No | Text fill colour as #rrggbb. Defaults to white. | |
| decorations | No | Per-character underline / strikethrough. { underline?: [{start,end}], strikethrough?: [{start,end}] } — half-open character ranges [start,end) (UTF-16 offsets) into `text`. E.g. underline the first word of "Big news": underline:[{start:0,end:3}]. Ranges are normalized (sorted + merged). Not rendered on curved text. | |
| font_family | No | Google Fonts family name, e.g. "Anton". Default "Anton". | |
| font_weight | No | Font weight 100..900 (400 regular, 700 bold, 800 black). Default 400. | |
| line_height | No | Line height as a multiple of font size (1.2 = 120%). | |
| text_shadow | No | Drop shadow { offsetX, offsetY, blur, color }; color is any CSS colour (rgba allowed). null clears it. | |
| text_valign | No | Vertical alignment of the text block within its box. "middle" (default) centres it; "bottom" pins it to the box floor so extra wrapped lines grow upward from a fixed baseline (captions use this so a wrapped line doesn't shift the others); "top" pins the ceiling. | |
| stroke_color | No | Outline colour as #rrggbb. Defaults to white when a width is set. | |
| stroke_width | No | Outline width in px (0 = no outline). | |
| text_autofit | No | How text fits its box. "hug" (default for new layers): hold text_size FIXED and DERIVE the box from the measured text plus padding, honouring the literal newlines you pass — the box shrink-wraps the exact content and grows/shrinks live as the text changes, so it can never re-wrap differently between the editor preview and the export (bake your own "\n" breaks; pair with set_text_background for a rounded caption box). "wrap": hold text_size FIXED in a fixed-size box and only word-wrap (hard-breaking a single over-wide word), never resize. "fit": ignore text_size and auto-size the font BOTH ways (grow and shrink) to the largest size whose wrapped block fills the box — resizing the box resizes the text. "shrink" (legacy): word-wrap then auto-shrink the font from text_size until the block fits; never grows. | |
| letter_spacing | No | Tracking between glyphs in px; may be negative. Default 0. | |
| text_transform | No | Case transform applied before layout. Default none. |