Comments API Threading, mentions, reactions, and reference anchoring for workspace and share entities.

Base URL: https://api.fast.io/current/ Auth: Bearer {jwt_token} Content-Type: application/json Format: JSON

Comments use JSON request bodies (Content-Type: application/json), unlike most other Fastio endpoints which use application/x-www-form-urlencoded.


Endpoint Summary

MethodEndpointDescription
GET /current/comments/{entity_type}/{parent_id}/ List all comments in a workspace, share, or File Share
GET /current/comments/{entity_type}/{parent_id}/{node_id}/ List comments for a specific node
POST /current/comments/{entity_type}/{parent_id}/ Create or update a comment on an entity
POST /current/comments/{entity_type}/{parent_id}/{node_id}/ Create or update a comment on a node
POST /current/comments/{comment_id}/update/ Edit a comment by ID (works for every comment surface, incl. task comments)
GET /current/comments/{comment_id}/details/ Get a single comment's details
DELETE /current/comments/{comment_id}/delete/ Soft-delete a comment and its replies
POST /current/comments/bulk/delete/ Bulk soft-delete multiple comments
POST /current/comments/{comment_id}/reactions/ Add or change an emoji reaction
DELETE /current/comments/{comment_id}/reactions/ Remove an emoji reaction
POST /current/comments/{comment_id}/link/ Link a comment to a workflow entity
POST /current/comments/{comment_id}/unlink/ Unlink a comment from a workflow entity
GET /current/comments/linked/{entity_type}/{entity_id}/ Get all comments linked to a workflow entity
GET /current/comments/{comment_id}/attachments/ List a comment's attachments (hydrated, access-gated)
POST /current/comments/{comment_id}/attachments/ Attach one or many objects to a comment
POST /current/comments/{comment_id}/attachments/detach/ Detach an object from a comment
GET /current/tasks/{list_id}/items/{task_id}/comments/ List a task's comment thread
POST /current/tasks/{list_id}/items/{task_id}/comments/ Post a comment on a task

Searching comments: To search comments by keyword, use the unified search endpoint — GET /current/workspace/{workspace_id}/search/ (or /current/share/{share_id}/search/) returns a comments bucket alongside files and other types, each with its own pagination. See Unified Search in the Storage Operations reference. Comment search results are permission-filtered to comments the caller can see. Task comments (see Task Comments below) are private to their task and are excluded from comment search.


Path Parameters

Comments are scoped to a workspace, share, or File Share, and optionally to a specific node (file or folder) within it. When no node ID is specified, all comments across the entire workspace or share are returned.

ParameterTypeFormatDescription
{entity_type} string "workspace", "share", or "fileshare" Entity type discriminator
{parent_id} string 19-digit numeric Workspace or share profile ID. Note: Do not confuse with parent_id in the POST request body, which is the parent comment ID for threading.
{node_id} string Alphanumeric opaque ID File or folder ID within the entity (optional)
{comment_id} string Alphanumeric opaque ID Comment identifier

File Share comments. When {entity_type} is "fileshare", {parent_id} is the File Share's 19-digit numeric profile ID. Comments on a File Share are scoped to that File Share — a recipient sees only the comments made under it, never comments on the same underlying file from the owning workspace or from another File Share. Commenting requires the viewer to be signed in; public anyone-with-link visitors cannot comment. Comments are available only when the File Share owner has enabled comments, and they are always disabled on public anyone-with-link shares. A client should read the File Share's effective comments_enabled flag from its details response to decide whether to show the comment UI.


Comment Object

Every comment returned by the API has this structure:

FieldTypeDescription
id string Alphanumeric opaque ID of the comment
entity string Opaque ID of the entity the comment belongs to (workspace, share, File Share, or node)
user_id string 19-digit numeric ID of the comment author
parent_id string|null Opaque ID of the parent comment (for replies), or null for top-level
body string Comment text content (may include mention markup)
profile_type string|null The container type ("workspace", "share", or "fileshare") that owns the entity
profile_id string|null 19-digit numeric ID of the workspace, share, or File Share that owns the entity
scope_id string|null When a comment originated under a File Share and is surfaced in a workspace context, the 19-digit numeric ID of that File Share — a present (non-null) value marks the comment as "via File Share". Null/omitted for comments that originated directly in the workspace or share
linked_entity_type string|null If linked to a workflow entity, one of "task", "workflow_review", or "approval"; otherwise null. "approval" is legacy-accepted for backward compatibility; new links should use "workflow_review"
linked_entity_id string|null Opaque ID of the linked workflow entity, or null
reference object|null Anchoring reference to a position in a file (see Reference Anchoring)
mentions array The server-validated set of mentioned profile IDs that took effect (19-digit numeric strings). Always present; empty when no mention took effect. This is the authoritative took-effect set — mentions in the body markup that fail validation (e.g. a non-member) are excluded here
reactions object Map of emoji character to total reaction count (e.g., {"👍": 3})
user_reaction string|null The current authenticated user's emoji reaction, or null
version_hash string|null Hash representing the current comment content version
version integer Monotonically increasing version counter (starts at 1)
attachment_count integer Number of objects attached to the comment (see Comment Attachments). Present on comment list rows and the comment detail response
attachments array Hydrated, access-gated attachment rows (see Comment Attachments). Detail endpoint only
edited_at string|null Timestamp of last edit if the comment has been edited (YYYY-MM-DD HH:MM:SS UTC), or null
can_edit boolean Whether the requesting user can edit this comment
can_delete boolean Whether the requesting user can delete this comment
can_reply boolean Whether the comment can be replied to (top-level only)
created string Creation timestamp (YYYY-MM-DD HH:MM:SS UTC)
updated string Last-updated timestamp (YYYY-MM-DD HH:MM:SS UTC)
deleted string|null Deletion timestamp (YYYY-MM-DD HH:MM:SS UTC), or null if active. Only included on the get-details endpoint or when explicitly requesting deleted comments.

