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

# Design Task Recipes

> Four ways to start a design task — create from scratch, edit in place, fill a template, or rebrand a template — across the REST API and the MCP tool.

`POST /v1/tasks` (REST) and the `start_design_task` MCP tool are the single entry point for every Moda design workflow. The same call covers four different patterns depending on which source-canvas field you set.

## Which recipe do I want?

| Goal                                      | Field to set                                                                                                                                                                                | What happens                                                                                                          |
| ----------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------- |
| Generate a brand-new design from a prompt | *(neither)*                                                                                                                                                                                 | A new canvas is created in your team and the agent designs into it.                                                   |
| Edit an existing canvas you own           | `canvas_id`                                                                                                                                                                                 | The agent modifies that canvas in place.                                                                              |
| Fill in a template with your content      | `template_canvas_id`                                                                                                                                                                        | A copy of the template is created; the agent edits the **copy**. The original is untouched.                           |
| Rebrand a template for a different brand  | `template_canvas_id` + a different `brand_kit_id` + a `prompt` that explicitly asks for a visual rebrand (e.g. `"Rebrand the colors, fonts, logo, and imagery to the selected brand kit."`) | A copy is created, the new brand kit is applied, and the agent rebrands colors, fonts, logo, and imagery on the copy. |

`canvas_id` and `template_canvas_id` are mutually exclusive. `conversation_id` is mutually exclusive with `template_canvas_id` (a template remix always starts a fresh conversation on the new copy). Setting incompatible fields returns `422 Unprocessable Entity`.

Every recipe returns a [`Task` envelope](/api-reference/tasks/get-task-status) for polling, with a prefixed `task_` ID and HATEOAS `links` for the running task and the resulting canvas.

<Info>
  Pin the API version on every request so the response shape stays stable. All examples below use `Moda-Version: 2026-05-01`. See [Versioning](/api-reference/versioning) for the supported list and sunset schedule.
</Info>

## 1. Create a new design

Pass a `prompt`, a `format`, and optionally a `canvas_name`. Moda creates a fresh canvas and the agent designs into it.

<Info>
  **REST vs MCP format arguments.** The REST API takes a nested `format` object (e.g. `format: { "category": "slides" }`). The MCP tool flattens the same fields into top-level arguments — `format_category`, `format_width`, `format_height`, `carousel_dimensions`, `carousel_page_count` — and assembles them into the same `format` object before calling the REST handler. Use whichever shape matches the surface you're calling.
</Info>

<CodeGroup>
  ```bash REST theme={null}
  curl -X POST https://api.moda.app/v1/tasks \
    -H "Authorization: Bearer $MODA_API_KEY" \
    -H "Moda-Version: 2026-05-01" \
    -H "Content-Type: application/json" \
    -d '{
      "prompt": "Sales deck for Q4 2026 — six slides, focus on enterprise growth",
      "canvas_name": "Acme Q4 sales deck",
      "format": { "category": "slides" }
    }'
  ```

  ```python MCP theme={null}
  result = await mcp.call_tool(
      "start_design_task",
      {
          "prompt": "Sales deck for Q4 2026 — six slides, focus on enterprise growth",
          "canvas_name": "Acme Q4 sales deck",
          "format_category": "slides",
      },
  )
  ```
</CodeGroup>

**When to use:** the design doesn't exist yet — you want Moda to compose layout, copy, and visuals from scratch. Pair with `brand_kit_id` (or rely on your team's default) to ground the output in your brand.

`format` is required when creating a new canvas. It is ignored when `canvas_id` or `template_canvas_id` is set — the existing canvas's dimensions win.

## 2. Edit an existing canvas

Pass `canvas_id` and the agent modifies that canvas in place. Use this when you want to iterate on a design you already have — fix typos, swap data, change a section — without forking it.

