Comments

Manage comments on docs and insights.

Comments let you add threaded conversations to docs. Page-level comments discuss the whole doc, while inline comments attach to a text selection. Comments are available under /docs/:doc_id/comments.

The same endpoints exist under /insights/:insight_id/comments, but the /insights paths are deprecated. Use /docs for all new integrations.

Endpoints

MethodPathDescription
GET/docs/:doc_id/commentsList all comments on a doc
GET/docs/:doc_id/comments/:comment_idGet a single comment
POST/docs/:doc_id/commentsCreate a comment
PATCH/docs/:doc_id/comments/:comment_idUpdate a comment
DELETE/docs/:doc_id/comments/:comment_idDelete a comment
POST/docs/:doc_id/comments/resolveResolve the comment thread
POST/docs/:doc_id/comments/unresolveUnresolve the comment thread

Listing comments

Retrieve all comments on a doc, including inline comments. Comments are returned in chronological order by default. Pass ?include_text_range=true to include selected text for inline comments.

GET https://dovetail.com/api/v1/docs/<DOC_ID>/comments
Authorization: Bearer <DOVETAIL_API_TOKEN>
{
  "data": [
    {
      "id": "<COMMENT_ID>",
      "body": "Great insight! We should follow up on this.",
      "author": {
        "id": "<USER_ID>",
        "name": "Jane Smith"
      },
      "created_at": "2026-01-15T10:30:00.000Z",
      "updated_at": "2026-01-15T10:30:00.000Z",
      "comment_type": "inline",
      "thread_id": "<THREAD_ID>"
    }
  ],
  "page": {
    "total_count": 1,
    "has_more": false,
    "next_cursor": null
  },
  "thread": {
    "resolved": false,
    "resolved_at": null,
    "resolved_by": null
  }
}

The thread field is null if no page-level comments have been posted. thread_id on each comment groups replies. On list, text_range is omitted unless include_text_range=true. Single-comment GET, PATCH, and DELETE always include text_range (null for page-level comments).

You can control sort order with the sort query parameter: created_at:asc (default) or created_at:desc. See Pagination for paging through results.

Getting a single comment

GET https://dovetail.com/api/v1/docs/<DOC_ID>/comments/<COMMENT_ID>
Authorization: Bearer <DOVETAIL_API_TOKEN>
{
  "data": {
    "id": "<COMMENT_ID>",
    "body": "Great insight! We should follow up on this.",
    "author": {
      "id": "<USER_ID>",
      "name": "Jane Smith"
    },
    "created_at": "2026-01-15T10:30:00.000Z",
    "updated_at": "2026-01-15T10:30:00.000Z",
    "comment_type": "page",
    "thread_id": "<THREAD_ID>",
    "text_range": null
  }
}

Creating a comment

POST https://dovetail.com/api/v1/docs/<DOC_ID>/comments
Authorization: Bearer <DOVETAIL_API_TOKEN>
Content-Type: application/json

{
  "body": "Great insight! We should follow up on this.",
  "body_type": "text"
}

If no page-level comment thread exists on the doc, one is created automatically. By default the comment is attributed to the authenticated user — i.e. the user that owns the API token. Pass optional thread_id from list or get comments to reply on that page-level or inline thread (404 if the thread is missing or not on this doc).

Content format

The body_type field controls how the body input is interpreted:

ValueDescription
textPlain text (default). Line breaks are preserved.
htmlHTML content. Tags like <strong>, <em>, <a>, etc. are supported.

Regardless of the input format, the body field in responses is always returned as plain text.

The maximum comment length is 10,000 characters.

Attributing a comment to another user (admin)

Workspace admins can pass an optional author_id when creating a comment to attribute it to a different workspace user. This is useful when importing existing comments from another tool — without it, every imported comment would appear to be authored by the API token's owner.

POST https://dovetail.com/api/v1/docs/<DOC_ID>/comments
Authorization: Bearer <DOVETAIL_API_TOKEN>
Content-Type: application/json

{
  "body": "Comment imported from Linear",
  "author_id": "<USER_ID>"
}
{
  "data": {
    "id": "<COMMENT_ID>",
    "body": "Comment imported from Linear",
    "author": {
      "id": "<USER_ID>",
      "name": "Jane Smith"
    },
    "created_at": "2026-01-15T10:30:00.000Z",
    "updated_at": "2026-01-15T10:30:00.000Z",
    "comment_type": "page",
    "thread_id": "<THREAD_ID>",
    "text_range": null
  }
}

Rules:

  • The API token's owner must be a workspace admin. Non-admin tokens that include author_id get 403 Forbidden. Tokens without author_id continue to work as before.
  • The target user (author_id) must be an active member of the same workspace. Missing, deleted, or out-of-workspace users get 400 Bad Request.
  • Once set, the comment is owned by author_id for permission purposes — only that user (not the original API caller) can edit or delete it via the API. The override is recorded in the workspace audit log as comment.author_id.updated.
  • author_id is only honoured at creation time. The PATCH endpoint cannot change a comment's author.

Updating a comment

PATCH https://dovetail.com/api/v1/docs/<DOC_ID>/comments/<COMMENT_ID>
Authorization: Bearer <DOVETAIL_API_TOKEN>
Content-Type: application/json

{
  "body": "Updated comment text.",
  "body_type": "text"
}

Only the original author of a comment can update it. Attempting to update another user's comment will return a 403 Forbidden error.

Deleting a comment

DELETE https://dovetail.com/api/v1/docs/<DOC_ID>/comments/<COMMENT_ID>
Authorization: Bearer <DOVETAIL_API_TOKEN>

Only the original author of a comment can delete it. The deleted comment is returned in the response. Deleted comments can be restored for up to 30 days.

Resolving and unresolving threads

Each doc has one page-level comment thread and may have multiple inline threads. These endpoints resolve or unresolve the page-level thread only; inline thread resolution is not exposed by the public API.

Resolve

POST https://dovetail.com/api/v1/docs/<DOC_ID>/comments/resolve
Authorization: Bearer <DOVETAIL_API_TOKEN>
{
  "data": {
    "resolved": true,
    "resolved_at": "2026-01-15T12:00:00.000Z",
    "resolved_by": {
      "id": "<USER_ID>",
      "name": "Jane Smith"
    }
  }
}

Unresolve

POST https://dovetail.com/api/v1/docs/<DOC_ID>/comments/unresolve
Authorization: Bearer <DOVETAIL_API_TOKEN>
{
  "data": {
    "resolved": false,
    "resolved_at": null,
    "resolved_by": null
  }
}

Did this page help you?