Note: the server-validated mentions set is surfaced as the top-level mentions array described above. The raw internal properties object (threading, pinning, content-filter flags, etc.) is never returned — only the curated mentions list is exposed.


List Comments

GET /current/comments/{entity_type}/{parent_id}/

List all comments across the entire workspace or share.

GET /current/comments/{entity_type}/{parent_id}/{node_id}/

List comments for a specific node within an entity.

Without {node_id}: returns all comments across the entire workspace or share. With {node_id}: returns only comments on that specific file or folder.

Note: Only comments created or edited after 2026-03-15 are included in scope-level results (without {node_id}); older comments are accessible via the node-level endpoint.

Auth: Required (JWT). Rate limited.

Query Parameters

ParameterTypeRequiredDefaultConstraintsDescription
sort string No asc "asc" or "desc" Sort order by creation time
limit integer No Min: 2, Max: 200 Number of comments to return
offset integer No 0 Min: 0 Number of comments to skip
page integer No Min: 1 Page number (alternative to offset-based pagination)
include_deleted boolean No false Include soft-deleted comments in results
reference_type string No Filter by reference anchor type (e.g., "page", "timestamp")
include_total boolean No false Include total count and pagination metadata in response

Request Example

curl -X GET "https://api.fast.io/current/comments/workspace/1234567890123456789/?limit=50&include_total=true" \
  -H "Authorization: Bearer {jwt_token}"

Response

{
  "result": true,
  "comments": [
    {
      "id": "abc123opaqueid",
      "entity": "xyz789opaqueid",
      "user_id": "1234567890123456789",
      "parent_id": null,
      "body": "This looks great!",
      "profile_type": "workspace",
      "profile_id": "1234567890123456789",
      "reference": null,
      "mentions": [],
      "reactions": {"👍": 2, "❤️": 1},
      "user_reaction": "👍",
      "version": 1,
      "can_edit": true,
      "can_delete": true,
      "can_reply": true,
      "created": "2025-01-15 10:30:00 UTC",
      "updated": "2025-01-15 10:30:00 UTC"
    }
  ],
  "count": 1,
  "allowed": true,
  "remaining": 95,
  "total": 5,
  "limit": 50,
  "offset": 0
}

Response Fields

FieldTypeDescription
response.comments array Array of comment objects
response.count int Number of comments in this response
response.allowed bool Whether the current user can post new comments (based on plan limits)
response.remaining int Remaining comments allowed under plan limit (only present if plan has a limit)
response.total int Total number of comments (only if include_total=true)
response.limit int Limit used in query (only if include_total=true)
response.offset int Offset used in query (only if include_total=true)

Access Levels

RoleAccess
Workspace Owner/MemberFull access — sees all comments
Share OwnerFull access — sees all comments
Share GuestFiltered — sees own comments; visibility of owner and other guest comments depends on share permissions

Error Responses

Error CodeHTTP StatusMessageCause
1605 (Invalid Input)400Invalid API format...Missing entity type or parent ID
1605 (Invalid Input)400Entity type must be "workspace" or "share"Invalid entity type
1680 (Access Denied)403Invalid entity or insufficient permissionsUser lacks access
1609 (Not Found)404Invalid entity or insufficient permissionsEntity not found
1654 (Internal Error)500Failed to retrieve commentsInternal error

Workspace node reads include File Share comments. A file shared through a File Share is the same node that lives in the owning workspace, so a workspace node read (GET /current/comments/workspace/{workspace_id}/{node_id}/) also returns comments left by File Share recipients on that file. Those File Share comments appear read-only in the workspace view: can_reply, can_edit, and can_delete are false (replies and edits to a File Share comment go through the File Share's own surface). The total count reflects everything visible in the listing (the workspace's own comments plus the File Share comments), while the allowed / remaining fields reflect only the workspace's own writable comments — so remaining is not reduced by File Share comments you cannot edit. This inclusion is one-directional: workspace members see File Share comments, but File Share recipients never see the workspace's internal comments.


Create or Update Comment

POST /current/comments/{entity_type}/{parent_id}/

Create a new comment or update an existing one on an entity.

POST /current/comments/{entity_type}/{parent_id}/{node_id}/

Create a new comment or update an existing one on a specific node.

Auth: Required (JWT). Rate limited.

