Skip to main content

User groups

A user group scopes a rule to a set of users. Groups come in two flavors: local groups you create and manage directly through this API, and sso groups synced from your identity provider (IdP). A rule references a group via its scope, and you control who the rule applies to by editing the group's membership. Use a local group when you want a rule's audience driven by your own logic (a script, a CMDB, a rollout schedule).

On this page: membership model, limits, examples, list members, endpoint reference, tips.


Membership model​

The provider field tells you where a group comes from:

providerOriginCan you edit membership via the API?
localCreated through this API (or the console)Yes, you own it
ssoSynced from your IdP using the Cloud Identity EngineNo, membership is governed upstream
note

Use local groups for automation. When you want a rule's audience to be driven by your own logic (a script, a CMDB, a rollout schedule), create a local user group and manage its members through the API. SSO groups mirror the IdP; change them there, not here.


Limits​

WhatLimit
Users in one local user group25,000
User groups one rule can scope (scope.users.userGroups)1000
limit on GET /user-groups and GET /user-groups/{id}/membersDefault 100; values above 1000 are capped at 1000

Examples​

Retrieve​

List and filter​

GET /seb-api/v1/user-groups
curl -sS -G "$PB_API_BASE/user-groups" \
-H "Authorization: Bearer $PB_TOKEN" \
--data-urlencode "limit=50"

Response (200):

{
"metadata": { "configurationVersion": { "id": "0CV01EXAMPLEXXXXXXXXXXXXXXXXX", "status": "draft", "number": 0 } },
"pageInfo": { "hasNextPage": false, "cursor": "", "totalCount": 1 },
"data": [
{
"id": "0UG01PILOTXXXXXXXXXXXXXXXXXXX",
"name": "Pilot - DevTools block",
"lastUpdated": "2026-01-15T10:00:00Z",
"createdAt": "2026-01-15T10:00:00Z",
"provider": "local"
}
// ... more groups
]
}

Results are cursor-paginated: the response carries a pageInfo object. Pass the next cursor value to page through large result sets.

Query paramNotes
limitNumber of groups to return. Default 100; values above 1000 are capped at 1000.
cursorOpaque string marking where to resume listing.

Get one​

GET /seb-api/v1/user-groups/{id}
curl -sS "$PB_API_BASE/user-groups/$UG_ID" \
-H "Authorization: Bearer $PB_TOKEN"

Response (200):

{
"id": "0UG01PILOTXXXXXXXXXXXXXXXXXXX",
"name": "Pilot - DevTools block",
"lastUpdated": "2026-01-15T10:00:00Z",
"createdAt": "2026-01-15T10:00:00Z",
"provider": "local",
"metadata": { "configurationVersion": { "id": "0CV01EXAMPLEXXXXXXXXXXXXXXXXX", "status": "draft", "number": 0 } }
}

Create​

POST /seb-api/v1/user-groups
curl -sS -X POST "$PB_API_BASE/user-groups" \
-H "Authorization: Bearer $PB_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "Pilot - DevTools block",
"userIds": [
"0UR01ALICEXXXXXXXXXXXXXXXXXXX",
"0UR01BOBXXXXXXXXXXXXXXXXXXXXX"
]
}'

Response (201). The userGroupId field is a deprecated alias for id:

{
"id": "0UG01PILOTXXXXXXXXXXXXXXXXXXX",
"userGroupId": "0UG01PILOTXXXXXXXXXXXXXXXXXXX"
}

Capture the ID for later snippets:

export UG_ID='0UG01PILOTXXXXXXXXXXXXXXXXXXX'

Key fields​

FieldTypeRequiredNotes
namestringYesDisplay name.
userIdsarrayYesMember user IDs (0UR...).

Update​

Membership edits use PUT with a list of per-user actions. This is incremental: you send only the users to add or remove, not the full roster.

note

PUT behaves like a PATCH here. It accepts only incremental per-user membership actions, not a complete replacement of the full roster. You send a list of users to add or remove, and only those changes are applied.

PUT /seb-api/v1/user-groups/{id}
# Add one user, remove another
curl -sS -X PUT "$PB_API_BASE/user-groups/$UG_ID" \
-H "Authorization: Bearer $PB_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"users": [
{ "userId": "0UR01CAROLXXXXXXXXXXXXXXXXXXX", "action": "add" },
{ "userId": "0UR01BOBXXXXXXXXXXXXXXXXXXXXX", "action": "remove" }
]
}'

Response (200):

{
"id": "0UG01PILOTXXXXXXXXXXXXXXXXXXX",
"userGroupId": "0UG01PILOTXXXXXXXXXXXXXXXXXXX"
}
note

Changes to a user group, including membership edits, land in the draft and go live only when you publish. Your automation must publish after every write.

Delete​

DELETE /seb-api/v1/user-groups/{id}
curl -sS -X DELETE "$PB_API_BASE/user-groups/$UG_ID" \
-H "Authorization: Bearer $PB_TOKEN"

