Return the comments on one work item. Comments are scoped to their parent work item, so this is the only way to read a work item's discussion — reach for it when rendering a work item detail view or mirroring a thread into another system.
Return comments carrying this identifier from your system. external_id is not a unique key, so this can match more than one comment — pair it with external_source and handle a multi-row result.
external_source:optionalstring
Return comments that came from this system, for example github or zendesk.
Search
search:optionalstring
Match comments against their plain-text body (comment_stripped), so HTML markup in comment_html never affects whether a term hits.
Ordering
order_by:optionalstring
Field to sort by. Prefix with - for descending. Send it explicitly whenever order matters — a thread you render should not depend on the server's unstated default.
created_at — oldest first
-created_at — newest first
id
-id
Pagination
per_page:optionalinteger
Page size. Defaults to 50, maximum 200.
offset:optionalinteger
Number of rows to skip from the start of the result set. Maximum 10000 — for deeper traversal switch to cursor pagination.
paginate:optionalstring
Set to cursor to opt into the COUNT-free keyset envelope instead of the default offset envelope. The response then carries next_cursor and has_more; send the value of next_cursor back as ?cursor= to fetch the next page. See Pagination for the full envelope.
count:optionalboolean
Defaults to true. Set to false to skip the COUNT(*) and omit total_count from the offset envelope.
access is validated, order_by is not
access is checked against its allowed values — an unrecognized value is rejected as a 400 validation_error, so you never get a silently empty list back. order_by is not checked: an unrecognized value falls back to the default ordering, so check your spelling there because a typo shows up as an unexpected sort order rather than an error.
List comments
Return the comments on one work item. Comments are scoped to their parent work item, so this is the only way to read a work item's discussion — reach for it when rendering a work item detail view or mirroring a thread into another system.
Path Parameters
slug:requiredstringThe workspace slug. It appears in your Plane URLs — in
https://app.plane.so/my-team/projects/, the slug ismy-team.project_id:requiredstring (uuid)The project the work item belongs to.
work_item_id:requiredstring (uuid)The work item whose comments you want. Comments never span work items, so this narrows the result set by itself.
Query Parameters
Filters
access:optionalstringReturn only comments with this visibility.
INTERNAL— visible to the project teamEXTERNAL— marked as visible outside the teamexternal_id:optionalstringReturn comments carrying this identifier from your system.
external_idis not a unique key, so this can match more than one comment — pair it withexternal_sourceand handle a multi-row result.external_source:optionalstringReturn comments that came from this system, for example
githuborzendesk.Search
search:optionalstringMatch comments against their plain-text body (
comment_stripped), so HTML markup incomment_htmlnever affects whether a term hits.Ordering
order_by:optionalstringField to sort by. Prefix with
-for descending. Send it explicitly whenever order matters — a thread you render should not depend on the server's unstated default.created_at— oldest first-created_at— newest firstid-idPagination
per_page:optionalintegerPage size. Defaults to 50, maximum 200.
offset:optionalintegerNumber of rows to skip from the start of the result set. Maximum 10000 — for deeper traversal switch to cursor pagination.
paginate:optionalstringSet to
cursorto opt into the COUNT-free keyset envelope instead of the default offset envelope. The response then carriesnext_cursorandhas_more; send the value ofnext_cursorback as?cursor=to fetch the next page. See Pagination for the full envelope.count:optionalbooleanDefaults to
true. Set tofalseto skip theCOUNT(*)and omittotal_countfrom the offset envelope.accessis validated,order_byis notaccessis checked against its allowed values — an unrecognized value is rejected as a400 validation_error, so you never get a silently empty list back.order_byis not checked: an unrecognized value falls back to the default ordering, so check your spelling there because a typo shows up as an unexpected sort order rather than an error.Scopes
projects.work_items.comments:readErrors
401unauthorized403forbidden404resource_not_found429rate_limitedRetry-Afterheader before retrying.