Skip to main content
Tella Motion lets an agent or a script build motion graphics in a Tella video: animated titles, shapes, charts, lower thirds, transitions and effects. You build them in a Tella Motion document with the same commands the Tella Motion editor uses, and the video plays the document as a clip, an overlay or b-roll. Every MCP tool has a REST endpoint under /v1/motion that takes the same arguments.

Commands

Every command and op a batch takes, with fields and examples.

Properties, easing and fonts

Property names and units, easing curves, blend modes and fonts.

Effects

All effect kinds and their parameters.

MCP tools and REST endpoints

REST requests use your API key as a bearer token (see Authentication). The full request and response shapes are under Tella Motion in the API reference.

How a Tella Motion document works

A document is a timeline of nodes on a canvas:
  • Canvas: a size in pixels, a frame rate and a length. A new document is as large as the video and 10 seconds long. Change it with the canvas.set op, or shrink an overlay to its content with fitCanvas.
  • Nodes: titles (text), shapes, paths, media (video and images), audio, groups, sequences (nodes that play one after another, like clips on a track) and composition instances. Each node has an id, a start and a duration, and paints over the nodes before it.
  • Compositions: reusable sub-timelines. An instance plays one; editing a composition changes every instance.
  • Clocks: a node’s times are on the clock of the composition it sits in. For nodes on the canvas, that is the document’s own time from 0.
  • Revision: every saved batch increases the document’s seq. Pass the seq you read as baseRevision and a batch is refused if someone changed the document since, in the editor or through the API.
Document IDs start with ffd_. Node IDs are unique in the document, so commands name a node by its ID alone.

Units

Show a document in a video

A video plays a document in one of three ways. Each plays it live: an edit to the document shows in the video at once, so you can time it to the speech where it plays and keep refining it. In apply_video_edits, add_media_overlay also takes motionDocumentId. Reading a clip’s overlays or layouts back reports Tella Motion media as type: "motion" with its document’s ID (motionDocumentId on overlays, media.documentId on layouts). Tella Motion media in the media library is a frozen snapshot: placing it makes a new document of the video’s.

Draft a document before it is in a video

Leave out videoId in create_motion_document and the document is yours, in no video yet. Build it as usual, then place it with create_clip (documentId), add_overlay (motionDocumentId) or a layout’s motion media. The first video you place it in takes it over, and it keeps its ID. From then on it belongs to that video like any other document, and no other video can use it. A copy keeps its document’s owner, so to use a draft in more than one video, copy it with duplicate_motion_document before you place it, then place each copy in its own video. To turn it into a video of its own, call create_clip with documentId and no videoId. It makes a new video as large as the document’s canvas, with one clip that plays it.
A document no video plays yet has no page in Tella. To see it, use get_motion_frame or get_motion_preview, which render the document on its own.

Build a title card, step by step

This builds an animated intro title as a clip of its own. The same steps work for an overlay or b-roll once you have its document. 1. Add a Tella Motion clip. It plays a blank document of its own.
The response has the clip’s clipId and its document, whose id (ffd_…) the next calls use. 2. Read the document with get_motion_document (GET /v1/motion/documents/{id}) for its canvas size and seq. 3. Apply a batch of edits. This sets the length, adds a background, a title and a subtitle, animates them in and adds a glow, as one transaction:
4. Check the result by looking at a frame: get_motion_frame with the document’s ID and a startTimeMs (REST: GET /v1/motion/documents/{id}/thumbnail?startTimeMs=1500). To see it as the video shows it, with its layout and the clip it plays on, use get_clip_frame with the clip’s ID (REST: GET /v1/videos/{id}/clips/{clipId}/thumbnail?startTimeMs=1500). 5. Reuse the design. duplicate_motion_document copies it and can change the copy in the same call, e.g. [{"type": "setTitle", "node": "title", "text": "Pricing"}], for the next section’s title.

Apply a batch of edits

apply_motion_editor_commands (REST: POST /v1/motion/documents/{id}/commands) takes 1 to 256 items, applied in order as one transaction and one undo step: nothing applies unless everything does. Each item is either:
  • A command, the editor’s own actions, with a camelCase type: titles, shapes, paths and media; split, trim, ripple delete, speed and transitions; In/Out animations, keyframes and easing on any property; effects, masks and track mattes; groups; time remapping; wiggle and loop expressions; per-character, word or line text animation; curves and bindings; fades and ducking. Commands keep the editor’s conventions, so the result stays editable in the editor like a hand edit.
  • An op, what the document stores, with a dotted type: node.patch for any field, node.insert, node.move, canvas.set, assets, compositions and more. Ops take raw render timeline values.