Content-Type: application/json

Request Body

FieldTypeRequiredConstraintsDescription
body string Required 1–8192 chars (raw); display text excluding mentions max 500 chars Comment text content
comment_id string No Valid opaque ID Include to update an existing comment; omit to create new
parent_id string No Valid opaque ID Parent comment ID for threaded reply (single-level only). Note: This is the parent comment's opaque ID, not the workspace/share ID from the URL path {parent_id}.
properties object No Arbitrary key-value metadata to attach
reference object No See Reference Anchoring Anchoring reference to a position in a file
target_id string No Valid object ID Inline attachment on a new comment — a single object to attach (see Comment Attachments). Ignored on update
target_ids array<string> No Non-empty array Inline attachments on a new comment — multiple objects to attach, up to 25 per comment. Ignored on update

Request Example — Create a new comment

curl -X POST "https://api.fast.io/current/comments/workspace/1234567890123456789/" \
  -H "Authorization: Bearer {jwt_token}" \
  -H "Content-Type: application/json" \
  -d '{
    "body": "Great work on this document!"
  }'

Request Example — Reply to a comment

curl -X POST "https://api.fast.io/current/comments/workspace/1234567890123456789/" \
  -H "Authorization: Bearer {jwt_token}" \
  -H "Content-Type: application/json" \
  -d '{
    "body": "Thanks for the feedback!",
    "parent_id": "abc123opaqueid"
  }'

Request Example — Comment with mention and page reference

curl -X POST "https://api.fast.io/current/comments/workspace/1234567890123456789/" \
  -H "Authorization: Bearer {jwt_token}" \
  -H "Content-Type: application/json" \
  -d '{
    "body": "Hey @[user:9876543210987654321:Jane Smith], can you review page 3?",
    "reference": {"type": "page", "page": 3}
  }'

Request Example — Update an existing comment

curl -X POST "https://api.fast.io/current/comments/workspace/1234567890123456789/" \
  -H "Authorization: Bearer {jwt_token}" \
  -H "Content-Type: application/json" \
  -d '{
    "comment_id": "def456opaqueid",
    "body": "Updated: This looks great after the revision."
  }'

Response

{
  "result": true,
  "comment": {
    "id": "abc123opaqueid",
    "entity": "xyz789opaqueid",
    "user_id": "1234567890123456789",
    "parent_id": null,
    "body": "Great work on this document!",
    "profile_type": "workspace",
    "profile_id": "1234567890123456789",
    "reference": null,
    "reactions": {},
    "user_reaction": null,
    "version": 1,
    "can_edit": true,
    "can_delete": true,
    "can_reply": true,
    "created": "2025-01-15 10:30:00 UTC",
    "updated": "2025-01-15 10:30:00 UTC"
  }
}

Response Fields

FieldTypeDescription
response.comment object The created or updated comment object (full schema above)

Access Levels

RoleAccess
Workspace Owner/MemberCan create and edit own comments
Share OwnerCan create and edit own comments
Share GuestCan only post if comments are enabled on the share

Error Responses

Error CodeHTTP StatusMessageCause
1680 (Access Denied)403Authentication required to post commentsUser not authenticated
1605 (Invalid Input)400Invalid JSON in request bodyMalformed JSON
1605 (Invalid Input)400Comment body must be between 1 and 8192 charactersBody length out of range
1605 (Invalid Input)400Comment text (excluding mentions) must not exceed 500 charactersDisplay text too long
1605 (Invalid Input)400Your comment appears to contain spam content...Spam detected
1605 (Invalid Input)400Invalid parent comment ID formatMalformed parent_id
1609 (Not Found)404Parent comment not foundReferenced parent does not exist
1605 (Invalid Input)400Parent comment belongs to different entityParent is on a different entity
1605 (Invalid Input)400Invalid reference data: ...Reference failed validation
1605 (Invalid Input)400Comment limit exceeded for your planPlan comment limit reached
1609 (Not Found)404Comment not foundComment ID for update not found
1680 (Access Denied)403You do not have permission to edit this commentUser is not the comment author
1654 (Internal Error)500Failed to save commentInternal error

Notes


Update Comment by ID

POST /current/comments/{comment_id}/update/

Edit an existing comment by its ID. Author-only. Works for every comment surface — workspace, share, node, File Share, and task comments. (The entity-scoped update above cannot address a task comment, whose entity is the task itself — use this endpoint.)

Auth: Required (JWT). Rate limited.

Content-Type: application/json

Request Body

FieldTypeRequiredConstraintsDescription
body string Required 1–8192 chars (raw); display text excluding mentions max 500 chars Replacement comment text
properties object No Arbitrary key-value metadata to merge
reference object No See Reference Anchoring Replacement anchoring reference

Request Example

curl -X POST "https://api.fast.io/current/comments/abc123opaqueid/update/" \
  -H "Authorization: Bearer {jwt_token}" \
  -H "Content-Type: application/json" \
  -d '{
    "body": "Updated: this looks great after the revision."
  }'

Response

The full updated comment object (same shape as Create or Update Comment above), with edited_at populated.

Error Responses

