Video Compositions
Read the contract a Video Editor node renders against, for both template mode and sceneGraph mode.
Wireflow assembles finished video with the video:remotion node, labelled Video Editor in the app. These endpoints publish what that node expects, so you can fill one correctly instead of guessing.
A Video Editor node runs in exactly one of two modes:
| Mode | Set by | Contract endpoint |
|---|---|---|
| Template | config.templateId (e.g. apollo-devotional) |
GET /api/v1/remotion/templates |
| SceneGraph | config.props.sceneGraph |
GET /api/v1/remotion/scene-graph |
Template mode renders a pre-built composition and its inputs are fixed. SceneGraph mode renders a composition you author yourself as JSON (scenes, tracks, overlays, captions, effects).
All three endpoints below are read-only and require the workflows:read scope.
List compositions
GET /api/v1/remotion/templates
Returns every template composition your account can use. Private and agency templates are filtered by an allowlist, so two accounts can legitimately see different lists.
Request
curl https://www.wireflow.ai/api/v1/remotion/templates \
-H "Authorization: Bearer sk-your-api-key"
Response 200 OK
{
"data": [
{
"id": "apollo-devotional",
"label": "Apollo Devotional",
"category": "reel",
"compositionId": "ApolloDevotional",
"fps": 30,
"width": 1920,
"height": 1080,
"durationInFrames": 4500,
"inputMappings": [
{
"propPath": "paragraphs",
"portId": "paragraphs",
"portLabel": "Tagged Script (or planned paragraphs)",
"portType": "TEXT",
"required": true
},
{
"propPath": "audioSrc",
"portId": "audio",
"portLabel": "Voiceover",
"portType": "AUDIO",
"required": true
},
{
"propPath": "brollClips",
"portId": "brollClips",
"portLabel": "B-roll Clips (JSON)",
"portType": "JSON",
"required": false
}
]
}
]
}
Trimmed for length: the real entry also carries description, thumbnail, and defaultProps, and this template declares seven mappings rather than the three shown.
Get one composition
GET /api/v1/remotion/templates/{id}
Same shape, one object instead of an array. Resolving a template by an id you already hold is allowed even when it is not in your catalog listing, so a workflow you cloned keeps working.
curl https://www.wireflow.ai/api/v1/remotion/templates/apollo-devotional \
-H "Authorization: Bearer sk-your-api-key"
An unknown id returns 404 with code not_found.
How inputMappings map to node ports
inputMappings is the useful part. One entry describes one wireable input:
| Field | Meaning |
|---|---|
propPath |
Where the value lands in the composition's props. Can be nested, e.g. shots.0.image. |
portId |
The port id on the node. An edge targets it as in-{portId}. |
portType |
TEXT, IMAGE, VIDEO, AUDIO, JSON, or NUMBER. |
required |
When true, leaving it unfed fails the render instead of shipping a blank MP4. |
propPath and portId are often the same string but they are not the same thing, and the difference is where mistakes come from. In the example above propPath is audioSrc while portId is audio, so the voiceover arrives on the handle in-audio and the composition reads it as props.audioSrc.
Two consequences worth internalising:
- The static port list on the node is not its real surface. A Video Editor node's ports are materialised from the selected template's
inputMappingswhen the workflow is saved. Read the template, not the node's defaults. - Every one of these is a port, not a setting. Ports are filled by wiring an upstream node, never by writing a config value. The MCP tool
update_workflow_configwill refuse every key on a Video Editor node for this reason, and it is right to.
Templates whose input count varies (a reel with N shots, say) compute inputMappings from their current props, so the response reflects the slots that exist now rather than a fixed maximum.
Get the sceneGraph contract
GET /api/v1/remotion/scene-graph
Publishes the authoring contract for sceneGraph mode.
curl https://www.wireflow.ai/api/v1/remotion/scene-graph \
-H "Authorization: Bearer sk-your-api-key"
Response 200 OK
{
"data": {
"mode": "sceneGraph",
"nodeType": "video:remotion",
"configPath": "config.props.sceneGraph",
"doc": "A SceneGraph is a JSON object the renderer turns into a real video:\n\n{\n \"fps\": 30, ...",
"jsonSchema": {
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "object",
"required": ["fps", "width", "height", "scenes"],
"properties": { "fps": {}, "width": {}, "height": {}, "scenes": {} }
}
}
}
doc is the same authoring guide the internal renderer agent receives. jsonSchema is emitted from the exact Zod schema that validates your graph at run time, so the published contract cannot drift from the enforced one. The full schema declares 15 top-level properties (fps, width, height, background, scenes, tracks, overlays, captionTrack, audioTrack, and more); the sample above is truncated.
$schema is JSON Schema draft 2020-12, so a consumer validating against it needs a matching validator build (with Ajv that is ajv/dist/2020, not the default import).
Two fields frame what you are reading. readerNote says the document is reference material: doc was written as a generation prompt, so imperatives inside it like "Output ONLY the JSON object" describe what a generator emits when producing a scene graph, not how to answer this fetch. scopeNote records that this endpoint needs only workflows:read, while the preview step doc recommends at the end (POST /api/v1/render/remotion/preview) needs workflows:execute. Read is implied by execute, never the reverse, so a read-only key can fetch the contract but will get a 401 from preview.
Some internal fields are withheld from the published schema, so treat it as the supported surface rather than an exhaustive one. For block scenes, use the blockId you were given.
It is big. Roughly 21KB of prose and 54KB of schema, about 77KB together. Take one half with include:
curl "https://www.wireflow.ai/api/v1/remotion/scene-graph?include=doc" \
-H "Authorization: Bearer sk-your-api-key"
include accepts doc, schema, or all (the default).
Authentication
These endpoints accept an sk- API key only:
Authorization: Bearer sk-your-api-key
An MCP OAuth access token is not accepted here and returns 401 with code invalid_api_key. If your agent talks to Wireflow over MCP, it needs a separate API key to read a composition contract. See Authentication.
Filling a Video Editor node
What you can do depends on how you are connected.
Over REST with the workflows:write scope, PUT /api/v1/workflows/{id} accepts the full nodes and edges arrays, so you can add a Video Editor node, wire its ports, set config.templateId, or author config.props.sceneGraph outright.
Over MCP, you cannot, though the reason is narrower than "the tools cannot write graphs". clone_template and create_workflow_from_prompt both persist a full set of nodes and edges. What MCP cannot do is add a node to a workflow that already exists, draw an edge, or generate a Video Editor node in the first place: the graph generator builds only from the model registry, which has no video:remotion entry. Combined with the node having no settable config keys, that means you cannot assemble a composed video from an empty canvas over MCP.
Start from a workflow template that already contains one (list_templates, then clone_template), then confirm with get_workflow that a video:remotion node is really present before you spend a run. The video category tag means "makes video", not "assembles video", so many tagged templates have no assembler node and some templates that have one are not tagged video. Then change the content by editing the upstream nodes that feed it or by passing inputs at run time. See MCP integration.