Prefer a command for anything the editor does, and use ops for the rest. Tella Motion commands lists all of them with their fields and an example each.
  • Name nodes yourself with nodeId when you add them, so later items in the same batch can refer to them. Left out, an ID is generated and returned in affected.created.
  • Check without saving with dryRun: true.
  • Guard a batch with an expect item: it fails the batch when a node or a property’s value is not what you expect.
  • Get exact schemas from get_motion_schema with schema: "edits" and a type, e.g. addTitle or node.patch (REST: GET /v1/motion/schema?schema=edits&type=addTitle). Without type it returns every edit (about 180 KB).

The batch result

The title card batch above returns:
seq is the new revision to pass as the next baseRevision. A notes array appears when an edit applied with an adjustment worth knowing, such as a font drawing the nearest weight it has, or the rectangle to place an overlay at after fitCanvas.

Errors

A failed call returns {"ok": false, "error": {"code", "message"}}. For a batch, the message starts with the failing item’s index (command 3: …) and nothing is applied. Over REST, errors use the API’s standard error body and these statuses:

Tella Motion clips

A Tella Motion clip plays its document instead of a recording, so it has no layouts, cuts, zooms or transcript, and the tools that edit those refuse it. update_clip renames it, reorder_clip moves it and delete_clip removes it; what it shows is edited on its document. The clip lasts as long as its document’s canvas. Overlays still work on top of it: the overlay, text overlay and sound effect tools (and their apply_video_edits operations) accept a Tella Motion clip. Their times are on the clip’s own clock, from the start of its document, and they draw above the document. list_motion_documents lists a clip’s document with the clip’s ID as its sceneID.

list_motion_documents

GET /v1/motion/documents?storyId=vid_…. Returns documents, newest first: the video’s Tella Motion clips’ documents and the documents its overlays and b-roll play. Without storyId, your documents that no video plays yet. Each has its id, name, scope (story for a video’s, user for yours), ownerID (the video, or you) and, for a clip’s document, sceneID (the clip).
string
The video (vid_…) whose documents to list. Leave it out for your documents that no video plays yet.

create_motion_document

POST /v1/motion/documents, returns 201 with document. Its canvas is as large as the video unless sized (1920×1080 without a video), and 10 s long; the canvas.set op changes that. It is not put in the media library.
string
The video (vid_…) that owns the document. Leave it out for a document of your own that no video plays yet: the first video it is placed in takes it over.
string
required
What it shows, e.g. Lower third.
number
Canvas width in pixels, 16–7680.
number
Canvas height in pixels, 16–7680.

create_clip

POST /v1/motion/clips (no type: it always adds a Tella Motion clip), returns 201. The clip lasts as long as its document and appears in the open editor at once. To add a clip from a recording or an uploaded file, use upload_clip.
string
The video (vid_…) to add the clip to. Required unless you pass documentId; leave it out with documentId to make a new video.
enum<string>
required
motion, the only type so far. MCP only.
string
required
The clip’s name, e.g. Intro title, and the new video’s when there is no videoId.
string
A document of yours that no video plays yet (ffd_…), for the clip to play instead of a blank one. The video takes it over. Without videoId, it makes a new video as large as the document’s canvas.
Returns the new clip’s clipId and its document, and, when it made a new video, its videoId and editUrl.

duplicate_motion_document

POST /v1/motion/documents/{id}/duplicate, returns 201. The copy has the same owner (a video’s stays that video’s, one of yours that no video plays yet stays yours) and is independent: later edits to either do not reach the other. Returns the copy as document and, with commands, the batch’s result as applied.
string
required
The document to copy (ffd_…). In the REST path.
string
required
The copy’s name, e.g. Topic title: Pricing.
array
1–256 edits to run on the copy, as apply_motion_editor_commands takes them, e.g. setTitle on its title node.

get_motion_document

GET /v1/motion/documents/{id}. The canvas, the outline of its nodes (IDs, types, windows in seconds, what they show, paint order, transitions), its compositions and assets, the editor’s names, colours, mute, solo and locks, and seq.
string
required
The document (ffd_…).

inspect_motion_node

GET /v1/motion/documents/{id}/nodes/raw?path=…. One node with every stored field, its window, the composition it sits in, and for an instance the outline of the composition it plays. Use it before a node.patch.
string
required
The document (ffd_…).
string
required
The node’s ID (or path) from the document’s outline, e.g. title.

inspect_motion_node_properties

GET /v1/motion/documents/{id}/nodes?path=…&at=…. A node as the editor’s inspector shows it at a time: every animatable property with its unit, range, value and keys (with their IDs, times, values and easing), its effect stack and expressions, its style (blend, flips, shadow), title or shape settings, and audio fades. Read a node this way before changing its look, animation or sound.
string
required
The document (ffd_…).
string
required
The node’s ID (or path).
number
Seconds on the node’s composition clock. Defaults to the node’s start.

