Group service#
Service for managing groups within an organization
OpenAPI file: nominal.authentication.groups.v1.json
Endpoints#
Create or update group#
POST /authentication/groups/v1
Org-scoped upsert.
Creates a new group if Group.rid is empty in the request (server assigns the rid). Both Group.org_rid and Group.group_id are required on create, and the new group_id must be unique within the organization.
Updates an existing group if Group.rid is present in the request. Group.org_rid and Group.group_id are immutable: when set on the update request they must match the existing values, but they may be omitted to leave them unchanged. Fields in the group message marked as OUTPUT_ONLY are ignored when present in the input request. All other mutable fields are fully overwritten, and will be cleared if not set in the request.
Throws HTTP 400 / gRPC 3 if a supplied immutable field does not match the existing group. Throws HTTP 404 / gRPC 5 if the group identified by Group.rid for an update does not exist. Throws HTTP 409 / gRPC 6 if a create would result in duplicate group_ids within the organization. Throws HTTP 403 / gRPC 7 if the caller is not authorized.
Body
groupGrouprequired
Fields of
Groupridstring
orgRidstringRequired on create requests; immutable on updates.
groupIdstringGroup ID, unique per org. If sourced from the customer’s IdP, will match IdP group name. Required on create requests; immutable on updates.
displayNamestring
descriptionstring
userRidsarray of string output onlyThe list of users in this group.
createdAtstring (date-time) output only
updatedAtstring (date-time) output only
symbolSymbolSymbol to identify groups
Fields of
Symbol- one of
icon,emoji,imagerequired
iconstringIcon name (e.g. castle)
emojistringEmoji name (e.g. :castle:)
imagestringImage url (e.g. https://example.com/image.png)
- one of
membershipManagedManuallybooleanWhether group membership is managed manually in Nominal. Defaults to false.
Response
ridstring
orgRidstringRequired on create requests; immutable on updates.
groupIdstringGroup ID, unique per org. If sourced from the customer’s IdP, will match IdP group name. Required on create requests; immutable on updates.
displayNamestring
descriptionstring
userRidsarray of stringThe list of users in this group.
createdAtstring (date-time)
updatedAtstring (date-time)
symbolSymbolSymbol to identify groups
Fields of
Symbol- one of
icon,emoji,image
iconstringIcon name (e.g. castle)
emojistringEmoji name (e.g. :castle:)
imagestringImage url (e.g. https://example.com/image.png)
- one of
membershipManagedManuallybooleanWhether group membership is managed manually in Nominal. Defaults to false.
Request
curl -X POST "https://api.gov.nominal.io/api/authentication/groups/v1" \
-H "Authorization: Bearer <api key>" \
-H "Content-Type: application/json" \
--data '{
"group": {
"rid": "<rid>",
"orgRid": "<org rid>",
"groupId": "<group id>",
"displayName": "<display name>",
"description": "<description>",
"symbol": {
"icon": "<icon>"
},
"membershipManagedManually": true
}
}'
import requests
response = requests.post(
"https://api.gov.nominal.io/api/authentication/groups/v1",
headers={"Authorization": "Bearer <api key>"},
json={
"group": {
"rid": "<rid>",
"orgRid": "<org rid>",
"groupId": "<group id>",
"displayName": "<display name>",
"description": "<description>",
"symbol": {"icon": "<icon>"},
"membershipManagedManually": True,
},
},
)
response.raise_for_status()
print(response.json())
import httpx
response = httpx.post(
"https://api.gov.nominal.io/api/authentication/groups/v1",
headers={"Authorization": "Bearer <api key>"},
json={
"group": {
"rid": "<rid>",
"orgRid": "<org rid>",
"groupId": "<group id>",
"displayName": "<display name>",
"description": "<description>",
"symbol": {"icon": "<icon>"},
"membershipManagedManually": True,
},
},
)
response.raise_for_status()
print(response.json())
import asyncio
import aiohttp
async def main() -> None:
async with aiohttp.ClientSession() as session:
async with session.post(
"https://api.gov.nominal.io/api/authentication/groups/v1",
headers={"Authorization": "Bearer <api key>"},
json={
"group": {
"rid": "<rid>",
"orgRid": "<org rid>",
"groupId": "<group id>",
"displayName": "<display name>",
"description": "<description>",
"symbol": {"icon": "<icon>"},
"membershipManagedManually": True,
},
},
) as response:
response.raise_for_status()
print(await response.json())
asyncio.run(main())
Response: 200
{
"rid": "<rid>",
"orgRid": "<org rid>",
"groupId": "<group id>",
"displayName": "<display name>",
"description": "<description>",
"userRids": [
"<user rids>"
],
"createdAt": "2026-01-01T00:00:00Z",
"updatedAt": "2026-01-01T00:00:00Z",
"symbol": {
"icon": "<icon>"
},
"membershipManagedManually": true
}
Get groups#
POST /authentication/groups/v1/batch-get
Get batch of groups within the user’s organization
Body
The body is an array of string.
Response
The body is a map of string to Group.
Fields of Group
ridstring
orgRidstringRequired on create requests; immutable on updates.
groupIdstringGroup ID, unique per org. If sourced from the customer’s IdP, will match IdP group name. Required on create requests; immutable on updates.
displayNamestring
descriptionstring
userRidsarray of stringThe list of users in this group.
createdAtstring (date-time)
updatedAtstring (date-time)
symbolSymbolSymbol to identify groups
Fields of
Symbol- one of
icon,emoji,image
iconstringIcon name (e.g. castle)
emojistringEmoji name (e.g. :castle:)
imagestringImage url (e.g. https://example.com/image.png)
- one of
membershipManagedManuallybooleanWhether group membership is managed manually in Nominal. Defaults to false.
Request
curl -X POST "https://api.gov.nominal.io/api/authentication/groups/v1/batch-get" \
-H "Authorization: Bearer <api key>" \
-H "Content-Type: application/json" \
--data '[
"string"
]'
import requests
response = requests.post(
"https://api.gov.nominal.io/api/authentication/groups/v1/batch-get",
headers={"Authorization": "Bearer <api key>"},
json=["string"],
)
response.raise_for_status()
print(response.json())
import httpx
response = httpx.post(
"https://api.gov.nominal.io/api/authentication/groups/v1/batch-get",
headers={"Authorization": "Bearer <api key>"},
json=["string"],
)
response.raise_for_status()
print(response.json())
import asyncio
import aiohttp
async def main() -> None:
async with aiohttp.ClientSession() as session:
async with session.post(
"https://api.gov.nominal.io/api/authentication/groups/v1/batch-get",
headers={"Authorization": "Bearer <api key>"},
json=["string"],
) as response:
response.raise_for_status()
print(await response.json())
asyncio.run(main())
Response: 200
{
"<key>": {
"rid": "<rid>",
"orgRid": "<org rid>",
"groupId": "<group id>",
"displayName": "<display name>",
"description": "<description>",
"userRids": [
"<user rids>"
],
"createdAt": "2026-01-01T00:00:00Z",
"updatedAt": "2026-01-01T00:00:00Z",
"symbol": {
"icon": "<icon>"
},
"membershipManagedManually": true
}
}
Get group by ID#
GET /authentication/groups/v1/id/{groupId}
Gets a group by its ID within the user’s organization
Path parameters
groupIdstring required
Response
ridstring
orgRidstringRequired on create requests; immutable on updates.
groupIdstringGroup ID, unique per org. If sourced from the customer’s IdP, will match IdP group name. Required on create requests; immutable on updates.
displayNamestring
descriptionstring
userRidsarray of stringThe list of users in this group.
createdAtstring (date-time)
updatedAtstring (date-time)
symbolSymbolSymbol to identify groups
Fields of
Symbol- one of
icon,emoji,image
iconstringIcon name (e.g. castle)
emojistringEmoji name (e.g. :castle:)
imagestringImage url (e.g. https://example.com/image.png)
- one of
membershipManagedManuallybooleanWhether group membership is managed manually in Nominal. Defaults to false.
Request
curl "https://api.gov.nominal.io/api/authentication/groups/v1/id/<group id>" \
-H "Authorization: Bearer <api key>"
import requests
response = requests.get(
"https://api.gov.nominal.io/api/authentication/groups/v1/id/<group id>",
headers={"Authorization": "Bearer <api key>"},
)
response.raise_for_status()
print(response.json())
import httpx
response = httpx.get(
"https://api.gov.nominal.io/api/authentication/groups/v1/id/<group id>",
headers={"Authorization": "Bearer <api key>"},
)
response.raise_for_status()
print(response.json())
import asyncio
import aiohttp
async def main() -> None:
async with aiohttp.ClientSession() as session:
async with session.get(
"https://api.gov.nominal.io/api/authentication/groups/v1/id/<group id>",
headers={"Authorization": "Bearer <api key>"},
) as response:
response.raise_for_status()
print(await response.json())
asyncio.run(main())
Response: 200
{
"rid": "<rid>",
"orgRid": "<org rid>",
"groupId": "<group id>",
"displayName": "<display name>",
"description": "<description>",
"userRids": [
"<user rids>"
],
"createdAt": "2026-01-01T00:00:00Z",
"updatedAt": "2026-01-01T00:00:00Z",
"symbol": {
"icon": "<icon>"
},
"membershipManagedManually": true
}
Search groups#
POST /authentication/groups/v1/search
Searches all groups in the user’s organization using given query
Body
pageSizeintegerPage sizes greater than 1_000 will be rejected. Default pageSize is 100.
nextPageTokenstring
querySearchGroupsQueryrequired
Fields of
SearchGroupsQuery- one of
exactSubstringText,and,or,memberUsers
exactSubstringTextstring
andSearchQueryAndand is implemented to allow for list (use SearchQueryAnd([]))
Fields of
SearchQueryAndqueriesarray ofSearchGroupsQuery
orSearchQueryOr
Fields of
SearchQueryOrqueriesarray ofSearchGroupsQuery
memberUsersSearchQueryMemberUsers
Fields of
SearchQueryMemberUsersuserRidsarray of string1 to 1,000 items. Each item: at most 256 characters.
- one of
Response
resultsarray ofGroup
Fields of
Groupridstring
orgRidstringRequired on create requests; immutable on updates.
groupIdstringGroup ID, unique per org. If sourced from the customer’s IdP, will match IdP group name. Required on create requests; immutable on updates.
displayNamestring
descriptionstring
userRidsarray of stringThe list of users in this group.
createdAtstring (date-time)
updatedAtstring (date-time)
symbolSymbolSymbol to identify groups
Fields of
Symbol- one of
icon,emoji,image
iconstringIcon name (e.g. castle)
emojistringEmoji name (e.g. :castle:)
imagestringImage url (e.g. https://example.com/image.png)
- one of
membershipManagedManuallybooleanWhether group membership is managed manually in Nominal. Defaults to false.
nextPageTokenstring
Request
curl -X POST "https://api.gov.nominal.io/api/authentication/groups/v1/search" \
-H "Authorization: Bearer <api key>" \
-H "Content-Type: application/json" \
--data '{
"query": {
"exactSubstringText": "<exact substring text>"
}
}'
import requests
response = requests.post(
"https://api.gov.nominal.io/api/authentication/groups/v1/search",
headers={"Authorization": "Bearer <api key>"},
json={"query": {"exactSubstringText": "<exact substring text>"}},
)
response.raise_for_status()
print(response.json())
import httpx
response = httpx.post(
"https://api.gov.nominal.io/api/authentication/groups/v1/search",
headers={"Authorization": "Bearer <api key>"},
json={"query": {"exactSubstringText": "<exact substring text>"}},
)
response.raise_for_status()
print(response.json())
import asyncio
import aiohttp
async def main() -> None:
async with aiohttp.ClientSession() as session:
async with session.post(
"https://api.gov.nominal.io/api/authentication/groups/v1/search",
headers={"Authorization": "Bearer <api key>"},
json={"query": {"exactSubstringText": "<exact substring text>"}},
) as response:
response.raise_for_status()
print(await response.json())
asyncio.run(main())
Response: 200
{
"results": [
{
"rid": "<rid>",
"orgRid": "<org rid>",
"groupId": "<group id>",
"displayName": "<display name>",
"description": "<description>",
"userRids": [
"<user rids>"
],
"createdAt": "2026-01-01T00:00:00Z",
"updatedAt": "2026-01-01T00:00:00Z",
"symbol": {
"icon": "<icon>"
},
"membershipManagedManually": true
}
],
"nextPageToken": "<next page token>"
}
Create group membership#
POST /authentication/groups/v1/{groupMembership.key.groupRid}/memberships
Adds a member to a manually managed group. Re-adding an existing member is a no-op. Throws HTTP 400 / gRPC 3 if group_rid or member_rid is missing, or member_rid is not a supported RID type. Throws HTTP 403 / gRPC 7 if the caller is not authorized to update the group, including when the group does not exist. The permission check runs before the group lookup so unknown groups are not disclosed. Throws HTTP 400 / gRPC 3 if the target user is not in the group’s organization. Throws HTTP 400 / gRPC 3 if the group’s membership is not managed manually.
Path parameters
groupMembership.key.groupRidstring requiredAt most 256 characters.
Body
keyobjectIdentity is a nested key so delete can address a membership without the full resource, which may gain fields later. Identity is a nested key so delete can address a membership without the full resource, which may gain fields later.
Response
keyGroupMembershipKeyIdentity is a nested key so delete can address a membership without the full resource, which may gain fields later.
Fields of
GroupMembershipKeygroupRidstringAt most 256 characters.
memberRidstringThe member of the group. Only user RIDs are accepted today. At most 256 characters.
Request
curl -X POST "https://api.gov.nominal.io/api/authentication/groups/v1/<group membership.key.group rid>/memberships" \
-H "Authorization: Bearer <api key>" \
-H "Content-Type: application/json" \
--data '{
"key": {
"memberRid": "<member rid>"
}
}'
import requests
response = requests.post(
"https://api.gov.nominal.io/api/authentication/groups/v1/<group membership.key.group rid>/memberships",
headers={"Authorization": "Bearer <api key>"},
json={"key": {"memberRid": "<member rid>"}},
)
response.raise_for_status()
print(response.json())
import httpx
response = httpx.post(
"https://api.gov.nominal.io/api/authentication/groups/v1/<group membership.key.group rid>/memberships",
headers={"Authorization": "Bearer <api key>"},
json={"key": {"memberRid": "<member rid>"}},
)
response.raise_for_status()
print(response.json())
import asyncio
import aiohttp
async def main() -> None:
async with aiohttp.ClientSession() as session:
async with session.post(
"https://api.gov.nominal.io/api/authentication/groups/v1/<group membership.key.group rid>/memberships",
headers={"Authorization": "Bearer <api key>"},
json={"key": {"memberRid": "<member rid>"}},
) as response:
response.raise_for_status()
print(await response.json())
asyncio.run(main())
Response: 200
{
"key": {
"groupRid": "<group rid>",
"memberRid": "<member rid>"
}
}
Get group#
GET /authentication/groups/v1/{groupRid}
Get group within the user’s organization
Path parameters
groupRidstring required
Response
ridstring
orgRidstringRequired on create requests; immutable on updates.
groupIdstringGroup ID, unique per org. If sourced from the customer’s IdP, will match IdP group name. Required on create requests; immutable on updates.
displayNamestring
descriptionstring
userRidsarray of stringThe list of users in this group.
createdAtstring (date-time)
updatedAtstring (date-time)
symbolSymbolSymbol to identify groups
Fields of
Symbol- one of
icon,emoji,image
iconstringIcon name (e.g. castle)
emojistringEmoji name (e.g. :castle:)
imagestringImage url (e.g. https://example.com/image.png)
- one of
membershipManagedManuallybooleanWhether group membership is managed manually in Nominal. Defaults to false.
Request
curl "https://api.gov.nominal.io/api/authentication/groups/v1/<group rid>" \
-H "Authorization: Bearer <api key>"
import requests
response = requests.get(
"https://api.gov.nominal.io/api/authentication/groups/v1/<group rid>",
headers={"Authorization": "Bearer <api key>"},
)
response.raise_for_status()
print(response.json())
import httpx
response = httpx.get(
"https://api.gov.nominal.io/api/authentication/groups/v1/<group rid>",
headers={"Authorization": "Bearer <api key>"},
)
response.raise_for_status()
print(response.json())
import asyncio
import aiohttp
async def main() -> None:
async with aiohttp.ClientSession() as session:
async with session.get(
"https://api.gov.nominal.io/api/authentication/groups/v1/<group rid>",
headers={"Authorization": "Bearer <api key>"},
) as response:
response.raise_for_status()
print(await response.json())
asyncio.run(main())
Response: 200
{
"rid": "<rid>",
"orgRid": "<org rid>",
"groupId": "<group id>",
"displayName": "<display name>",
"description": "<description>",
"userRids": [
"<user rids>"
],
"createdAt": "2026-01-01T00:00:00Z",
"updatedAt": "2026-01-01T00:00:00Z",
"symbol": {
"icon": "<icon>"
},
"membershipManagedManually": true
}
Update group metadata#
PUT /authentication/groups/v1/{groupRid}/metadata
Updates the metadata of a group
Path parameters
groupRidstring required
Body
displayNamestring
descriptionstring
symbolUpdateGroupSymbolWrapper
Fields of
UpdateGroupSymbolWrappervalueSymbol
Fields of
Symbol- one of
icon,emoji,imagerequired
iconstringIcon name (e.g. castle)
emojistringEmoji name (e.g. :castle:)
imagestringImage url (e.g. https://example.com/image.png)
- one of
Response
ridstring
orgRidstringRequired on create requests; immutable on updates.
groupIdstringGroup ID, unique per org. If sourced from the customer’s IdP, will match IdP group name. Required on create requests; immutable on updates.
displayNamestring
descriptionstring
userRidsarray of stringThe list of users in this group.
createdAtstring (date-time)
updatedAtstring (date-time)
symbolSymbolSymbol to identify groups
Fields of
Symbol- one of
icon,emoji,image
iconstringIcon name (e.g. castle)
emojistringEmoji name (e.g. :castle:)
imagestringImage url (e.g. https://example.com/image.png)
- one of
membershipManagedManuallybooleanWhether group membership is managed manually in Nominal. Defaults to false.
Request
curl -X PUT "https://api.gov.nominal.io/api/authentication/groups/v1/<group rid>/metadata" \
-H "Authorization: Bearer <api key>" \
-H "Content-Type: application/json" \
--data '{
"displayName": "<display name>",
"description": "<description>",
"symbol": {
"value": {
"icon": "<icon>"
}
}
}'
import requests
response = requests.put(
"https://api.gov.nominal.io/api/authentication/groups/v1/<group rid>/metadata",
headers={"Authorization": "Bearer <api key>"},
json={
"displayName": "<display name>",
"description": "<description>",
"symbol": {"value": {"icon": "<icon>"}},
},
)
response.raise_for_status()
print(response.json())
import httpx
response = httpx.put(
"https://api.gov.nominal.io/api/authentication/groups/v1/<group rid>/metadata",
headers={"Authorization": "Bearer <api key>"},
json={
"displayName": "<display name>",
"description": "<description>",
"symbol": {"value": {"icon": "<icon>"}},
},
)
response.raise_for_status()
print(response.json())
import asyncio
import aiohttp
async def main() -> None:
async with aiohttp.ClientSession() as session:
async with session.put(
"https://api.gov.nominal.io/api/authentication/groups/v1/<group rid>/metadata",
headers={"Authorization": "Bearer <api key>"},
json={
"displayName": "<display name>",
"description": "<description>",
"symbol": {"value": {"icon": "<icon>"}},
},
) as response:
response.raise_for_status()
print(await response.json())
asyncio.run(main())
Response: 200
{
"rid": "<rid>",
"orgRid": "<org rid>",
"groupId": "<group id>",
"displayName": "<display name>",
"description": "<description>",
"userRids": [
"<user rids>"
],
"createdAt": "2026-01-01T00:00:00Z",
"updatedAt": "2026-01-01T00:00:00Z",
"symbol": {
"icon": "<icon>"
},
"membershipManagedManually": true
}
Delete group membership#
DELETE /authentication/groups/v1/{key.groupRid}/memberships/{key.memberRid}
Removes a member from a manually managed group. Removing a non-member is a no-op. Throws HTTP 400 / gRPC 3 if group_rid or member_rid is missing, or member_rid is not a supported RID type. Throws HTTP 403 / gRPC 7 if the caller is not authorized to update the group, including when the group does not exist. The permission check runs before the group lookup so unknown groups are not disclosed. Throws HTTP 400 / gRPC 3 if the group’s membership is not managed manually.
Path parameters
key.groupRidstring requiredAt most 256 characters.
key.memberRidstring requiredThe member of the group. Only user RIDs are accepted today. At most 256 characters.
Response
An empty JSON object, {}.
Request
curl -X DELETE "https://api.gov.nominal.io/api/authentication/groups/v1/<key.group rid>/memberships/<key.member rid>" \
-H "Authorization: Bearer <api key>"
import requests
response = requests.delete(
"https://api.gov.nominal.io/api/authentication/groups/v1/<key.group rid>/memberships/<key.member rid>",
headers={"Authorization": "Bearer <api key>"},
)
response.raise_for_status()
print(response.json())
import httpx
response = httpx.delete(
"https://api.gov.nominal.io/api/authentication/groups/v1/<key.group rid>/memberships/<key.member rid>",
headers={"Authorization": "Bearer <api key>"},
)
response.raise_for_status()
print(response.json())
import asyncio
import aiohttp
async def main() -> None:
async with aiohttp.ClientSession() as session:
async with session.delete(
"https://api.gov.nominal.io/api/authentication/groups/v1/<key.group rid>/memberships/<key.member rid>",
headers={"Authorization": "Bearer <api key>"},
) as response:
response.raise_for_status()
print(await response.json())
asyncio.run(main())
Response: 200
{}
Errors#
Errors shows how these errors are sent.
Each error’s errorName is NominalAuthenticationGroupsV1: followed by its name below.
Status |
Name |
Notes |
|---|---|---|
400 |
|
Request identity field does not match the existing group |
400 |
|
RID field is invalid |
400 |
|
Group membership is not managed manually |
400 |
|
Required field missing on request |
400 |
|
Requested page size is too large |
400 |
|
User is not a member of the group organization |
403 |
|
Not authorized for group |
404 |
|
Group not found |
409 |
|
Group with given group_id already exists in organization |
Types#
Group#
A group represents a collection of users within an organization
ridstring
orgRidstringRequired on create requests; immutable on updates.
groupIdstringGroup ID, unique per org. If sourced from the customer’s IdP, will match IdP group name. Required on create requests; immutable on updates.
displayNamestring
descriptionstring
userRidsarray of string output onlyThe list of users in this group.
createdAtstring (date-time) output only
updatedAtstring (date-time) output only
symbolSymbolSymbol to identify groups
membershipManagedManuallybooleanWhether group membership is managed manually in Nominal. Defaults to false.
GroupMembershipKey#
Client-known identity of a group membership.
groupRidstring requiredAt most 256 characters.
memberRidstring requiredThe member of the group. Only user RIDs are accepted today. At most 256 characters.
SearchGroupsQuery#
Set at most one of the fields below.
- one of
exactSubstringText,and,or,memberUsers
exactSubstringTextstring
andSearchQueryAndand is implemented to allow for list (use SearchQueryAnd([]))
orSearchQueryOr
memberUsersSearchQueryMemberUsers
SearchQueryAnd#
queriesarray ofSearchGroupsQuery
SearchQueryMemberUsers#
Matches the groups that any of the users is a direct member of, whether that membership is synced from the identity provider or managed manually.
userRidsarray of string1 to 1,000 items. Each item: at most 256 characters.
SearchQueryOr#
queriesarray ofSearchGroupsQuery
Symbol#
Set exactly one of the fields below.
- one of
icon,emoji,imagerequired
iconstringIcon name (e.g. castle)
emojistringEmoji name (e.g. :castle:)
imagestringImage url (e.g. https://example.com/image.png)
UpdateGroupSymbolWrapper#
valueSymbol
Page design based on Scalar, MIT License.