Departments
A department is the team a task belongs to, such as Housekeeping or Maintenance. Every task needs one: createTask requires a departmentId, and listTasks can filter on it. A department’s category also changes how its tasks complete. This guide covers the four department operations. Every field is listed on the operation’s page in the API Reference.
| Operation | Request | Permission |
|---|---|---|
listDepartments | GET /departments | view_tasks |
createDepartment | POST /departments | modify_tasks |
updateDepartment | PATCH /departments/{id} | modify_tasks |
updateDepartmentMembers | PATCH /departments/{id}/members | manage_users |
Paths are relative to your region’s base URL, for example https://api-us.suiteop.com/api/v1. See Authentication for permissions.
The API can’t archive or delete a department, or change its auto-assignment settings. Those are only available in the app.
Categories
Section titled “Categories”category is required on create and takes one of cleans, maintenance, inspections, guest_experience or other. It is not just a label: completing a task that has a property in a cleans or inspections department requires a property status declaration (see Tasks). Choose it deliberately, and don’t recategorize a department that has open tasks as part of a routine sync.
Listing departments
Section titled “Listing departments”GET /departments is paginated (default limit 50, maximum 100) and returns only active departments, ordered by their stored name.
curl "https://api-us.suiteop.com/api/v1/departments?nameContains=clean&language=fr" \ -H "Authorization: Bearer sk_live_your_key_here"{ "data": [ { "id": "0b6f2c1e-4d3a-4f8b-9c2e-7a1d5e6f8b90", "name": "Ménage", "description": "Turnover cleans", "color": "#847AEA", "category": "cleans", "assignmentMethod": null, "backupAssignmentMethod": null, "autoAssignEnabled": false, "blockingPriority": "high", "isMaintenance": false, "archivedAt": null, "createdAt": "2026-03-02T14:05:11.000Z", "updatedAt": "2026-08-19T09:40:27.000Z", "activeTaskCount": 12, "memberCount": 4, "managerNames": ["Ana Ruiz"] } ], "meta": { "requestId": "3f1c9a52-…", "pagination": { "total": 1, "limit": 50, "offset": 0 } }}nameContainsis a case-insensitive substring. It matches the stored name or the name translated intolanguage.%and_are matched literally, not as wildcards.languageresolvesnameinto that language, falling back to the stored name when there is no translation. It defaults to English. The order still follows the stored name.includeArchived=truealso returns archived departments. TheirarchivedAtis set.idsreturns only the departments you name, up to 200. Repeat the parameter for each ID (?ids=…&ids=…).forMemberIdreturns the departments one member belongs to. It takes the member’smemberIdfromlistTeamMembers, not theiruserId.categorykeeps one category.
activeTaskCount counts tasks that are neither completed nor cancelled. memberCount and managerNames are read-only here.
Creating a department
Section titled “Creating a department”POST /departments needs name and category. It answers 201 with the new department.
curl -X POST https://api-us.suiteop.com/api/v1/departments \ -H "Authorization: Bearer sk_live_your_key_here" \ -H "Idempotency-Key: 6a1f3c9e-2b7d-4e5a-8c0f-1d9b3e7a5c24" \ -H "Content-Type: application/json" \ -d '{"name": "Pool care", "category": "maintenance", "color": "#1E90FF", "blockingPriority": "medium"}'{ "data": { "id": "5c2e8a1f-9b3d-4a6e-8f7c-0d1b2e3f4a5b", "name": "Pool care", "nameId": "a4d9e2c1-7f3b-4e8a-9c5d-2b1e0f6a7c83", "description": null, "color": "#1E90FF", "category": "maintenance", "blockingPriority": "medium", "isMaintenance": false, "autoAssignEnabled": false, "archivedAt": null, "createdAt": "2026-09-30T10:14:02.000Z", "updatedAt": "2026-09-30T10:14:02.000Z" }, "meta": { "requestId": "…" }}namemust not match another active department in the organization, or the call returns409 conflict_error. An archived department may hold the same name. CalllistDepartmentsfirst to see whether a suitable one already exists.coloris a six-digit hex colour with a leading#. It defaults to#847AEA.blockingPriorityis one ofwatch,low,medium,highorurgent, and is unset when omitted.languageis the languagenameis written in. SuiteOp stores the name as a translatable string, andnameIdis its translation record, whichgetTranslationEntriesreads.- The new department has no members. Add them with
updateDepartmentMembers.
Send an Idempotency-Key so a retried create doesn’t make a second department (see Idempotency).
Updating a department
Section titled “Updating a department”PATCH /departments/{id} takes a data object. Send only the fields you are changing.
curl -X PATCH "https://api-us.suiteop.com/api/v1/departments/5c2e8a1f-9b3d-4a6e-8f7c-0d1b2e3f4a5b" \ -H "Authorization: Bearer sk_live_your_key_here" \ -H "Content-Type: application/json" \ -d '{"data": {"blockingPriority": null, "isMaintenance": true}}'name,description,color,category,blockingPriority(nullunsets it) andisMaintenancecan change. A newnamemust not match another active department, or the call returns409 conflict_error.languagenames the language of the newname.datamust change at least one field. An emptydata, or one holding onlylanguage, returns400 validation_error.- Any other key is rejected with
400 validation_errorrather than ignored. That includesmanagers,departmentUsers,autoAssignEnabledandmaxDailyHours. Change membership withupdateDepartmentMembers; auto-assignment is only set in the app. - A department in another organization returns
404 not_found_error. Archived departments can still be updated.
The response is the department in the same shape createDepartment returns.
Adding and removing members
Section titled “Adding and removing members”PATCH /departments/{id}/members adds people to one department and removes people from it in the same call. Everyone you don’t name stays as they are. It needs manage_users, not modify_tasks, because membership decides who receives work.
curl -X PATCH "https://api-us.suiteop.com/api/v1/departments/5c2e8a1f-9b3d-4a6e-8f7c-0d1b2e3f4a5b/members" \ -H "Authorization: Bearer sk_live_your_key_here" \ -H "Content-Type: application/json" \ -d '{"add": [{"userId": "7d1e4b2a-0c9f-4e3d-8a6b-5f2c1d0e9a37", "isManager": true}], "remove": ["c3a9e6f1-2b8d-4f0a-9e5c-7b1d3a2f6e04"]}'{ "data": { "id": "5c2e8a1f-9b3d-4a6e-8f7c-0d1b2e3f4a5b", "members": [ { "memberId": "2f9c6a1e-8b4d-4c3f-9a7e-1d0b5c2e8f63", "userId": "7d1e4b2a-0c9f-4e3d-8a6b-5f2c1d0e9a37", "isManager": true, "isActive": true } ] }, "meta": { "requestId": "…" }}- People are
userIds, theuserIdfield fromlistTeamMembers, never amemberId. The response names each person by both. addtakes up to 100 entries.isManager: truemakes the person a manager of the department andfalsemakes them a plain member, demoting a current manager. Omit it to keep a current member’s role; a newcomer joins as a plain member.removetakes up to 100userIds. A person may appear in only one of the two lists, and at least one person must be named, or the call returns400 validation_error.- Adding someone who is already a member, or removing someone who isn’t, changes nothing.
- You must outrank each person you name, except yourself, or the call returns
403 authorization_error. An API key acts as acustommember (see Members), which ranks withmanager, so a key can’t add or remove owners, admins, managers or othercustommembers. - An added person must be an active member. An unknown
userId, a suspended person inadd, or a department in another organization returns404 not_found_error. You can still remove a suspended person.
The response is the department’s whole roster after the write, including suspended members (isActive: false). It carries no names: resolve people with listTeamMembers.