> ## Documentation Index
> Fetch the complete documentation index at: https://docs.trycontinuum.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Creative+ canvas, pipelines, and delivery

> MCP tools for canvas workflows, saved pipelines, Elements, and sending finished creative to a post or an ad: inputs, examples, and errors.

Generated from the server's own tool registry, as released on 2026-11-05. Every section lists what the tool needs, whether it waits for a yes, how it completes, each action's inputs, valid example calls, and the errors it can return. Before you call a tool, fetch its live schema with `help_describe`; if the server and this page disagree, the server wins.

| Tool | What it does | Changes things |
| - | - | - |
| [`studio_workflow`](#studio_workflow) | Builds, edits, runs, saves, and lists canvas workflows. | Yes |
| [`studio_deliver`](#studio_deliver) | Previews and sends finished creative to a planned post, an organic publish, or a live ad, and restores a swapped ad. | Yes |
| [`pipeline_search`](#pipeline_search) | Finds your team's saved pipelines. | No |
| [`pipeline_describe`](#pipeline_describe) | Shows what a pipeline needs. | No |
| [`pipeline_invoke`](#pipeline_invoke) | Runs a pipeline, up to 10 versions per request. | Yes |
| [`pipeline_run_status`](#pipeline_run_status) | Checks a pipeline run. | No |
| [`list_elements`](#list_elements) | Lists your saved Elements. | No |

### `studio_workflow`

Builds, edits, runs, saves, and lists canvas workflows.

**Good to know:**

* Canvas reads and builds work on a workspace (`room_id`). `target: "library"` saves a reusable template instead.
* `delete` and `workspace_delete` are two-phase. A brand holds at most three workspaces.
* To make the creative for a Planner draft, pass `source_draft_id` to `build`.
* `run` without a `room_id` returns `needs_workspace`: ask the person to open the canvas in Continuum, then retry.

| Contract | Behavior |
| - | - |
| Changes things | Yes |
| Listed in your assistant | Always. |
| Role | Operator or higher, for every action. |
| Needs | An active brand. |
| Confirmation | Writes preview first and return a `confirm_token` with `expires_at`. Confirm with that token after the person says yes. |
| Completion | Returns right away. Longer work continues as a job; read the id in the result. |
| Retry | Not idempotent. Check the current state before retrying. |
| Rate limit | Canvas runs: 10 an hour, per brand. See [Limits](https://docs.trycontinuum.ai/mcp/reference.md#limits). |

**Actions** (`action`):

| action | Required inputs | Other inputs it uses |
| - | - | - |
| `get` | `action` | `workflow_id`, `room_id`, `target`, `name` |
| `list` | `action` | — |
| `build` | `action`, `nodes\|source_draft_id` | `connections`, `target`, `room_id`, `mode`, `name`, `description`, `confirm_token` |
| `edit` | `action`, `ops`, `target` | `workflow_id`, `expected_updated_at`, `room_id`, `seed_workflow_id`, `name`, `description`, `confirm_token` |
| `run` | `action`, `room_id` | `workflow_id`, `node_ids`, `target` |
| `run_status` | `action`, `run_request_id` | — |
| `rename` | `action`, `workflow_id`, `name` | `description` |
| `delete` | `action`, `workflow_id` | `confirm_token` |
| `workspace_list` | `action` | — |
| `workspace_create` | `action`, `name` | — |
| `workspace_delete` | `action`, `room_id` | `confirm_token` |
| `save` | `action`, `workflow_id`, `expected_updated_at`, `room_id` | `name`, `description` |
| `save_as_copy` | `action`, `workflow_id\|room_id` | `name`, `description` |

In this table, `a|b` means one of them and `a+b` means together.

**Examples** (IDs are illustrative; use the ones earlier calls return):

* Read the current canvas: `{"name":"studio_workflow","arguments":{"action":"get"}}`
* Build an image workflow onto the canvas: `{"name":"studio_workflow","arguments":{"action":"build","target":"canvas","nodes":[{"ref":"prompt","type":"string","data":{"value":"a sneaker on concrete"}},{"ref":"img","type":"nanoGen"}],"connections":[{"from_ref":"prompt","to_ref":"img","role":"prompt"}]}}`
* Rename a saved workflow: `{"name":"studio_workflow","arguments":{"action":"rename","workflow_id":"wf_123","name":"Summer launch"}}`

**Errors and statuses:**

| Code | When |
| - | - |
| `VALIDATION_ERROR` | action=build requires `nodes`; unknown node types are rejected. |
| `CONFIRMATION_REQUIRED` | build mode='replace' and edit `remove_node`/disconnect/`detach_media` and action=delete are two-phase — preview returns a `confirm_token`; re-send the same call with it. |
| `CONFLICT` | The item changed or is busy. Read it again, then retry with the current state. |
| `INTERNAL` | Something went wrong on our side. Retry once, then contact support. |
| `NOT_FOUND` | The item doesn't exist, or this brand can't see it. |
| `needs_brand` | No brand is active. Call `brands_select`. |
| `needs_role` | The person's role is too low for this call. Needs: Operator or higher, for every action. Ask an Admin or Owner. |

**Related:** `studio_deliver`, `media_search`, `content_create`, `help_describe`, `library_manage`, `unsplash_search`.

Full schema: `help_describe {"tool":"studio_workflow","action":"get"}`. As JSON: [`/mcp/schemas/studio_workflow.json`](https://docs.trycontinuum.ai/mcp/schemas/studio_workflow.json).

### `studio_deliver`

Previews and sends finished creative to a planned post, an organic publish, or a live ad, and restores a swapped ad.

**Good to know:**

* Writes are two-phase and carry an `operation_id`: an exact retry replays the same receipt.
* A result marked `indeterminate` isn’t safe to retry blindly. Check the destination first.
* `replace_paid_creative` returns a restore handle; `restore_paid_creative` undoes the swap.

| Contract | Behavior |
| - | - |
| Changes things | Yes |
| Listed in your assistant | Always. |
| Role | Operator or higher. |
| Needs | An active brand. |
| Confirmation | Writes preview first and return a `confirm_token` with `expires_at`. Confirm with that token after the person says yes. |
| Completion | Returns the result in the same call. |
| Retry | Retry with the same `idempotency_key` to avoid duplicates. |

**Actions** (`action`):

| action | Required inputs | Other inputs it uses |
| - | - | - |
| `find_targets` | `action` | `target_type`, `format`, `asset_ids`, `asset_refs`, `draft_id`, `expected_updated_at`, `ad_account_id`, `campaign_id`, `adset_id`, `ad_id`, `expected_creative_id`, `replacement_id`, `level`, `parent_id`, and 9 more |
| `preview` | `action` | `target_type`, `format`, `asset_ids`, `asset_refs`, `draft_id`, `expected_updated_at`, `ad_account_id`, `campaign_id`, `adset_id`, `ad_id`, `expected_creative_id`, `replacement_id`, `level`, `parent_id`, and 9 more |
| `attach_to_planner` | `action` | `target_type`, `format`, `asset_ids`, `asset_refs`, `draft_id`, `expected_updated_at`, `ad_account_id`, `campaign_id`, `adset_id`, `ad_id`, `expected_creative_id`, `replacement_id`, `level`, `parent_id`, and 9 more |
| `publish_organic` | `action` | `target_type`, `format`, `asset_ids`, `asset_refs`, `draft_id`, `expected_updated_at`, `ad_account_id`, `campaign_id`, `adset_id`, `ad_id`, `expected_creative_id`, `replacement_id`, `level`, `parent_id`, and 9 more |
| `replace_paid_creative` | `action` | `target_type`, `format`, `asset_ids`, `asset_refs`, `draft_id`, `expected_updated_at`, `ad_account_id`, `campaign_id`, `adset_id`, `ad_id`, `expected_creative_id`, `replacement_id`, `level`, `parent_id`, and 9 more |
| `restore_paid_creative` | `action` | `target_type`, `format`, `asset_ids`, `asset_refs`, `draft_id`, `expected_updated_at`, `ad_account_id`, `campaign_id`, `adset_id`, `ad_id`, `expected_creative_id`, `replacement_id`, `level`, `parent_id`, and 9 more |
| `status` | `action` | `target_type`, `format`, `asset_ids`, `asset_refs`, `draft_id`, `expected_updated_at`, `ad_account_id`, `campaign_id`, `adset_id`, `ad_id`, `expected_creative_id`, `replacement_id`, `level`, `parent_id`, and 9 more |

**Examples** (IDs are illustrative; use the ones earlier calls return):

* Find organic drafts to deliver to: `{"name":"studio_deliver","arguments":{"action":"find_targets","target_type":"organic_draft","format":"image"}}`
* Preview attaching a creative to a Planner draft: `{"name":"studio_deliver","arguments":{"action":"preview","intent":"attach_to_planner","draft_id":"00000000-0000-0000-0000-000000000000","expected_updated_at":"2026-07-24T00:00:00.000Z","format":"image","asset_ids":["11111111-1111-4111-8111-111111111111"]}}`

**Errors and statuses:**

| Code | When |
| - | - |
| `CONFIRMATION_REQUIRED` | Writes are two-phase: action=preview returns a `confirm_token`, then the intent action (`attach_to_planner` / `replace_paid_creative` / …) with it. |
| `CONFLICT` | `draft_changed` / `paid_target_changed` — the destination moved since preview (stale-write refusal). Re-preview to pin the current version. |
| `NOT_FOUND` | The item doesn't exist, or this brand can't see it. |
| `needs_brand` | No brand is active. Call `brands_select`. |
| `needs_role` | The person's role is too low for this call. Needs: Operator or higher. Ask an Admin or Owner. |
| `VALIDATION_ERROR` | An input is missing or wrong, or it changed since the preview. `details` names the field. |

**Related:** `studio_workflow`, `content_create`, `paid_manage`, `help_describe`.

Full schema: `help_describe {"tool":"studio_deliver","action":"find_targets"}`. As JSON: [`/mcp/schemas/studio_deliver.json`](https://docs.trycontinuum.ai/mcp/schemas/studio_deliver.json).

### `pipeline_search`

Finds your team's saved pipelines.

| Contract | Behavior |
| - | - |
| Changes things | No |
| Listed in your assistant | When your role on a brand you can reach allows it. |
| Role | Viewer or higher |
| Needs | An active brand. |
| Confirmation | None. The call runs when made. |
| Completion | Returns the result in the same call. |
| Retry | Safe to retry: it only reads. |

**Inputs:**

| Input | Type | Required | About |
| - | - | - | - |
| `query` | string | No | Optional words matched against pipeline names, descriptions, inputs, outputs, and produces. |
| `limit` | integer | No | Maximum capabilities to return. |
| `offset` | integer | No | Number of matches to skip. |

**Examples** (IDs are illustrative; use the ones earlier calls return):

* Find a saved pipeline: `{"name":"pipeline_search","arguments":{"query":"product photo to lifestyle","limit":5}}`

**Errors and statuses:**

| Code | When |
| - | - |
| `INTERNAL` | Something went wrong on our side. Retry once, then contact support. |
| `BRAND_NOT_SELECTED` | No brand is active. Call `brands_select`. |
| `VALIDATION_ERROR` | An input is missing or wrong, or it changed since the preview. `details` names the field. |

**Related:** `pipeline_describe`, `pipeline_invoke`.

Full schema: `help_describe {"tool":"pipeline_search"}`. As JSON: [`/mcp/schemas/pipeline_search.json`](https://docs.trycontinuum.ai/mcp/schemas/pipeline_search.json).

### `pipeline_describe`

Shows what a pipeline needs.

| Contract | Behavior |
| - | - |
| Changes things | No |
| Listed in your assistant | When your role on a brand you can reach allows it. |
| Role | Viewer or higher |
| Needs | An active brand. |
| Confirmation | None. The call runs when made. |
| Completion | Returns the result in the same call. |
| Retry | Safe to retry: it only reads. |

**Inputs:**

| Input | Type | Required | About |
| - | - | - | - |
| `pipeline_id` | string | Yes | — |

**Examples** (IDs are illustrative; use the ones earlier calls return):

* What a pipeline needs: `{"name":"pipeline_describe","arguments":{"pipeline_id":"1c4e7a9d-3b5f-4d2a-8e6c-9f0b2d4a6c81"}}`

**Errors and statuses:**

| Code | When |
| - | - |
| `NOT_FOUND` | The item doesn't exist, or this brand can't see it. |
| `BRAND_NOT_SELECTED` | No brand is active. Call `brands_select`. |
| `VALIDATION_ERROR` | An input is missing or wrong, or it changed since the preview. `details` names the field. |

**Related:** `pipeline_invoke`, `pipeline_search`.

Full schema: `help_describe {"tool":"pipeline_describe"}`. As JSON: [`/mcp/schemas/pipeline_describe.json`](https://docs.trycontinuum.ai/mcp/schemas/pipeline_describe.json).

### `pipeline_invoke`

Runs a pipeline, up to 10 versions per request.

**Good to know:**

* Returns one receipt per run right away, usually `queued`. Read progress with `pipeline_run_status`.
* Reusing the same `idempotency_key` for the exact same request is safe. Use a new key for a new request.

| Contract | Behavior |
| - | - |
| Changes things | Yes |
| Listed in your assistant | Always. |
| Role | Operator or higher, because a run can spend. |
| Needs | An active brand. |
| Confirmation | None. The call runs when made. |
| Completion | Returns right away. Longer work continues as a job; read the id in the result. |
| Retry | Retry with the same `idempotency_key` to avoid duplicates. |
| Rate limit | Up to 10 runs in one call. See [Limits](https://docs.trycontinuum.ai/mcp/reference.md#limits). |

**Inputs:**

| Input | Type | Required | About |
| - | - | - | - |
| `pipeline_id` | string | Yes | `pipeline_id` returned by `pipeline_describe`. |
| `family_id` | string | Yes | identity.`family_id` returned by `pipeline_describe`. |
| `revision` | integer | Yes | identity.revision returned by `pipeline_describe`. |
| `contract_hash` | string | Yes | identity.`contract_hash` returned by `pipeline_describe`. |
| `idempotency_key` | string | Yes | Stable caller-generated key. Reuse it only to retry this exact invocation. In a batch, run i is keyed `<idempotency_key>:<i>`. |
| `text_inputs` | array | No | — |
| `asset_inputs` | array | No | — |
| `element_inputs` | array | No | — |
| `runs` | array | No | Up to 10 variations in one call, each with its own input lists. Use instead of the top-level input lists, never together with them. |

**Examples** (IDs are illustrative; use the ones earlier calls return):

* Run a pipeline twice with different headlines: `{"name":"pipeline_invoke","arguments":{"pipeline_id":"1c4e7a9d-3b5f-4d2a-8e6c-9f0b2d4a6c81","family_id":"6d9b2f4a-8c1e-4f3b-b7d5-2a4c6e8f0b39","revision":3,"contract_hash":"4e9f1c7a2b8d3e6f0a5c9b1d7e2f4a8c6b0d3e5f7a9c1b2d4e6f8a0c2e4b6d81","idempotency_key":"autumn-launch-2026-11-09","runs":[{"text_inputs":[{"input_id":"headline","value":"Autumn roast, out now"}]},{"text_inputs":[{"input_id":"headline","value":"Limited batch: autumn roast"}]}]}}`

**Errors and statuses:**

| Code | When |
| - | - |
| `INTERNAL` | Something went wrong on our side. Retry once, then contact support. |
| `VALIDATION_ERROR` | An input is missing or wrong, or it changed since the preview. `details` names the field. |
| `needs_brand` | No brand is active. Call `brands_select`. |
| `needs_role` | The person's role is too low for this call. Needs: Operator or higher, because a run can spend. Ask an Admin or Owner. |

**Related:** `pipeline_describe`, `pipeline_run_status`.

Full schema: `help_describe {"tool":"pipeline_invoke"}`. As JSON: [`/mcp/schemas/pipeline_invoke.json`](https://docs.trycontinuum.ai/mcp/schemas/pipeline_invoke.json).

### `pipeline_run_status`

Checks a pipeline run.

| Contract | Behavior |
| - | - |
| Changes things | No |
| Listed in your assistant | When your role on a brand you can reach allows it. |
| Role | Viewer or higher |
| Needs | An active brand. |
| Confirmation | None. The call runs when made. |
| Completion | Returns the result in the same call. |
| Retry | Safe to retry: it only reads. |

**Inputs:**

| Input | Type | Required | About |
| - | - | - | - |
| `run_ids` | array | Yes | `run_id` values from the receipts `pipeline_invoke` returned. |

**Examples** (IDs are illustrative; use the ones earlier calls return):

* Check a run: `{"name":"pipeline_run_status","arguments":{"run_ids":["f4a8c2e6-0b3d-4a7f-9c1e-5b7d9f1a3c62"]}}`

**Errors and statuses:**

| Code | When |
| - | - |
| `BRAND_NOT_SELECTED` | No brand is active. Call `brands_select`. |
| `VALIDATION_ERROR` | An input is missing or wrong, or it changed since the preview. `details` names the field. |

**Related:** `pipeline_describe`, `pipeline_invoke`.

Full schema: `help_describe {"tool":"pipeline_run_status"}`. As JSON: [`/mcp/schemas/pipeline_run_status.json`](https://docs.trycontinuum.ai/mcp/schemas/pipeline_run_status.json).

### `list_elements`

Lists your saved Elements.

| Contract | Behavior |
| - | - |
| Changes things | No |
| Listed in your assistant | When your role on a brand you can reach allows it. |
| Role | Viewer or higher |
| Needs | An active brand. |
| Confirmation | None. The call runs when made. |
| Completion | Returns the result in the same call. |
| Retry | Safe to retry: it only reads. |

**Inputs:**

| Input | Type | Required | About |
| - | - | - | - |
| `category` | string | No | Restrict to one category, e.g. "product" or "character". One of `model`, `character`, `product`, `object`, `material`, `setting`, `location`, `landscape`, `style`, `moodboard`, `palette`, `animation`, `effect`, `general`. |

**Examples** (IDs are illustrative; use the ones earlier calls return):

* Every Element this brand has saved: `{"name":"list_elements","arguments":{}}`
* Only the products, before wiring an element node: `{"name":"list_elements","arguments":{"category":"product"}}`

**Errors and statuses:**

| Code | When |
| - | - |
| `BRAND_NOT_SELECTED` | Elements are per-brand. Call `brands_select` first. |
| `needs_role` | Reading Elements needs the viewer role on the active brand. |
| `VALIDATION_ERROR` | An input is missing or wrong, or it changed since the preview. `details` names the field. |

**Related:** `studio_workflow`, `media_search`, `library_manage`.

Full schema: `help_describe {"tool":"list_elements"}`. As JSON: [`/mcp/schemas/list_elements.json`](https://docs.trycontinuum.ai/mcp/schemas/list_elements.json).

## What's next

* [All tools](https://docs.trycontinuum.ai/mcp/tools.md): Every tool on one page, and the machine-readable index.
* [Account, brand, and jobs](https://docs.trycontinuum.ai/mcp/tools/account.md): Lists the brands you can access, and more.
* [Analytics, trends, and competitors](https://docs.trycontinuum.ai/mcp/tools/insights.md): Organic, paid, and website results by platform: accounts, top posts, campaigns, ad sets, and ads, and more.
* [Organic+ planning and publishing](https://docs.trycontinuum.ai/mcp/tools/organic.md): Reads and proposes a week of posts, approves it, reschedules and copies posts, and attaches media, and more.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.