Create v1 Directives, convert binding and resource configuration, and switch asset creation to the new Directive without losing access to v0 runs.
A Directive keeps the API version used to create it. To move a Directive from the Robots Beta API (v0) to the GA API (v1), create a new Directive with v1 configuration, test it, then replace the old Directive ID in your asset-creation integrations. The existing Directive does not change version.
Migrate with your coding agent
Paste this prompt into your agent to review your integration, apply the relevant changes, and test the migration.
Start with the Robots API migration guide for workflow parameter and output changes. Update and deploy webhook handlers before starting v1 runs. See the Directives API referenceAPI for the complete configuration.
Open an existing v0 Directive and choose Create v1 copy. Review the workflows, resources, and options, then create the new Directive. Legacy options that v1 no longer supports are omitted from the copy. Remove workflows unavailable in v1, such as Find Scenes, before creating it; replace scene analysis with Analyze Structure where appropriate.
The copy has a new ID. The v0 Directive stays in place, and integrations that attach its ID keep triggering it. Creating a copy does not move asset references, modify external integrations, or delete the original.
GET /robots/v0/directives/{DIRECTIVE_ID}.id, timestamps, and _links.POST /robots/v1/directives.| Configuration field | V0 | V1 |
|---|---|---|
| Workflow bindings | workflows[] | bindings[] |
| Binding options | params | parameters |
| Mux API source options | source.params | source.parameters |
| Caption resource selector | kind: "caption" | kind: "subtitles" |
| Track resource language | language | language_code |
| Caption generation source audio language | source.params.source_audio_language | source.parameters.source_audio_language_code |
| Shot-generation action | action: "request_shots" | action: "generate_shots" |
Binding workflow, binding/resource reference_id, inputs[], and source.binding keep their names. Preserve reference IDs so dependencies still resolve. Don't put asset_id or the source track_id in binding parameters; the Directive supplies them.
Apply the workflow parameter changes inside every binding too: translation targets become output_language_code, key-moment target durations become seconds, and deprecated fields are removed. Replace find-scenes bindings with an appropriately configured analyze-structure binding.
For example, this v0 configuration generates a caption resource, then translates it:
{
"name": "Generate and translate captions",
"subject": { "type": "video.asset" },
"resources": [
{
"reference_id": "captions_en",
"type": "video.asset.track",
"kind": "caption",
"language": "en",
"source": {
"via": "mux_api",
"action": "generate_subtitles",
"params": {
"language_code": "en",
"source_audio_language": "en-US"
}
}
}
],
"workflows": [
{
"reference_id": "translate_es",
"workflow": "translate-captions",
"inputs": ["captions_en"],
"params": { "to_language_code": "es" }
}
]
}Save this v1 configuration as directive-v1.json:
{
"name": "Generate and translate captions v1",
"subject": { "type": "video.asset" },
"resources": [
{
"reference_id": "captions_en",
"type": "video.asset.track",
"kind": "subtitles",
"language_code": "en",
"source": {
"via": "mux_api",
"action": "generate_subtitles",
"parameters": {
"language_code": "en",
"source_audio_language_code": "en-US"
}
}
}
],
"bindings": [
{
"reference_id": "translate_es",
"workflow": "translate-captions",
"inputs": ["captions_en"],
"parameters": { "output_language_code": "es" }
}
]
}Create it through v1:
curl https://api.mux.com/robots/v1/directives \
-u "$MUX_TOKEN_ID:$MUX_TOKEN_SECRET" \
-H "Content-Type: application/json" \
-d @directive-v1.jsonUnknown fields are ignored, so a successful create request does not mean obsolete optional fields still take effect. Review the resulting configuration and its behavior on a test asset.
GET /robots/v1/directives returns slim summaries of both v0 and v1 Directives, with id, name, created_at, updated_at, and _links.self. It no longer returns the full configuration in every list entry.
Follow _links.self.href to get the full configuration. A summary with a /robots/v0/directives/... link still represents a v0 Directive even though you discovered it through the v1 list. The v0 list continues returning full v0 configurations.
Individual detail, delete, and run routes require the version that created the Directive. A version mismatch returns 404; the v1 detail endpoint only returns v1 Directives. Keep the version that created each Directive with any saved Directive ID. If an older saved link contains only an ID, try the v1 detail endpoint and fall back to v0 only on 404, not authentication or server errors.
For a v0 Directive, keep using /robots/v0/directives/{id}/runs and its run-detail routes while it remains active. For a v1 Directive, use the corresponding v1 routes.
V1 uses one run representation across start responses, lists, detail reads, and webhook data. It includes id, directive_id, subject_id, status, node_states, started_at, and completed_at.
| Surface | V0 | V1 |
|---|---|---|
| HTTP run identifier | run_id | id |
| Run relationship | V0 HTTP responses vary by operation | directive_id consistently identifies the Directive. |
| Dispatched/waiting node workflow | workflow_name | workflow |
| Source dependency status | waiting_for_source_workflow | waiting_for_source_bindings |
| Source dependency references | source_workflows[] | source_bindings[] |
| Directive-run webhook asset | data.asset_id | data.subject_id |
source_bindings[] contains binding reference IDs, not workflow names. Node failure details remain in reason. Run timestamps are still Unix seconds. The manual start request still uses { "asset_id": "YOUR_ASSET_ID" }; subject_id is a response field, not a renamed request parameter.
Child jobs inherit the Directive's version. Fetch their details through that version too, rather than assuming that every job visible in your dashboard or list is v1.
A Directive triggers automatically when its ID is attached to an asset at creation. Test the new Directive, then switch those attachments to its ID.
curl https://api.mux.com/robots/v1/directives/YOUR_V1_DIRECTIVE_ID/runs \
-u "$MUX_TOKEN_ID:$MUX_TOKEN_SECRET" \
-H "Content-Type: application/json" \
-d '{ "asset_id": "YOUR_TEST_ASSET_ID" }'robots.v1.directive_run.* and robots.v1.job.* webhook handlers. V1 caption track selection rules also apply when a Directive dispatches jobs.curl https://api.mux.com/video/v1/assets \
-u "$MUX_TOKEN_ID:$MUX_TOKEN_SECRET" \
-H "Content-Type: application/json" \
-d '{
"inputs": [{ "url": "https://example.com/my-video.mp4" }],
"playback_policies": ["public"],
"directives": [{ "id": "YOUR_V1_DIRECTIVE_ID" }]
}'directives[] entry.Attaching both the old and new Directive IDs can start both Directives. Their child jobs can both execute and consume units. Creating the v1 copy does not replace the old attachment automatically.
To roll back during the v0 support period, restore the old v0 ID in the integrations that create assets. Keep the original Directive until you have verified the cutover; deleting it removes that rollback option.
_links.self.