Members
A member is one person’s membership in your organization: their role, permissions, departments and the properties they can reach. This guide covers the member operations most integrations need. Every field and filter is listed on the operation’s page in the API Reference.
| Operation | Request | Permission |
|---|---|---|
listTeamMembers | GET /members | view_users |
getMember | GET /members/{id} | view_users |
inviteMember | POST /members | manage_users |
updateMember | PATCH /members/{id} | manage_users |
updateMemberRole | POST /members/{id}/role | manage_users |
addPropertyScope | POST /members/{id}/property-scopes | manage_users |
removePropertyScope | DELETE /members/{id}/property-scopes/{propertyId} | manage_users |
updateMemberScopes | PATCH /members/{id}/scopes | manage_users |
suspendMember | POST /members/{id}/suspend | manage_users |
Paths are relative to your region’s base URL, for example https://api-us.suiteop.com/api/v1. See Authentication for permissions.
Member ID and user ID
Section titled “Member ID and user ID”Every member has two IDs, and operations don’t accept them interchangeably:
memberIdidentifies the membership. It is the{id}in every/members/{id}path, andgetMemberreturns it asmembershipId. Passing a user ID there returns404.userIdidentifies the person. Task fields such asassigneeUserIdtake this one.
Listing members
Section titled “Listing members”GET /members is paginated (default limit 50, maximum 100). Rows are ordered by display name.
curl "https://api-us.suiteop.com/api/v1/members?statusFilter=assignable&roleFilter=field_team_member&search=ana" \ -H "Authorization: Bearer sk_live_your_key_here"Useful filters:
| Filter | Notes |
|---|---|
statusFilter | assignable (active internal and AI-agent members work can be given to), active (those minus internal members who never logged in), invited (yet to log in), external (outside collaborators), inactive (suspended). Omit it and every membership is returned |
roleFilter | owner, admin, manager, custom, member, field_supervisor, field_team_member, viewer. Repeat the key for several values |
search | Case-insensitive substring search. Each word (the first 10 distinct ones) must match the first or last name, in any order, so Silva Ana finds Ana Silva; the whole string is also matched against the email. % and _ act as wildcards |
departmentIds, propertyGroupIds | Members in at least one of these departments, or directly scoped to at least one of these groups. The group filter matches direct scopes only, so a member with scopeAllProperties (every owner and admin has it) is returned only if also scoped to the group directly |
userGroupIds | Members in at least one of these user groups |
Each row carries memberId, userId, firstName, lastName, email, role, permissions, departments, memberType, isActive and joinedAt. Without statusFilter the list includes suspended people, AI agents and the machine members that API keys act as, so check memberType and isActive.
GET /members/{id} adds what the list leaves out: phone, skills, propertyGroups, properties and scopeAllProperties. It does not carry memberType. A suspended member is still returned, with isActive: false and empty scope lists.
Inviting a member
Section titled “Inviting a member”email, firstName, lastName, role and compensationType are required. compensationType is hourly, per_task_flat, per_task_hourly, salaried, or null to decide later.
curl -X POST https://api-us.suiteop.com/api/v1/members \ -H "Authorization: Bearer sk_live_your_key_here" \ -H "Idempotency-Key: 3b1f6c2a-9d4e-4f7a-8c1b-2e5d6f7a8b9c" \ -H "Content-Type: application/json" \ -d '{ "email": "[email protected]", "firstName": "Ana", "lastName": "Diaz", "role": "field_team_member", "compensationType": "hourly", "defaultHourlyRateCents": 2500, "departmentIds": ["0b6f2c1e-…"], "propertyGroupIds": ["5e8a…"] }'The response is 201. data.outcome says what happened:
invited: the membership was created or granted. New people are emailed a link to set a password.resent: the address already had an unaccepted invitation, which was sent again unchanged. Theroleandpermissionsyou passed are ignored; useupdateMemberRoleto change them.
Field notes:
- Role limits: you can only assign a role strictly below your own, and you must hold every permission the new member ends up with, role defaults included. An API key acts as a
custommember, which ranks withmanager, so a key can invite onlymember,field_supervisor,field_team_memberandviewer. permissionsreplaces the role’s default permissions with the exact list you send.defaultHourlyRateCentsis required and positive whencompensationTypeishourly, and discarded otherwise.2500is $25.00 an hour.- Scopes:
departmentIds,propertyGroupIdsandpropertyIdsare optional. An ID from another organization fails the whole invite.scopeAllProperties: truegrants every property; owners and admins get it regardless. - Existing people: an email that already signs in to your organization returns
409 conflict_error. An external collaborator is converted to a full member. A suspended member is reactivated, with their old department and property scopes wiped.
Updating a profile
Section titled “Updating a profile”PATCH /members/{id} changes name, language, spokenLanguages, compensation and clock-in and location-tracking rules. Unlike PATCH /tasks/{id} and PATCH /properties/{id}, the fields go at the top level of the body, not inside a data object:
curl -X PATCH https://api-us.suiteop.com/api/v1/members/2f9c… \ -H "Authorization: Bearer sk_live_your_key_here" \ -H "Content-Type: application/json" \ -d '{"compensationType": "per_task_flat", "spokenLanguages": ["es", "pt"]}'- At least one field is required, and the response echoes only the fields you sent.
spokenLanguagesreplaces the whole set. Don’t include the primarylanguage.- You must outrank the member, unless it’s your own membership.
- Role, permissions and property access can’t be changed here.
Changing a role
Section titled “Changing a role”POST /members/{id}/role sets the role and replaces the member’s whole permission set in the same write:
curl -X POST https://api-us.suiteop.com/api/v1/members/2f9c…/role \ -H "Authorization: Bearer sk_live_your_key_here" \ -H "Content-Type: application/json" \ -d '{"role": "field_supervisor"}'- Omitting
permissionsdoes not keep the current set. The new role’s defaults overwrite it. - Changing to any role other than
owneroradminclears an all-properties grant. Resending the member’s current role keeps it. - You must rank strictly above both the member and the new role, so an owner’s role and your own can’t be changed. An API key can set only
member,field_supervisor,field_team_memberandviewer. - No operation makes someone the owner. Only the organization’s current owner can hand ownership to an active admin, and only from the SuiteOp dashboard.
- You must hold every permission the member ends up with, including the new role’s defaults when you omit
permissions; otherwise the call returns403. - A suspended member returns
404.
Managing property access
Section titled “Managing property access”A member reaches a property directly, through a property group, or through scopeAllProperties. getMember shows the current properties, propertyGroups and scopeAllProperties.
To add or remove one direct grant, leaving everything else alone:
curl -X POST https://api-us.suiteop.com/api/v1/members/2f9c…/property-scopes \ -H "Authorization: Bearer sk_live_your_key_here" \ -H "Content-Type: application/json" \ -d '{"propertyId": "9a3d7e40-…"}'
curl -X DELETE https://api-us.suiteop.com/api/v1/members/2f9c…/property-scopes/9a3d7e40-… \ -H "Authorization: Bearer sk_live_your_key_here"Both are refused unless your role outranks the member’s, so never on yourself, a peer or a higher role. Adding answers 201 and removing answers 200, both with the member’s resulting scopes. Adding a grant the member already holds, or removing one they don’t, still succeeds. Removing a direct grant doesn’t end access the member has through a group.
PATCH /members/{id}/scopes replaces whole sets. Each of propertyIds, propertyGroupIds and skillIds you send overwrites that entire set, and an empty array clears it; fields you omit are unchanged, and at least one is required. Read getMember first and send the full intended set. You must outrank the member.
scopeAllProperties: true grants every property and supersedes the lists. false only de-scopes roles below admin: for owners and admins it is ignored, and the call still reports success.
Suspending a member
Section titled “Suspending a member”curl -X POST https://api-us.suiteop.com/api/v1/members/2f9c…/suspend \ -H "Authorization: Bearer sk_live_your_key_here" \ -H "Content-Type: application/json" \ -d '{}'Suspending empties the member’s permissions, clears their private staff code, deletes every department, skill, property-group and property scope, removes them from department manager lists, and queues their door PINs for removal from the locks.
An owner can’t be suspended, you can’t suspend yourself, and you must rank strictly above the member. There is no un-suspend: inviting the same email again with inviteMember reactivates the membership, but the deleted scopes don’t come back.