Error CodeHTTP StatusMessageCause
1605 (Invalid Input)400Comment body must be between 1 and 8192 charactersBody length out of range
1605 (Invalid Input)400Comment is deletedThe comment has been deleted
1609 (Not Found)404Comment not foundUnknown comment ID, or the comment's surface is not visible to you
1680 (Access Denied)403You do not have permission to edit this commentCaller is not the comment author

Notes


Get Comment Details

GET /current/comments/{comment_id}/details/

Get a single comment's full details.

Auth: Required (JWT). Rate limited.

Request Example

curl -X GET "https://api.fast.io/current/comments/abc123opaqueid/details/" \
  -H "Authorization: Bearer {jwt_token}"

Response

{
  "result": true,
  "comment": {
    "id": "abc123opaqueid",
    "entity": "xyz789opaqueid",
    "user_id": "1234567890123456789",
    "parent_id": null,
    "body": "This looks great!",
    "profile_type": "workspace",
    "profile_id": "1234567890123456789",
    "reference": null,
    "reactions": {},
    "user_reaction": null,
    "version": 1,
    "can_edit": true,
    "can_delete": true,
    "can_reply": true,
    "created": "2025-01-15 10:30:00 UTC",
    "updated": "2025-01-15 10:30:00 UTC",
    "deleted": null
  }
}

Error Responses

Error CodeHTTP StatusMessageCause
1605 (Invalid Input)400Comment ID is requiredMissing comment ID
1605 (Invalid Input)400Invalid comment ID formatMalformed opaque ID
1609 (Not Found)404Comment not foundComment does not exist
1680 (Access Denied)403You do not have permission to view this commentUser lacks access to the entity

Delete Comment

DELETE /current/comments/{comment_id}/delete/

Soft-delete a comment. Recursive — also deletes all replies to this comment.

Who can delete: the comment's author, and workspace/share admins or owners (moderation — admins can remove any comment on their workspace or share). File Share comments can only be deleted by their author; they are never moderator-deletable, including from the workspace view. The can_delete flag on every returned comment reflects this, so clients should drive the delete affordance from can_delete.

Auth: Required (JWT). Rate limited.

Request Example

curl -X DELETE "https://api.fast.io/current/comments/abc123opaqueid/delete/" \
  -H "Authorization: Bearer {jwt_token}"

Response

{
  "result": true,
  "message": "Comment deleted successfully",
  "comment": {
    "id": "abc123opaqueid",
    "entity": "xyz789opaqueid",
    "user_id": "1234567890123456789",
    "parent_id": null,
    "body": "This looks great!",
    "profile_type": "workspace",
    "profile_id": "1234567890123456789",
    "reference": null,
    "reactions": {},
    "user_reaction": null,
    "version": 1,
    "can_edit": false,
    "can_delete": false,
    "can_reply": false,
    "created": "2025-01-15 10:30:00 UTC",
    "updated": "2025-01-16 08:00:00 UTC",
    "deleted": "2025-01-16 08:00:00 UTC"
  }
}

Access Levels

RoleAccess
Comment AuthorCan delete own comments
Entity OwnerCan delete any comment on their entity
Other UsersDenied

Error Responses

Error CodeHTTP StatusMessageCause
1605 (Invalid Input)400Comment ID is requiredMissing comment ID
1605 (Invalid Input)400Invalid comment ID formatMalformed opaque ID
1609 (Not Found)404Comment not foundComment does not exist
1605 (Invalid Input)400Comment is already deletedComment was previously deleted
1680 (Access Denied)403You do not have permission to delete this commentNot author or entity owner
1654 (Internal Error)500Failed to delete commentInternal error

Bulk Delete Comments

POST /current/comments/bulk/delete/

Bulk soft-delete multiple comments. Each comment is processed independently — partial success is possible. NOT recursive — does not delete replies.

Auth: Required (JWT). Rate limited.

Content-Type: application/json

Request Body

FieldTypeRequiredConstraintsDescription
comment_ids array<string> Required Max 100 items Array of comment opaque IDs to delete

Request Example

curl -X POST "https://api.fast.io/current/comments/bulk/delete/" \
  -H "Authorization: Bearer {jwt_token}" \
  -H "Content-Type: application/json" \
  -d '{"comment_ids": ["abc123opaqueid", "def456opaqueid", "ghi789opaqueid"]}'

Response

{
  "result": true,
  "success": true,
  "deleted_count": 3,
  "failed_count": 0,
  "total_count": 3,
  "results": {
    "abc123opaqueid": {"id": "abc123opaqueid", "success": true, "error": null},
    "def456opaqueid": {"id": "def456opaqueid", "success": true, "error": null},
    "ghi789opaqueid": {"id": "ghi789opaqueid", "success": true, "error": null}
  }
}

Response Fields

FieldTypeDescription
response.success bool true only if all comments were deleted (failed_count === 0)
response.deleted_count int Number of successfully deleted comments
response.failed_count int Number that failed to delete
response.total_count int Total number of IDs provided
response.results object Per-comment results keyed by comment ID
response.results.{id}.success bool Whether this comment was deleted
response.results.{id}.error string|null Error message if failed, null on success

