---
title: "Start Design Task"
method: POST
path: "/tasks"
tags: ["tasks"]
---

# Start Design Task

`POST /tasks`

Start an AI design task. Returns immediately with a task ID for polling.

## Headers

- `Moda-Version` '2026-04-12' | '2026-05-01'

## Request body

- StartTaskRequest
  - `prompt` string, required — Natural-language description of the design task for the AI agent.
  - `conversation_id` string, nullable — Prefixed ``conv_`` wire ID (Crockford base32 body) — the canonical, recommended form. For back-compat, **a bare UUID string is also accepted** in both path parameters and JSON request bodies (older integrations that stored raw UUIDs keep working). Both are permanent, supported inputs.
  - `canvas_id` string, nullable — Prefixed ``cvs_`` wire ID (Crockford base32 body) — the canonical, recommended form. For back-compat, **a bare UUID string is also accepted** in both path parameters and JSON request bodies (older integrations that stored raw UUIDs keep working). Both are permanent, supported inputs.
  - `template_canvas_id` string, nullable — Prefixed ``cvs_`` wire ID (Crockford base32 body) — the canonical, recommended form. For back-compat, **a bare UUID string is also accepted** in both path parameters and JSON request bodies (older integrations that stored raw UUIDs keep working). Both are permanent, supported inputs.
  - `canvas_name` string, nullable — Name for the new canvas. Used when creating (``canvas_id`` omitted) or when remixing via ``template_canvas_id`` (overrides the default ``Remix of <source>``).
  - `brand_kit_id` string, nullable — Prefixed ``bk_`` wire ID (Crockford base32 body) — the canonical, recommended form. For back-compat, **a bare UUID string is also accepted** in both path parameters and JSON request bodies (older integrations that stored raw UUIDs keep working). Both are permanent, supported inputs.
  - `skip_brand_kit` boolean — If true, no brand kit is applied — every brand-kit source is suppressed, including the canvas's own kit, the team default, and any explicit ``brand_kit_id`` override. Use only when the design must be unbranded; to merely leave the canvas's existing kit alone, omit ``brand_kit_id`` instead.
  - `callback_url` string, nullable — HTTPS URL to receive a webhook POST when the job completes, fails, or is cancelled. See the Webhooks documentation for payload format and signature verification.
  - `idempotency_key` string, nullable — Client-generated unique key to prevent duplicate job creation. If a job with this key already exists, its status is returned instead of creating a new one.
  - `attachments` union[], nullable — List of reference images or files for the AI agent to use as inspiration. Each item is either a URL-shape attachment (``{url, name?, type?}``) or a file-id-shape attachment (``{file_id, role, label?}``) referencing a file previously uploaded via ``POST /v1/uploads``. The two shapes are distinguished by their required fields (``url`` vs ``file_id``).
    - union
      - AttachmentInput
        - `url` string, required — Public URL of the image or file.
        - `name` string, nullable — Display name for the attachment.
        - `type` 'image' | 'pdf' | 'pptx' | 'url' — Attachment type: 'image', 'pdf', 'pptx', or 'url'.
      - FileAttachment — Reference to a previously uploaded file by its prefixed ``file_`` id. Paired with ``AttachmentInput`` under ``StartTaskRequest.attachments`` via Pydantic smart-union. The caller uploads a file first via ``POST /v1/uploads`` (or the MCP upload-URL flow) and then passes the resulting ``file_id`` here with a ``role`` that tells the agent how to treat the file.
        - `file_id` string, required — Prefixed ``file_`` ID returned by ``POST /v1/uploads``.
        - `role` 'source' | 'reference' | 'asset' | 'import', required — How the agent should treat this file: 'source' = extract content from it; 'reference' = emulate its style without reproducing verbatim; 'asset' = use the file directly in outputs (hint only — directly-use behavior evolves with ENG-2549). 'import' = convert a PowerPoint (.pptx) deck into editable slides on the canvas, then design against it. Only valid for PPTX attachments; any other file type is rejected.
        - `label` string, nullable — Optional human-facing label.
  - `format` FormatInput
    - `category` 'slides' | 'social' | 'carousel' | 'pdf' | 'diagram' | 'ui' | 'animation' | 'prints' | 'web-ads' | 'other', nullable — Format category: 'slides', 'social', 'carousel', 'pdf', 'diagram', 'ui', 'animation', 'prints', 'web-ads', or 'other'. Controls the layout approach.
    - `width` integer, nullable — Canvas width in pixels. Common: 1920x1080 (slides), 1080x1080 (social square), 1080x1920 (social story).
    - `height` integer, nullable — Canvas height in pixels.
    - `label` string, nullable — Human-readable format label (e.g. 'Instagram Story', '16:9 Slides').
    - `dimensions` 'square' | 'linkedin' | 'portrait', nullable — Carousel dimensions preset. 'square' = 1080x1080, 'linkedin' = 1080x1350 LinkedIn landscape, 'portrait' = 1080x1920 Instagram story. Only used when ``category='carousel'``.
    - `page_count` integer, nullable — Number of carousel pages to generate. Capped at 5 per product constraint. Only used when ``category='carousel'``.
  - `model_tier` 'fable' | 'pro' | 'standard' | 'lite' | 'kimi-k2.5' | 'kimi-k2.6' | 'gpt-5.6', nullable — AI model tier: 'fable' (Expert — our most capable model), 'pro' (best for complex tasks), 'standard', 'lite', 'kimi-k2.5' (Fireworks-hosted Kimi K2.5), 'kimi-k2.6' (Fireworks-hosted Kimi K2.6), or 'gpt-5.6' (OpenAI GPT-5.6 at high reasoning). Defaults to automatic selection based on task complexity.
  - `reference_canvas_ids` string[], nullable — List of prefixed ``cvs_`` IDs to use as design inspiration. The agent can see these designs and reference their style, layout, or content.
  - `number_of_slides` integer, nullable — Optional maximum number of slides for slide-generation jobs. When omitted for slides, Moda defaults to an 8-slide target and clamps to your plan limit.
  - `export_on_complete` ExportOnCompleteOption — Auto-export preferences carried alongside a ``start_design_task`` request. The agent-jobs completion hook (``app.services.exports.auto_export``) reads these to decide whether to render the finished design, in what format, and at what scale. Defaults follow the canvas category — typically the right choice — so most callers leave the field unset entirely.
    - `enabled` boolean — When ``true`` (default), the design task auto-exports its finished canvas to ``result.export``. Set to ``false`` to skip the auto-export — useful when you only need the canvas reference and will request a different artifact later.
    - `format` 'png' | 'jpeg' | 'pdf' | 'pptx', nullable — Output format for the auto-export. Omit to use the canvas category default (``slides``→``pptx``, ``pdf``→``pdf``, others→``png``). Multi-page PNG/JPEG exports are delivered as a ``.zip`` of per-page files; in that case ``result.export.format`` is ``zip`` while the per-page files inside use the requested raster format.
    - `pixel_ratio` integer, nullable — Render scale multiplier (1-4). Omit to use the category default (``social``/``carousel`` PNGs render at 1×; PDFs at 3×; everything else at 2×). Pinning this matches the value that ``POST /v1/canvases/{id}/export`` would compute for the same canvas, so a follow-up manual export reuses the cached artifact.

