NoteBugsDocs

API reference

Comments, attachments, history and links

What hangs off a card, and the history, which is read-only.

Comments and history stay outside the board payload: only the card dialog needs them. Attachments have two creation routes (the card's and the comment composer's), because a pasted image must exist before the comment does.

GET/api/cards/[id]/comments
Role: ViewerWorkspace

A card's comments, in chronological order.

Path parameters

FieldTypeDescription
idrequiredcuid

Request

curl -s http://localhost:3000/api/cards/cmttg1vv00017lf01ol5bnlx2/comments \
  -H "Authorization: Bearer $TOKEN"

Response200

[
  {
    "id": "cmttg1w7i001hlf01wiw5pjwa",
    "cardId": "cmttg1vv00017lf01ol5bnlx2",
    "content": "Primeira versão publicada em `/api`.",
    "createdAt": "2026-09-09T01:52:59.214Z",
    "updatedAt": "2026-09-09T01:52:59.214Z",
    "attachments": []
  }
]

Error responses

CodeWhen it happens
401No credential, or one that no longer holds. Send the session cookie or the Authorization: Bearer header.
403The account does not reach the resource's workspace. It is 403 and not 404 on purpose: the answer reveals no workspace.
404The resource does not exist, or has already been deleted.

Outside the /api/board payload: only the card dialog needs the body of the conversation.

POST/api/cards/[id]/comments
Role: MemberWorkspace

Comments on a card.

Path parameters

FieldTypeDescription
idrequiredcuid

Request body

FieldTypeDescription
contentrequiredstring (Markdown)Markdown. It is sanitised at render time, and what comes back here is the text as it was sent.
attachmentIdscuid[]The images the composer already uploaded through /comments/uploads and that the body references.

Request

curl -s -X POST http://localhost:3000/api/cards/cmttg1vv00017lf01ol5bnlx2/comments \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{ "content": "Primeira versão publicada em `/api`." }'

Response201

{
  "id": "cmttg1w7i001hlf01wiw5pjwa",
  "cardId": "cmttg1vv00017lf01ol5bnlx2",
  "content": "Primeira versão publicada em `/api`.",
  "createdAt": "2026-09-09T01:52:59.214Z",
  "updatedAt": "2026-09-09T01:52:59.214Z",
  "attachments": []
}

Error responses

CodeWhen it happens
401No credential, or one that no longer holds. Send the session cookie or the Authorization: Bearer header.
403The account does not reach the resource's workspace. It is 403 and not 404 on purpose: the answer reveals no workspace.
404The resource does not exist, or has already been deleted.
422The body did not pass the schema. The details field carries zod's fieldErrors and formErrors, field by field.
PATCH/api/comments/[id]
Role: MemberWorkspace

Edits a comment.

Path parameters

FieldTypeDescription
idrequiredcuid

Request body

FieldTypeDescription
contentrequiredstring (Markdown)
attachmentIdscuid[]

Request

curl -s -X PATCH http://localhost:3000/api/comments/cmttg1w7i001hlf01wiw5pjwa \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{ "content": "Primeira versão publicada. Revisado." }'

Response200

{
  "id": "cmttg1w7i001hlf01wiw5pjwa",
  "cardId": "cmttg1vv00017lf01ol5bnlx2",
  "content": "Primeira versão publicada em `/api`.",
  "createdAt": "2026-09-09T01:52:59.214Z",
  "updatedAt": "2026-09-09T01:52:59.214Z",
  "attachments": []
}

Error responses

CodeWhen it happens
401No credential, or one that no longer holds. Send the session cookie or the Authorization: Bearer header.
403The account does not reach the resource's workspace. It is 403 and not 404 on purpose: the answer reveals no workspace.
404The resource does not exist, or has already been deleted.
422The body did not pass the schema. The details field carries zod's fieldErrors and formErrors, field by field.
DELETE/api/comments/[id]
Role: MemberWorkspace

Deletes a comment, taking its images along.

Path parameters

FieldTypeDescription
idrequiredcuid

Request

curl -s -X DELETE http://localhost:3000/api/comments/cmttg1w7i001hlf01wiw5pjwa \
  -H "Authorization: Bearer $TOKEN"

Response200

{ "deleted": true }

Error responses

CodeWhen it happens
401No credential, or one that no longer holds. Send the session cookie or the Authorization: Bearer header.
403The account does not reach the resource's workspace. It is 403 and not 404 on purpose: the answer reveals no workspace.
404The resource does not exist, or has already been deleted.
POST/api/cards/[id]/comments/uploads
Role: MemberWorkspacemultipart/form-data

Uploads a comment's images before publishing it.

It exists apart from creation because the composer needs the image URL to write it into the Markdown, before the comment exists. The attachments are born with scope: COMMENT and loose, and the attachmentIds of creation binds them.

Path parameters

FieldTypeDescription
idrequiredcuid

Request body

FieldTypeDescription
filesrequiredarquivo[]

Request

curl -s -X POST http://localhost:3000/api/cards/cmttg1vv00017lf01ol5bnlx2/comments/uploads \
  -H "Authorization: Bearer $TOKEN" \
  -F "[email protected]"

Response201

[
  {
    "id": "cmttg2rz8001llf010yq4sk1m",
    "storedName": "18ab694d-48ed-4b56-bd2b-3a324fec55de.png",
    "originalName": "print.png",
    "mimeType": "image/png",
    "size": 25381,
    "url": "/api/files/18ab694d-48ed-4b56-bd2b-3a324fec55de.png"
  }
]

Error responses

CodeWhen it happens
401No credential, or one that no longer holds. Send the session cookie or the Authorization: Bearer header.
403Attachments are disabled in this installation.
404The resource does not exist, or has already been deleted.
413The file is over the maximum size per attachment.
415The format is not accepted. It is identified by the magic bytes, not by the file name extension.
POST/api/cards/[id]/attachments
Role: MemberWorkspacemultipart/form-data