Per-Comment Error Messages

ErrorCause
Invalid comment ID formatNot a valid opaque ID
Comment not foundNo comment with this ID
Comment already deletedPreviously soft-deleted
Permission deniedUser is not author or entity owner
Failed to delete commentInternal error

Request-Level Error Responses

Error CodeHTTP StatusMessageCause
1605 (Invalid Input)400Invalid JSON request bodyMalformed JSON
1605 (Invalid Input)400comment_ids array is requiredMissing or non-array field
1605 (Invalid Input)400comment_ids array cannot be emptyEmpty array
1605 (Invalid Input)400Maximum 100 comments can be deleted at onceExceeds bulk limit

Important: Unlike single delete, bulk delete does not recursively delete replies.


Add or Change Reaction

POST /current/comments/{comment_id}/reactions/

Add an emoji reaction to a comment. One reaction per user per comment — sending a new reaction replaces any previous one.

Auth: Required (JWT). Rate limited.

Content-Type: application/json

Request Body

FieldTypeRequiredConstraintsDescription
emoji string Required Single emoji character; max 2 UTF-8 characters; must match Unicode emoji ranges Emoji to react with

Request Example

curl -X POST "https://api.fast.io/current/comments/abc123opaqueid/reactions/" \
  -H "Authorization: Bearer {jwt_token}" \
  -H "Content-Type: application/json" \
  -d '{"emoji": "👍"}'

Response

{
  "result": true,
  "reactions": {"👍": 3, "❤️": 1},
  "user_reaction": "👍"
}

Response Fields

FieldTypeDescription
response.reactions object Map of emoji to total reaction count across all users
response.user_reaction string|null The current user's active reaction emoji

Error Responses

Error CodeHTTP StatusMessageCause
1605 (Invalid Input)400Comment ID is requiredMissing comment ID
1605 (Invalid Input)400Invalid comment ID formatMalformed opaque ID
1609 (Not Found)404Comment not foundComment does not exist or is deleted
1680 (Access Denied)403You do not have permission to react to this commentUser lacks entity access
1605 (Invalid Input)400emoji parameter is requiredMissing or non-string emoji
1605 (Invalid Input)400Invalid emoji characterDoes not match Unicode emoji pattern
1605 (Invalid Input)400Only single emoji allowedString exceeds 2 UTF-8 characters
1654 (Internal Error)500Failed to save reactionInternal error

Remove Reaction

DELETE /current/comments/{comment_id}/reactions/

Remove an emoji reaction from a comment.

Auth: Required (JWT). Rate limited.

Content-Type: application/json

Request Body

FieldTypeRequiredConstraintsDescription
emoji string No Must match Unicode emoji ranges if provided Specific emoji to remove. Omit to remove any reaction by the current user

Request Example — Remove specific emoji

curl -X DELETE "https://api.fast.io/current/comments/abc123opaqueid/reactions/" \
  -H "Authorization: Bearer {jwt_token}" \
  -H "Content-Type: application/json" \
  -d '{"emoji": "👍"}'

Request Example — Remove any reaction

curl -X DELETE "https://api.fast.io/current/comments/abc123opaqueid/reactions/" \
  -H "Authorization: Bearer {jwt_token}" \
  -H "Content-Type: application/json" \
  -d '{}'

Response

{
  "result": true,
  "reactions": {"❤️": 1},
  "user_reaction": null
}

Response Fields

FieldTypeDescription
response.reactions object Updated map of emoji to total reaction count
response.user_reaction string|null Current user's reaction after removal (null if removed)

Error Responses

Error CodeHTTP StatusMessageCause
1605 (Invalid Input)400Comment ID is requiredMissing comment ID
1605 (Invalid Input)400Invalid comment ID formatMalformed opaque ID
1609 (Not Found)404Comment not foundComment does not exist or is deleted
1680 (Access Denied)403You do not have permission to react to this commentUser lacks entity access
1605 (Invalid Input)400emoji must be a stringNon-string emoji parameter
1605 (Invalid Input)400Invalid emoji characterDoes not match Unicode emoji pattern
1654 (Internal Error)500Failed to remove reactionInternal error

Notes: Removing a reaction that does not exist returns success (idempotent). A "removed" event is triggered only when a reaction was actually removed.


POST /current/comments/{comment_id}/link/

Link a comment to a workflow entity such as a task or workflow review. This creates an association between the comment and the target entity, enabling reverse lookups and workflow integration.

Auth: Required (JWT). Rate limited.

Content-Type: application/json

Request Body

FieldTypeRequiredConstraintsDescription
entity_type string Required One of "task", "workflow_review", or "approval" The type of workflow entity to link to. "approval" is legacy-accepted for backward compatibility; new links should use "workflow_review"
entity_id string Required Valid alphanumeric opaque ID The ID of the workflow entity to link to

Request Example

curl -X POST "https://api.fast.io/current/comments/abc123opaqueid/link/" \
  -H "Authorization: Bearer {jwt_token}" \
  -H "Content-Type: application/json" \
  -d '{
    "entity_type": "task",
    "entity_id": "task789opaqueid"
  }'