## Response `200`

Successful Response

- Task — Canonical wire-format for every async design operation. All consumers -- REST, webhooks, SSE, MCP -- serialize through ``Task.from_db()`` so the shape is always consistent.
  - `id` string, required — Prefixed ``task_...`` identifier.
  - `kind` 'design' | 'export' | 'remix' | 'brand_kit_extract', required — Discriminator for the kind-specific ``result`` payload.
  - `status` 'queued' | 'running' | 'succeeded' | 'failed' | 'canceled' | 'expired', required — Frozen public status taxonomy. DB enum values are mapped at the API boundary -- never exposed directly.
  - `created_at` string, nullable — ISO 8601 timestamp.
  - `started_at` string, nullable — ISO 8601 timestamp.
  - `completed_at` string, nullable — ISO 8601 timestamp.
  - `progress` TaskProgress — Live progress indicator for a running task.
    - `percent` integer, nullable — Estimated completion percentage (0-100).
    - `step` string, nullable — Machine-readable step name the agent is executing.
    - `message` string, nullable — Human-readable progress message.
  - `attempt` integer, required — Current attempt number (1-based).
  - `max_attempts` integer, required — Maximum attempts before dead-lettering.
  - `input` object, nullable — Sanitized echo of the original request.
  - `result` TaskResult — Result payload of a design or remix task. Populated when ``status`` is ``succeeded``, and partially populated for some in-flight tasks (a remix surfaces its source canvas before the design task finishes). Extra keys are permitted so synchronous-completion payloads pass through without schema churn.
    - `canvas_id` string, nullable — Prefixed ``cvs_...`` id of the resulting canvas.
    - `canvas_url` string, nullable — URL to open the canvas in the Moda editor.
    - `canvas_name` string, nullable — Display name of the resulting canvas.
    - `conversation_id` string, nullable — Prefixed ``conv_...`` id — pass to a later task to keep iterating with full context.
    - `source_canvas_id` string, nullable — Prefixed ``cvs_...`` id of the source canvas, for template-remix tasks.
    - `source_canvas_url` string, nullable — Editor URL of the source canvas, for template-remix tasks.
    - `theme_canvas_id` string, nullable — Prefixed ``cvs_...`` id of the theme canvas attached to the resulting canvas, when a brand kit default theme was applied. Null when the deck is unthemed.
    - `export` TaskExport — Rendered export of a finished design task. Present on ``result.export`` once a programmatic (MCP / API) design task completes — the design is auto-exported in the canvas's category-default format and cached. Read this artifact directly instead of issuing a separate ``POST /v1/canvases/{id}/export`` for the same canvas.
      - `url` string, required — Signed, time-limited URL to download the rendered file.
      - `format` string, required — Delivered format — ``png``, ``jpeg``, ``pdf``, ``pptx``, or ``zip``. Multi-page PNG/JPEG exports are bundled into a ``.zip`` of per-page files (``page-1.png``, ``page-2.png``, …) since a single image container can't carry multiple pages.
      - `status` string, required — Render status; ``completed`` when the file is ready at ``url``.
      - `page_count` integer, required — Number of pages in the exported file.
  - `error` object, nullable — Error info for failed tasks: ``{message, retryable}``.
  - `credits` CreditUsage
    - `credits_used` integer, nullable — Number of credits consumed by this operation. Null if billing is not enabled or the job hasn't completed yet.
    - `credits_remaining` integer, nullable — Credit balance after this operation. Null if billing is not enabled.
  - `links` TaskLinks, required — HATEOAS-style links for navigating from a Task resource.
    - `self` string, required — Canonical URL of this task resource.
    - `events` string, nullable — SSE stream URL for real-time task events.
    - `cancel` string, nullable — URL to POST a cancellation request.
    - `canvas` string, nullable — URL to open the canvas in the Moda editor.
  - `retry_after_ms` integer, nullable — Suggested milliseconds to wait before the next poll. Null for terminal tasks.

## Other responses

- `401` — Authentication required.
- `403` — Permission denied for this scope.
- `404` — Resource not found.
- `409` — Conflict (idempotency / resource state).
- `422` — Request validation failed.
- `429` — Rate limit exceeded.
- `500` — Internal error.

---

[API](https://skmtc.dev/moda/apis/moda-public-api.md) · [All operations](https://skmtc.dev/moda/apis/moda-public-api/llms.txt) · [OpenAPI document](https://skmtc-service-production.skmtc.workers.dev/v1/apis/moda/moda-public-api/revisions/b34cb4cca59e/schema)
