# Comments endpoints

> Task comments on a run. Every operation with parameters, body, responses, errors and examples.

Source: https://developers.processcart.com/reference/comments

Task comments on a run.

Base URL `https://app.processcart.com/api/v1`. Every operation below is also in the [OpenAPI document](https://developers.processcart.com/openapi.json) and the [interactive reference](https://developers.processcart.com/reference).

| Operation | Method and path | Scope |
| --- | --- | --- |
| [List a run's comments](#listRunComments) | <code class="pc-docs-wrap">GET /v1<wbr>/runs<wbr>/{id}<wbr>/comments</code> | Scope `runs:read` |
| [Comment on a task](#createRunComment) | <code class="pc-docs-wrap">POST /v1<wbr>/runs<wbr>/{id}<wbr>/comments</code> | Scope `runs:write` |
| [Get a comment](#getRunComment) | <code class="pc-docs-wrap">GET /v1<wbr>/runs<wbr>/{id}<wbr>/comments<wbr>/{commentId}</code> | Scope `runs:read` |

## GET /v1/runs/{id}/comments
**List a run's comments.** Scope `runs:read` · checked against the key's workflow / folder allowlist (403 `not_allowed_for_key` outside it) · paginated (`{ data, nextCursor, hasMore }`). Operation id `listRunComments` · [open in the API reference](https://developers.processcart.com/reference#tag/comments/GET/v1/runs/{id}/comments).

The run's live comments, oldest first, with the author, the sanitized body, a plain-text rendering and the mentioned member ids. A run in Trash still answers.

**Path parameters**

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `id` | string (uuid) | yes |  |

**Query parameters** (an unknown parameter is a 422 `validation_failed` with `errors[].code = "unknown_parameter"`)

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `limit` | integer | no |  |
| `cursor` | string | no | The `nextCursor` of the previous page. Opaque, and bound to the query that produced it — a cursor from a different filter or sort is a 422. |

**Responses**

| Status | Meaning | Body |
| --- | --- | --- |
| 200 | OK. | [ListRunCommentsResponse](https://developers.processcart.com/reference/schemas#listruncommentsresponse) |
| 401 | No usable credential. `unauthorized` — Authentication required; `invalid_api_key` — Invalid API key; `key_revoked` — API key revoked. | [Problem](https://developers.processcart.com/errors) |
| 403 | `insufficient_scope` — Insufficient scope; `not_allowed_for_key` — Not allowed for this key. | [Problem](https://developers.processcart.com/errors) |
| 404 | `not_found` — Not found. | [Problem](https://developers.processcart.com/errors) |
| 405 | The verb is not supported on this path. `method_not_allowed` — Method not allowed. | [Problem](https://developers.processcart.com/errors) |
| 422 | `validation_failed` — Validation failed. | [Problem](https://developers.processcart.com/errors) |
| 429 | `rate_limited` — Too many requests. | [Problem](https://developers.processcart.com/errors) |
| 500 | `internal_error` — Internal error. | [Problem](https://developers.processcart.com/errors) |
| 503 | `unavailable` — Service unavailable. | [Problem](https://developers.processcart.com/errors) |

**Errors** (every code this operation can answer; see [Errors](https://developers.processcart.com/errors))

- 401 [`invalid_api_key`](https://developers.processcart.com/errors#invalid_api_key) — Invalid API key
- 401 [`key_revoked`](https://developers.processcart.com/errors#key_revoked) — API key revoked
- 401 [`unauthorized`](https://developers.processcart.com/errors#unauthorized) — Authentication required
- 403 [`insufficient_scope`](https://developers.processcart.com/errors#insufficient_scope) — Insufficient scope
- 403 [`not_allowed_for_key`](https://developers.processcart.com/errors#not_allowed_for_key) — Not allowed for this key
- 404 [`not_found`](https://developers.processcart.com/errors#not_found) — Not found
- 405 [`method_not_allowed`](https://developers.processcart.com/errors#method_not_allowed) — Method not allowed
- 422 [`validation_failed`](https://developers.processcart.com/errors#validation_failed) — Validation failed
- 429 [`rate_limited`](https://developers.processcart.com/errors#rate_limited) — Too many requests
- 500 [`internal_error`](https://developers.processcart.com/errors#internal_error) — Internal error
- 503 [`unavailable`](https://developers.processcart.com/errors#unavailable) — Service unavailable

**Example response** (200)

```json
{
  "data": [
    {
      "id": "32629d31-996c-48af-8637-261a6aea7eca",
      "runId": "3245e6a5-3fbe-463a-ad0b-a7fd871957b0",
      "taskKey": "details",
      "runTaskId": "7d6b86f6-5f67-4729-870c-ed29c1be3009",
      "author": {
        "kind": "api",
        "keyId": "d422b49f-a3f2-4244-b97e-8d50f25c3036",
        "name": "collab key"
      },
      "body": {
        "type": "doc",
        "content": [
          {
            "type": "paragraph",
            "content": [
              {
                "text": "Hello from the API",
                "type": "text"
              },
              {
                "type": "hardBreak"
              },
              {
                "text": "second line",
                "type": "text"
              }
            ]
          }
        ]
      },
      "text": "Hello from the API\nsecond line",
      "mentions": [],
      "createdAt": "2026-10-13T01:09:30.295Z",
      "editedAt": null,
      "url": "https://app.processcart.com/runs/3245e6a5-3fbe-463a-ad0b-a7fd871957b0?task=details"
    },
    {
      "id": "65c213cd-053b-47aa-93ec-c7fd21b06a49",
      "runId": "3245e6a5-3fbe-463a-ad0b-a7fd871957b0",
      "taskKey": "details",
      "runTaskId": "7d6b86f6-5f67-4729-870c-ed29c1be3009",
      "author": {
        "kind": "api",
        "keyId": "d422b49f-a3f2-4244-b97e-8d50f25c3036",
        "name": "collab key"
      },
      "body": {
        "type": "doc",
        "content": [
          {
            "type": "paragraph",
            "content": [
              {
                "text": "Ping ",
                "type": "text"
              },
              {
                "type": "mention",
                "attrs": {
                  "id": "0515df8b-d0b5-43c5-b535-3b87ec2df4a8",
                  "label": "Fixture Member"
                }
              },
              {
                "text": " and ",
                "type": "text"
              },
              {
                "text": " cc ",
                "type": "text"
              },
              {
                "type": "mention",
                "attrs": {
                  "id": "f3e7a668-7e78-44f2-bc92-4457a9a54337",
                  "label": "Fixture Admin"
                }
              }
            ]
          }
        ]
      },
      "text": "Ping @Fixture Member and  cc @Fixture Admin",
      "mentions": [
        "0515df8b-d0b5-43c5-b535-3b87ec2df4a8",
        "f3e7a668-7e78-44f2-bc92-4457a9a54337"
      ],
      "createdAt": "2026-10-13T01:09:32.773Z",
      "editedAt": null,
      "url": "https://app.processcart.com/runs/3245e6a5-3fbe-463a-ad0b-a7fd871957b0?task=details"
    },
    {
      "id": "b70b33e8-8a42-4289-8fa7-564929b05c43",
      "runId": "3245e6a5-3fbe-463a-ad0b-a7fd871957b0",
      "taskKey": "details",
      "runTaskId": "7d6b86f6-5f67-4729-870c-ed29c1be3009",
      "author": {
        "kind": "user",
        "userId": "f3e7a668-7e78-44f2-bc92-4457a9a54337",
        "name": "Fixture Admin"
      },
      "body": {
        "type": "doc",
        "content": [
          {
            "type": "paragraph",
            "content": [
              {
                "text": "From Ada",
                "type": "text"
              }
            ]
          }
        ]
      },
      "text": "From Ada",
      "mentions": [],
      "createdAt": "2026-10-13T01:09:34.271Z",
      "editedAt": null,
      "url": "https://app.processcart.com/runs/3245e6a5-3fbe-463a-ad0b-a7fd871957b0?task=details"
    }
  ],
  "nextCursor": null,
  "hasMore": false
}
```


## POST /v1/runs/{id}/comments
**Comment on a task.** Scope `runs:write` · checked against the key's workflow / folder allowlist (403 `not_allowed_for_key` outside it) · accepts `Idempotency-Key`. Operation id `createRunComment` · [open in the API reference](https://developers.processcart.com/reference#tag/comments/POST/v1/runs/{id}/comments).

Posts a comment on one of the run's tasks as the API key (`author.kind` = `api`). Send plain `text` or a rich `body` — never both. The body is sanitized strictly: unknown node and mark types are dropped, a mention's label is re-derived from the member list, and a mention of a non-member is removed. Mentioned members are notified. Comments never change the run's revision. Refused on an archived or trashed run.

**Path parameters**

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `id` | string (uuid) | yes |  |

**Request headers**

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `Idempotency-Key` | string | no | Makes the request safe to retry: a second request with the same key and a byte-identical body (and the same `Expected-Revision`) replays the stored response (`Idempotent-Replayed: true`); a different body with the same key is refused (422 `idempotency_key_reused`) and no second resource is created. Keys are stored per workspace for 24 hours and replayed only to the API key that made the request (or the key one rotation away from it); another API key sending the same value is refused (422 `idempotency_key_reused`), so prefix keys per integration. 409, 429 and 5xx answers are never stored. |

**Request body** — `application/json`, [CreateRunCommentBody](https://developers.processcart.com/reference/schemas#createruncommentbody)

| Property | Type | Required | Description |
| --- | --- | --- | --- |
| `taskKey` | string | yes | The task to comment on (any task of the run). |
| `text` | string | no | Plain text: blank lines separate paragraphs, a single newline is a line break, and `@Name` becomes a mention when it matches exactly one member. |
| `body` | object | no | A rich-text document (ProseMirror JSON). Allowed node types: paragraph, text, heading, bulletList, orderedList, listItem, blockquote, codeBlock, hardBreak, horizontalRule, image, table, tableRow, tableCell, tableHeader, mention, mergeTag (attrs.fieldKey must be a valid field key, else dropped), embed (an https video src on YouTube, Loom or Vimeo, else removed); marks: bold, italic, code, link, textStyle, highlight. Anything else is dropped on save. A mention node is `{ type: "mention", attrs: { id: "<member user id>" } }` — its label is always re-derived from the member list. |

**Responses**

| Status | Meaning | Body |
| --- | --- | --- |
| 201 | Created. `Location` names the new resource. | [Comment](https://developers.processcart.com/reference/schemas#comment) |
| 401 | No usable credential. `unauthorized` — Authentication required; `invalid_api_key` — Invalid API key; `key_revoked` — API key revoked. | [Problem](https://developers.processcart.com/errors) |
| 403 | `insufficient_scope` — Insufficient scope; `not_allowed_for_key` — Not allowed for this key; `read_only_key` — Read-only key. | [Problem](https://developers.processcart.com/errors) |
| 404 | `not_found` — Not found. | [Problem](https://developers.processcart.com/errors) |
| 405 | The verb is not supported on this path. `method_not_allowed` — Method not allowed. | [Problem](https://developers.processcart.com/errors) |
| 409 | `idempotency_in_progress` — Request in progress; `run_archived` — Run is archived; `run_trashed` — Run is in Trash. | [Problem](https://developers.processcart.com/errors) |
| 413 | `payload_too_large` — Payload too large. | [Problem](https://developers.processcart.com/errors) |
| 415 | `unsupported_media_type` — Unsupported media type. | [Problem](https://developers.processcart.com/errors) |
| 422 | `idempotency_key_reused` — Idempotency key reused; `validation_failed` — Validation failed. | [Problem](https://developers.processcart.com/errors) |
| 429 | `rate_limited` — Too many requests. | [Problem](https://developers.processcart.com/errors) |
| 500 | `internal_error` — Internal error. | [Problem](https://developers.processcart.com/errors) |
| 503 | `unavailable` — Service unavailable. | [Problem](https://developers.processcart.com/errors) |

**Errors** (every code this operation can answer; see [Errors](https://developers.processcart.com/errors))

- 401 [`invalid_api_key`](https://developers.processcart.com/errors#invalid_api_key) — Invalid API key
- 401 [`key_revoked`](https://developers.processcart.com/errors#key_revoked) — API key revoked
- 401 [`unauthorized`](https://developers.processcart.com/errors#unauthorized) — Authentication required
- 403 [`insufficient_scope`](https://developers.processcart.com/errors#insufficient_scope) — Insufficient scope
- 403 [`not_allowed_for_key`](https://developers.processcart.com/errors#not_allowed_for_key) — Not allowed for this key
- 403 [`read_only_key`](https://developers.processcart.com/errors#read_only_key) — Read-only key
- 404 [`not_found`](https://developers.processcart.com/errors#not_found) — Not found
- 405 [`method_not_allowed`](https://developers.processcart.com/errors#method_not_allowed) — Method not allowed
- 409 [`idempotency_in_progress`](https://developers.processcart.com/errors#idempotency_in_progress) — Request in progress
- 409 [`run_archived`](https://developers.processcart.com/errors#run_archived) — Run is archived
- 409 [`run_trashed`](https://developers.processcart.com/errors#run_trashed) — Run is in Trash
- 413 [`payload_too_large`](https://developers.processcart.com/errors#payload_too_large) — Payload too large
- 415 [`unsupported_media_type`](https://developers.processcart.com/errors#unsupported_media_type) — Unsupported media type
- 422 [`idempotency_key_reused`](https://developers.processcart.com/errors#idempotency_key_reused) — Idempotency key reused
- 422 [`validation_failed`](https://developers.processcart.com/errors#validation_failed) — Validation failed
- 429 [`rate_limited`](https://developers.processcart.com/errors#rate_limited) — Too many requests
- 500 [`internal_error`](https://developers.processcart.com/errors#internal_error) — Internal error
- 503 [`unavailable`](https://developers.processcart.com/errors#unavailable) — Service unavailable

**Example request**

```json
{
  "taskKey": "details",
  "text": "Hello from the API\nsecond line"
}
```

**Example response** (201)

```json
{
  "id": "32629d31-996c-48af-8637-261a6aea7eca",
  "runId": "3245e6a5-3fbe-463a-ad0b-a7fd871957b0",
  "taskKey": "details",
  "runTaskId": "7d6b86f6-5f67-4729-870c-ed29c1be3009",
  "author": {
    "kind": "api",
    "keyId": "d422b49f-a3f2-4244-b97e-8d50f25c3036",
    "name": "collab key"
  },
  "body": {
    "type": "doc",
    "content": [
      {
        "type": "paragraph",
        "content": [
          {
            "type": "text",
            "text": "Hello from the API"
          },
          {
            "type": "hardBreak"
          },
          {
            "type": "text",
            "text": "second line"
          }
        ]
      }
    ]
  },
  "text": "Hello from the API\nsecond line",
  "mentions": [],
  "createdAt": "2026-10-13T01:09:30.295Z",
  "editedAt": null,
  "url": "https://app.processcart.com/runs/3245e6a5-3fbe-463a-ad0b-a7fd871957b0?task=details"
}
```


## GET /v1/runs/{id}/comments/{commentId}
**Get a comment.** Scope `runs:read` · checked against the key's workflow / folder allowlist (403 `not_allowed_for_key` outside it). Operation id `getRunComment` · [open in the API reference](https://developers.processcart.com/reference#tag/comments/GET/v1/runs/{id}/comments/{commentId}).

One live comment of the run — the resource a `POST` answered with (its `Location`). A deleted comment is a 404.

**Path parameters**

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `id` | string (uuid) | yes |  |
| `commentId` | string (uuid) | yes |  |

**Responses**

| Status | Meaning | Body |
| --- | --- | --- |
| 200 | OK. | [Comment](https://developers.processcart.com/reference/schemas#comment) |
| 401 | No usable credential. `unauthorized` — Authentication required; `invalid_api_key` — Invalid API key; `key_revoked` — API key revoked. | [Problem](https://developers.processcart.com/errors) |
| 403 | `insufficient_scope` — Insufficient scope; `not_allowed_for_key` — Not allowed for this key. | [Problem](https://developers.processcart.com/errors) |
| 404 | `not_found` — Not found. | [Problem](https://developers.processcart.com/errors) |
| 405 | The verb is not supported on this path. `method_not_allowed` — Method not allowed. | [Problem](https://developers.processcart.com/errors) |
| 422 | `validation_failed` — Validation failed. | [Problem](https://developers.processcart.com/errors) |
| 429 | `rate_limited` — Too many requests. | [Problem](https://developers.processcart.com/errors) |
| 500 | `internal_error` — Internal error. | [Problem](https://developers.processcart.com/errors) |
| 503 | `unavailable` — Service unavailable. | [Problem](https://developers.processcart.com/errors) |

**Errors** (every code this operation can answer; see [Errors](https://developers.processcart.com/errors))

- 401 [`invalid_api_key`](https://developers.processcart.com/errors#invalid_api_key) — Invalid API key
- 401 [`key_revoked`](https://developers.processcart.com/errors#key_revoked) — API key revoked
- 401 [`unauthorized`](https://developers.processcart.com/errors#unauthorized) — Authentication required
- 403 [`insufficient_scope`](https://developers.processcart.com/errors#insufficient_scope) — Insufficient scope
- 403 [`not_allowed_for_key`](https://developers.processcart.com/errors#not_allowed_for_key) — Not allowed for this key
- 404 [`not_found`](https://developers.processcart.com/errors#not_found) — Not found
- 405 [`method_not_allowed`](https://developers.processcart.com/errors#method_not_allowed) — Method not allowed
- 422 [`validation_failed`](https://developers.processcart.com/errors#validation_failed) — Validation failed
- 429 [`rate_limited`](https://developers.processcart.com/errors#rate_limited) — Too many requests
- 500 [`internal_error`](https://developers.processcart.com/errors#internal_error) — Internal error
- 503 [`unavailable`](https://developers.processcart.com/errors#unavailable) — Service unavailable

**Example response** (200)

```json
{
  "id": "32629d31-996c-48af-8637-261a6aea7eca",
  "runId": "3245e6a5-3fbe-463a-ad0b-a7fd871957b0",
  "taskKey": "details",
  "runTaskId": "7d6b86f6-5f67-4729-870c-ed29c1be3009",
  "author": {
    "kind": "api",
    "keyId": "d422b49f-a3f2-4244-b97e-8d50f25c3036",
    "name": "collab key"
  },
  "body": {
    "type": "doc",
    "content": [
      {
        "type": "paragraph",
        "content": [
          {
            "text": "Hello from the API",
            "type": "text"
          },
          {
            "type": "hardBreak"
          },
          {
            "text": "second line",
            "type": "text"
          }
        ]
      }
    ]
  },
  "text": "Hello from the API\nsecond line",
  "mentions": [],
  "createdAt": "2026-10-13T01:09:30.295Z",
  "editedAt": null,
  "url": "https://app.processcart.com/runs/3245e6a5-3fbe-463a-ad0b-a7fd871957b0?task=details"
}
```