Response

{
  "result": true,
  "comment": {
    "id": "abc123opaqueid",
    "entity": "xyz789opaqueid",
    "user_id": "1234567890123456789",
    "parent_id": null,
    "body": "This looks great!",
    "profile_type": "workspace",
    "profile_id": "1234567890123456789",
    "linked_entity_type": "task",
    "linked_entity_id": "task789opaqueid",
    "reference": null,
    "reactions": {},
    "user_reaction": null,
    "version": 1,
    "can_edit": true,
    "can_delete": true,
    "can_reply": true,
    "created": "2025-01-15 10:30:00 UTC",
    "updated": "2025-01-15 10:30:00 UTC"
  }
}

Response Fields

FieldTypeDescription
response.comment object The updated comment object with the link applied

Error Responses

Error CodeHTTP StatusMessageCause
1680 (Access Denied)403Authentication required to link commentsUser not authenticated
1605 (Invalid Input)400Comment ID is requiredMissing comment ID in path
1605 (Invalid Input)400Invalid comment ID formatMalformed comment opaque ID
1605 (Invalid Input)400Invalid JSON in request bodyMalformed JSON
1605 (Invalid Input)400entity_type is requiredMissing or non-string entity_type
1605 (Invalid Input)400entity_type must be one of: task, workflow_review, approvalInvalid entity type
1605 (Invalid Input)400entity_id is requiredMissing or non-string entity_id
1605 (Invalid Input)400Invalid entity_id formatMalformed entity opaque ID
1609 (Not Found)404Comment not foundComment does not exist
1680 (Access Denied)403You do not have permission to link this commentUser lacks access to the comment's entity
1609 (Not Found)404Target entity not foundThe workflow entity to link to does not exist
1605 (Invalid Input)400Invalid link parametersLink validation failed
1654 (Internal Error)500Failed to link commentInternal error

POST /current/comments/{comment_id}/unlink/

Remove the link between a comment and its associated workflow entity. After unlinking, the comment still exists but is no longer associated with any workflow entity.

Auth: Required (JWT). Rate limited.

Content-Type: application/json

Request Body

FieldTypeRequiredConstraintsDescription
entity_id string No Valid alphanumeric opaque ID The ID of the linked entity (recommended for optimal performance; not strictly required)

Request Example

curl -X POST "https://api.fast.io/current/comments/abc123opaqueid/unlink/" \
  -H "Authorization: Bearer {jwt_token}" \
  -H "Content-Type: application/json" \
  -d '{
    "entity_id": "task789opaqueid"
  }'

Request Example — Without entity_id

curl -X POST "https://api.fast.io/current/comments/abc123opaqueid/unlink/" \
  -H "Authorization: Bearer {jwt_token}" \
  -H "Content-Type: application/json" \
  -d '{}'

Response

{
  "result": true,
  "comment": {
    "id": "abc123opaqueid",
    "entity": "xyz789opaqueid",
    "user_id": "1234567890123456789",
    "parent_id": null,
    "body": "This looks great!",
    "profile_type": "workspace",
    "profile_id": "1234567890123456789",
    "reference": null,
    "reactions": {},
    "user_reaction": null,
    "version": 1,
    "can_edit": true,
    "can_delete": true,
    "can_reply": true,
    "created": "2025-01-15 10:30:00 UTC",
    "updated": "2025-01-15 10:30:00 UTC"
  }
}

Response Fields

FieldTypeDescription
response.comment object The updated comment object with the link removed

Error Responses

Error CodeHTTP StatusMessageCause
1680 (Access Denied)403Authentication required to unlink commentsUser not authenticated
1605 (Invalid Input)400Comment ID is requiredMissing comment ID in path
1605 (Invalid Input)400Invalid comment ID formatMalformed comment opaque ID
1609 (Not Found)404Comment not foundComment does not exist
1680 (Access Denied)403You do not have permission to unlink this commentUser lacks access to the comment's entity
1605 (Invalid Input)400Comment is not linked to any entityComment has no existing link
1654 (Internal Error)500Failed to unlink commentInternal error

Get Linked Comments

GET /current/comments/linked/{entity_type}/{entity_id}/

Reverse lookup: retrieve all comments that have been linked to a specific workflow entity (task, workflow_review, or approval).

Auth: Required (JWT). Rate limited.

Path Parameters

ParameterTypeFormatDescription
{entity_type} string One of "task", "workflow_review", or "approval" The type of workflow entity. "approval" is legacy-accepted for backward compatibility; new links should use "workflow_review"
{entity_id} string Alphanumeric opaque ID The ID of the workflow entity

Query Parameters

ParameterTypeRequiredDefaultConstraintsDescription
limit integer No 50 Min: 1, Max: 200 Number of comments to return
offset integer No 0 Min: 0 Number of comments to skip

Request Example

curl -X GET "https://api.fast.io/current/comments/linked/task/task789opaqueid/?limit=25&offset=0" \
  -H "Authorization: Bearer {jwt_token}"

Response

