Skip to content

Projects and commands

A project is one timeline document, and the only way to change it is a list of commands run through the same reducer the editor uses.

The project#

A project is an edit document: output settings (aspect ratio, width, height, frame rate, background), a list of tracks, and a list of clips. Clips are top-level in the document, each pointing at the track it sits on with trackIndex. A clip is video, audio, image, text, captions or a shape, with a start and duration in seconds on the timeline.

Read one with GET /v1/projects/{id}. The default clips view summarises every clip; ?view=document returns the document verbatim, exactly what the editor and the renderer read.

Commands#

You never write the document directly. You send commands, and the server applies them with the same reducer the web editor, the phone app and the MCP server use:

JSON
{
  "commands": [
    { "op": "addClip", "type": "video", "src": "https://api.vidmoat.com/uploads/clip.mp4", "start": 0, "duration": 6, "trackIndex": 0 },
    { "op": "addTextClip", "text": "Shipped from the API", "start": 0.4, "duration": 3, "trackIndex": 1, "style": { "fontSize": 72 }, "patch": { "y": -220 } }
  ]
}

GET /v1/schema/commands lists every op and its parameters. It is the same schema the editor validates against: if an op is not in there, it does not exist.

How a batch is applied#

  • Commands run in order, one to 200 per request.
  • Each command succeeds or fails on its own. A failure is reported in results[] (ok: false with an error), not as an HTTP error. The batch is saved when at least one command succeeded, so read ok and results, not only the status code.
  • A feature the plan does not include (scripting, for example) is dropped and listed in blocked; the rest still applies.
  • If the project changed while the batch ran, nothing is saved and you get 409 with conflictCode: "stale_rev". Re-read the project and send the batch again.
  • The call is not idempotent. A retried batch adds its clips a second time. After a timeout, re-read the project before deciding to resend.

Check before you save#

  • "dryRun": true on POST /v1/projects/{id}/commands runs the batch and saves nothing.
  • POST /v1/projects/{id}/validate does the same with only a read scope, so a read-only key can check a program.
  • Both return lint (overlapping text, off-canvas elements, unreadable sizes) and suggestedPreviewTimes. Look at those frames with the preview endpoint before you render.

Workspaces#

A workspace is a folder for projects: a client, a series, a campaign. It is not a team; a team decides who can see a project, a workspace decides what body of work it belongs to. File a project with PUT /v1/projects/{id}/workspace, list a folder with GET /v1/projects?workspace=<id>. Deleting a workspace never deletes the projects in it. Workspaces use the projects scopes.