User Group Management GraphQL API
Add users to groups and remove users from groups from your own systems, without opening the Admin Console. A user's groups decide which apps they can launch, so a membership change updates their app access.
Use this API when an event in another system should change what a user can access. For example, when a user transfers from the operations team to the trading desk, your HR system moves them from an operations group to a trading group, and their app list changes to match their new role.
Your GraphQL endpoint is https://tenant-name.is.here.io/here/api/graphql
POST /here/api/graphql
x-openfin-cloud-api-key: <your API key>
Content-Type: application/json
mutation {
addUserToGroup(userIdentifier: "jane.doe@example.com", groupIdentifier: "trading") {
uuid
id
}
}
Scope
This API changes group membership only. You still create groups and assign content to them in the Admin Console.
| You can | You can't |
|---|---|
| Add one or more users to an existing group. | Create or delete groups. |
| Remove one or more users from an existing group. | Assign content to groups or remove it from them. |
| Move a user between groups by removing and then adding. | Assign roles or permissions. |
Authentication
Every request must carry one of these credentials:
| Credential | How to send it | Use it for |
|---|---|---|
| API key | x-openfin-cloud-api-key header | Unattended systems, such as an HR system or a backend service. |
| Bearer token | Authorization: Bearer <token> header | Callers that already hold a HERE access token. |
| Session cookie | here-session cookie | Scripts or tools run by a signed-in user. |
For a system that calls the API on its own, use an API key.
Only an admin with the Full Access admin type can add users to groups or remove them. A Content Manager can't, even though they can change content through the Content Configuration API. An API key always works, because it has Full Access.
A missing, expired, or invalid credential fails with UNAUTHENTICATED. A valid credential without Full Access fails with FORBIDDEN. Error codes appear in extensions.code on each GraphQL error.
An API key has Full Access, so it can see and modify all items in the Admin Console. Store API keys in a secrets manager, give them only to the systems that need them, and rotate them regularly.
Identifiers
Every mutation accepts either identifier for users and groups:
| Argument | Accepts | Example |
|---|---|---|
userIdentifier, userIdentifiers | The user's uuid or id. A user's id is their username. | 1375d728-9fe2-4e9d-8b9b-809f1e29d2cb or jane.doe@example.com |
groupIdentifier | The group's uuid or id. A group's id is its name. | b416ae4b-a6a4-4c9d-9863-9aa6aa1e4474 or trading |
If the value parses as a UUID, the API uses it as a UUID. Otherwise, the API looks it up by username or group name.
A username is often an email address. Pass it exactly as users { id } returns it. To find identifiers, query users:
query {
users(first: 50) {
edges { node { uuid id firstName lastName } }
}
}
groupIdentifier must identify a group. If it points to a role or a permission, the mutation fails with NOT_FOUND.
Mutations
| Mutation | Returns | Purpose |
|---|---|---|
addUserToGroup | User! | Add one user to a group. |
removeUserFromGroup | User! | Remove one user from a group. |
addUsersToGroup | BulkAddUsersToGroupResult! | Add several users to one group. |
removeUsersFromGroup | BulkRemoveUsersFromGroupResult! | Remove several users from one group. |
addUserToGroup
addUserToGroup(userIdentifier: ID!, groupIdentifier: ID!): User!
Adds a user to a group and returns the user. To confirm the change in the same response, request groups. If the user is already a member, the mutation still succeeds.
mutation AddUserToGroup($user: ID!, $group: ID!) {
addUserToGroup(userIdentifier: $user, groupIdentifier: $group) {
uuid
id
groups {
edges { node { id displayName } }
}
}
}
{
"user": "jane.doe@example.com",
"group": "trading"
}
{
"data": {
"addUserToGroup": {
"uuid": "1375d728-9fe2-4e9d-8b9b-809f1e29d2cb",
"id": "jane.doe@example.com",
"groups": {
"edges": [
{ "node": { "id": "all-users", "displayName": "All Users" } },
{ "node": { "id": "trading", "displayName": "Trading" } }
]
}
}
}
}
removeUserFromGroup
removeUserFromGroup(userIdentifier: ID!, groupIdentifier: ID!): User!
Removes a user from a group and returns the user. If the user isn't a member, the mutation still succeeds.
mutation RemoveUserFromGroup($user: ID!, $group: ID!) {
removeUserFromGroup(userIdentifier: $user, groupIdentifier: $group) {
uuid
id
groups {
edges { node { id displayName } }
}
}
}
{
"user": "jane.doe@example.com",
"group": "operations"
}
addUsersToGroup
addUsersToGroup(userIdentifiers: [ID!]!, groupIdentifier: ID!): BulkAddUsersToGroupResult!
type BulkAddUsersToGroupResult {
added: [User!]!
}
Adds several users to one group. userIdentifiers can mix UUIDs and usernames.
The request is all-or-nothing. If any identifier doesn't resolve, the request fails and no one's membership changes. Users who are already members still appear in added.
mutation AddUsersToGroup($users: [ID!]!, $group: ID!) {
addUsersToGroup(userIdentifiers: $users, groupIdentifier: $group) {
added { uuid id }
}
}
{
"users": [
"jane.doe@example.com",
"sam.patel@example.com",
"58311cf0-77d6-4e98-881b-aef475f856ad"
],
"group": "trading"
}
{
"data": {
"addUsersToGroup": {
"added": [
{ "uuid": "1375d728-9fe2-4e9d-8b9b-809f1e29d2cb", "id": "jane.doe@example.com" },
{ "uuid": "0b6e2f7a-3c1d-4e8b-9a5f-2d7c6e1b4a90", "id": "sam.patel@example.com" },
{ "uuid": "58311cf0-77d6-4e98-881b-aef475f856ad", "id": "alex.chen@example.com" }
]
}
}
}
removeUsersFromGroup
removeUsersFromGroup(userIdentifiers: [ID!]!, groupIdentifier: ID!): BulkRemoveUsersFromGroupResult!
type BulkRemoveUsersFromGroupResult {
removed: [User!]!
}
Removes several users from one group. Like addUsersToGroup, the request is all-or-nothing. Users who aren't members are ignored. removed returns full user records, since the users still exist after they leave the group.
mutation RemoveUsersFromGroup($users: [ID!]!, $group: ID!) {
removeUsersFromGroup(userIdentifiers: $users, groupIdentifier: $group) {
removed { uuid id }
}
}
{
"users": ["jane.doe@example.com", "sam.patel@example.com"],
"group": "operations"
}
Move a user between groups
No single mutation moves a user. Remove the user from the old group, then add them to the new one. You can send both in one request, because GraphQL runs mutation fields in the order you list them.
mutation ChangeTeam($user: ID!) {
leave: removeUserFromGroup(userIdentifier: $user, groupIdentifier: "operations") {
id
}
join: addUserToGroup(userIdentifier: $user, groupIdentifier: "trading") {
id
groups {
edges { node { id displayName } }
}
}
}
{ "user": "jane.doe@example.com" }
The two operations are independent. If the remove succeeds and the add fails, the user is left in neither group. Check the response for errors and retry the whole request. Both operations are safe to repeat, so a retry completes the move.
To keep the user's access during the move, reverse the order: add the user to the new group first, then remove them from the old one.
Retries and repeated requests
Each mutation sets a state rather than applying a change:
- An add makes sure the user is a member. Adding an existing member succeeds.
- A remove makes sure the user isn't a member. Removing a non-member succeeds.
That means you can retry any request after a timeout or network error without checking membership first. If your system sends the same event twice, the second request won't cause an error.
A missing user or group is always an error, even on a remove.
When the change takes effect
The new membership applies as soon as the mutation returns. The user doesn't need to sign out or restart HERE Enterprise Browser.
The platform doesn't push the change to open sessions. Search shows the new app list the next time it loads. The dock updates on its next refresh, which can take a short time.
Example: update access when a user changes teams
- In the Admin Console, create a group for each team, such as
operationsandtrading. - Assign each group the apps that team needs.
- Create an API key for your HR system.
- When a user changes teams, have the HR system send the move request with the user's username.
curl https://tenant-name.is.here.io/here/api/graphql \
-H "Content-Type: application/json" \
-H "x-openfin-cloud-api-key: $HERE_API_KEY" \
-d '{
"query": "mutation ($user: ID!) { leave: removeUserFromGroup(userIdentifier: $user, groupIdentifier: \"operations\") { id } join: addUserToGroup(userIdentifier: $user, groupIdentifier: \"trading\") { id } }",
"variables": { "user": "jane.doe@example.com" }
}'
The user sees the trading desk's apps the next time search loads, without a restart.
Behavior to plan for
- The Admin Console and the API change the same data. An administrator can undo a membership change your system made, and the reverse. Decide which groups your system manages, and leave the rest to administrators.
- Groups must already exist. The API doesn't create groups. If an administrator renames a group, requests that use the old name fail with
NOT_FOUND. If group names might change, use group UUIDs.