{
  "result": true,
  "comments": [
    {
      "id": "abc123opaqueid",
      "entity": "xyz789opaqueid",
      "user_id": "1234567890123456789",
      "parent_id": null,
      "body": "This looks great!",
      "profile_type": "workspace",
      "profile_id": "1234567890123456789",
      "linked_entity_type": "task",
      "linked_entity_id": "task789opaqueid",
      "reference": null,
      "reactions": {"👍": 2},
      "user_reaction": "👍",
      "version": 1,
      "can_edit": true,
      "can_delete": true,
      "can_reply": true,
      "created": "2025-01-15 10:30:00 UTC",
      "updated": "2025-01-15 10:30:00 UTC"
    }
  ],
  "count": 1,
  "entity_type": "task",
  "entity_id": "task789opaqueid",
  "limit": 25,
  "offset": 0
}

Response Fields

FieldTypeDescription
response.comments array Array of comment objects linked to the entity
response.count int Number of comments in this response
response.entity_type string The entity type that was queried
response.entity_id string The entity ID that was queried
response.limit int Limit used in the query
response.offset int Offset used in the query

Error Responses

Error CodeHTTP StatusMessageCause
1605 (Invalid Input)400entity_type is required in URL pathMissing entity type
1605 (Invalid Input)400entity_type must be one of: task, workflow_review, approvalInvalid entity type
1605 (Invalid Input)400entity_id is required in URL pathMissing entity ID
1605 (Invalid Input)400Invalid entity_id formatMalformed opaque ID
1654 (Internal Error)500Failed to retrieve linked commentsInternal error

Comment Attachments

Attach arbitrary platform objects to a comment to give it context — a file or folder, a workflow, a sign envelope, a share, a File Share, a workspace, or a task. An attachment is a lightweight reference: it records what is attached, not a copy of it.

Attachment Object (hydrated)

Every attachment returned by the API is hydrated and access-gated to the caller: an object the caller cannot see (or that no longer exists) is returned with available: false and display_name: null rather than leaking its name. Render defensively: when available is false, never show a name.

FieldTypeDescription
target_idstringThe attached object's ID (19-digit numeric for a workspace/share/workflow/envelope/File Share, or an opaque ID for a file/folder node or task)
target_typestringCoarse object type: node, workflow, envelope, share, workspace, fileshare, or task
kindstringAlias of target_type (same value)
display_namestring|nullThe object's resolved display name, or null when the caller cannot see it or it has no name
availablebooltrue when the caller can access the object (and display_name is authoritative); false when it is inaccessible, missing, or could not be resolved

List Comment Attachments

GET /current/comments/{comment_id}/attachments/

List all objects attached to a comment, hydrated and access-gated to the caller.

Auth: Required (JWT). Rate limited.

Response

{
  "result": true,
  "comment_id": "abc123opaqueid",
  "attachments": [
    {
      "target_id": "n1o2p3q4r5s6t7u8v9w0x1y2z3a4b5",
      "target_type": "node",
      "kind": "node",
      "display_name": "spec.pdf",
      "available": true
    },
    {
      "target_id": "9876543210987654321",
      "target_type": "share",
      "kind": "share",
      "display_name": null,
      "available": false
    }
  ],
  "count": 2
}

Attach Objects to a Comment

POST /current/comments/{comment_id}/attachments/

Attach one object (target_id) or many (target_ids) to a comment. Idempotent; the new objects are committed atomically. Returns the full, updated hydrated attachment list.

Auth: Required (JWT). Rate limited. Content-Type: application/json.

Request Body

FieldTypeRequiredConstraintsDescription
target_idstringOne of target_id / target_idsValid object IDA single object to attach
target_idsarray<string>One of target_id / target_idsNon-empty arrayMultiple objects to attach

A request whose new attachments would push the comment over the 25-attachment cap is rejected before anything is written.

Request Example — single

curl -X POST "https://api.fast.io/current/comments/abc123opaqueid/attachments/" \
  -H "Authorization: Bearer {jwt_token}" \
  -H "Content-Type: application/json" \
  -d '{"target_id": "n1o2p3q4r5s6t7u8v9w0x1y2z3a4b5"}'

Request Example — bulk

curl -X POST "https://api.fast.io/current/comments/abc123opaqueid/attachments/" \
  -H "Authorization: Bearer {jwt_token}" \
  -H "Content-Type: application/json" \
  -d '{"target_ids": ["n1o2p3q4r5s6t7u8v9w0x1y2z3a4b5", "9876543210987654321"]}'

Response

{
  "result": true,
  "comment_id": "abc123opaqueid",
  "attached": 1,
  "attachments": [
    {
      "target_id": "n1o2p3q4r5s6t7u8v9w0x1y2z3a4b5",
      "target_type": "node",
      "kind": "node",
      "display_name": "spec.pdf",
      "available": true
    }
  ],
  "count": 1
}

Response Fields

FieldTypeDescription
comment_idstringThe comment the attachments belong to
attachedintNumber of objects newly attached by this request (0 when every target was already attached)
attachmentsarrayThe full hydrated attachment list after the operation
countintNumber of attachments in the list

Error Responses

