message.comDevelopers

Departments Live

Departments are routing groups. A conversation routed to a department is visible to every agent in that department; the first to claim it (or whoever round-robin picks) becomes the assignee. Internally the table is called groups; the UI and these docs use the word "department".

For the conceptual distinction between departments, teams, and channels, see Concept: department vs team.

List departments

GET/api/v1/departmentsAuth: Bearer

Cursor-paginated list of departments in the workspace. Most workspaces have under a dozen.

Code samples

cURL
curl 'https://app.message.com/api/v1/departments' \
  -H 'Authorization: Bearer YOUR_WORKSPACE_JWT'
JavaScript
const res = await fetch('https://app.message.com/api/v1/departments', {
  headers: { Authorization: 'Bearer ' + token }
});
const { departments } = await res.json();
Python
import requests
r = requests.get(
    "https://app.message.com/api/v1/departments",
    headers={"Authorization": f"Bearer {token}"},
)
departments = r.json()["departments"]
Ruby
require "net/http"
require "json"
uri = URI("https://app.message.com/api/v1/departments")
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
departments = JSON.parse(res.body)["departments"]
PHP
<?php
$ctx = stream_context_create([
  "http" => ["method" => "GET", "header" => "Authorization: Bearer $token"]
]);
$departments = json_decode(file_get_contents("https://app.message.com/api/v1/departments", false, $ctx), true)["departments"];

Get one department

GET/api/v1/departments/:idAuth: Bearer

Full department record including the current member roster.

200 OK
{
  "id": "uuid",
  "version": 2,
  "name": "Billing",
  "slug": "billing",
  "color": "#22C55E",
  "routingStrategy": "round_robin",
  "memberAgentIds": ["uuid-a", "uuid-b"],
  "businessHoursOverride": null,
  "createdAt": "2026-01-04T12:00:00Z"
}

Create a department

POST/api/v1/departmentsAuth: Bearer

Creates a department. Admin-only.

FieldTypeDescription
namerequiredstringDisplay name. Used in the inbox queue header and routing UI.
coloroptionalstringHex colour for the badge that appears next to conversations.
routingStrategyoptionalenumOne of round_robin, least_busy, first_claim. Defaults to first_claim.
memberAgentIdsoptionaluuid[]Initial members. Agents can belong to many departments.
Body
{
  "name": "Billing",
  "color": "#22C55E",
  "routingStrategy": "round_robin",
  "memberAgentIds": ["uuid-a", "uuid-b"]
}

Update a department

PATCH/api/v1/departments/:idAuth: Bearer

Edit name, colour, routing strategy. Requires expectedVersion.

Manage members

POST/api/v1/departments/:id/membersAuth: Bearer
DELETE/api/v1/departments/:id/members/:agentIdAuth: Bearer

Add or remove a single agent. These exist alongside PATCH for surgical membership changes that do not require knowing the full current list.

Delete a department

DELETE/api/v1/departments/:idAuth: Bearer

Open conversations currently routed to the department fall back to the workspace default queue. Closed conversations keep the groupId field as a historical record; the resolved department label may show as "(deleted)".

Errors

CodeWhen
400 invalid_bodyPayload validation failed.
403 forbiddenAgent role is not admin.
404 not_foundDepartment does not exist in this workspace.
409 conflictDepartment name already taken in this workspace.
409 stale_versionexpectedVersion mismatch.

Common pitfalls

  • Confusing departments with channels. Channels are chat, ticket, call (medium). Departments are routing groups (Sales, Support, Billing). An agent on Support can still handle a phone call.
  • Treating membership as exclusive. Agents belong to many departments. There is no primary department.
  • Forgetting business-hours overrides. A department can have its own hours; outside hours the queue still receives conversations but does not page anyone.