Cards

Update card fields

Pass expectedUpdatedAt (the updatedAt you read) to refuse the write with 412 when someone changed the card in between, instead of silently replacing their work. Or pass expectedSeq (the card's seq from getCard, exclusive with expectedUpdatedAt) to also cover comment, checklist-item and subtask writes and moves across lists — not reorders, a move within one list, or an editor autosave inside its checkpoint window, which append no event (pass expectedUpdatedAt when a human may be typing in the card). A call that changes nothing — every field restated as the card holds it, assignees merely reordered — writes nothing: no event, no Tre-Event-Seq, and updatedAt stays, so the expectedUpdatedAt you hold remains valid; anything that does change moves updatedAt, a reorder of links included (reported as changes.links.reordered). A 412 carries details.currentSeq and details.events (missed events, oldest first, at most 20; eventsTruncated when there were more). While a subtask holds a planned date, the card's plan can be widened but neither cleared nor narrowed under it: the refusal (400, details.rule CARD_HAS_NO_DATES or SUBTASK_OUT_OF_RANGE) names the blocking subtask and the narrowest plan that would do — Tre never widens the card for you. A description over the 2000-character cap answers 400 VALIDATION_ERROR with details: { rule: 'index-card', limit: 2000, hint } and the same hint in the validation message (see createCard). To rewrite one block and leave the rest exactly as it is, send sections instead of description: { STATUS: { date: 'YYYY-MM-DD', text }, NEXT_STEP, PURPOSE, OTHER } (or STATO / PROSSIMO_PASSO / SCOPO / ALTRO; null clears a block; both together answer 400). A block's text ends at the next line that opens with an uppercase LABEL:: a paragraph such as SOURCES: … or CONTEXT: … belongs to OTHER and survives a write to the other three blocks (one the stored document had filed inside the block you rewrite is moved to the front of OTHER, and the event names other too); a write never touches a block it does not name. For the same reason the text you send for PURPOSE, STATUS or NEXT STEP cannot itself carry such a line below its first: 400 BAD_REQUEST with details: { rule: 'block-text', block, line } — send the block without it. To change or remove the paragraph, write OTHER, which is replaced whole. The server composes the description from the blocks; the STATUS/STATO it replaces goes to the description history (GET /api/cards/{cardId}/history) and leaves no comment. On reference, digest and guidance cards the dated block is written as UPDATED/AGGIORNATO whichever of STATUS/STATO/UPDATED/AGGIORNATO you send. The event names the blocks in sections. The composed description, labels and the blank lines between blocks included, must fit the 2000-character cap: past it the write answers 400 BAD_REQUEST with details: { rule: 'index-card', block, limit: 2000 } naming the longest block, so a text accepted on create can be refused on update — shorten it or move content to checklist items, comments or links. On a call that sends sections alone, a stale expectedUpdatedAt no longer refuses outright: the write applies when none of the blocks you name changed in between, and the answer carries merged.sections (the blocks others changed); a named block that moved on answers 412 with details.conflictingSections, so re-read that block only. A stale call that also sends any other field (a title, a kind, a date, links, assignees — even one restated unchanged) is refused whole with 412 and writes nothing: send the blocks in their own call. The workspace guidance card is gated: rewriting its description, setting kind: 'guidance' on a card, or changing the kind of the card that is guidance is for a workspace owner or admin from the web app — or for a Bearer token that owner or admin has allowed for the workspace (grantGuidanceWrite; Settings → API tokens → Allow guidance writes), which must then send confirm: 'guidance' AND expectedUpdatedAt in the same call. Without a live grant the answer is 403 FORBIDDEN with details: { reason, grant: 'guidance-write', how } (reason is no_grant, grant_expired, grant_revoked or not_workspace_admin; no_consent_path is the refusal of the consent-less paths — createCard with kind: 'guidance' and restoreCardHistoryVersion — never of this operation); with a grant but without the consent it is 400 BAD_REQUEST with details: { missing: [...] }; a stale expectedUpdatedAt is the 412 above. A granted write's card.updated event carries guidance: { grantId, grantedBy, grantedAt, expiresAt } beside its diff.

patch/api/cards/{cardId}

Request

  • Base URL: https://tre-app.com
  • URL: https://tre-app.com/api/cards/{cardId}
  • Auth: HTTP bearer

Request body

expectedUpdatedAtstring date-time

The updatedAt you read before deciding this change, passed back VERBATIM — the comparison is exact string equality against the stored ISO serialization, not a timestamp comparison. When the card has changed since, the update is refused (412) instead of overwriting the other writer — re-read and decide again. It guards the card row alone: comments, checklist items, subtasks and moves never bump updatedAt. Exclusive with expectedSeq.

expectedSeqinteger

The card's seq from get_card (or the receipt of your last write to this card: seq runs across the workspace, so the receipt of a write to another card would pass over this card's events). The write is refused with 412 when any retained event of the card has seq greater than this — comment, checklist-item and subtask writes, moves across lists and update_card/PATCH writes to the card row. What appends no event is not seen: a reorder, a move within one list, or an editor autosave inside its checkpoint window (pass expectedUpdatedAt when a human may be typing in the card). Exclusive with expectedUpdatedAt. A card with no retained events has seq 0; expectedSeq 0 then passes.

titlestring
descriptionstring

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.

colorstring
startDatestring 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.

endDatestring 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).

actualStartDatestring date nullable

Observed start, explicitly recorded from evidence. Independent of the schedule; null means unknown, never not started.

actualEndDatestring date nullable

Observed end, explicitly recorded from evidence. May fall outside the plan. Null means unknown, never incomplete.

verifiedOnstring 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.

verificationSourcestring nullable

Source reference and scope of the last factual verification (document, record, URL or cardKey). Set or clear together with verifiedOn.

assigneeUserIdsstring[]
kind'control' | 'work' | 'reference' | 'decision' | 'digest' | 'guidance' nullable

What the card is for; null clears it. Lint reads reference/digest/guidance. Setting guidance, changing the kind of the guidance card, or rewriting its description is for a workspace owner or admin from the web app — or for a token that owner or admin has allowed for it (Settings → API tokens → Allow guidance writes, time-limited and revocable), which must then also send confirm: 'guidance' and expectedUpdatedAt; any other caller answers 403.

confirm'guidance'

Required, together with expectedUpdatedAt, when a token rewrites the guidance card's description, promotes a card to kind guidance or changes the guidance card's kind under a guidance write grant: pass exactly 'guidance'. Ignored on every other write.

Response

Success

idstring uuid required
boardIdstring uuid required
listIdstring uuid required
cardNumberinteger required
cardKeystring required
titlestring required
descriptionstring required
colorstring required
orderinteger required
startDatestring date nullable required
endDatestring 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.

actualStartDatestring date nullable required

Observed start, explicitly recorded from evidence. Independent of the schedule; null means unknown, never not started.

actualEndDatestring date nullable required

Observed end, explicitly recorded from evidence. May fall outside the plan. Null means unknown, never incomplete.

verifiedOnstring 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.

verificationSourcestring nullable required

Source reference and scope of the last factual verification (document, record, URL or cardKey). Set or clear together with verifiedOn.

createdAtstring date-time required
updatedAtstring date-time required
createdByUserIdstring uuid nullable required
assigneeUserIdsstring[] required
kind'control' | 'work' | 'reference' | 'decision' | 'digest' | 'guidance' nullable required

Changes

No recorded changes to this operation across all 1 revision of this API.