Error CodeHTTP StatusMessageCause
1605 (Invalid Input)400A target_id or non-empty target_ids array is requiredNo target supplied
1605 (Invalid Input)400Invalid attachment targetA target ID could not be decoded
1605 (Invalid Input)400Attachment limit reached (maximum 25 per comment)The new attachments would exceed the cap
1605 (Invalid Input)400Attachments are not supported on workflow-review commentsComment is part of a workflow review
1680 (Access Denied)403You do not have permission to modify attachments on this commentCaller is not the comment author
1609 (Not Found)404Comment not foundComment does not exist, is not visible to you, or is trashed

Detach an Object from a Comment

POST /current/comments/{comment_id}/attachments/detach/

Remove an attachment by its target_id. Idempotent — detaching an object that is not attached returns success with removed: false. Returns the updated hydrated attachment list.

Auth: Required (JWT). Rate limited. Content-Type: application/json.

Request Body

FieldTypeRequiredConstraintsDescription
target_idstringYesValid object IDThe object to detach

Response

{
  "result": true,
  "comment_id": "abc123opaqueid",
  "removed": true,
  "attachments": [],
  "count": 0
}

Response Fields

FieldTypeDescription
comment_idstringThe comment the attachment belonged to
removedbooltrue if an attachment was actually removed; false if the object was not attached
attachmentsarrayThe full hydrated attachment list after the operation
countintNumber of attachments remaining

Attaching at comment-create time (inline)

You can attach objects when creating a comment by including target_id or target_ids in the comment-create body (see Create or Update Comment). Inline attachments apply only to a new comment — they are ignored on an update, and the comment plus its attachments are written together so the comment never appears without them. An invalid target or one that would exceed the cap rejects the whole create.

attachment_count is returned on every comment list row and on the comment detail response. The hydrated attachments array is returned only on the comment detail response (GET /current/comments/{comment_id}/details/). All counts are computed live on each read.


Task Comments

Tasks have their own dedicated comment thread, surfaced under the task path rather than the generic comment paths. A task comment is a normal comment object (same schema, threading, mentions, reactions, and reference anchoring as above) — only the list/create surface differs.

MethodPathDescription
GET/current/tasks/{list_id}/items/{task_id}/comments/List the task's comment thread (paginated; limit min 2, max 200; offset)
POST/current/tasks/{list_id}/items/{task_id}/comments/Post a comment on the task (body, optional parent_id for a reply, optional reference, mentions parsed from body)

Privacy. Task comments are private to their task: they are not returned by the general comment listing (GET /current/comments/{entity_type}/{parent_id}/) and not included in comment search. They surface only through the task comment path above.

Reactions, edit, and delete of a task comment use the existing comment-by-id endpoints in this reference — POST /current/comments/{comment_id}/reactions/, DELETE /current/comments/{comment_id}/reactions/, POST /current/comments/{comment_id}/update/ (edit), and DELETE /current/comments/{comment_id}/delete/.

The task create endpoint never edits. A POST to the task comments path whose body includes a comment_id field is rejected with 400 Invalid Input (it does not create a duplicate); trailing path segments after …/comments/ return 404. Edits go through POST /current/comments/{comment_id}/update/ only.

Access. The task's workflow feature must be enabled on the owning workspace or share. On shares, member or admin access is required — guests are blocked. A soft-deleted task returns 404. Mentions are validated against the task's workspace/share membership.

The full request/response shapes for the task comment list and create endpoints are documented in the Workflow (Task Management) reference under Task Comments.


Threading

Comments support single-level threading only.

Comment A (top-level)
├── Comment B (reply to A)
├── Comment C (reply to B → auto-flattened to reply to A)
└── Comment D (reply to A)

Mentions

Use mention markup in the body field to tag other users:

@[user:USER_ID:Display Name]
ComponentDescription
userLiteral prefix (always user)
USER_IDThe user's 19-digit numeric profile ID
Display NameDisplay name to show in the UI

Character limit details

Example body with mentions

Hey @[user:1234567890123456789:Jane Smith] and @[user:9876543210987654321:Bob Jones], please review this file.

Reference Anchoring

Comments can be anchored to specific positions within a file using the reference object.

Reference object fields

FieldTypeDescription
type string Required. The anchor type: "page", "timestamp", "region", "text"
timestamp number For video/audio — position in seconds
page integer For documents — page number
region object For images — coordinates {x, y, width, height} defining a rectangular area
text_snippet string For text files — the referenced text passage

Example — Video timestamp

{
  "body": "The transition at this point needs work.",
  "reference": {"type": "timestamp", "timestamp": 42.5}
}

Example — Document page

{
  "body": "Typo in the second paragraph.",
  "reference": {"type": "page", "page": 7}
}

Example — Image region

{
  "body": "This area needs higher contrast.",
  "reference": {"type": "region", "region": {"x": 120, "y": 80, "width": 200, "height": 150}}
}

Example — Text snippet

{
  "body": "This sentence should be rephrased.",
  "reference": {"type": "text", "text_snippet": "The quick brown fox jumps over the lazy dog."}
}

Content Filtering

Comment bodies undergo automatic filtering:

↑ Back to top