API Reference
Support Tickets
Overview
Support tickets let a Client (workspace owner) raise issues or suggestions with the platform team as a threaded conversation. A ticket has a subject, a category (issue · suggestion · billing · other), a status (open · in_progress · resolved), and a list of messages from both sides.
These endpoints are for the Clientside only. Each client sees only its own tickets — every query is scoped to the caller's clientId. Tickets live in the root DB.
Auth & headers
All support routes require a Client Bearer token (the isClient token). Send tenant headers so the middleware resolves the caller.
| Header | Value |
|---|---|
| Authorization | Bearer <client_access_token> |
| is-tenant | true |
| x-client-id | {{clientId}} |
Create ticket
{baseUrl}/api/{apiVersion}/support/ticketsAuthentication
Required (Client Bearer token)
Opens a ticket with the first message. Required: subject, message. Optional: category (defaults to issue).
{
"subject": "Unable to log in",
"category": "issue",
"message": "It says \"Invalid email or password\"."
}Response (HTTP 201)
{
"success": true,
"message": "Ticket created successfully",
"data": {
"_id": "6a5f...c17d",
"clientId": "699fe1377846dcfb775c645c",
"subject": "Unable to log in",
"category": "issue",
"status": "open",
"messages": [
{
"_id": "6a5f...c17e",
"authorType": "client",
"authorName": "Client Pro 1",
"body": "It says \"Invalid email or password\".",
"createdAt": "2026-07-21T09:04:09.578Z"
}
],
"clientUnread": false,
"lastMessageAt": "2026-07-21T09:04:09.578Z",
"createdAt": "2026-07-21T09:04:09.578Z"
},
"error": null
}List my tickets
{baseUrl}/api/{apiVersion}/support/tickets?page=1&limit=10&status=openAuthentication
Required (Client Bearer token)
Lists the client's own tickets, newest-first. Query params: page (default 1), limit (default 20, max 50), status (optional filter).
{
"success": true,
"message": "Tickets fetched successfully",
"data": {
"list": [
{
"_id": "6a5f...c17d",
"subject": "Unable to log in",
"category": "issue",
"status": "in_progress",
"clientUnread": true,
"lastMessageAt": "2026-07-21T09:12:00.000Z",
"createdAt": "2026-07-21T09:04:09.578Z"
}
],
"pagination": {
"currentPage": 1,
"totalCount": 1,
"pageSize": 10,
"hasNextPage": false,
"hasPreviousPage": false
}
},
"error": null
}Get ticket
{baseUrl}/api/{apiVersion}/support/tickets/{ticketId}Authentication
Required (Client Bearer token)
Returns the full ticket with its messages thread. Reading a ticket clears its unread flagfor the client (so the nav badge decrements). A 404 is returned for a ticket that isn't the caller's.
Reply to a ticket
{baseUrl}/api/{apiVersion}/support/tickets/{ticketId}/replyAuthentication
Required (Client Bearer token)
Appends a message. Body: { "message": "…" }. Replying to a resolved ticket re-opens it. Returns the updated ticket.
Unread count
{baseUrl}/api/{apiVersion}/support/unread-countAuthentication
Required (Client Bearer token)
Returns { "count": <number> }— the number of the client's tickets with an unread reply from the support team. Drives the sidebar badge.
Stats
{baseUrl}/api/{apiVersion}/support/statsAuthentication
Required (Client Bearer token)
Per-status counts for the client's tickets, in one call — powers the summary tiles.
{
"success": true,
"message": "Support stats fetched successfully",
"data": { "open": 0, "in_progress": 1, "resolved": 1, "total": 2 },
"error": null
}Realtime
Live updates ride the dedicated /support Socket.IO namespace (path /connection). Connect with the client token, join a ticket room, and listen for support_message_receive, support_status_receive, support_typing_receive, and support_queue_update. REST is the source of truth; the socket only reflects changes instantly, so the feature degrades to polling if the socket drops.
Common Errors
| Code | Reason |
|---|---|
| 401 Unauthorized | Client token missing, invalid, or expired. |
| 403 Forbidden | A non-client (end-user) token was used — support is client-only. |
| 404 Not Found | Ticket not found, or it isn't the caller's ticket. |
Best Practices
- Use Statsfor the summary tiles instead of counting the list client-side — it's one query.
- Poll Unread count for the badge, and refresh it live on the
support_queue_updatesocket event. - After sending a reply, append the returned message inline rather than refetching the whole list.
- Always send tenant headers with the client Bearer token over HTTPS.
Support inbox ready
Wire these into a client-facing support screen: list tickets, open a thread, reply, and badge unread — with the /support socket for live updates.