Saved views Live
Saved views capture a set of inbox filters under a name and an icon. Used to pin commonly-needed slices of the queue (Unanswered VIPs, Tickets older than 24h, Calls awaiting callback). Saved views render in the dashboard sidebar.
List saved views
GET/api/v1/saved-viewsAuth: Bearer
Cursor-paginated. Filters: scope (workspace / personal).
Code samples
cURL
curl 'https://app.message.com/api/v1/saved-views' \
-H 'Authorization: Bearer YOUR_WORKSPACE_JWT'JavaScript
const res = await fetch('https://app.message.com/api/v1/saved-views', {
headers: { Authorization: 'Bearer ' + token }
});
const { savedViews } = await res.json();Python
import requests
r = requests.get(
"https://app.message.com/api/v1/saved-views",
headers={"Authorization": f"Bearer {token}"},
)
views = r.json()["savedViews"]Ruby
require "net/http"
require "json"
uri = URI("https://app.message.com/api/v1/saved-views")
res = Net::HTTP.start(uri.host, uri.port, use_ssl: true) do |http|
req = Net::HTTP::Get.new(uri)
req["Authorization"] = "Bearer #{token}"
http.request(req)
end
views = JSON.parse(res.body)["savedViews"]PHP
<?php
$ctx = stream_context_create([
"http" => ["method" => "GET", "header" => "Authorization: Bearer $token"]
]);
$views = json_decode(file_get_contents("https://app.message.com/api/v1/saved-views", false, $ctx), true)["savedViews"];Get one saved view
GET/api/v1/saved-views/:idAuth: Bearer
200 OK
{
"id": "uuid",
"version": 1,
"name": "Unanswered VIP chats",
"icon": "star",
"filters": {
"channel": "chat",
"status": ["open"],
"assigneeId": null,
"tags": ["vip"]
},
"scope": "workspace",
"createdByAgentId": "uuid",
"createdAt": "2026-05-13T15:30:00Z"
}Create a saved view
POST/api/v1/saved-viewsAuth: Bearer
| Field | Type | Description |
|---|---|---|
| namerequired | string | Display name. 1 to 80 chars. Must be unique within scope. |
| iconoptional | string | Icon name from our icon set (e.g., star, flag, clock). |
| filtersrequired | object | Filter map; same fields as the conversations list endpoint accepts. |
| scopeoptional | enum | One of workspace (shared) or personal. Defaults to personal. |
Body
{
"name": "Unanswered VIP chats",
"icon": "star",
"filters": {
"channel": "chat",
"status": ["open"],
"assigneeId": null,
"tags": ["vip"]
},
"scope": "workspace"
}Filter fields
Same shape the dashboard sends to /conversations:
channel:chat,ticket,call, or array.status: array ofopen,pending,solved,spam.assigneeId: agent UUID,nullfor unassigned, ormesentinel.departmentId: department UUID or array.tags: array of tag strings (AND).olderThanMinutes: numeric; for SLA-style views.
Update a saved view
PATCH/api/v1/saved-views/:idAuth: Bearer
Edit name, icon, filters, or scope. Requires expectedVersion.
Delete a saved view
DELETE/api/v1/saved-views/:idAuth: Bearer
To re-order workspace views in the sidebar, set sortOrder in PATCH; the dashboard surfaces a drag-and-drop UI that sends those updates as a batch.
Errors
| Code | When |
|---|---|
400 invalid_body | Filter shape invalid. |
403 forbidden | Agent cannot edit a workspace-scoped view. |
409 conflict | Name already taken within scope. |
409 stale_version | Optimistic-lock mismatch. |
Common pitfalls
- Saving a view with
assigneeId: "me"at workspace scope. The sentinel resolves per-agent, so the same view shows each agent their own queue. That is usually desired; verify before sharing. - Confusing saved views with saved replies. Views filter the queue; replies populate the composer.
- Overusing
tagsfilters. Tags drift over time. Bake structural filters (department, status) first and lean on tags as a refinement.