Purple Chat API Documentation
Machine-readable OpenAPI 3.0 specification: https://marketplace.moveworks.com/api/purple-suite/chat/openapi.json
The consolidated all-apps document at https://marketplace.moveworks.com/api/purple-suite/openapi.json can be narrowed to this app with ?apps=chat, or combined with other apps comma-separated (e.g. ?apps=chat,itsm).
Overview
Endpoints
GET /api/purple-suite/chat/channels
List Purple Collab channels
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
X-Instance-ID | header | string | yes | The Purple Suite instance ID that scopes all subcollections |
limit | query | integer | no | Legacy page size (default 50). Prefer $top. Ignored when $top/$skip are used. |
cursor | query | string | no | Legacy keyset cursor — pass the previous response's nextCursor. Prefer $skip/$top. |
$filter | query | string | no | OData filter expression. Comparison operators: eq, ne, gt, ge, lt, le. Logical: and, or, not, with parentheses for grouping. String functions: contains(field,'x'), startswith(field,'x'), endswith(field,'x'). Membership: field in ('a','b'). Case-insensitive matching via tolower(field) / toupper(field). Nested fields use a slash, e.g. pto_balance/vacation_days. String literals use single quotes; dates are ISO-8601. Examples: "status eq 'active'"; "salary gt 50000 and department eq 'Engineering'"; "contains(tolower(name),'acme')"; "closeDate gt 2026-01-01". |
$select | query | string | no | Comma-separated list of fields to return, e.g. "id,firstName,email". Nested fields via slash ("pto_balance/vacation_days"). The id field is always included. |
$orderby | query | string | no | Sort clause(s), comma-separated, each "field [asc|desc]" (asc is the default). Example: "createdAt desc, lastName asc". Null values sort last. |
$search | query | string | no | Free-text, case-insensitive substring match across the resource's searchable fields. |
$top | query | integer | no | Maximum number of items to return (page size). |
$skip | query | integer | no | Number of matching items to skip before returning results (offset paging). Combine with $top. |
$count | query | boolean | no | When true, include @odata.count (total matches after $filter/$search, before paging) in the response. |
Responses
200- Paginated list
application/jsondataarrayarray of:
ChannelidstringnamestringtypestringdescriptionstringmemberCountintegermembersarray — Array of user IDs who are members of this channelArray of user IDs who are members of this channelarray of:
string
createdBystringcreatedAtstringupdatedAtstring
nextCursorstring — Cursor for the next page, or null on the last page. With $top/$skip this is the next $skip value; otherwise a keyset cursor.totalinteger — Total documents in the collection.@odata.countinteger — Present only when $count=true: total matches after $filter/$search.@odata.truncatedboolean — Present and true only when the collection exceeded the in-memory query cap and results may be incomplete.
400- Invalid OData query (e.g. malformed $filter)
POST /api/purple-suite/chat/channels
Create a Purple Collab channel
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
X-Instance-ID | header | string | yes | The Purple Suite instance ID that scopes all subcollections |
Request body
application/json — required
Channel
idstringnamestringtypestringdescriptionstringmemberCountintegermembersarray — Array of user IDs who are members of this channelArray of user IDs who are members of this channelarray of:
string
createdBystringcreatedAtstringupdatedAtstring
Responses
201- Created
application/jsonChannelidstringnamestringtypestringdescriptionstringmemberCountintegermembersarray — Array of user IDs who are members of this channelArray of user IDs who are members of this channelarray of:
string
createdBystringcreatedAtstringupdatedAtstring
GET /api/purple-suite/chat/channels/{id}
Get channel
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
X-Instance-ID | header | string | yes | The Purple Suite instance ID that scopes all subcollections |
id | path | string | yes |
Responses
200- Found
application/jsonChannelidstringnamestringtypestringdescriptionstringmemberCountintegermembersarray — Array of user IDs who are members of this channelArray of user IDs who are members of this channelarray of:
string
createdBystringcreatedAtstringupdatedAtstring
404- Not found
DELETE /api/purple-suite/chat/channels/{id}
Delete channel
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
X-Instance-ID | header | string | yes | The Purple Suite instance ID that scopes all subcollections |
id | path | string | yes |
Responses
200- Deleted
application/jsonsuccessboolean
404- Not found
PATCH /api/purple-suite/chat/channels/{id}
Update channel
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
X-Instance-ID | header | string | yes | The Purple Suite instance ID that scopes all subcollections |
id | path | string | yes |
Request body
application/json
Channel
idstringnamestringtypestringdescriptionstringmemberCountintegermembersarray — Array of user IDs who are members of this channelArray of user IDs who are members of this channelarray of:
string
createdBystringcreatedAtstringupdatedAtstring
Responses
200- Updated
application/jsonChannelidstringnamestringtypestringdescriptionstringmemberCountintegermembersarray — Array of user IDs who are members of this channelArray of user IDs who are members of this channelarray of:
string
createdBystringcreatedAtstringupdatedAtstring
404- Not found
GET /api/purple-suite/chat/messages
List Purple Collab chat messages
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
X-Instance-ID | header | string | yes | The Purple Suite instance ID that scopes all subcollections |
limit | query | integer | no | Legacy page size (default 50). Prefer $top. Ignored when $top/$skip are used. |
cursor | query | string | no | Legacy keyset cursor — pass the previous response's nextCursor. Prefer $skip/$top. |
$filter | query | string | no | OData filter expression. Comparison operators: eq, ne, gt, ge, lt, le. Logical: and, or, not, with parentheses for grouping. String functions: contains(field,'x'), startswith(field,'x'), endswith(field,'x'). Membership: field in ('a','b'). Case-insensitive matching via tolower(field) / toupper(field). Nested fields use a slash, e.g. pto_balance/vacation_days. String literals use single quotes; dates are ISO-8601. Examples: "status eq 'active'"; "salary gt 50000 and department eq 'Engineering'"; "contains(tolower(name),'acme')"; "closeDate gt 2026-01-01". |
$select | query | string | no | Comma-separated list of fields to return, e.g. "id,firstName,email". Nested fields via slash ("pto_balance/vacation_days"). The id field is always included. |
$orderby | query | string | no | Sort clause(s), comma-separated, each "field [asc|desc]" (asc is the default). Example: "createdAt desc, lastName asc". Null values sort last. |
$search | query | string | no | Free-text, case-insensitive substring match across the resource's searchable fields. |
$top | query | integer | no | Maximum number of items to return (page size). |
$skip | query | integer | no | Number of matching items to skip before returning results (offset paging). Combine with $top. |
$count | query | boolean | no | When true, include @odata.count (total matches after $filter/$search, before paging) in the response. |
channelId | query | string | no | Filter messages by channel ID |
parent_message_id | query | string | no | Filter to thread replies of a specific parent message ID |
Responses
200- Paginated list
application/jsondataarrayarray of:
MessageidstringchannelIdstring — ID of the channel this message belongs toauthorstringtextstringreactionsobject — Map of emoji to list of user emails who reactededitedAtstringparent_message_idstring — Set when this message is a thread reply; populated automatically by POST /messages/:id/replythread_countinteger — Number of replies in this message's thread; incremented automatically by POST /messages/:id/replyinteractive_stateobject — Current state of interactive button values keyed by action_id; managed by POST /messages/:id/interactinteractionsarray — Append-only log of all interactions on this message; managed by POST /messages/:id/interactAppend-only log of all interactions on this message; managed by POST /messages/:id/interactarray of:
action_idstringvaluetimestampstring
createdAtstringupdatedAtstring
nextCursorstring — Cursor for the next page, or null on the last page. With $top/$skip this is the next $skip value; otherwise a keyset cursor.totalinteger — Total documents in the collection.@odata.countinteger — Present only when $count=true: total matches after $filter/$search.@odata.truncatedboolean — Present and true only when the collection exceeded the in-memory query cap and results may be incomplete.
400- Invalid OData query (e.g. malformed $filter)
POST /api/purple-suite/chat/messages
Post a message to a Collab channel
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
X-Instance-ID | header | string | yes | The Purple Suite instance ID that scopes all subcollections |
Request body
application/json — required
Message
idstringchannelIdstring — ID of the channel this message belongs toauthorstringtextstringreactionsobject — Map of emoji to list of user emails who reactededitedAtstringparent_message_idstring — Set when this message is a thread reply; populated automatically by POST /messages/:id/replythread_countinteger — Number of replies in this message's thread; incremented automatically by POST /messages/:id/replyinteractive_stateobject — Current state of interactive button values keyed by action_id; managed by POST /messages/:id/interactinteractionsarray — Append-only log of all interactions on this message; managed by POST /messages/:id/interactAppend-only log of all interactions on this message; managed by POST /messages/:id/interactarray of:
action_idstringvaluetimestampstring
createdAtstringupdatedAtstring
Responses
201- Created
application/jsonMessageidstringchannelIdstring — ID of the channel this message belongs toauthorstringtextstringreactionsobject — Map of emoji to list of user emails who reactededitedAtstringparent_message_idstring — Set when this message is a thread reply; populated automatically by POST /messages/:id/replythread_countinteger — Number of replies in this message's thread; incremented automatically by POST /messages/:id/replyinteractive_stateobject — Current state of interactive button values keyed by action_id; managed by POST /messages/:id/interactinteractionsarray — Append-only log of all interactions on this message; managed by POST /messages/:id/interactAppend-only log of all interactions on this message; managed by POST /messages/:id/interactarray of:
action_idstringvaluetimestampstring
createdAtstringupdatedAtstring
GET /api/purple-suite/chat/messages/{id}
Get message
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
X-Instance-ID | header | string | yes | The Purple Suite instance ID that scopes all subcollections |
id | path | string | yes |
Responses
200- Found
application/jsonMessageidstringchannelIdstring — ID of the channel this message belongs toauthorstringtextstringreactionsobject — Map of emoji to list of user emails who reactededitedAtstringparent_message_idstring — Set when this message is a thread reply; populated automatically by POST /messages/:id/replythread_countinteger — Number of replies in this message's thread; incremented automatically by POST /messages/:id/replyinteractive_stateobject — Current state of interactive button values keyed by action_id; managed by POST /messages/:id/interactinteractionsarray — Append-only log of all interactions on this message; managed by POST /messages/:id/interactAppend-only log of all interactions on this message; managed by POST /messages/:id/interactarray of:
action_idstringvaluetimestampstring
createdAtstringupdatedAtstring
404- Not found
DELETE /api/purple-suite/chat/messages/{id}
Delete a Collab message
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
X-Instance-ID | header | string | yes | The Purple Suite instance ID that scopes all subcollections |
id | path | string | yes |
Responses
200- Deleted
application/jsonsuccessboolean
404- Not found
PATCH /api/purple-suite/chat/messages/{id}
Edit a Collab message or its reactions
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
X-Instance-ID | header | string | yes | The Purple Suite instance ID that scopes all subcollections |
id | path | string | yes |
Request body
application/json
Message
idstringchannelIdstring — ID of the channel this message belongs toauthorstringtextstringreactionsobject — Map of emoji to list of user emails who reactededitedAtstringparent_message_idstring — Set when this message is a thread reply; populated automatically by POST /messages/:id/replythread_countinteger — Number of replies in this message's thread; incremented automatically by POST /messages/:id/replyinteractive_stateobject — Current state of interactive button values keyed by action_id; managed by POST /messages/:id/interactinteractionsarray — Append-only log of all interactions on this message; managed by POST /messages/:id/interactAppend-only log of all interactions on this message; managed by POST /messages/:id/interactarray of:
action_idstringvaluetimestampstring
createdAtstringupdatedAtstring
Responses
200- Updated
application/jsonMessageidstringchannelIdstring — ID of the channel this message belongs toauthorstringtextstringreactionsobject — Map of emoji to list of user emails who reactededitedAtstringparent_message_idstring — Set when this message is a thread reply; populated automatically by POST /messages/:id/replythread_countinteger — Number of replies in this message's thread; incremented automatically by POST /messages/:id/replyinteractive_stateobject — Current state of interactive button values keyed by action_id; managed by POST /messages/:id/interactinteractionsarray — Append-only log of all interactions on this message; managed by POST /messages/:id/interactAppend-only log of all interactions on this message; managed by POST /messages/:id/interactarray of:
action_idstringvaluetimestampstring
createdAtstringupdatedAtstring
404- Not found
GET /api/purple-suite/chat/scheduled-messages
List scheduled messages
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
X-Instance-ID | header | string | yes | The Purple Suite instance ID that scopes all subcollections |
limit | query | integer | no | Legacy page size (default 50). Prefer $top. Ignored when $top/$skip are used. |
cursor | query | string | no | Legacy keyset cursor — pass the previous response's nextCursor. Prefer $skip/$top. |
$filter | query | string | no | OData filter expression. Comparison operators: eq, ne, gt, ge, lt, le. Logical: and, or, not, with parentheses for grouping. String functions: contains(field,'x'), startswith(field,'x'), endswith(field,'x'). Membership: field in ('a','b'). Case-insensitive matching via tolower(field) / toupper(field). Nested fields use a slash, e.g. pto_balance/vacation_days. String literals use single quotes; dates are ISO-8601. Examples: "status eq 'active'"; "salary gt 50000 and department eq 'Engineering'"; "contains(tolower(name),'acme')"; "closeDate gt 2026-01-01". |
$select | query | string | no | Comma-separated list of fields to return, e.g. "id,firstName,email". Nested fields via slash ("pto_balance/vacation_days"). The id field is always included. |
$orderby | query | string | no | Sort clause(s), comma-separated, each "field [asc|desc]" (asc is the default). Example: "createdAt desc, lastName asc". Null values sort last. |
$search | query | string | no | Free-text, case-insensitive substring match across the resource's searchable fields. |
$top | query | integer | no | Maximum number of items to return (page size). |
$skip | query | integer | no | Number of matching items to skip before returning results (offset paging). Combine with $top. |
$count | query | boolean | no | When true, include @odata.count (total matches after $filter/$search, before paging) in the response. |
channelId | query | string | no | Filter scheduled messages by channel ID |
Responses
200- Paginated list
application/jsondataarrayarray of:
ScheduledMessageA message queued to be delivered to a channel at a future time (Slack-style scheduled message).idstringchannelIdstring — ID of the channel the message will be posted toauthorstringtextstringscheduledForstring — When the message is scheduled to be sentcreatedAtstringupdatedAtstring
nextCursorstring — Cursor for the next page, or null on the last page. With $top/$skip this is the next $skip value; otherwise a keyset cursor.totalinteger — Total documents in the collection.@odata.countinteger — Present only when $count=true: total matches after $filter/$search.@odata.truncatedboolean — Present and true only when the collection exceeded the in-memory query cap and results may be incomplete.
400- Invalid OData query (e.g. malformed $filter)
POST /api/purple-suite/chat/scheduled-messages
Create scheduled message
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
X-Instance-ID | header | string | yes | The Purple Suite instance ID that scopes all subcollections |
Request body
application/json — required
ScheduledMessage
idstringchannelIdstring — ID of the channel the message will be posted toauthorstringtextstringscheduledForstring — When the message is scheduled to be sentcreatedAtstringupdatedAtstring
Responses
201- Created
application/jsonScheduledMessageA message queued to be delivered to a channel at a future time (Slack-style scheduled message).idstringchannelIdstring — ID of the channel the message will be posted toauthorstringtextstringscheduledForstring — When the message is scheduled to be sentcreatedAtstringupdatedAtstring
GET /api/purple-suite/chat/scheduled-messages/{id}
Get scheduled message
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
X-Instance-ID | header | string | yes | The Purple Suite instance ID that scopes all subcollections |
id | path | string | yes |
Responses
200- Found
application/jsonScheduledMessageA message queued to be delivered to a channel at a future time (Slack-style scheduled message).idstringchannelIdstring — ID of the channel the message will be posted toauthorstringtextstringscheduledForstring — When the message is scheduled to be sentcreatedAtstringupdatedAtstring
404- Not found
DELETE /api/purple-suite/chat/scheduled-messages/{id}
Delete scheduled message
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
X-Instance-ID | header | string | yes | The Purple Suite instance ID that scopes all subcollections |
id | path | string | yes |
Responses
200- Deleted
application/jsonsuccessboolean
404- Not found
PATCH /api/purple-suite/chat/scheduled-messages/{id}
Update scheduled message
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
X-Instance-ID | header | string | yes | The Purple Suite instance ID that scopes all subcollections |
id | path | string | yes |
Request body
application/json
ScheduledMessage
idstringchannelIdstring — ID of the channel the message will be posted toauthorstringtextstringscheduledForstring — When the message is scheduled to be sentcreatedAtstringupdatedAtstring
Responses
200- Updated
application/jsonScheduledMessageA message queued to be delivered to a channel at a future time (Slack-style scheduled message).idstringchannelIdstring — ID of the channel the message will be posted toauthorstringtextstringscheduledForstring — When the message is scheduled to be sentcreatedAtstringupdatedAtstring
404- Not found
GET /api/purple-suite/chat/drafts
List drafts
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
X-Instance-ID | header | string | yes | The Purple Suite instance ID that scopes all subcollections |
limit | query | integer | no | Legacy page size (default 50). Prefer $top. Ignored when $top/$skip are used. |
cursor | query | string | no | Legacy keyset cursor — pass the previous response's nextCursor. Prefer $skip/$top. |
$filter | query | string | no | OData filter expression. Comparison operators: eq, ne, gt, ge, lt, le. Logical: and, or, not, with parentheses for grouping. String functions: contains(field,'x'), startswith(field,'x'), endswith(field,'x'). Membership: field in ('a','b'). Case-insensitive matching via tolower(field) / toupper(field). Nested fields use a slash, e.g. pto_balance/vacation_days. String literals use single quotes; dates are ISO-8601. Examples: "status eq 'active'"; "salary gt 50000 and department eq 'Engineering'"; "contains(tolower(name),'acme')"; "closeDate gt 2026-01-01". |
$select | query | string | no | Comma-separated list of fields to return, e.g. "id,firstName,email". Nested fields via slash ("pto_balance/vacation_days"). The id field is always included. |
$orderby | query | string | no | Sort clause(s), comma-separated, each "field [asc|desc]" (asc is the default). Example: "createdAt desc, lastName asc". Null values sort last. |
$search | query | string | no | Free-text, case-insensitive substring match across the resource's searchable fields. |
$top | query | integer | no | Maximum number of items to return (page size). |
$skip | query | integer | no | Number of matching items to skip before returning results (offset paging). Combine with $top. |
$count | query | boolean | no | When true, include @odata.count (total matches after $filter/$search, before paging) in the response. |
channelId | query | string | no | Filter drafts by channel ID |
Responses
200- Paginated list
application/jsondataarrayarray of:
DraftAn unsent message draft (Slack-style draft). Saving a draft does NOT deliver the message.idstringchannelIdstring — Target channel, when the draft is for a channelrecipientstring — Target user email, when the draft is a direct messageauthorstringtextstringcreatedAtstringupdatedAtstring
nextCursorstring — Cursor for the next page, or null on the last page. With $top/$skip this is the next $skip value; otherwise a keyset cursor.totalinteger — Total documents in the collection.@odata.countinteger — Present only when $count=true: total matches after $filter/$search.@odata.truncatedboolean — Present and true only when the collection exceeded the in-memory query cap and results may be incomplete.
400- Invalid OData query (e.g. malformed $filter)
POST /api/purple-suite/chat/drafts
Create draft
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
X-Instance-ID | header | string | yes | The Purple Suite instance ID that scopes all subcollections |
Request body
application/json — required
Draft
idstringchannelIdstring — Target channel, when the draft is for a channelrecipientstring — Target user email, when the draft is a direct messageauthorstringtextstringcreatedAtstringupdatedAtstring
Responses
201- Created
application/jsonDraftAn unsent message draft (Slack-style draft). Saving a draft does NOT deliver the message.idstringchannelIdstring — Target channel, when the draft is for a channelrecipientstring — Target user email, when the draft is a direct messageauthorstringtextstringcreatedAtstringupdatedAtstring
GET /api/purple-suite/chat/drafts/{id}
Get draft
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
X-Instance-ID | header | string | yes | The Purple Suite instance ID that scopes all subcollections |
id | path | string | yes |
Responses
200- Found
application/jsonDraftAn unsent message draft (Slack-style draft). Saving a draft does NOT deliver the message.idstringchannelIdstring — Target channel, when the draft is for a channelrecipientstring — Target user email, when the draft is a direct messageauthorstringtextstringcreatedAtstringupdatedAtstring
404- Not found
DELETE /api/purple-suite/chat/drafts/{id}
Delete draft
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
X-Instance-ID | header | string | yes | The Purple Suite instance ID that scopes all subcollections |
id | path | string | yes |
Responses
200- Deleted
application/jsonsuccessboolean
404- Not found
PATCH /api/purple-suite/chat/drafts/{id}
Update draft
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
X-Instance-ID | header | string | yes | The Purple Suite instance ID that scopes all subcollections |
id | path | string | yes |
Request body
application/json
Draft
idstringchannelIdstring — Target channel, when the draft is for a channelrecipientstring — Target user email, when the draft is a direct messageauthorstringtextstringcreatedAtstringupdatedAtstring
Responses
200- Updated
application/jsonDraftAn unsent message draft (Slack-style draft). Saving a draft does NOT deliver the message.idstringchannelIdstring — Target channel, when the draft is for a channelrecipientstring — Target user email, when the draft is a direct messageauthorstringtextstringcreatedAtstringupdatedAtstring
404- Not found
POST /api/purple-suite/chat/messages/{id}/reply
Reply in a Collab message thread
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
X-Instance-ID | header | string | yes | The Purple Suite instance ID that scopes all subcollections |
id | path | string | yes | Document ID |
Request body
application/json — required
channelIdstring required — ID of the channel this reply belongs toauthorstring required — Email of the user posting the replytextstring required — Reply message textreactionsobject — Initial reactions map (emoji → list of user emails); optionaleditedAtstring — Timestamp of last edit; optional, defaults to null
Responses
201- Reply message created
application/jsonMessageidstringchannelIdstring — ID of the channel this message belongs toauthorstringtextstringreactionsobject — Map of emoji to list of user emails who reactededitedAtstringparent_message_idstring — Set when this message is a thread reply; populated automatically by POST /messages/:id/replythread_countinteger — Number of replies in this message's thread; incremented automatically by POST /messages/:id/replyinteractive_stateobject — Current state of interactive button values keyed by action_id; managed by POST /messages/:id/interactinteractionsarray — Append-only log of all interactions on this message; managed by POST /messages/:id/interactAppend-only log of all interactions on this message; managed by POST /messages/:id/interactarray of:
action_idstringvaluetimestampstring
createdAtstringupdatedAtstring
404- Parent message not found
POST /api/purple-suite/chat/messages/{id}/interact
Click a button on a Collab message
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
X-Instance-ID | header | string | yes | The Purple Suite instance ID that scopes all subcollections |
id | path | string | yes | Document ID |
Request body
application/json — required
action_idstring required — Identifier of the interactive element that was triggeredvalue— New value to set for the action (any JSON-serialisable value)
Responses
200- Updated message after interaction
application/jsonMessageidstringchannelIdstring — ID of the channel this message belongs toauthorstringtextstringreactionsobject — Map of emoji to list of user emails who reactededitedAtstringparent_message_idstring — Set when this message is a thread reply; populated automatically by POST /messages/:id/replythread_countinteger — Number of replies in this message's thread; incremented automatically by POST /messages/:id/replyinteractive_stateobject — Current state of interactive button values keyed by action_id; managed by POST /messages/:id/interactinteractionsarray — Append-only log of all interactions on this message; managed by POST /messages/:id/interactAppend-only log of all interactions on this message; managed by POST /messages/:id/interactarray of:
action_idstringvaluetimestampstring
createdAtstringupdatedAtstring
400- action_id is required
404- Message not found
GET /api/purple-suite/chat/users
List Purple Collab workspace members
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
X-Instance-ID | header | string | yes | The Purple Suite instance ID that scopes all subcollections |
limit | query | integer | no | Legacy page size (default 50). Prefer $top. Ignored when $top/$skip are used. |
cursor | query | string | no | Legacy keyset cursor — pass the previous response's nextCursor. Prefer $skip/$top. |
$filter | query | string | no | OData filter expression. Comparison operators: eq, ne, gt, ge, lt, le. Logical: and, or, not, with parentheses for grouping. String functions: contains(field,'x'), startswith(field,'x'), endswith(field,'x'). Membership: field in ('a','b'). Case-insensitive matching via tolower(field) / toupper(field). Nested fields use a slash, e.g. pto_balance/vacation_days. String literals use single quotes; dates are ISO-8601. Examples: "status eq 'active'"; "salary gt 50000 and department eq 'Engineering'"; "contains(tolower(name),'acme')"; "closeDate gt 2026-01-01". |
$select | query | string | no | Comma-separated list of fields to return, e.g. "id,firstName,email". Nested fields via slash ("pto_balance/vacation_days"). The id field is always included. |
$orderby | query | string | no | Sort clause(s), comma-separated, each "field [asc|desc]" (asc is the default). Example: "createdAt desc, lastName asc". Null values sort last. |
$search | query | string | no | Free-text, case-insensitive substring match across the resource's searchable fields. |
$top | query | integer | no | Maximum number of items to return (page size). |
$skip | query | integer | no | Number of matching items to skip before returning results (offset paging). Combine with $top. |
$count | query | boolean | no | When true, include @odata.count (total matches after $filter/$search, before paging) in the response. |
Responses
200- Paginated list
application/jsondataarrayarray of:
UseridstringdisplayNamestringemailstringstatusstringrolestringtimezonestringjoinedAtstringcreatedAtstringupdatedAtstring
nextCursorstring — Cursor for the next page, or null on the last page. With $top/$skip this is the next $skip value; otherwise a keyset cursor.totalinteger — Total documents in the collection.@odata.countinteger — Present only when $count=true: total matches after $filter/$search.@odata.truncatedboolean — Present and true only when the collection exceeded the in-memory query cap and results may be incomplete.
400- Invalid OData query (e.g. malformed $filter)
POST /api/purple-suite/chat/users
Create user
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
X-Instance-ID | header | string | yes | The Purple Suite instance ID that scopes all subcollections |
Request body
application/json — required
User
idstringdisplayNamestringemailstringstatusstringrolestringtimezonestringjoinedAtstringcreatedAtstringupdatedAtstring
Responses
201- Created
application/jsonUseridstringdisplayNamestringemailstringstatusstringrolestringtimezonestringjoinedAtstringcreatedAtstringupdatedAtstring
GET /api/purple-suite/chat/users/{id}
Get user
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
X-Instance-ID | header | string | yes | The Purple Suite instance ID that scopes all subcollections |
id | path | string | yes |
Responses
200- Found
application/jsonUseridstringdisplayNamestringemailstringstatusstringrolestringtimezonestringjoinedAtstringcreatedAtstringupdatedAtstring
404- Not found
DELETE /api/purple-suite/chat/users/{id}
Delete user
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
X-Instance-ID | header | string | yes | The Purple Suite instance ID that scopes all subcollections |
id | path | string | yes |
Responses
200- Deleted
application/jsonsuccessboolean
404- Not found
PATCH /api/purple-suite/chat/users/{id}
Update user
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
X-Instance-ID | header | string | yes | The Purple Suite instance ID that scopes all subcollections |
id | path | string | yes |
Request body
application/json
User
idstringdisplayNamestringemailstringstatusstringrolestringtimezonestringjoinedAtstringcreatedAtstringupdatedAtstring
Responses
200- Updated
application/jsonUseridstringdisplayNamestringemailstringstatusstringrolestringtimezonestringjoinedAtstringcreatedAtstringupdatedAtstring
404- Not found
GET /api/purple-suite/chat/files
List files
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
X-Instance-ID | header | string | yes | The Purple Suite instance ID that scopes all subcollections |
limit | query | integer | no | Legacy page size (default 50). Prefer $top. Ignored when $top/$skip are used. |
cursor | query | string | no | Legacy keyset cursor — pass the previous response's nextCursor. Prefer $skip/$top. |
$filter | query | string | no | OData filter expression. Comparison operators: eq, ne, gt, ge, lt, le. Logical: and, or, not, with parentheses for grouping. String functions: contains(field,'x'), startswith(field,'x'), endswith(field,'x'). Membership: field in ('a','b'). Case-insensitive matching via tolower(field) / toupper(field). Nested fields use a slash, e.g. pto_balance/vacation_days. String literals use single quotes; dates are ISO-8601. Examples: "status eq 'active'"; "salary gt 50000 and department eq 'Engineering'"; "contains(tolower(name),'acme')"; "closeDate gt 2026-01-01". |
$select | query | string | no | Comma-separated list of fields to return, e.g. "id,firstName,email". Nested fields via slash ("pto_balance/vacation_days"). The id field is always included. |
$orderby | query | string | no | Sort clause(s), comma-separated, each "field [asc|desc]" (asc is the default). Example: "createdAt desc, lastName asc". Null values sort last. |
$search | query | string | no | Free-text, case-insensitive substring match across the resource's searchable fields. |
$top | query | integer | no | Maximum number of items to return (page size). |
$skip | query | integer | no | Number of matching items to skip before returning results (offset paging). Combine with $top. |
$count | query | boolean | no | When true, include @odata.count (total matches after $filter/$search, before paging) in the response. |
Responses
200- Paginated list
application/jsondataarrayarray of:
FileidstringnamestringmimeTypestringsizeinteger — File size in bytesurlstringuploadedBystringchannelIdstring — Channel the file was shared in, if applicablemessageIdstring — Message the file is attached to, if applicablecreatedAtstringupdatedAtstring
nextCursorstring — Cursor for the next page, or null on the last page. With $top/$skip this is the next $skip value; otherwise a keyset cursor.totalinteger — Total documents in the collection.@odata.countinteger — Present only when $count=true: total matches after $filter/$search.@odata.truncatedboolean — Present and true only when the collection exceeded the in-memory query cap and results may be incomplete.
400- Invalid OData query (e.g. malformed $filter)
POST /api/purple-suite/chat/files
Create file
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
X-Instance-ID | header | string | yes | The Purple Suite instance ID that scopes all subcollections |
Request body
application/json — required
File
idstringnamestringmimeTypestringsizeinteger — File size in bytesurlstringuploadedBystringchannelIdstring — Channel the file was shared in, if applicablemessageIdstring — Message the file is attached to, if applicablecreatedAtstringupdatedAtstring
Responses
201- Created
application/jsonFileidstringnamestringmimeTypestringsizeinteger — File size in bytesurlstringuploadedBystringchannelIdstring — Channel the file was shared in, if applicablemessageIdstring — Message the file is attached to, if applicablecreatedAtstringupdatedAtstring
GET /api/purple-suite/chat/files/{id}
Get file
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
X-Instance-ID | header | string | yes | The Purple Suite instance ID that scopes all subcollections |
id | path | string | yes |
Responses
200- Found
application/jsonFileidstringnamestringmimeTypestringsizeinteger — File size in bytesurlstringuploadedBystringchannelIdstring — Channel the file was shared in, if applicablemessageIdstring — Message the file is attached to, if applicablecreatedAtstringupdatedAtstring
404- Not found
DELETE /api/purple-suite/chat/files/{id}
Delete file
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
X-Instance-ID | header | string | yes | The Purple Suite instance ID that scopes all subcollections |
id | path | string | yes |
Responses
200- Deleted
application/jsonsuccessboolean
404- Not found
PATCH /api/purple-suite/chat/files/{id}
Update file
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
X-Instance-ID | header | string | yes | The Purple Suite instance ID that scopes all subcollections |
id | path | string | yes |
Request body
application/json
File
idstringnamestringmimeTypestringsizeinteger — File size in bytesurlstringuploadedBystringchannelIdstring — Channel the file was shared in, if applicablemessageIdstring — Message the file is attached to, if applicablecreatedAtstringupdatedAtstring
Responses
200- Updated
application/jsonFileidstringnamestringmimeTypestringsizeinteger — File size in bytesurlstringuploadedBystringchannelIdstring — Channel the file was shared in, if applicablemessageIdstring — Message the file is attached to, if applicablecreatedAtstringupdatedAtstring
404- Not found