inspect_motion_composition

GET /v1/motion/documents/{id}/compositions/{compositionId}. Editing a composition changes every instance that plays it.
string
required
The document (ffd_…).
string
required
The composition asset’s ID.

download_motion_document

GET /v1/motion/documents/{id}/download. The whole stored document (formatVersion, name, timeline with every node, composition and asset, and editor state) and its seq. It is large: save it and pull out what you need with a tool such as jq. Its shape is get_motion_schema with schema: "document". Times are ticks (timeline.canvas.ticksPerSecond).
string
required
The document (ffd_…).

get_motion_schema

GET /v1/motion/schema?schema=…&type=…. JSON Schemas, generated from the same code that validates edits.
enum<string>
required
edits: one item of an apply_motion_editor_commands batch, every command and op (about 180 KB; select one with jq '.oneOf[] | select(.properties.type.const == "addTitle")'), or with type that one edit’s small, self-contained schema. document: a document as download_motion_document returns it (about 160 KB).
string
With edits: one op or command, e.g. node.patch or addTitle.

apply_motion_editor_commands

POST /v1/motion/documents/{id}/commands. See Apply a batch of edits and Tella Motion commands.
string
required
The document (ffd_…). In the REST path.
array
required
1–256 commands and ops, each with a type.
integer
The seq you read. The batch is refused (REST: 409) if the document has changed since.
boolean
Check the batch without saving it.

get_motion_frame

GET /v1/motion/documents/{id}/thumbnail. A rendered frame of the document on its own, at a time on its own clock, for any document you can edit, also one no video plays yet. For jpg, png or webp, returns inline image content plus a signed URL; for gif, the signed URL only. To see the document as a video shows it (its layout, other clips), use get_clip_frame. Over REST it returns a 302 redirect to the signed URL, or {"url"} with ?response=json, like GET /v1/videos/{id}/thumbnail. Every edit to the document gets a new render. Both tools refuse a document that plays media you can’t access with forbidden (REST: 403).
string
required
The document (ffd_…). In the REST path.
enum<string>
jpg (default), png, webp, or gif
integer
The frame’s time in ms from the document’s start (default 0). At or past its end, its last frame.
integer
Duration in ms when format is gif
integer
Output width in pixels (range 1–1920, default 320). Omit height to keep the canvas’s aspect ratio.
integer
Output height in pixels (range 1–1920). Derived from the canvas’s aspect ratio when omitted.

get_motion_preview

GET /v1/motion/documents/{id}/thumbnail?format=mp4. An MP4 preview of the document on its own, with its sound, for any document you can edit, also one no video plays yet. It returns a signed url and waits for the render as get_clip_preview does: status: "ready" means the URL downloads immediately, and status: "rendering" means call again with the same arguments to keep waiting, for about 3 minutes in total.
string
required
The document (ffd_…). In the REST path.
integer
Preview start in ms from the document’s start (default 0)
integer
Preview duration in ms (default 5000, range 500–30000)
integer
1, 2, 5, 10, or 30 (default 30)
integer
Output width in pixels (range 1–1920, default 320). Omit height to keep the canvas’s aspect ratio.
integer
Output height in pixels (range 1–1920). Derived from the canvas’s aspect ratio when omitted.

list_motion_media

GET /v1/motion/documents/{id}/media. Each item has the mediaId the addMedia command places. To place a photo, video or sound that isn’t in the document yet, pass addMedia its sourceId instead: a source from create_source, a chat attachment or a library item’s. Tella reads from the upload whether it is an image, a video or a sound and adds it as one.
string
required
The document (ffd_…).

list_motion_fonts

GET /v1/motion/fonts. No parameters. Each font comes with its slug, its family and the weights it can draw as weights: {min, max}. The list is also in Properties, easing and fonts. A title takes any weight from 100 (thin) to 900 (black) in addTitle and setTitle. When the font can’t draw that weight (a family that tops out at 700, or one that ships as a single weight), the edit still applies, draws the nearest weight the font has, and returns a note saying which weight it draws.

list_motion_effects

GET /v1/motion/effects?kind=…&preset=…. Without parameters, each effect kind comes with its parameters’ names, types, ranges, units and defaults, and its presets by name and description. presetsKeep names the parameters no preset sets: they keep their value when a preset is applied or switched, and a preset sets every other one. The list is also in Tella Motion effects. addEffect and setEffect apply a preset by name, with any params you pass on top. To see the values a preset sets, pass kind, and preset for one of them.
string
One effect kind, e.g. fx.liquidGlass. The response is effect: that kind, with each preset’s values where they differ from the kind’s defaults.
string
With kind: one of its presets, e.g. regularLight. The response’s effect.params is every value it sets.
Last modified on October 27, 2026