---
title: "List Templates"
method: GET
path: "/templates"
tags: ["canvas-actions"]
---

# List Templates

`GET /templates`

## Request

- Base URL: `https://api.moda.app/v1`
- URL: `https://api.moda.app/v1/templates`
- Auth: HTTP bearer

List the team's template canvases with signed thumbnails (newest first).

The discovery half of the template flow: VIEW the thumbnails (download the
signed URLs and look at them — same discipline as brand logos), pick a
template whose look fits, then instantiate it with ``POST /v1/canvases`` +
``template_canvas_id``. ``total`` is the true team-wide template count;
when ``has_more`` is ``true``, pass ``next_cursor`` for the rest.

Team-scoped only — templates from other teams never appear, and the ids
here are ordinary canvas ids usable across the canvas endpoints.

## Query parameters

- `cursor` string, nullable: Opaque pagination cursor. Pass the ``next_cursor`` from the previous response. Omit on the first request.
- `limit` integer: Max templates per page. Defaults to 20, caps at 100.

## Headers

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

## Response `200`

Successful Response

- ListTemplatesResponse: Cursor-paginated team-template list (uniform #9317 envelope). ``total`` is the true team-wide template count — the filter is an indexed real column (``template_type``) over a small team-scoped set, so the COUNT is cheap (the brand-kits lane's posture, not the JSONB-bound canvases lane's). ``returned``/``has_more`` are derived server-side.
  - `data` TemplateItem[], required: Templates in this page, newest first.
    - `id` string, required: Canvas wire id (``cvs_...``) — pass as ``template_canvas_id`` to instantiate.
    - `uuid` string, required: The same canvas id as a bare UUID.
    - `editor_url` string, required: Full URL to open the template canvas in the Moda editor (a template IS a canvas).
    - `name` string, required: Template display name.
    - `category` string, nullable: Canvas format category (slides, social, carousel, pdf, diagram, ui, animation, prints, web-ads, other) — ``null`` when unset. The copy inherits it.
    - `page_count` integer, required: Number of pages in the template document, from the stored projection — may briefly lag a template that is being live-edited right now. The copy always carries the source's real pages.
    - `description` string, nullable: Template description, when the team wrote one.
    - `tags` string[], nullable: Template tags, when set.
    - `thumbnail_url` string, nullable: Signed thumbnail URL (bounded lifetime, ~24h) — download it to LOOK at the template with your own vision before choosing; ``null`` when no thumbnail has been rendered yet. Use-and-discard: never persist this URL.
    - `thumbnail_unavailable` boolean: ``true`` when a thumbnail EXISTS but its URL could not be signed right now (transient) — distinct from ``thumbnail_url: null`` with ``false``, which means no thumbnail has been rendered. Don't skip the template for a transient signing failure; retry the list.
    - `created_at` string, nullable: ISO 8601 creation timestamp.
    - `updated_at` string, nullable: ISO 8601 last-modification timestamp.
  - `next_cursor` string, nullable: Opaque cursor to pass as ``?cursor=`` on the next request. ``null`` means you've reached the end of the collection.
  - `returned` integer: Number of items in this page (always ``len(data)``; derived server-side).
  - `has_more` boolean: ``true`` when more items exist beyond this page — keep requesting with ``next_cursor`` until this is ``false``. Never trust ``len(data) < limit`` alone.
  - `limit` integer, nullable: The effective page-size limit this response was computed with.
  - `total` integer, nullable: True total number of items in the collection (after filters), when the endpoint can count cheaply. ``null`` on log/search lanes — use ``has_more`` there.

## Other responses

- `401`: Authentication required.
- `402`: Insufficient credits for a metered operation.
- `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.

## Changes

- **2026-11-03** `9ac6a3abc0f8`: 1 info
  - endpoint added

[Operation history](https://skmtc.dev/moda/apis/moda-public-api/changes/templates/get.md)

---

[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.dev/moda/apis/moda-public-api/revisions/9ac6a3abc0f8?raw)
