Messages API
Realtime chat channels that hang off a live Meeting. Every Meeting starts with one default thread (main) and - just like a Slack channel - any client can spin up extra threads on‑the‑fly (/v1/meetings/{meeting_id}/threads
). Use them to separate side‑bars (qa‑chat), action‑items, or Assistant‑only command lanes.
Looking for auth, base URLs, pagination, or error formats? Head over to API Foundations.
Endpoints at a glance
Method & Path | Purpose |
---|---|
GET /v1/meetings/{meeting_id}/threads/{id}/messages | List messages (cursor‑paginated) |
POST /v1/meetings/{meeting_id}/threads/{id}/messages | Post a user chat message / inline tool call |
GET /v1/meetings/{meeting_id}/threads/{id}/stream | Stream live messages (SSE, WebSocket upgrade) |
Real‑world hook: Daily Scrum Assistant auto‑flags new blockers in the blockers thread while the team is still in the stand‑up.
Message object schema
Field | Type | Description |
---|---|---|
id | string | Identifier (prefix msg_ ). |
thread_id | string | Owning thread. |
created_at | timestamp | ISO‑8601 UTC. |
role | string | user , assistant , system , transcript_segment , tool_call_started , tool_call_finished . |
type | string | answer (default) tool_suggestion or tool_response . |
content | string|object | Message text or tool payload/result JSON. |
segment_offset | integer? | Milliseconds offset inside the meeting for transcript segments. |
tool_name | string? | Populated for tool call rows. |
tool_params | object? | Arguments passed to the tool. |
tool_result | object? | Result blob once tool_call_finished arrives. |
Pagination follows the shared cursor model (cursor
, limit
, has_more
). Newest‑first ordering by default; set order=asc
to replay chronologically.
List messages
GET /v1/meetings/{meeting_id}/threads/{id}/messages
Query params
Name | Type | Default | Description |
---|---|---|---|
cursor | string? | – | Pointer from previous page. |
limit | integer? | 50 | 1–200 messages per page. |
order | string? | desc | asc or desc . |
Post a message / inline tool call
POST /v1/meetings/{meeting_id}/threads/{id}/messages
Body parameters
Field | Type | Required | Notes |
---|---|---|---|
role | string | yes | user only - assistant/system messages are server‑generated. |
content | string | yes* | Natural‑language prompt. If it requests an action, the platform automatically infers and executes the proper tool. |
🛠️ Tool call flow: Simply phrase the request (e.g. "Post 🚨 New blocker: login API 500s to #general on Slack"). The Assistant will reply with a
tool_suggestion
. Confirm by postingconfirmToolUse: true
to execute the action, orfalse
to decline.
Example – ask a question
curl -X POST https://api.voilo.io/meetings/meeting_123/threads/th_abc/messages \
-H "Authorization: Bearer $VOILO_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"role": "user",
"content": "Summarize the last 30 seconds"
}'
Execution Flow for Tool Calls
When a user request may require running an external tool (Slack, Jira, calendar, etc.) the exchange now follows the five‑step handshake below:
To enable the tool, you need to configure it and the assistant. See Tool Calling for more details.
- User request - The client posts a normal chat message to
POST /v1/meetings/{meeting_id}/threads/{id}/messages
. No special fields are needed to ask for the action.
curl -X POST https://api.voilo.io/meetings/meeting_123/threads/th_abc/messages \
-H "Authorization: Bearer $VOILO_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"role": "user",
"content": "Post 🚨 New blocker: login API 500s to #general on Slack"
}'
- Assistant suggestion - If the Assistant decides the request should be handled by a tool, it replies with a message whose
type
is"tool_suggestion"
. The payload includestool_name
andtool_params
.
{
"type": "tool_suggestion",
"tool_name": "slack_post_message",
"tool_description": "Post a message to a Slack channel",
"tool_params": {
"channel": "general",
"text": "🚨 New blocker: login API 500s"
},
"expected_outcome": "The message is posted to the Slack channel",
"tool_calls": [
{
"name": "slack_post_message",
"args": {
"channel": "general",
"text": "🚨 New blocker: login API 500s"
},
"type": "tool_call",
"id": "call_123"
}
]
}
- Client decision - Your UI (or server logic) chooses whether to execute the suggested tool. You can surface the details to the end‑user or auto‑approve.
- Confirmation - Post a follow‑up chat message in the same thread containing the top‑level field
"confirmToolUse": true
(orfalse
).
curl -X POST https://api.voilo.io/meetings/meeting_123/threads/th_abc/messages \
-H "Authorization: Bearer $VOILO_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"role": "user",
"content": "",
"confirmToolUse": true
}'
- Tool execution - When
confirmToolUse
istrue
the platform runs the tool and streams back atype = "tool_response"
message carrying the result intool_result
.
{
"type": "tool_response",
"answer": "The message is posted to the Slack channel",
"tool_results": [{
"tool": "slack_post_message",
"args": {
"channel": "general",
"text": "🚨 New blocker: login API 500s"
},
"result": "The message is posted to the Slack channel"
}]
}
Stream live messages
GET /v1/meetings/{meeting_id}/threads/{id}/stream
The server only supports WebSocket for realtime delivery. Include the typical handshake headers (Connection: Upgrade
, Upgrade: websocket
) plus any subprotocol you need.
- Each inbound text frame is a JSON‑encoded Message delivered the moment it is created.
- Heartbeat ping frames are emitted every 30 seconds; respond with pong (most WS libraries do this automatically).
// sample text frame payload
{
"thread_id": "th_blockers",
"created_at": "2025-06-17T11:50:03Z",
"role": "user",
"content": "List all blockers",
"segment_offset": 271200
}
See also
- Assistant Configuration – how to wire prompts & tools.
- API Foundations – base URLs, auth, pagination, and errors.
- Threads API – how to create threads.
- Tool Calling – how to enable tools.