<CodeGroup>
  ```bash REST theme={null}
  curl -X POST https://api.moda.app/v1/tasks \
    -H "Authorization: Bearer $MODA_API_KEY" \
    -H "Moda-Version: 2026-05-01" \
    -H "Content-Type: application/json" \
    -d '{
      "prompt": "Replace the Q3 numbers on the metrics page with: ARR 12M, NRR 118%, customers 340",
      "canvas_id": "cvs_01HT9WK8N3M2J4A5Z6P7Q8R9TV"
    }'
  ```

  ```python MCP theme={null}
  result = await mcp.call_tool(
      "start_design_task",
      {
          "prompt": "Replace the Q3 numbers on the metrics page with: ARR 12M, NRR 118%, customers 340",
          "canvas_id": "cvs_01HT9WK8N3M2J4A5Z6P7Q8R9TV",
      },
  )
  ```
</CodeGroup>

**When to use:** you have a canvas already in the loop (a live document, an ongoing collaboration) and you want changes applied to that canvas rather than a copy.

<Warning>
  Edit-in-place mutates the source. If you want to keep the original untouched, use `template_canvas_id` instead (see recipes 3 and 4).
</Warning>

## 3. Fill in a template

Pass the source canvas as `template_canvas_id`. Moda copies the canvas into your team and the agent edits the **copy** — the original stays clean.

The source does not have to be flagged as a template (`template_type='template'`); any canvas you can read from your team works.

