---
title: "Create a card with optional inline checklist"
method: POST
path: "/api/boards/{boardId}/cards"
tags: ["Cards"]
---

# Create a card with optional inline checklist

`POST /api/boards/{boardId}/cards`

## Request

- Base URL: `https://tre-app.com`
- URL: `https://tre-app.com/api/boards/{boardId}/cards`
- Auth: HTTP bearer

Pass `ifSimilar: 'reject'` to be refused with 409 CONFLICT and `details: { similar: [{ cardKey, title, similarity }] }` — the titles on the workspace's boards you can read with trigram similarity >= 0.5, at most five, best first; a private board you are not a member of is never consulted — instead of creating a near-duplicate. Default is 'create'. A `description` over the 2000-character cap answers 400 VALIDATION_ERROR with `details: { rule: 'index-card', limit: 2000, hint }` — the hint names the index-card split of card-authoring.md; the validation message itself carries the same hint, which is also what MCP callers receive, in the same envelope, since the server validates tool inputs itself (2026-09-11). `kind: 'guidance'` cannot be set at creation by a Bearer token, grant or not (403 FORBIDDEN, `details.reason: 'no_consent_path'`): create the card, then promote it with updateCard under a guidance write grant with `confirm: 'guidance'` and `expectedUpdatedAt`; a workspace owner or admin sets it from the web app directly.

## Headers

- `Idempotency-Key` string

## Request body

- CardCreate
  - `title` string, required
  - `listId` string, uuid, required
  - `description` string: Concise narrative context carrying only the current truth, written under fixed uppercase labels: `PURPOSE: …`, a dated `STATUS YYYY-MM-DD: …` line rewritten in place (preserve its date during editorial corrections), `NEXT STEP: action → who` (who acts: the name of a person, the name of a token, or `waiting for <name> (<organisation>)`; a date only when real) — or the Italian set SCOPO / STATO / PROSSIMO PASSO. The server reads that dated line for freshness and staleness; the colon is the canonical delimiter, a dash is accepted and normalized to it. A line break is stored as `\n`: `\r\n` or a lone `\r` is accepted and normalized to it, so the text you read back can differ from the text you sent by those characters. History belongs in dated card comments, never in layered corrections here. Do not place a mutable list of independently trackable records or steps here; use checklist items.
  - `color` string
  - `startDate` string, date, nullable: Start of the retained plan (not an observed start). For one exact operational deadline, pass the same ISO day in startDate and endDate. Never infer it from a reference date.
  - `endDate` string, date, nullable: End of the retained plan (not an observed completion). For one exact operational deadline, pass the same ISO day in startDate and endDate.
  - `scheduleState` 'unclassified' | 'planned' | 'suspended' | 'cancelled': Meaning of the retained schedule; one server rule on every surface. Omit it: a create with a planned date is stored as planned, one without as unclassified; on update, touching a planned date promotes unclassified to planned, clearing both planned dates resets to unclassified, any other stored state is kept. Send suspended or cancelled explicitly; a non-unclassified state with both planned dates null is refused (400 BAD_REQUEST).
  - `actualStartDate` string, date, nullable: Observed start, explicitly recorded from evidence. Independent of the schedule; null means unknown, never not started.
  - `actualEndDate` string, date, nullable: Observed end, explicitly recorded from evidence. May fall outside the plan. Null means unknown, never incomplete.
  - `verifiedOn` string, date, nullable: Day the named source was actually checked, never later than the server UTC day. Independent of updatedAt and the status date in the description; never advance for editorial work.
  - `verificationSource` string, nullable: Source reference and scope of the last factual verification (document, record, URL or cardKey). Set or clear together with verifiedOn.
  - `links` object[]
    - `label` string, required
    - `url` string, required
  - `assigneeUserIds` string[]
  - `kind` 'control' | 'work' | 'reference' | 'decision' | 'digest' | 'guidance': What the card is for: control | work | reference | decision | digest | guidance. `guidance` cannot be set at creation by a token (403): create the card, then promote it with update_card under a guidance write grant (Settings → API tokens → Allow guidance writes) with confirm: 'guidance' and expectedUpdatedAt; a workspace owner or admin sets it from the web app directly.
  - `ifSimilar` 'create' | 'reject': Duplicate guard over the titles on boards you can read in the workspace (trigram similarity >= 0.5, at most five): 'reject' answers 409 CONFLICT with details.similar and creates nothing; the default 'create' creates the card and returns those titles as similar in the response, so a near-duplicate is never silent.
  - `position` union: Where the new card lands: 'top', 'bottom' (the default), or { afterCardId } — the anchor is the card's UUID only, not a cardKey.
    - 'top'
    - 'bottom'
    - object
      - `afterCardId` string, uuid, required
  - `checklist` object[]: Initial checklist: one item per independently trackable source record, decision, execution step, or verification gate. Permanent control cards remain even when this array is empty.
    - `text` string, required: Text for one independently trackable source record, decision, execution step, or verification gate. Begin with a stable source identifier when one exists.
    - `assigneeUserId` string, uuid, nullable
    - `priority` 'none' | 'low' | 'normal' | 'high' | 'urgent'

## Response `201`

Success

- Card
  - `id` string, uuid, required
  - `boardId` string, uuid, required
  - `listId` string, uuid, required
  - `cardNumber` integer, required
  - `cardKey` string, required
  - `title` string, required
  - `description` string, required
  - `color` string, required
  - `order` integer, required
  - `startDate` string, date, nullable, required
  - `endDate` string, date, nullable, required
  - `scheduleState` 'unclassified' | 'planned' | 'suspended' | 'cancelled', required: Meaning of the retained schedule. Unclassified means its intent has not been reviewed; suspended/cancelled retain the plan for retrospective comparison.
  - `actualStartDate` string, date, nullable, required: Observed start, explicitly recorded from evidence. Independent of the schedule; null means unknown, never not started.
  - `actualEndDate` string, date, nullable, required: Observed end, explicitly recorded from evidence. May fall outside the plan. Null means unknown, never incomplete.
  - `verifiedOn` string, date, nullable, required: Day the named source was actually checked, never later than the server UTC day. Independent of updatedAt and the status date in the description; never advance for editorial work.
  - `verificationSource` string, nullable, required: Source reference and scope of the last factual verification (document, record, URL or cardKey). Set or clear together with verifiedOn.
  - `links` object[], required
    - `label` string, required
    - `url` string, required
  - `createdAt` string, date-time, required
  - `updatedAt` string, date-time, required
  - `createdByUserId` string, uuid, nullable, required
  - `assigneeUserIds` string[], required
  - `kind` 'control' | 'work' | 'reference' | 'decision' | 'digest' | 'guidance', nullable, required

## Other responses

- `400`: Invalid request
- `401`: Unauthenticated
- `403`: Forbidden: insufficient role or token scope; scope denials name the held scope and the operation
- `404`: Not found
- `409`: Conflict
- `422`: Idempotency-Key reused with a different request body (IDEMPOTENCY_KEY_REUSED)
- `429`: Rate limited
- `500`: Internal server error
- `503`: Temporarily unavailable

---

[API](https://skmtc.dev/tre-app/apis/tre-rest-api.md) · [All operations](https://skmtc.dev/tre-app/apis/tre-rest-api/llms.txt) · [OpenAPI document](https://skmtc.dev/tre-app/apis/tre-rest-api/revisions/26a7187a05fc?raw)