Response (200):

{
"id": "0UG01PILOTXXXXXXXXXXXXXXXXXXX",
"userGroupId": "0UG01PILOTXXXXXXXXXXXXXXXXXXX"
}

Publish with partial publish​

The typical gradual rollout loop is: edit group membership, then partial publish only that group so unrelated draft edits are left untouched. Partial publish is available through the API only. It is a preview feature: send x-prisma-browser-preview: partial-publish. The id to publish comes back in the response of the write itself, so no extra lookup is needed.

curl -sS -X POST "$PB_API_BASE/configuration-management/draft/partial-publish" \
-H "Authorization: Bearer $PB_TOKEN" \
-H "x-prisma-browser-preview: partial-publish" \
-H "Content-Type: application/json" \
-d '{ "entityIds": ["'"$UG_ID"'"], "description": "ServiceNow INC0042311: contractor offboarding" }'

Returns 201 with the new configuration version and the IDs that went live. Creating and deleting groups follow the same pattern: perform the write, then publish the id it returned.

If the group has no pending change, the call returns 404. This happens when the write changed nothing (for example, it added a user who was already a member), in which case there is nothing to publish:

{
"error": {
"code": "NOT_FOUND",
"message": "No pending change found for one or more of the specified entities.",
"timestamp": "2026-08-06T09:15:00Z",
"details": {
"errors": [
{
"index": 0,
"field": "entityIds",
"error": "no pending change in the current draft",
"value": "0UG01PILOTXXXXXXXXXXXXXXXXXXX"
}
]
}
}
}

See Publish a single object (partial publish) for the full error matrix.

List the members of a group​

GET /seb-api/v1/user-groups/{id}/members
note

Preview. Returns the members of a user group is a preview feature. Send x-prisma-browser-preview: user-group-members on every call; without it the request returns 400.

curl -sS -G "$PB_API_BASE/user-groups/$UG_ID/members" \
-H "Authorization: Bearer $PB_TOKEN" \
-H "x-prisma-browser-preview: user-group-members" \
--data-urlencode "limit=2"

Response (200):

{
"data": [
{ "id": "0UR01ALICEXXXXXXXXXXXXXXXXXXX", "name": "Alice Example", "email": "alice@example.com" },
{ "id": "0UR01BOBXXXXXXXXXXXXXXXXXXXXX", "name": "Bob Example", "email": "bob@example.com" }
],
"pageInfo": { "hasNextPage": true, "cursor": "eyJ2ZXJzaW9uIjoxfQ", "totalCount": 45 },
"metadata": { "configurationVersion": { "id": "0CV01EXAMPLEXXXXXXXXXXXXXXXXX", "status": "draft", "number": 0 } }
}
Query paramNotes
configurationVersiondraft (default) or active. Applies to local groups. SSO group membership comes from directory sync and is always read live. Send the same value on every page.
limitDefault 100; values above 1000 are capped at 1000.
cursorpageInfo.cursor from the previous page.
includeTotalCountpageInfo.totalCount is filled on the first page by default; set true or false to override.

Each member is a user reference with id, name, and email. API service accounts are not listed.

How it differs from GET /users?groupId=:

GET /user-groups/{id}/membersGET /users?groupId=
Membership readDraft by default, or active with configurationVersion=activeAlways active
Returnsid, name, email per memberFull user objects

Use the members endpoint to check a membership edit before you publish it. metadata is omitted when the tenant has no configuration versioning; on such a tenant, do not send configurationVersion, or the request returns 400.

The path id must be a user group ID such as 0UG01PILOTXXXXXXXXXXXXXXXXXXX. A malformed ID returns 400; an unknown group returns 404.

Read back what is live​

Reads default to the draft, so a group you have edited but not published still comes back from a plain GET. To verify what is actually enforced, ask for the active version:

curl -sS "$PB_API_BASE/user-groups/$UG_ID?configurationVersion=active" \
-H "Authorization: Bearer $PB_TOKEN"

Endpoint reference​

MethodPathPurpose
GET/user-groupsList user groups (paginate)
GET/user-groups/{id}Read one user group
GET/user-groups/{id}/membersList the members of a user group (preview: user-group-members)
POST/user-groupsCreate a user group
PUT/user-groups/{id}Add or remove members (incremental)
DELETE/user-groups/{id}Delete a user group

All paths are under the /seb-api/v1 base.


Tips and gotchas​

note

One call changes who a rule covers. Editing a group's membership changes the audience of every rule that references it, without touching the rules themselves. Publish just that group with partial publish (API only today, preview) so the membership change does not ship unrelated draft edits. See Publish a single object (partial publish).

note

userGroupId is deprecated. Responses still return a userGroupId field for backward compatibility; use id.

note

Reference from a rule's scope. A rule scopes to a group via scope.users.userGroups. Add or remove groups on a rule with addUserGroups / removeUserGroups (see Rules and Manage users on a rule).