Attaches one or more files to the card.

Path parameters

FieldTypeDescription
idrequiredcuid

Request body

FieldTypeDescription
filesrequiredarquivo[]Repeat the field to send several. file, singular, is also accepted.

Request

curl -s -X POST http://localhost:3000/api/cards/cmttg1vv00017lf01ol5bnlx2/attachments \
  -H "Authorization: Bearer $TOKEN" \
  -F "[email protected]" \
  -F "[email protected]"

Response201

[
  {
    "id": "cmttg2rz8001llf010yq4sk1m",
    "storedName": "18ab694d-48ed-4b56-bd2b-3a324fec55de.png",
    "originalName": "print.png",
    "mimeType": "image/png",
    "size": 25381,
    "url": "/api/files/18ab694d-48ed-4b56-bd2b-3a324fec55de.png"
  }
]

Error responses

CodeWhen it happens
400No file came in the multipart, or the file is empty.
401No credential, or one that no longer holds. Send the session cookie or the Authorization: Bearer header.
403Attachments are disabled in this installation.
404The resource does not exist, or has already been deleted.
413The file is over the maximum size per attachment.
415The format is not accepted. It is identified by the magic bytes, not by the file name extension.

The file name is generated by the SERVER, and the type is detected from the magic bytes: the extension of the sent name decides nothing.

DELETE/api/attachments/[id]
Role: MemberWorkspace

Removes the attachment and the file behind it.

Path parameters

FieldTypeDescription
idrequiredcuid

Request

curl -s -X DELETE http://localhost:3000/api/attachments/cmttg2rz8001llf010yq4sk1m \
  -H "Authorization: Bearer $TOKEN"

Response200

{ "deleted": true }

Error responses

CodeWhen it happens
401No credential, or one that no longer holds. Send the session cookie or the Authorization: Bearer header.
403The account does not reach the resource's workspace. It is 403 and not 404 on purpose: the answer reveals no workspace.
404The resource does not exist, or has already been deleted.
GET/api/cards/[id]/history
Role: ViewerWorkspace

The card's history of column changes, oldest first.

The column travels by the NAME it had at the moment of the change: renaming or deleting the column afterwards does not rewrite the past.

Path parameters

FieldTypeDescription
idrequiredcuid

Request

curl -s http://localhost:3000/api/cards/cmttg1vv00017lf01ol5bnlx2/history \
  -H "Authorization: Bearer $TOKEN"

Response200

[
  {
    "id": "cmttg1vw50019lf01b7knmm8g",
    "fromName": null,
    "toName": "A fazer",
    "movedAt": "2026-09-09T01:52:58.805Z"
  },
  {
    "id": "cmttg1w3r001flf01xfiggnhl",
    "fromName": "A fazer",
    "toName": "Fazendo",
    "movedAt": "2026-09-09T01:52:59.080Z"
  }
]

Error responses

CodeWhen it happens
401No credential, or one that no longer holds. Send the session cookie or the Authorization: Bearer header.
403The account does not reach the resource's workspace. It is 403 and not 404 on purpose: the answer reveals no workspace.
404The resource does not exist, or has already been deleted.

There is no history write route. The record is written by the server, in the same transaction that changes the column, along the three paths that change it.

POST/api/cards/[id]/relations
Role: MemberWorkspace

Creates a link with the route's card as the SOURCE.

The route knows nothing about “direction chosen on screen”: for the inverse labels (“is a child of”, “is blocked by”), the client swaps the ids and calls this same route on the other card.

Path parameters

FieldTypeDescription
idrequiredcuid

Request body

FieldTypeDescription
targetIdrequiredcuidThe target card, from the same workspace.
kindrequiredenumThe link type, in the source → target direction.PARENT · BLOCKS · GENERATED · RELATED

Request

curl -s -X POST http://localhost:3000/api/cards/cmttg1vv00017lf01ol5bnlx2/relations \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "targetId": "cmttg1vyj001blf01888i4wn8",
    "kind": "BLOCKS"
  }'

Response201

{
  "id": "cmttg2rve001jlf018csp3gc0",
  "sourceId": "cmttg1vv00017lf01ol5bnlx2",
  "targetId": "cmttg1vyj001blf01888i4wn8",
  "kind": "BLOCKS",
  "createdAt": "2026-09-09T01:53:40.251Z"
}

Error responses

CodeWhen it happens
401No credential, or one that no longer holds. Send the session cookie or the Authorization: Bearer header.
403The account does not reach the resource's workspace. It is 403 and not 404 on purpose: the answer reveals no workspace.
404The resource does not exist, or has already been deleted.
409A link between those two cards already exists. There is at most one, in either direction.
422A card does not link to itself.
422Both cards must be in the same workspace. That boundary has no setting that opens it.
422Links across different projects are turned off. Enable allowCrossProjectLinks in Settings: two cards with no project count as the same grouping.

There is at most ONE link between two cards, in either direction.

DELETE/api/relations/[id]
Role: MemberWorkspace

Removes the link: it disappears from both cards.

Path parameters

FieldTypeDescription
idrequiredcuid

Request

curl -s -X DELETE http://localhost:3000/api/relations/cmttg2rve001jlf018csp3gc0 \
  -H "Authorization: Bearer $TOKEN"

Response200

{ "deleted": true }

Error responses

CodeWhen it happens
401No credential, or one that no longer holds. Send the session cookie or the Authorization: Bearer header.
403The account does not reach the resource's workspace. It is 403 and not 404 on purpose: the answer reveals no workspace.
404The resource does not exist, or has already been deleted.