Core concepts
Five objects underlie everything in Motionpit. Once you understand how they relate, the API surface is obvious.
Format
A format is the template — the full video definition. It holds:
- An ordered op list (the timeline): a sequence of block ops and transition ops.
- A brand kit reference (logo, colors, music).
- A parameter binding table: the named API variables the format exposes and where in the op list each one writes.
- A default override map: the author-set fallback values for every binding.
Formats are identified by a URL-safe slug derived from the format's name (e.g. daily-sports-recap). All render API calls use the slug, not an internal ID.
A format has a status of draft or published. Only published formats can accept render requests from API-key callers.
Block
A block is one segment of a format's timeline — a single rendered scene. There are two categories:
Built-in blocks are provided by the platform. They have fixed structure and a defined set of parameterizable fields:
| Block kind | Parameterizable fields |
|---|---|
| titleCard | headline, subheadline |
| quote | text, attribution |
| keyValue | label, value, caption |
| photo | caption |
| logoReveal | tagline |
| endCard | handle, tagline, website |
| outroCTA | headline, cta, ctaUrl |
| countdown | targetAt, labelPrefix, expiredText |
| labeledList | title |
| statGrid | title |
User blocks are custom canvas layouts your team authors at /user-blocks/new. A user block contains one or more cells — positioned elements (text, stat, image, data table, etc.) — whose fields can be parameterized individually.
Transition ops (cuts, fades) sit between blocks on the timeline. They cannot be parameterized — they have no content surface.
Parameter and binding
A parameter is a named, typed variable that an API caller can supply to change a specific field in a specific block. Parameters have:
- A public name — the dotted string callers use in
variables(e.g.game1.player.name). - A type — one of
text,number,currency,percent,image,color, ortable. - A default value — the value used when the caller omits the variable.
- A required flag — when
true, the render API returns422 missing_required_variableif the caller doesn't supply it. - A deprecated flag — set automatically when the target field is deleted or renamed; callers sending deprecated names still render but see a warning.
A binding is the server-side record that links a public name to the exact JSON path inside the op list where the value should land. Bindings are managed automatically by the format editor — authors never write JSON Pointers directly.
Instance label
When a block (built-in or user block) is dropped onto a format timeline, it gets an instance label — a short identifier like game1 or titleCard-1. The instance label is a prefix that namespaces the block's parameters within the format.
Example: a user block with a player.name parameter, dropped as instance game1, exposes game1.player.name in the render API. If you drop the same block twice as game1 and game2, callers supply game1.player.name and game2.player.name independently.
Built-in blocks get synthetic labels like titleCard-1, quote-2. Authors can rename them in the timeline editor.
Render job
A render job is a queued request to produce an MP4 from a format with a specific set of variable values. Jobs are asynchronous: the API returns a job id immediately, and you poll GET /v1/renders/:id for status.
Possible statuses: queued → rendering → completed or failed.
Once completed, call GET /v1/renders/:id/signed-url to fetch a presigned download URL (valid 24 hours). Alternatively, configure webhooks to receive a push event instead of polling.
A failed job is terminal — create a new render rather than retrying the same job ID.
How they fit together
Format
└── Op list
├── Block op (titleCard-1) ← has bindings
│ binding: "titleCard-1.headline" → /ops/0/content/headline
├── Transition op (cut) ← no bindings possible
├── Block op (game1) ← user block, has bindings
│ binding: "game1.player.name" → /ops/2/content/cells/abc.../content/text
└── Block op (endCard-1) ← has bindings
binding: "endCard-1.handle" → /ops/3/content/handle
POST /v1/formats/daily-sports-recap/renders
{ "variables": { "game1.player.name": "LeBron James", "titleCard-1.headline": "Tonight's Recap" } }
↓
Render job (id: rj_01...)
↓
GET /v1/renders/rj_01.../signed-url → presigned MP4 URL
See the Quickstart for a working end-to-end example.