**Pick a `brand_kit_id` that matches the source canvas's brand kit.** Skill selection is a direct comparison between the source's brand kit and the request's `brand_kit_id` — if they match, you get the content-only remix (preserve design, update content). If they differ, you get the full rebrand instead. Omitting `brand_kit_id` falls back to your team's default, which only behaves the same as recipe 3 when the team default *is* the source's brand kit; otherwise you'll land in recipe 4 behavior. See [Automatic mode selection](#automatic-mode-selection) for the full matrix.

<CodeGroup>
  ```bash REST theme={null}
  curl -X POST https://api.moda.app/v1/tasks \
    -H "Authorization: Bearer $MODA_API_KEY" \
    -H "Moda-Version: 2026-05-01" \
    -H "Content-Type: application/json" \
    -d '{
      "prompt": "Fill out this template to announce our auto-reimbursement feature",
      "template_canvas_id": "cvs_01HT9WK8N3M2J4A5Z6P7Q8R9TV",
      "brand_kit_id": "bk_01HT9WK8N3M2J4A5Z6P7Q8R9TV",
      "canvas_name": "Acme — auto-reimbursement announcement"
    }'
  ```

  ```python MCP theme={null}
  result = await mcp.call_tool(
      "start_design_task",
      {
          "prompt": "Fill out this template to announce our auto-reimbursement feature",
          "template_canvas_id": "cvs_01HT9WK8N3M2J4A5Z6P7Q8R9TV",
          "brand_kit_id": "bk_01HT9WK8N3M2J4A5Z6P7Q8R9TV",
          "canvas_name": "Acme — auto-reimbursement announcement",
      },
  )
  ```
</CodeGroup>

**Behind the scenes:** because the requested brand kit matches the source's brand kit, Moda runs the **content-only remix** skill — it preserves layout, colors, fonts, and imagery, and updates only copy and data to match your prompt. Callers don't have to ask for this mode — it's selected automatically from the brand-kit comparison (see [Automatic mode selection](#automatic-mode-selection) below).

## 4. Rebrand a template for a different brand

The same call shape as recipe 3, but pass a **different** `brand_kit_id` than the one the source canvas was built for. This is the agency / multi-client pattern: take one well-designed template and produce variants across different brand identities.

<Warning>
  **You must tell the agent to rebrand in the prompt.** Setting a different `brand_kit_id` selects the rebrand skill on the backend, but the agent only changes what your prompt asks it to. If your prompt only describes the new content (e.g. "announce v3 of TPS reports"), the agent will update copy and leave the existing colors, fonts, logo, and imagery in place. Lead the prompt with an explicit instruction like **"Rebrand the colors, fonts, logo, and imagery to the selected brand kit."** and then add what the design should say. The example below is the recommended shape.
</Warning>

<CodeGroup>
  ```bash REST theme={null}
  curl -X POST https://api.moda.app/v1/tasks \
    -H "Authorization: Bearer $MODA_API_KEY" \
    -H "Moda-Version: 2026-05-01" \
    -H "Content-Type: application/json" \
    -d '{
      "prompt": "Rebrand the colors, fonts, logo, and imagery to the selected brand kit. Adapt the copy for Initech, announcing v3 of TPS reports.",
      "template_canvas_id": "cvs_01HT9WK8N3M2J4A5Z6P7Q8R9TV",
      "brand_kit_id": "bk_01J0NEWBRANDXYZ0123456789",
      "canvas_name": "Initech — TPS v3 launch"
    }'
  ```

  ```python MCP theme={null}
  result = await mcp.call_tool(
      "start_design_task",
      {
          "prompt": (
              "Rebrand the colors, fonts, logo, and imagery to the selected brand kit. "
              "Adapt the copy for Initech, announcing v3 of TPS reports."
          ),
          "template_canvas_id": "cvs_01HT9WK8N3M2J4A5Z6P7Q8R9TV",
          "brand_kit_id": "bk_01J0NEWBRANDXYZ0123456789",
          "canvas_name": "Initech — TPS v3 launch",
      },
  )
  ```
</CodeGroup>

**Behind the scenes:** because the requested brand kit differs from the source's, Moda runs the **full rebrand** skill — colors, fonts, logos, hero images, and copy all adapt to the new brand, while the structural layout is preserved.

## Automatic mode selection

You never tell the API which "skill" to use. For any task with `template_canvas_id`, the backend resolves an effective brand kit for the request and compares it against the source canvas's brand kit.

The effective brand kit is resolved in this order:

1. `skip_brand_kit: true` → no brand kit, skip the default.
2. Explicit `brand_kit_id` on the request.
3. Team's default brand kit (if one is set).
4. None.

Then:

| Source canvas's brand kit | Effective request brand kit                                                      | Skill that runs    |
| ------------------------- | -------------------------------------------------------------------------------- | ------------------ |
| `bk_acme`                 | `bk_acme`                                                                        | Content-only remix |
| `bk_acme`                 | `bk_initech` (any kit different from source)                                     | Full rebrand       |
| `bk_acme`                 | none (e.g. `skip_brand_kit: true` or no team default and `brand_kit_id` omitted) | Full rebrand       |

The same `/v1/tasks` call covers all of these. Switch brands by switching `brand_kit_id`.

<Warning>
  **Be explicit if you want recipe 3 behavior.** Omitting `brand_kit_id` resolves to your team's default — *not* the source canvas's brand kit. If those two are different, you'll get the full rebrand skill even when you only meant to update copy. To guarantee content-only remix, pass the source canvas's own `brand_kit_id` explicitly.
</Warning>

The skill controls what the agent is **allowed** to change. Your prompt still controls what the agent **actually** changes. For the full-rebrand skill, that means you have to ask the agent to update colors, fonts, logo, and imagery — see the warning under [recipe 4](#4-rebrand-a-template-for-a-different-brand). For the content-only skill, the agent never touches those dimensions regardless of how the prompt is phrased.

## Response shape

Every recipe returns a [`Task` envelope](/api-reference/tasks/get-task-status). For template-based recipes (3 and 4), the envelope also carries the source canvas on both `input` and `result` so pollers can correlate the new canvas with its source without an extra fetch:

```json theme={null}
{
  "id": "task_01HT9WK8N3M2J4A5Z6P7Q8R9TV",
  "kind": "design",
  "status": "succeeded",
  "input": {
    "prompt": "Fill out this template to announce our auto-reimbursement feature",
    "source_canvas_id": "cvs_01HT9WK8N3M2J4A5Z6P7Q8R9TV"
  },
  "result": {
    "canvas_id": "cvs_01J0NEWCANVASCREATEDABCDE",
    "canvas_url": "https://app.moda.com/canvas/01J0NEWCANVASCREATEDABCDE",
    "conversation_id": "conv_01J0NEWCONVERSATIONFGHIJK",
    "source_canvas_id": "cvs_01HT9WK8N3M2J4A5Z6P7Q8R9TV",
    "source_canvas_url": "https://app.moda.com/canvas/01HT9WK8N3M2J4A5Z6P7Q8R9TV"
  },
  "links": {
    "self": "/v1/tasks/task_01HT9WK8N3M2J4A5Z6P7Q8R9TV",
    "events": null,
    "cancel": null,
    "canvas": "https://app.moda.com/canvas/01J0NEWCANVASCREATEDABCDE"
  },
  "retry_after_ms": null
}
```

The `input` block is a normalized echo of the request, not a verbatim copy: `template_canvas_id` is rewritten to `source_canvas_id` so the same field name carries the source on both the input and the result side. For recipes 1 and 2, `source_canvas_id` and `source_canvas_url` are absent from both blocks.

When you create a **fresh slides deck** with a brand kit that has a saved default theme, `result.theme_canvas_id` carries the prefixed id of the auto-applied theme canvas — the layout source for the generated slides — so you can confirm the deck was themed without a separate fetch. It's `null` for non-slides designs, edits, and the template recipes above.

## Common options

These apply to every recipe:

| Field                  | Effect                                                                                                                                                                                                                                     |
| ---------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `prompt`               | **Required.** Natural-language instruction for the agent.                                                                                                                                                                                  |
| `brand_kit_id`         | Apply a specific brand kit. Omit to use your team's default. Must belong to your team. When `template_canvas_id` is set, the resolved kit is also what drives skill selection — see [Automatic mode selection](#automatic-mode-selection). |
| `skip_brand_kit`       | `true` to skip brand-kit application entirely (even the team default). Overrides `brand_kit_id` when both are set.                                                                                                                         |
| `idempotency_key`      | Replay-safe identifier. A retry with the same key returns the original task without creating a duplicate canvas.                                                                                                                           |
| `callback_url`         | HTTPS URL to receive a signed webhook when the task terminates. See [Webhooks](/api-reference/webhooks) for signature verification.                                                                                                        |
| `attachments`          | Reference images or files. Use either inline URLs or `file_id`s from `POST /v1/uploads` (or [`POST /v1/uploads/url`](/api-reference/large-file-uploads) for files above \~32 MiB).                                                         |
| `reference_canvas_ids` | Canvas IDs to show the agent as inspiration. Read-only — they are not modified.                                                                                                                                                            |
| `format`               | Output format. Required for recipe 1 (new canvas); ignored when `canvas_id` or `template_canvas_id` is set.                                                                                                                                |
| `model_tier`           | `pro` (most capable), `pro-fast` (Pro quality, faster output, more credits), `standard`, or `lite`. Omit for automatic selection.                                                                                                          |
| `number_of_slides`     | Optional cap for slide-generation tasks. Omit to use the 8-slide default, clamped to your plan limit.                                                                                                                                      |
| `conversation_id`      | Resume an existing conversation. **Mutually exclusive with `template_canvas_id`** — a template remix always starts a fresh conversation on the new copy.                                                                                   |

## Polling and webhooks

Every recipe returns a `Task` envelope with a prefixed `id` (e.g. `task_01HT9WK8N3M2J4A5Z6P7Q8R9TV`). Poll `GET /v1/tasks/{id}` until `status` reaches a terminal value (`succeeded`, `failed`, `canceled`, or `expired`). The envelope's `retry_after_ms` is a suggested poll interval.

If you'd rather not poll, set `callback_url` on the request and Moda fires a signed `task.succeeded` / `task.failed` / `task.canceled` webhook when the task terminates. See [Webhooks](/api-reference/webhooks) for envelope shape, signature verification, and retry behavior.

## See also

* [Start Design Task](/api-reference/tasks/start-design-task) — full schema for every request field.
* [Get Task Status](/api-reference/tasks/get-task-status) — `Task` envelope reference and polling guidance.
* [Webhooks](/api-reference/webhooks) — signed-callback setup, payload shape, and signature verification.
* [List Brand Kits](/api-reference/brand-kits/list-brand-kits) — the brand kits you can pass to `brand_kit_id`.
* [Authentication](/api-reference/authentication) — API keys, scopes, and security.
* [Versioning](/api-reference/versioning) — pin a stable response shape with `Moda-Version`.
