Chats
Tags: chat, communication, messaging, voice
A Chat is a conversation thread between Members, Agents, and staff. These endpoints create chats, send and read messages, manage participants, place and inspect voice calls, and export conversation history and statistics.
In the product: Chats
Resources
Request and response models used by the endpoints on this page.
ChatLabelResponse
| Field | Type | Required | Description |
|---|---|---|---|
color | String | ✓ | |
description | String | ✓ | |
id | Integer | ✓ | |
name | String | ✓ | |
slug | String | ✓ | |
uuid | String | ✓ |
Example:
{
"id": 0 // Integer,
"uuid": "string" // String,
"name": "string" // String,
"slug": "string" // String,
"color": "string" // String,
"description": "string" // String
}
ChatParticipantResponse
| Field | Type | Required | Description |
|---|---|---|---|
additionalInstructions | String | ||
chatModel | String | ||
chatModelConfig | Dict[str, Any] | ||
memberId | Integer | ||
memberType | String | ||
name | String | ✓ | |
realtimeModel | String | ||
realtimeModelConfig | Dict[str, Any] | ||
role | String | ✓ |
Example:
{
"name": "string" // String,
"additionalInstructions": "string" // String, optional,
"role": "string" // String,
"memberId": 0 // Integer, optional,
"memberType": "string" // String, optional,
"chatModel": "string" // String, optional,
"realtimeModel": "string" // String, optional,
"chatModelConfig": {} // Dict[str, Any], optional,
"realtimeModelConfig": {} // Dict[str, Any], optional
}
ChatResponse
| Field | Type | Required | Description |
|---|---|---|---|
archived | Boolean | ✓ | |
assignmentId | Integer | ✓ | |
canSendAsAssistant | Boolean | ✓ | |
channel | String | ✓ | |
chatType | String | ✓ | |
createdAt | DateTime | ✓ | |
currentTaskName | String | ||
folderId | Integer | ✓ | |
fromMessageId | Integer | ✓ | |
id | Integer | ✓ | |
inboxId | Integer | ✓ | |
initialMessageError | String | ||
interrupt | ChatInterruptResponse | ||
isTest | Boolean | ✓ | |
labels | Array | ✓ | |
lastMessageReceivedAt | DateTime | ✓ | |
messageCount | Integer | ✓ | |
muted | Boolean | ✓ | |
needsResponse | Boolean | ✓ | |
participants | Array | ✓ | |
paused | Boolean | ✓ | |
pausedAt | DateTime | ✓ | |
pausedReason | String | ✓ | |
phoneNumberId | Integer | ✓ | |
siteId | Integer | ✓ | |
summary | String | ✓ | |
summaryUpdatedAt | DateTime | ✓ | |
title | String | ✓ | |
updatedAt | DateTime | ✓ | |
uuid | String | ✓ | |
workflowId | Integer | ✓ | |
workflowRevisionId | Integer |
Example:
{
"id": 0 // Integer,
"uuid": "string" // String,
"archived": false // Boolean,
"muted": false // Boolean,
"channel": "string" // String,
"chatType": "string" // String,
"paused": false // Boolean,
"pausedAt": "2024-01-01T00:00:00Z" // DateTime,
"pausedReason": "string" // String,
"needsResponse": false // Boolean,
"assignmentId": 0 // Integer,
"workflowId": 0 // Integer,
"workflowRevisionId": 0 // Integer, optional,
"currentTaskName": "string" // String, optional,
"fromMessageId": 0 // Integer,
"phoneNumberId": 0 // Integer,
"inboxId": 0 // Integer,
"siteId": 0 // Integer,
"folderId": 0 // Integer,
"createdAt": "2024-01-01T00:00:00Z" // DateTime,
"updatedAt": "2024-01-01T00:00:00Z" // DateTime,
"title": "string" // String,
"summary": "string" // String,
"summaryUpdatedAt": "2024-01-01T00:00:00Z" // DateTime,
"lastMessageReceivedAt": "2024-01-01T00:00:00Z" // DateTime,
"messageCount": 0 // Integer,
"participants": [] // Array<ChatParticipantResponse>,
"canSendAsAssistant": false // Boolean,
"labels": [] // Array<ChatLabelResponse>,
"isTest": false // Boolean,
"interrupt": 0 // ChatInterruptResponse, optional,
"initialMessageError": "string" // String, optional
}
ChatTokenUsageResponse
| Field | Type | Required | Description |
|---|---|---|---|
audioInputTokens | Integer | Default: 0 | |
audioOutputTokens | Integer | Default: 0 | |
cachedTokens | Integer | Default: 0 | |
completionTokens | Integer | Default: 0 | |
credits | Number | Default: 0.0 | |
creditsPerHour | Number | ||
creditsRemaining | Number | ||
extraUsageEnabled | Boolean | ||
promptTokens | Integer | Default: 0 | |
sttUsage | Array | Default: [] | |
totalTokens | Integer | Default: 0 | |
ttsUsage | Array | Default: [] | |
usageByModel | Array | Default: [] | |
voiceDurationSeconds | Number |
Example:
{
"promptTokens": 0 // Integer, optional, default: 0,
"completionTokens": 0 // Integer, optional, default: 0,
"totalTokens": 0 // Integer, optional, default: 0,
"cachedTokens": 0 // Integer, optional, default: 0,
"audioInputTokens": 0 // Integer, optional, default: 0,
"audioOutputTokens": 0 // Integer, optional, default: 0,
"credits": 0.0 // Number, optional, default: 0.0,
"creditsRemaining": 0.0 // Number, optional,
"extraUsageEnabled": false // Boolean, optional,
"usageByModel": [] // Array<ModelUsageResponse>, optional, default: [],
"sttUsage": [] // Array<VoiceUsageResponse>, optional, default: [],
"ttsUsage": [] // Array<VoiceUsageResponse>, optional, default: [],
"voiceDurationSeconds": 0.0 // Number, optional,
"creditsPerHour": 0.0 // Number, optional
}
ModelUsageResponse
| Field | Type | Required | Description |
|---|---|---|---|
audioInputTokens | Integer | Default: 0 | |
audioOutputTokens | Integer | Default: 0 | |
cachedMultiplier | Number | Default: 1.0 | |
cachedTokens | Integer | Default: 0 | |
completionTokens | Integer | Default: 0 | |
credits | Number | ✓ | |
inputMultiplier | Number | Default: 1.0 | |
model | String | ✓ | |
multiplier | Number | ✓ | |
outputMultiplier | Number | Default: 1.0 | |
promptTokens | Integer | Default: 0 | |
totalTokens | Integer | ✓ |
Example:
{
"model": "string" // String,
"promptTokens": 0 // Integer, optional, default: 0,
"completionTokens": 0 // Integer, optional, default: 0,
"totalTokens": 0 // Integer,
"cachedTokens": 0 // Integer, optional, default: 0,
"credits": 0.0 // Number,
"multiplier": 0.0 // Number,
"inputMultiplier": 0.0 // Number, optional, default: 1.0,
"outputMultiplier": 0.0 // Number, optional, default: 1.0,
"cachedMultiplier": 0.0 // Number, optional, default: 1.0,
"audioInputTokens": 0 // Integer, optional, default: 0,
"audioOutputTokens": 0 // Integer, optional, default: 0
}
OpenAIFunctionToolCall
| Field | Type | Required | Description |
|---|---|---|---|
function | Dict[str, Any] | Default: {} | |
id | String | Default: `` | |
type | String | Default: function |
Example:
{
"id": "string" // String, optional, default: ,
"type": "string" // String, optional, default: function,
"function": {} // Dict[str, Any], optional, default: {}
}
OpenAIMessageResponse
| Field | Type | Required | Description |
|---|---|---|---|
audioFileUuid | String | ||
audioMetadata | Dict[str, Any] | ||
content | Union[str, List[Dict[str, Any]], null] | ||
created_at | DateTime | ||
email_id | Integer | ||
id | String | ||
inbox_id | Integer | ||
memberId | Integer | ||
originalContent | Union[str, List[Dict[str, Any]], null] | ||
role | String | ||
smsDeliveryErrorCode | String | ||
smsDeliveryFailureReason | String | ||
smsDeliveryStatus | String | ||
smsDeliveryUpdatedAt | DateTime | ||
suggestions | Array | ||
taskId | Integer | ||
tokenUsage | MessageTokenUsageResponse | ||
tool_call_id | String | ||
tool_calls | Array | Default: [] | |
truncatedAtMs | Integer | ||
truncationReason | String | ||
userRating | Number | ||
userRatingComment | String |
Example:
{
"id": "string" // String, optional,
"role": "string" // String, optional,
"content": {} // Union[str, List[Dict[str, Any]], null], optional,
"originalContent": {} // Union[str, List[Dict[str, Any]], null], optional,
"truncationReason": "string" // String, optional,
"truncatedAtMs": 0 // Integer, optional,
"tool_calls": [] // Array<OpenAIFunctionToolCall>, optional, default: [],
"tool_call_id": "string" // String, optional,
"suggestions": "string" // Array<String>, optional,
"created_at": "2024-01-01T00:00:00Z" // DateTime, optional,
"email_id": 0 // Integer, optional,
"inbox_id": 0 // Integer, optional,
"tokenUsage": null // MessageTokenUsageResponse, optional,
"memberId": 0 // Integer, optional,
"taskId": 0 // Integer, optional,
"audioFileUuid": "string" // String, optional,
"audioMetadata": {} // Dict[str, Any], optional,
"smsDeliveryStatus": "string" // String, optional,
"smsDeliveryErrorCode": "string" // String, optional,
"smsDeliveryUpdatedAt": "2024-01-01T00:00:00Z" // DateTime, optional,
"smsDeliveryFailureReason": "string" // String, optional,
"userRating": 0.0 // Number, optional,
"userRatingComment": "string" // String, optional
}
OutboundCallRequest
| Field | Type | Required | Description |
|---|---|---|---|
chatId | Integer | ✓ | |
phoneNumberId | Integer | ✓ |
Example:
{
"phoneNumberId": 0 // Integer,
"chatId": 0 // Integer
}
PhoneCallResponse
| Field | Type | Required | Description |
|---|---|---|---|
agent | BaseAssistantResponse | ||
carrierStatus | String | Twilio CallStatus / DialCallStatus terminal value (GRA-6416): completed, busy, no-answer, failed, or canceled. Independent of product intent — a successful transfer is terminationReason=forward + carrierStatus=completed; a transfer whose destination was busy is forward + busy. | |
chatId | Integer | ||
createdAt | DateTime | ✓ | |
credits | Number | ||
failureDetail | String | Transport / infra failure detail (GRA-6416): connection_reset (Twilio ErrorCode on completed call), stream_reset (media-stream WebSocket reset, e.g. Twilio 31921), never_connected (bridge-leg provisional), timeout, bridge_call_create_failed, bridge_call_create_missing_sid, fax_t30_failed, other closed fax_* receive codes, or error. | |
finishedAt | DateTime | ||
id | Integer | ✓ | |
inbound | Boolean | ✓ | |
member | WorkspaceMemberResponse | ||
phoneNumberId | Integer | ✓ | |
startedAt | DateTime | ||
status | String | ✓ | |
terminationReason | String | Product / app outcome for how the call ended (GRA-6416). Preferred values: hangup (assistant ended), forward (call forwarded), handoff, completed (caller hung up / normal end), policy rejects (voice_disabled, anonymous_rejected, …), blocked_outbound_safety, voicemail, amd_unknown. Legacy rows may also hold carrier strings (busy, no-answer, …) or transport failures (connection_reset, stream_reset, never_connected); prefer carrierStatus / failureDetail when present. Null for in-progress/unknown calls. | |
twilioCallId | String | ✓ | |
workflowId | Integer | ID of the workflow associated with this call, resolved via the chat's assignment (PhoneCall.chat_id -> Chat.assignment_id -> Assignment.workflow_revision_id -> WorkflowRevision.workflow_id). Null for direct human-to-human calls with no chat, or chats with no assignment. |
Example:
{
"id": 0 // Integer,
"phoneNumberId": 0 // Integer,
"chatId": 0 // Integer, optional,
"twilioCallId": "string" // String,
"status": "string" // String,
"createdAt": "2024-01-01T00:00:00Z" // DateTime,
"startedAt": "2024-01-01T00:00:00Z" // DateTime, optional,
"finishedAt": "2024-01-01T00:00:00Z" // DateTime, optional,
"member": null // WorkspaceMemberResponse, optional,
"agent": null // BaseAssistantResponse, optional,
"inbound": false // Boolean,
"credits": 0.0 // Number, optional,
"terminationReason": "string" // String, optional, Product / app outcome for how the call ended (GRA-6416). Preferred values: `hangup` (assistant ended), `forward` (call forwarded), `handoff`, `completed` (caller hung up / normal end), policy rejects (`voice_disabled`, `anonymous_rejected`, …), `blocked_outbound_safety`, `voicemail`, `amd_unknown`. Legacy rows may also hold carrier strings (`busy`, `no-answer`, …) or transport failures (`connection_reset`, `stream_reset`, `never_connected`); prefer `carrierStatus` / `failureDetail` when present. Null for in-progress/unknown calls.,
"carrierStatus": "string" // String, optional, Twilio CallStatus / DialCallStatus terminal value (GRA-6416): `completed`, `busy`, `no-answer`, `failed`, or `canceled`. Independent of product intent — a successful transfer is `terminationReason=forward` + `carrierStatus=completed`; a transfer whose destination was busy is `forward` + `busy`.,
"failureDetail": "string" // String, optional, Transport / infra failure detail (GRA-6416): `connection_reset` (Twilio ErrorCode on completed call), `stream_reset` (media-stream WebSocket reset, e.g. Twilio 31921), `never_connected` (bridge-leg provisional), `timeout`, `bridge_call_create_failed`, `bridge_call_create_missing_sid`, `fax_t30_failed`, other closed `fax_*` receive codes, or `error`.,
"workflowId": 0 // Integer, optional, ID of the workflow associated with this call, resolved via the chat's assignment (PhoneCall.chat_id -> Chat.assignment_id -> Assignment.workflow_revision_id -> WorkflowRevision.workflow_id). Null for direct human-to-human calls with no chat, or chats with no assignment.
}
VoiceUsageResponse
| Field | Type | Required | Description |
|---|---|---|---|
characterCount | Integer | ||
credits | Number | ✓ | |
durationSeconds | Number | ||
model | String | ✓ | |
multiplier | Number | ✓ |
Example:
{
"model": "string" // String,
"credits": 0.0 // Number,
"multiplier": 0.0 // Number,
"durationSeconds": 0.0 // Number, optional,
"characterCount": 0 // Integer, optional
}
Endpoints
Create chats
Messages
GET /api/v2/w/{workspace_uuid}/chats/{chat_id}/messages- MessagesGET /api/v2/w/{workspace_uuid}/chats/{chat_id}/messages- MessagesPOST /api/v2/w/{workspace_uuid}/chats/{chat_id}/messages- MessagesPOST /api/v2/w/{workspace_uuid}/chats/{chat_id}/messages/{message_uuid}/rate- RateGET /api/v2/w/{workspace_uuid}/chats/{chat_id}/tool-calls/{call_id}/messages- Messages
Chat actions
POST /api/v2/w/{workspace_uuid}/chats/{chat_id}/participants- ParticipantsPOST /api/v2/w/{workspace_uuid}/chats/{chat_id}/send-assistant-message- Send Assistant MessagePOST /api/v2/w/{workspace_uuid}/chats/{chat_id}/summarize- Summarize
Voice calls
GET /api/v2/w/{workspace_uuid}/chats/outbound-call-handler/{phone_number_id}/{chat_id}/{phone_call_id}- Outbound Call HandlerPOST /api/v2/w/{workspace_uuid}/chats/outbound-call-handler/{phone_number_id}/{chat_id}/{phone_call_id}- Outbound Call HandlerPOST /api/v2/w/{workspace_uuid}/chats/{chat_id}/outbound-call- Outbound CallGET /api/v2/w/{workspace_uuid}/chats/{chat_id}/phone-calls- Phone Calls
Statistics & export
GET /api/v2/w/{workspace_uuid}/chats/export- ExportGET /api/v2/w/{workspace_uuid}/chats/needs-response- Needs ResponseGET /api/v2/w/{workspace_uuid}/chats/stats/daily-creation- Daily CreationGET /api/v2/w/{workspace_uuid}/chats/tool-call-names- Tool Call Names
Token usage
Create chats
Create chats, including direct-message chats between two participants.
Create
POST /api/v2/w/{workspace_uuid}/chats
Description:
Create a new chat conversation in the workspace.
Self-access: Any authenticated member can create a chat (becomes the owner).
Creates either a simple chat or, when workflowId is provided, a workflow
assignment chat. The assignment is created automatically; callers do not
create or pass an assignment first. For phone-voice assignment chats with
the assistant enabled, chat creation also places the outbound call.
Request Body:
channel: Communication channel (web-chat, phone-sms, phone-voice, email)workflowId: Workflow to run; creates the assignment automatically when providedworkflowRevisionId: Published workflow revision to pin this assignment to (defaults to the active revision)memberId: Member this chat is for; defaults to the authenticated memberphoneNumberId: Workspace phone number for SMS/voice; workflow default is used when availableinboxId: Workspace inbox for email chats; mutually exclusive withphoneNumberIdparticipants: Additional member participants such as an assistant/operator memberassistantEnabled: Whether the AI assistant runs the chat (default: true)assistantMemberId: Specific assistant member to use instead of the workflow agentassistantChatModelId/assistantRealtimeModelId: Per-chat assistant model overridesinitialMessage: Initial operator message for agent-disabled SMS/email chatstitle,siteId,isTest,chatType: Optional metadata and chat classification
Response:
Returns a ChatResponse object with the newly created chat, including all participants,
message counts, and metadata. When an operator-typed initialMessage could not be
sent (SMS/email dispatch failed, recipient opted out, missing phone/inbox), the chat
is still created and returned with initialMessageError set to a PHI-free reason
code — a partial success, not an error. Callers should surface a "reload and retry"
warning when that field is present.
Permissions: Requires authenticated member session. Chat ownership is automatically assigned to the creator.
Error Responses:
400 Bad Request: Invalid request parameters or missing required fields401 Unauthorized: Missing or invalid authentication404 Not Found: Referenced workflow, member, or assistant member not found500 Internal Server Error: Database or processing error
Related Endpoints:
GET /chats- List all chatsGET /chats/{chat_id}- Get chat detailsPUT /chats/{chat_id}- Update chat properties
Authentication: Requires workspace member
Parameters:
chat(CreateChatRequest)
Response: See ChatResponse
Dm
POST /api/v2/w/{workspace_uuid}/chats/dm
Description:
Find or create a DM chat with a specific member.
Returns the existing DM chat between the current member and the target member, or creates a new one if none exists.
Self-access: a member may always start their own DM with an agent — it is
their own conversation, so no scope is required (matching record self-access,
where creating your own record needs no records:write). Initiating a DM
with another human member is cross-member contact and requires
dm:write.
Authentication: Requires workspace member
Parameters:
request- See FindOrCreateDMChatRequest
Response: See ChatResponse
Messages
Read and send messages in a chat, rate responses, and inspect tool-call messages.
Messages
GET /api/v2/w/{workspace_uuid}/chats/{chat_id}/messages
Description:
Get messages from a specific chat with pagination.
Retrieves the message history for a chat in OpenAI-compatible format. Messages include content, role (user/assistant/system), tool calls, and metadata. Results are paginated for efficient loading of long conversations.
Path Parameters:
id: Chat ID to retrieve messages from
Query Parameters:
limit: Maximum number of messages to return (1-100, default: 10)offset: Number of messages to skip for pagination (default: 0)
Response: Returns an array of OpenAIMessageResponse objects in reverse chronological order (most recent first), each containing message content, role, timestamps, and tool call data.
Permissions: Self-access: Users can view messages in their own chats. Admin access: CHATS_READ scope required to view other members' chat messages.
Error Responses:
401 Unauthorized: Missing or invalid authentication403 Forbidden: User does not have permission to view this chat404 Not Found: Chat not found
Related Endpoints:
GET /chats/{chat_id}- Get chat detailsGET /chats/{chat_id}/tool-calls/{call_id}/messages- Get tool call messagesPOST /chats/{chat_id}/send-assistant-message- Send a message as assistant
Authentication: Requires workspace member
Parameters:
chat_id(int | str)limit(Integer) — default: 10, min: 1, max: 100offset(Integer) — default: 0, min: 0
Response: List of OpenAIMessageResponse
Messages
GET /api/v2/w/{workspace_uuid}/chats/{chat_id}/messages
Description:
Get paginated messages for a specific chat.
Retrieves chat messages with full pagination support including total count calculation. Messages are returned in OpenAI-compatible format with role, content, and tool call information.
Path Parameters:
chat_id: Chat ID to retrieve messages from
Query Parameters:
limit: Maximum messages per page (1-100, default: 10)offset: Number of messages to skip (default: 0)total_count: Whether to calculate total message count (default: false for performance)
Response: Returns a paginated response with message array, total count, page number, page size, and total pages. Messages are in OpenAI format with full metadata.
Permissions: Self-access: Users can view messages in their own chats. Admin access: CHATS_READ scope required to view other members' chat messages.
Error Responses:
401 Unauthorized: Missing or invalid authentication403 Forbidden: User does not have permission to view this chat404 Not Found: Chat not found
Related Endpoints:
GET /chats/{chat_id}/messages- Alternative messages endpointGET /chats/{chat_id}- Get chat details
Authentication: Requires workspace member
Parameters:
workspace_uuid(String)chat_id(int | str)limit(Integer) — default: 10, min: 1, max: 100offset(Integer) — default: 0, min: 0total_count(Boolean) — default: False
Response: See PaginatedResponse[OpenAIMessageResponse]
Messages
POST /api/v2/w/{workspace_uuid}/chats/{chat_id}/messages
Description:
Send a user message in a chat.
For DM chats with human recipients, triggers SendDmNotificationWorkflow. Agent DM responses are handled via the AGUI streaming endpoint.
Authorization: Requires chats:write scope
Parameters:
chat_id(int | str)request- See SendUserMessageRequest
Response: See OpenAIMessageResponse
Rate
POST /api/v2/w/{workspace_uuid}/chats/{chat_id}/messages/{message_uuid}/rate
Description:
Rate an assistant message for quality feedback.
Persists the rating to the workspace-plane chat_feedback table (durable,
customer-visible). Langfuse scoring is best-effort observability on top and
never affects the API response once the workspace row is written — missing
traces, unconfigured Langfuse, or Langfuse errors are logged, not returned
to the client.
Path Parameters:
chat_id: Chat ID containing the messagemessage_uuid: UUID of the message to rate
Request Body:
rating: Numeric rating value (e.g., 1.0 for positive, 0.0 for negative)comment: Optional text comment explaining the rating
Response:
Returns {"status": "success"} when the durable workspace rating was
recorded. Langfuse outcome is never exposed to the client.
Permissions: Self-access: Users can rate messages in their own chats. Admin access: CHATS_WRITE scope required to rate other members' chat messages.
Error Responses:
400 Bad Request: Message is not an assistant message or integrity check failed401 Unauthorized: Missing or invalid authentication403 Forbidden: User does not have permission to rate messages in this chat404 Not Found: Chat or message not found
Related Endpoints:
GET /chats/{chat_id}/messages- Get chat messages to ratePOST /chats/{chat_id}/send-assistant-message- Send assistant messages
Authentication: Requires workspace member
Parameters:
chat_id(int | str)message_uuid(String)rating_data(RateMessageRequest)
Messages
GET /api/v2/w/{workspace_uuid}/chats/{chat_id}/tool-calls/{call_id}/messages
Description:
Get messages from a specific tool call execution.
Retrieves the detailed message history from a tool call's ReACT loop execution. This includes sub-agent messages, tool invocations, and results from custom tools that run their own conversation loops.
Path Parameters:
id: Chat ID containing the tool callcall_id: Tool call ID to retrieve messages from
Query Parameters:
limit: Maximum number of messages to return (1-1000, default: 100)offset: Number of messages to skip for pagination (default: 0)
Response: Returns an array of OpenAIMessageResponse objects representing the internal conversation flow within the tool execution, useful for debugging and transparency.
Permissions: Self-access: Users can view tool call messages in their own chats. Admin access: CHATS_READ scope required to view other members' chat messages.
Error Responses:
401 Unauthorized: Missing or invalid authentication403 Forbidden: User does not have permission to view this chat404 Not Found: Chat or tool call not found
Related Endpoints:
GET /chats/{chat_id}/messages- Get main chat messagesGET /chats/{chat_id}/tools- Get available tools for chat
Authentication: Requires workspace member
Parameters:
chat_id(int | str)call_id(String)limit(Integer) — default: 100, min: 1, max: 1000offset(Integer) — default: 0, min: 0
Response: List of OpenAIMessageResponse
Chat actions
Act on an existing chat: manage participants, trigger an Agent reply, or summarize.
Participants
POST /api/v2/w/{workspace_uuid}/chats/{chat_id}/participants
Description:
Add a participant to a chat with a specified role.
Allows workspace managers to add members to chats with various roles including contributors. Contributors can be consulted via contributor_input_request tool during conversations.
Path Parameters:
chat_id: Chat ID to add participant to
Request Body:
memberId: ID of the member to add as a participantrole: Role for the participant (default: "contributor")
Response: Returns a success status, message, and the ID of the created participant.
Permissions:
Requires chats:write scope.
Error Responses:
401 Unauthorized: Missing or invalid authentication403 Forbidden: User lackschats:writescope404 Not Found: Chat or member not found400 Bad Request: Invalid role or participant already exists
Related Endpoints:
GET /chats/{id}- Get chat details including participantsGET /members- List workspace members
Authorization: Requires chats:write scope
Parameters:
chat_id(Integer)request- See AddChatParticipantRequest
Response: See ChatParticipantAddedResponse
Send Assistant Message
POST /api/v2/w/{workspace_uuid}/chats/{chat_id}/send-assistant-message
Description:
Send a message as the assistant in a chat conversation.
Allows workspace managers to manually send messages on behalf of the chat's assistant. Supports SMS and email channels with automatic delivery. Can optionally include tool calls which will be executed before message delivery. Automatically clears the needs_response flag when used.
Path Parameters:
chat_id: Chat ID to send the message in
Request Body:
message: Message content to send (supports markdown for email)tool_calls: Optional array of tool calls to execute with the message
Response: Returns a success confirmation with the created message details including ID, UUID, role, content, and timestamp.
Permissions:
Requires chats:admin scope to send messages as the assistant.
Error Responses:
400 Bad Request: Invalid chat configuration, missing phone/email, or notifications disabled401 Unauthorized: Missing or invalid authentication403 Forbidden: User lackschats:adminscope404 Not Found: Chat, assistant, or participant not found500 Internal Server Error: Failed to send SMS/email or execute tools
Related Endpoints:
GET /chats/{id}/messages- Get chat message historyPOST /chats/{id}/messages/{uuid}/rate- Rate an assistant messageGET /chats/{id}/tools- Get available tools for the chat
Authorization: Requires chats:admin scope
Parameters:
chat_id(Integer)payload- See SendAssistantMessageRequest
Summarize
POST /api/v2/w/{workspace_uuid}/chats/{chat_id}/summarize
Description:
Generate an AI summary of the chat conversation.
Creates an AI-generated summary of the chat's message history, updating the chat's title and summary fields. Optionally analyzes conversation content to automatically update chat labels. Summary generation happens synchronously within the request.
Path Parameters:
chat_id: Chat ID to summarize
Query Parameters:
update_labels: If true, also updates chat labels based on conversation content (default: false)
Response: Returns the updated ChatResponse object with new title, summary, summary_updated_at timestamp, and optionally updated labels.
Permissions: Self-access: Users can summarize their own chats. Admin access: CHATS_WRITE scope required to summarize other members' chats.
Error Responses:
401 Unauthorized: Missing or invalid authentication403 Forbidden: User does not have permission to summarize this chat404 Not Found: Chat not found500 Internal Server Error: AI summarization failed
Related Endpoints:
GET /chats/{id}- Get chat details including current summaryGET /chats/{id}/messages- View messages being summarizedPUT /chats/{id}- Update chat manually
Authentication: Requires workspace member
Parameters:
chat_id(Integer)update_labels(Boolean) — default: False
Response: See ChatResponse
Voice calls
Place outbound voice calls on a chat and inspect its phone calls.
Outbound Call Handler
GET /api/v2/w/{workspace_uuid}/chats/outbound-call-handler/{phone_number_id}/{chat_id}/{phone_call_id}
Description:
Handle Twilio webhook for outbound calls.
The phone_call_id path parameter references a PhoneCall row that was
pre-created by initiate_outbound_call_for_chat() in PENDING state.
This handler finds that row and updates agent_id, started_at, and
status now that the call has actually connected to Twilio's stream.
Auth: this is a Twilio-fetched webhook, authenticated by the request
signature (validate_twilio_request inside _handle_outbound_call_impl),
NOT by an org/member session. It therefore depends on require_ws_db_public,
which omits the org-SSO gate. Using the gated require_ws_db here 401'd
Twilio's unauthenticated fetch on ssoOnly orgs (Bearer realm="org"
challenge), which Twilio surfaced as error 11200 and spoke to the callee as
"an application error has occurred" — killing every outbound call for those
orgs before the handler ran. Keep this on the public dependency.
Authentication: Requires authenticated user
Parameters:
chat_id(Integer)phone_number_id(Integer)phone_call_id(Integer)
Outbound Call Handler
POST /api/v2/w/{workspace_uuid}/chats/outbound-call-handler/{phone_number_id}/{chat_id}/{phone_call_id}
Description:
Handle Twilio webhook for outbound calls.
The phone_call_id path parameter references a PhoneCall row that was
pre-created by initiate_outbound_call_for_chat() in PENDING state.
This handler finds that row and updates agent_id, started_at, and
status now that the call has actually connected to Twilio's stream.
Auth: this is a Twilio-fetched webhook, authenticated by the request
signature (validate_twilio_request inside _handle_outbound_call_impl),
NOT by an org/member session. It therefore depends on require_ws_db_public,
which omits the org-SSO gate. Using the gated require_ws_db here 401'd
Twilio's unauthenticated fetch on ssoOnly orgs (Bearer realm="org"
challenge), which Twilio surfaced as error 11200 and spoke to the callee as
"an application error has occurred" — killing every outbound call for those
orgs before the handler ran. Keep this on the public dependency.
Authentication: Requires authenticated user
Parameters:
chat_id(Integer)phone_number_id(Integer)phone_call_id(Integer)
Outbound Call
POST /api/v2/w/{workspace_uuid}/chats/{chat_id}/outbound-call
Description:
Initiate an outbound phone call for a chat.
Starts an outbound voice call from the assistant to the chat participant using Twilio. The call will be connected to the workspace's configured phone number and handled by the chat's assigned assistant with real-time audio streaming.
Path Parameters:
chat_id: Chat ID to initiate the call for
Request Body:
phoneNumberId: ID of the workspace phone number to use for the outbound call
Response: Returns a status object confirming the call was initiated successfully.
Permissions: Requires workspace management permissions and sufficient phone call budget.
Error Responses:
400 Bad Request: Invalid phone number ID or chat configuration401 Unauthorized: Missing or invalid authentication403 Forbidden: Insufficient permissions or exceeded budget limits404 Not Found: Chat or phone number not found500 Internal Server Error: Failed to initiate call with Twilio
Related Endpoints:
GET /chats/{id}- Get chat detailsPOST /chats- Create a new chat for phone conversations
Authorization: Requires phones:write scope
Parameters:
chat_id(Integer)request- See OutboundCallRequest
Response: See OutboundDialResult
Phone Calls
GET /api/v2/w/{workspace_uuid}/chats/{chat_id}/phone-calls
Description:
Get phone calls associated with a chat.
Returns all phone calls linked to the given chat, ordered by most recent first. Used by the chat detail view to display call termination information.
Authorization: Requires chats:read scope
Parameters:
chat_id(Integer)
Response: List of PhoneCallResponse
Statistics & export
Chat statistics, needs-response queues, and conversation exports.
Export
GET /api/v2/w/{workspace_uuid}/chats/export
Description:
Export chats as CSV with filtering applied.
Exports all chats matching the current filters to a CSV file. Respects the same filtering parameters as the list_chats endpoint but returns all matching results (not paginated). Useful for bulk analysis, reporting, and integration with external tools.
Query Parameters:
All the same filtering parameters as GET /chats:
sortBy,sortOrder: Sort order for consistent outputmine,archived,needsResponse,paused: Status filterschannel,chatType,memberId,assistantMemberId: Type and participant filterssearch: Text search across chat content and metadataisTest: Filter test chatsisAnonymous: Owner-anonymity scope, identical toGET /chats.true= anonymous-owner chats only (requireschats:admin);false= known-owner chats only; omitted = no owner-anonymity filter, so achats:admincaller exports both. The export and the list therefore return the same chat set for the same request.filters: JSON-encoded advanced filter rulescreatedAfter: ISO-8601 timestamp with timezone offset — only export chats created on or after this instantcreatedBefore: ISO-8601 timestamp with timezone offset — only export chats created on or before this instant
Response: Returns a CSV file with chat data including metadata, participants, and status.
Permissions:
Requires chats:read scope. Members without this scope cannot bulk-export chats.
Filtering to anonymous chats (isAnonymous=true) additionally requires chats:admin.
Members without chats:admin never receive anonymous-owner rows — that is
a server-enforced authorization boundary, not a removable filter.
Authorization: Requires chats:read scope
Parameters:
sortBy(ChatSortField)sortOrder(SortOrder)mine(Boolean)archived(Boolean)needsResponse(Boolean)paused(Boolean)channel(String)chatType(String)memberId(Integer)search(String)filters(String)query(String)isTest(Boolean)isAnonymous(Boolean)assistantMemberId(Integer)createdAfter(datetime)createdBefore(datetime)
Needs Response
GET /api/v2/w/{workspace_uuid}/chats/needs-response
Description:
Get IDs of chats that need a response.
Returns a lightweight list of chat IDs that require attention from the workspace team. Only includes non-archived, non-muted chats with the needs_response flag set to true. Useful for dashboard notifications and task management workflows.
Response: Returns an array of chat IDs (integers) that need responses. Empty array if none found.
Permissions: Self-access: Users see their own chats needing response. Admin access: CHATS_READ scope required to see all chats needing response.
Authentication: Requires workspace member
Daily Creation
GET /api/v2/w/{workspace_uuid}/chats/stats/daily-creation
Description:
Get daily chat creation statistics for the last 30 days.
Returns aggregated chat creation counts grouped by date and chat type for the past 30 days. This data is useful for visualizing chat activity trends and patterns by type.
Query Parameters:
archived: Filter by archived status (true/false, default: excludes archived)isTest: Filter by test status (true/false, default: excludes test chats)
Response:
Returns a dictionary with dailyStats array containing objects with:
date: YYYY-MM-DD formatcount: total chat countassignment,manager,dm,testing: breakdown by type
Permissions:
- Admin users see all workspace chats
- Regular users see only their own chats
Authentication: Requires workspace member
Parameters:
archived(Boolean)isTest(Boolean)
Tool Call Names
GET /api/v2/w/{workspace_uuid}/chats/tool-call-names
Description:
Get distinct tool call names used across workspace chats.
Returns an alphabetically sorted list of unique tool call names from all messages in the workspace. Useful for populating filter dropdowns.
Permissions:
- Admin users see tool calls from all workspace chats
- Regular users see tool calls only from their own chats
Authentication: Requires workspace member
Token usage
Token usage recorded for a chat.
Token Usage
GET /api/v2/w/{workspace_uuid}/chats/{chat_id}/token-usage
Description:
Get aggregated token usage statistics for a specific chat.
Returns the total prompt tokens, completion tokens, total tokens, cached tokens, and credits used by all messages in this chat, including STT and TTS usage from voice calls.
Path Parameters:
chat_id: Chat ID to retrieve token usage for
Response: Returns a ChatTokenUsageResponse with aggregated token counts and credits.
Permissions: Self-access: Users can view token usage for their own chats. Admin access: CHATS_READ scope required to view other members' chat usage.
Error Responses:
401 Unauthorized: Missing or invalid authentication403 Forbidden: User does not have permission to view this chat404 Not Found: Chat not found
Authentication: Requires workspace member
Parameters:
chat_id(Integer)
Response: See ChatTokenUsageResponse