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.
Canvases and exports
All canvas-shaped read + export flows live under/v1/canvases and /v1/remix. Plus the share-token read pattern for public canvases and the /v1/share_links/resolve helper.
Endpoints
| Verb | Path | Scope |
|---|---|---|
| GET | /canvases | canvases:read |
| GET | /canvases/search | canvases:read |
| GET | /canvases/{id} | designs:read |
| GET | /canvases/{id}/tokens | designs:read |
| GET | /canvases/{id}/pages | designs:read |
| POST | /canvases/{id}/export | designs:export |
| POST | /canvases/{id}/share | canvases:write |
| POST | /remix | tasks:write |
| POST | /share_links/resolve | (public) |
Listing and search
{data, next_cursor}). Sort is (created_at DESC, id DESC). See pagination.md.
List items include id, name, url, category, visibility, created_at, updated_at.
Reading a canvas
get_moda_canvas. Requires team access.
Reading a public share
POST /v1/share_links/resolve to parse a share URL first:
Tokens only
{variables, colors, fonts, radii, dimensions} — fast path for theme regeneration in CI.
Pages metadata
{canvas_name, total_pages, pages: [{page_number, name, width, height, node_count}]}. Call before GET /v1/canvases/{id}?page_number=N on multi-page canvases to plan per-page fetches.
Export — synchronous
| Param | Values | Default |
|---|---|---|
format | png / jpeg / pdf / pptx | png |
page_number | integer ≥ 1 | all pages for documents, page 1 for images |
pixel_ratio | 1–4 | server default |
flatten | bool (PDF only — raster-only no text) | true |
designs:export and team membership. Share-token-only callers (no team access) cannot export — reads via share_token are not enough.
Export when a design task is running
If the target canvas has an in-flight design task, export returns:Retry-After seconds and retry. This is expected behavior in pipelines that chain a task → export — either pass through the wait, or (better) let the task’s webhook trigger the export.
Export is NOT a Task
Unlike design / remix / brand-kit extraction, exports don’t return a Task envelope today. Theexport kind exists in webhook event types (for future async export flows), but POST /v1/canvases/{id}/export itself is inline. Don’t poll /v1/tasks/{id} for an export.
Sharing — blocking thumbnail default
wait_for_thumbnail: false to skip if you don’t care about unfurls.
Remix
kind: "remix"). Without a prompt: the task is synchronous, returns status: "succeeded" inline, result.canvas_id is the new canvas. With a prompt: queues a design task on the copy, returns non-terminal; poll same as /tasks/{id}.
The source canvas is never modified.
Design-to-code walk
POST /v1/canvases/{id}/export?format=png.
Common wrong guesses
- Expecting
POST /v1/canvases/{id}/exportto return a Task envelope. Synchronous; returns{url, format}inline. - Treating the
409 canvas_active_jobresponse as a bug. It’s the intended retry signal when chaining task → export. - Ignoring
Retry-Afteron the 409 response. Back off the suggested seconds; don’t hammer. - Using
share_token=to export. Only reads are permitted via share token. Export requires team access. - Skipping
wait_for_thumbnail: falseon/sharecalls in a script. By default it blocks — in a batch share-link generator, the latency adds up. Passfalseif you don’t care about unfurls. - Treating
GET /v1/canvases/{id}withoutpage_numberas cheap on multi-page designs. It returns all pages concatenated. - Holding an export URL longer than 7 days. Expires. Re-export if needed.
- Storing the
X-Request-IDheader from a successful export to use as an idempotency key. That’s what the body-fieldidempotency_keyonPOST /v1/tasksis for — exports don’t need it (stateless + fast).