/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.setop, or shrink an overlay to its content withfitCanvas. - 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 theseqyou read asbaseRevisionand a batch is refused if someone changed the document since, in the editor or through the API.
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 outvideoId 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.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:
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.patchfor any field,node.insert,node.move,canvas.set, assets, compositions and more. Ops take raw render timeline values.
- Name nodes yourself with
nodeIdwhen you add them, so later items in the same batch can refer to them. Left out, an ID is generated and returned inaffected.created. - Check without saving with
dryRun: true. - Guard a batch with an
expectitem: it fails the batch when a node or a property’s value is not what you expect. - Get exact schemas from
get_motion_schemawithschema: "edits"and atype, e.g.addTitleornode.patch(REST:GET /v1/motion/schema?schema=edits&type=addTitle). Withouttypeit 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.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 gifinteger
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 gifinteger
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.