Chat API
Chat threads represent conversations between users, while messages are individual communications within those threads.
Endpoints
| Method | Endpoint | Description |
|---|---|---|
| GET | /chat/threads | List chat threads |
| POST | /chat/threads | Create a new chat thread |
| GET | /chat/threads/{thread_id} | Get a specific chat thread |
| POST | /chat/threads/{thread_id}/messages | Add a message to a chat thread |
| PATCH | /chat/threads/{thread_id}/messages/{message_id} | Update a message in a chat thread |
| GET | /chat/threads/{thread_id}/participants | Get participants of a chat thread |
| POST | /chat/threads/{thread_id}/participants | Add a participant to a chat thread |
Thread Endpoints
List Threads
GET /api/v2/chat/threads
Retrieves a paginated list of chat threads. All filters are optional. When client_account_id is omitted, threads are returned across all of the user’s eligible client accounts.
Query Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| client_account_id | integer | No | Filter threads by client account ID |
| provider_client_account_id | integer | No | Filter threads by provider client account ID |
| relation_type | string | No | Filter threads by relation type (e.g. document, businesspartner) |
| relation_id | integer | No | Filter threads by relation ID |
| free_text | string | No | Full-text search across thread subjects and message content (case-insensitive, partial word match) |
| order_by | string | No | Sort field (e.g. created_at, -last_message_created_at) |
| page | integer | No | Page number for paginated results (default: 1) |
| per_page | integer | No | Number of items per page (default: 100) |
Search Examples
Search threads by text content:
GET /api/v2/chat/threads?free_text=invoice
Combine search with other filters:
GET /api/v2/chat/threads?free_text=invoice&client_account_id=123&relation_type=document
Create Thread
POST /api/v2/chat/threads
Creates a new chat thread. The authenticated user is recorded as created_by_id. The user must have access to either the client_account_id or the provider_client_account_id of the thread being created. Messages can be included in the request body to be created together with the thread.
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
| client_account_id | integer | Yes | The client account the thread belongs to |
| provider_client_account_id | integer | No | The provider client account (set when the thread spans an accountant–client relationship) |
| subject | string | No | The subject line of the thread |
| relation_type | string | No | The type of entity the thread is associated with (e.g. document, businesspartner) |
| relation_id | integer | No | The ID of the related entity |
| is_completed | boolean | No | Whether the thread is marked as completed (default: false) |
| is_archived | boolean | No | Whether the thread is archived (default: false) |
| messages | array | No | Initial messages to add to the thread. See Add Message for the message body shape |
Example Request
{
"client_account_id": 123,
"provider_client_account_id": 7,
"subject": "Invoice 1004 - missing VAT code",
"relation_type": "document",
"relation_id": 5678,
"messages": [
{
"message": "Could you confirm which VAT code applies to this purchase?"
}
]
}
Response
Returns the created thread with status 201 Created.
{
"id": 42,
"created_by_id": 12,
"created_at": "2026-06-01T09:00:00Z",
"last_message_created_at": "2026-06-01T09:00:00Z",
"client_account_id": 123,
"provider_client_account_id": 7,
"subject": "Invoice 1004 - missing VAT code",
"relation_type": "document",
"relation_id": 5678,
"is_completed": false,
"is_archived": false
}
Get Thread
GET /api/v2/chat/threads/{thread_id}
Retrieves a specific chat thread by ID.
Response
Returns the thread object. See Thread Attributes.
Errors
| Status | Description |
|---|---|
| 403 | No access to the thread’s client account or provider client account |
| 404 | Thread not found |
Message Endpoints
Add Message
POST /api/v2/chat/threads/{thread_id}/messages
Adds a new message to a chat thread. The authenticated user is recorded as both from_user_id and created_by_id. The user must have access to either the thread’s client_account_id or provider_client_account_id.
Messages containing a codeaction block trigger automatic processing — the block is first run in preview mode and, if no approval is required, automatically re-run in write mode. See Code Blocks in Messages.
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
| message | string | Yes | The content of the message. May contain codeaction, approvecodeaction, or coderesult blocks |
| is_draft | boolean | No | Whether the message is a draft (default: false) |
Example Request
{
"message": "Posted as 6300 (Office Supplies). Let me know if that needs adjusting."
}
Response
Returns the created message with status 201 Created. Code blocks in the message field are obscured in the response (see Code Blocks in Messages).
{
"id": 1042,
"created_by_id": 12,
"created_at": "2026-06-01T09:15:00Z",
"thread_id": 42,
"from_user_id": 12,
"message": "Posted as 6300 (Office Supplies). Let me know if that needs adjusting.",
"is_draft": false,
"action_items": [],
"action_mode": null,
"action_error": false
}
Errors
| Status | Description |
|---|---|
| 403 | No access to the thread’s client account or provider client account |
| 404 | Thread not found |
Update Message
PATCH /api/v2/chat/threads/{thread_id}/messages/{message_id}
Updates an existing message in a chat thread. Useful for editing draft messages before they are finalized, or for replacing message content. The authenticated user is recorded as the new from_user_id.
Only the fields below are accepted in the update payload — thread_id, from_user_id, created_at, and created_by_id cannot be changed.
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
| message | string | No | New content for the message |
| is_draft | boolean | No | Update the draft flag |
Example Request
Promote a draft to a sent message:
{
"message": "Confirmed — VAT code 3 (25%) is correct for this purchase.",
"is_draft": false
}
Response
Returns the updated message with status 201 Created. As with create, code blocks in the message field are obscured.
Errors
| Status | Description |
|---|---|
| 403 | No access to the thread’s client account or provider client account |
| 404 | Thread or message not found |
Participant Endpoints
List Participants
GET /api/v2/chat/threads/{thread_id}/participants
Returns the participants of a chat thread.
Response
[
{
"id": 11,
"created_by_id": 12,
"created_at": "2026-06-01T09:00:00Z",
"user_id": 12,
"thread_id": 42
},
{
"id": 12,
"created_by_id": 12,
"created_at": "2026-06-01T09:01:00Z",
"user_id": 34,
"thread_id": 42
}
]
Errors
| Status | Description |
|---|---|
| 403 | No access to the thread’s client account or provider client account |
| 404 | Thread not found |
Add Participant
POST /api/v2/chat/threads/{thread_id}/participants
Adds a participant (user) to a chat thread. The authenticated user is recorded as created_by_id.
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
| user_id | integer | Yes | The ID of the user to add as a participant |
Example Request
{
"user_id": 34
}
Response
Returns the created participant with status 201 Created.
{
"id": 12,
"created_by_id": 12,
"created_at": "2026-06-01T09:01:00Z",
"user_id": 34,
"thread_id": 42
}
Errors
| Status | Description |
|---|---|
| 403 | No access to the thread’s client account or provider client account |
| 404 | Thread not found |
Thread Attributes
| Attribute | Type | Description |
|---|---|---|
| id | integer | The ID of the chat thread |
| created_by_id | integer | The ID of the user who created the thread |
| created_at | string | The date and time when the thread was created (ISO 8601) |
| last_message_created_at | string | The date and time of the most recent message in the thread (ISO 8601, read-only) |
| client_account_id | integer | The client account ID associated with the thread |
| provider_client_account_id | integer | The provider client account ID associated with the thread |
| subject | string | The subject line of the thread |
| relation_type | string | The type of entity the thread is associated with (e.g. document, businesspartner) |
| relation_id | integer | The ID of the related entity |
| is_completed | boolean | Whether the thread is marked as completed |
| is_archived | boolean | Whether the thread is archived |
Message Attributes
| Attribute | Type | Description |
|---|---|---|
| id | integer | The ID of the message |
| thread_id | integer | The ID of the chat thread associated with the message |
| from_user_id | integer | The ID of the user who sent the message |
| message | string | The content of the message. Code blocks are obscured (see Code Blocks in Messages) |
| is_draft | boolean | Whether the message is a draft |
| created_at | string | The date and time when the message was created (ISO 8601) |
| created_by_id | integer | The ID of the user who created the message |
| action_items | array | List of preview objects extracted from coderesult blocks |
| action_mode | string | The execution mode from coderesult blocks (preview or write), or null |
| action_error | boolean | true if the coderesult block reported an execution error |
Participant Attributes
| Attribute | Type | Description |
|---|---|---|
| id | integer | The ID of the participant |
| thread_id | integer | The ID of the chat thread associated with the participant |
| user_id | integer | The ID of the user associated with the participant |
| created_by_id | integer | The ID of the user who added this participant |
| created_at | string | The date and time when the participant was added (ISO 8601) |
Code Blocks in Messages
Messages can contain special code blocks that are processed by the system:
| Block Type | Description |
|---|---|
| codeaction | Executable code blocks that perform actions. Initially run in preview mode. If no approval is needed, automatically run in write mode. |
| approvecodeaction | Approval blocks that trigger write-mode execution of the previous codeaction block. The result is posted as a new message. |
| coderesult | Result blocks containing execution output and preview objects. Generated automatically after processing codeaction blocks. |
Code Block Processing
- codeaction blocks:
- First run in preview mode
- If no errors and no objects need approval, automatically run in write mode
- A coderesult block is added after the codeaction block
- Results are posted as a new message
- approvecodeaction blocks:
- Finds the last codeaction block in the thread
- Runs that block in write mode (is_approved=true)
- Posts the result as a new message containing only the coderesult block
API Response Format
When retrieving messages, code blocks are handled securely:
- Code content in codeaction and coderesult blocks is hidden with “[code hidden]”
- Preview objects from coderesult blocks are extracted into structured data
- The execution mode is included when available
Example response for a message with processed code blocks:
{
"id": 123,
"message": "Let's process this:\n```codeaction\n[code hidden]\n```\n```coderesult\n[code hidden]\n```",
"action_items": [
{
"type": "preview",
"needs_approval": true,
"id": 1
}
],
"action_mode": "preview"
}
Example of an approval message:
{
"id": 124,
"message": "```approvecodeaction\n```",
"action_items": [],
"action_mode": null
}
Example of the result message after approval:
{
"id": 125,
"message": "```coderesult\n[code hidden]\n```",
"action_items": [
{
"type": "preview",
"needs_approval": false,
"id": 1
}
],
"action_mode": "write"
}
Relationships
| Relationship | Type | Description |
|---|---|---|
| messages | [Message] | The messages in a chat thread |
| participants | [Participant] | The participants in a chat thread |
Notes
- All endpoints require authentication.
- All filter parameters on
GET /chat/threadsare optional. Usefree_textonly when you need full-text search across thread subjects and messages. - Access to threads and messages is restricted based on the user’s eligible client accounts. Access is granted if the user can access either the thread’s
client_account_idor itsprovider_client_account_id. - Error responses:
- 403 Forbidden: When trying to access a thread the user is not associated with.
- 404 Not Found: When a specified thread or message doesn’t exist.