Skip to content
Hexel StudioDocs

Manage groups

Create groups, add and remove members, attach policies to a group, and read a group's membership history.

On this page

A group is a set of members of your organization. Policies attached to a group, and permission sets assigned to it, apply to every member of the group. Use groups to manage access for teams instead of attaching policies to people one by one.

Your organization already has some groups: the four membership groups behind the member roles, and a default group. See Groups for what they are and which of them you can change.

Permissions you need

StepEndpointAction
Create, rename or delete a groupPOST /v1/groups, PATCH and DELETE /v1/groups/<group-id>iam:group:write
Add or remove membersPOST /v1/groups/<group-id>/members, DELETE /v1/groups/<group-id>/members/<user-id>iam:group:manage_members
Attach or detach policiesPOST /v1/policies/<policy-id>/attachments, DELETE .../attachments/<attachment-id>iam:policy:write
List groups, read a group, its members and its membership historyGET /v1/groups, GET /v1/groups/<group-id>, .../members, .../audit-logsNone: any member of the organization

Owners hold every action. Admins hold these through IAM Admin Access. To add a member to a group you must also hold every action the group's policies allow (see below), and to attach a policy, every action that policy allows.

Create a group

curl -X POST https://api.hexelstudio.com/v1/groups \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "platform-team",
    "display_name": "Platform team",
    "description": "Engineers who run our deployments"
  }'
namestringbody

A short name, unique in your organization. default and the membership group names are taken.

display_namestringbody

The name shown in the console.

descriptionstringbody

Optional description.

The response is 201 with the group. The group belongs to the organization of your token.

JSON
{
  "id": "grp_7d8e9f0a...",
  "organization_id": "org_9a8b7c...",
  "name": "platform-team",
  "display_name": "Platform team",
  "description": "Engineers who run our deployments",
  "group_type": "TEAM",
  "created_at": "2026-10-20T10:00:00.000000Z",
  "updated_at": "2026-10-20T10:00:00.000000Z"
}

A group name already used in your organization fails with 500 and the database error.

Add members

POST /v1/groups/<group-id>/members adds one member, by user ID. Take the ID from the user_id field of the organization's members list.

Bash
curl -X POST https://api.hexelstudio.com/v1/groups/<group-id>/members \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"user_id": "<user-id>"}'
user_idstringbodyrequired

The user ID of a member of your organization, or the ID of one of its service users (su_...).

The response is 201:

JSON
{
  "id": "gm_3c4d5e6f...",
  "group_id": "grp_7d8e9f0a...",
  "user_id": "<user-id>",
  "added_by_user_id": "<your-user-id>",
  "added_at": "2026-10-20T10:05:00.000000Z"
}

The new member gets every policy attached to the group, and every permission set assigned to it, at once on their existing tokens. Because of that, you can add a member only if you hold every action those policies allow.

StatusBodyCause
400{"error": "user_id is required"}user_id is missing.
403{"error": "forbidden"}You don't hold iam:group:manage_members.
403{"error": "forbidden", "reason": "cannot grant actions the caller does not hold", "missing_actions": [...]}The group grants actions you don't hold.
403{"error": "membership groups are managed through organization membership"}The group is a membership group. Change the member's role instead.
404{"error": "group not found"}No such group in your organization.
422{"error": "not_org_member", "message": "..."}user_id is not a member or service user of your organization.
500{"error": "..."}The user is already in the group.
503{"error": "membership lookup failed"}Membership couldn't be checked. Try again.

List members

Bash
curl https://api.hexelstudio.com/v1/groups/<group-id>/members \
  -H "Authorization: Bearer $ACCESS_TOKEN"

The response is an array of the membership objects shown above.

Remove a member

Bash
curl -X DELETE https://api.hexelstudio.com/v1/groups/<group-id>/members/<user-id> \
  -H "Authorization: Bearer $ACCESS_TOKEN"

The response is 204, also when the user was not in the group. The member loses the group's policies at once. Removing a member needs only iam:group:manage_members: you don't need to hold the group's policies.

Attach policies to a group

Attach a policy with target type GROUP:

Bash
curl -X POST https://api.hexelstudio.com/v1/policies/<policy-id>/attachments \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"target_type": "GROUP", "target_id": "<group-id>"}'

The policy applies organization-wide to every member of the group. To grant a group access in one workspace or environment only, assign it a permission set with a scope and "principal_type": "GROUP". Both are described in Write and attach policies, with detaching and the errors.

You can attach policies to a membership group too, to give every member of that role more access. See What a member gets by default.

Read and change a group

  • GET /v1/groups lists every group of your organization, by name, including the membership groups and default.
  • GET /v1/groups/<group-id> returns one group. A group of another organization returns 404 with {"error": "group not found"}.
  • PATCH /v1/groups/<group-id> changes name, display_name or description. The response is 200 with the group.
Bash
curl -X PATCH https://api.hexelstudio.com/v1/groups/<group-id> \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"display_name": "Platform engineering"}'

Membership groups can't be changed or deleted: those calls return 403 with {"error": "membership groups are managed through organization membership"}.

Groups don't nest. A group has a parent_group_id field, but members of a group don't get the policies of its parent.

Delete a group

Bash
curl -X DELETE https://api.hexelstudio.com/v1/groups/<group-id> \
  -H "Authorization: Bearer $ACCESS_TOKEN"

The response is 204. Hexel Studio removes the group's members and the policies attached to it, so its members lose that access at once. Permission set assignments made to the group are not removed: delete them with DELETE /v1/permission-sets/<permission-set-id>/assignments/<assignment-id>. They grant nothing once the group is gone.

Group audit logs

GET /v1/groups/<group-id>/audit-logs returns the group's membership history, newest first.

Bash
curl https://api.hexelstudio.com/v1/groups/<group-id>/audit-logs \
  -H "Authorization: Bearer $ACCESS_TOKEN"
JSON
[
  {
    "id": "gal_8f9a0b1c...",
    "group_id": "grp_7d8e9f0a...",
    "action": "MEMBER_REMOVED",
    "target_user_id": "<user-id>",
    "created_at": "2026-10-21T08:00:00.000000Z"
  },
  {
    "id": "gal_2a3b4c5d...",
    "group_id": "grp_7d8e9f0a...",
    "action": "MEMBER_ADDED",
    "actor_user_id": "<your-user-id>",
    "target_user_id": "<user-id>",
    "created_at": "2026-10-20T10:05:00.000000Z"
  }
]
actionstring

MEMBER_ADDED or MEMBER_REMOVED.

actor_user_idstring

Who added the member. Not recorded for removals.

target_user_idstring

The member added or removed.

This log holds membership changes made with the groups API only. Creating, renaming and deleting groups, attaching policies to them, and changes of member roles are recorded in the audit logs.