# Create a Role Group

> POST /v1/role-groups · Access management API

Source: https://developer.kustomer.com/api/access-management/create-a-role-group

```http
POST https://{orgname}.api.kustomerapp.com/v1/role-groups
Authorization: Bearer <API key>
```

## Authorization

Requires any one of these roles: `org.permission.role_group.write`; or legacy `org.admin.role_group.write`. The API key or user must hold at least one of them. Legacy roles predate permission sets and still work.

Creates a custom role group.

### Auth Roles
For a list of the latest available auth roles, check out the response from the Get Auth Roles API endpoint.

## About Role groups

A role group, called a permission set in the Kustomer app, is a named bundle of roles that decides what its members can see and do. Kustomer provides built-in role groups such as Administrator, and admins can create custom ones and assign them to users and teams.

Permissions in Kustomer are expressed as roles: dot-separated strings such as `org.permission.customer.read` or `org.admin.klass.write` (see [how roles are named](https://developer.kustomer.com/docs/get-started/api-keys-and-roles)). Rather than giving each person a list of roles, admins group them into role groups and assign those. A user can have one role group assigned directly, in the user's `roleGroups`, and can get more through the [teams](https://developer.kustomer.com/api/access-management#teams) they belong to. Changing a role group's `roles` changes what every member can do.

#### System and custom role groups

| | `system: true` | `system: false` |
| --- | --- | --- |
| Created by | Kustomer, in every org (for example Administrator and Manager) | Your admins |
| Can be changed | No. Updating or deleting one fails with `409`. | Yes |

Every role group has a `name` (up to 255 characters), an optional `description` (up to 1,024) and `roles`, a list of unique role strings. `GET /v1/auth/roles` lists the top-level roles available to your org. You can only put roles in a role group that you hold yourself; anything else fails with `400`.

#### Outbound brand visibility

`meta.outboundBrandVisibility` limits which email From addresses members can see, based on the [brands](https://developer.kustomer.com/api/core-resources#brands) those addresses are mapped to. `brandIds` lists the visible brands, and `includeUnassigned` also shows addresses that aren't mapped to any brand. The filter applies only when a client requests [`GET /v1/outboundAccounts`](https://developer.kustomer.com/api/core-resources/get-outbound-accounts) with `applyOutboundBrandVisibility=true`. A user in several role groups, directly or through teams, sees the union of their brands, and users who can edit role groups are never filtered. Send `null` to clear the setting. An empty allowlist (`brandIds: []` with `includeUnassigned: false`) is different from no setting: it hides every address when the filter is applied.

#### Which endpoint to use

| To | Call |
| --- | --- |
| See the roles you can put in a role group | [`GET /v1/auth/roles`](https://developer.kustomer.com/api/access-management/get-auth-roles) |
| List system and custom role groups | [`GET /v1/role-groups`](https://developer.kustomer.com/api/access-management/get-all-role-groups) |
| Read one role group and its roles | [`GET /v1/role-groups/{id}`](https://developer.kustomer.com/api/access-management/get-a-role-group-by-id) |
| Create, update or delete a custom role group | [`POST /v1/role-groups`](https://developer.kustomer.com/api/access-management/create-a-role-group), [`PUT /v1/role-groups/{id}`](https://developer.kustomer.com/api/access-management/update-a-role-group) or [`DELETE /v1/role-groups/{id}`](https://developer.kustomer.com/api/access-management/delete-a-role-group) |

Any signed-in user or API key can read role groups; creating, changing and deleting them needs a role group write role. A role group that is still assigned to a user or a team can't be deleted (`409`), so move those users and teams to another role group first. Role groups don't list their members: to give a person a role group, set `roleGroups` on the [user](https://developer.kustomer.com/api/access-management/update-user-by-id).

Related: [API keys and roles](https://developer.kustomer.com/docs/get-started/api-keys-and-roles), [Users](https://developer.kustomer.com/api/access-management#users), [Teams](https://developer.kustomer.com/api/access-management#teams)

### Recipes

#### 1. Create a narrow role group and assign it

Give a group of people only the roles they need, for example read-only access for a quality team, instead of a broad system role group.

**Step 1.** [`GET /v1/auth/roles`](https://developer.kustomer.com/api/access-management/get-auth-roles.md). List the roles you can grant. Each item's `id` is a role string; prefer the `org.permission.*` roles, which each allow one action. See [API keys and roles](https://developer.kustomer.com/docs/get-started/api-keys-and-roles).

```bash title="cURL"
curl "https://api.kustomerapp.com/v1/auth/roles" \
  --header "Authorization: Bearer $KUSTOMER_API_KEY"
```

```bash title="kusty"
kusty api GET /v1/auth/roles | jq -r '.data[].id'
```

**Step 2.** [`POST /v1/role-groups`](https://developer.kustomer.com/api/access-management/create-a-role-group.md). Create the role group with a `name`, a `description` that says who it's for, and its `roles`. You can only include roles you hold yourself; otherwise the request fails with `400`.

```bash title="cURL"
curl --request POST "https://api.kustomerapp.com/v1/role-groups" \
  --header "Authorization: Bearer $KUSTOMER_API_KEY" \
  --header "Content-Type: application/json" \
  --data '{"name": "QA reviewers", "description": "Read-only access for the quality team", "roles": ["org.permission.customer.read", "org.permission.conversation.read", "org.permission.message.read"]}'
```

```bash title="kusty"
ROLE_GROUP_ID=$(kusty api POST /v1/role-groups --field name="QA reviewers" \
  --field description="Read-only access for the quality team" \
  --field 'roles:=["org.permission.customer.read", "org.permission.conversation.read", "org.permission.message.read"]' \
  | jq -r '.data.id')
```

**Step 3.** [`PUT /v1/users/{id}`](https://developer.kustomer.com/api/access-management/update-user-by-id.md). Assign it to each user. A user has at most one role group of their own, so this replaces the one they had; teams can add more.

```bash title="cURL"
curl --request PUT "https://api.kustomerapp.com/v1/users/$USER_ID" \
  --header "Authorization: Bearer $KUSTOMER_API_KEY" \
  --header "Content-Type: application/json" \
  --data "{\"roleGroups\": [\"$ROLE_GROUP_ID\"]}"
```

```bash title="kusty"
kusty api PUT /v1/users/$USER_ID --field "roleGroups:=[\"$ROLE_GROUP_ID\"]"
```

> Try the role group on one user before assigning it widely, since parts of Kustomer may need roles you left out. To change the group later, send the complete `roles` list to `PUT /v1/role-groups/{id}`; it replaces the old list.

#### 2. Find everyone who gets a role group

List the users who have a role group, directly or through a team, before you change or remove it.

**Step 1.** [`GET /v1/users`](https://developer.kustomer.com/api/access-management/get-users.md). Role groups don't list their members, and there's no user filter by role group, so page through active users and check `roleGroups` yourself.

```bash title="cURL"
curl "https://api.kustomerapp.com/v1/users?deleted=false&pageSize=500" \
  --header "Authorization: Bearer $KUSTOMER_API_KEY"
```

```bash title="kusty"
kusty api GET /v1/users --query deleted=false --query pageSize=500 --all \
  | jq -r --arg rg "$ROLE_GROUP_ID" 'select(.data.attributes.roleGroups | index($rg)) | .data.id' > direct.txt
```

**Step 2.** [`GET /v1/teams`](https://developer.kustomer.com/api/access-management/get-teams.md). Teams can carry role groups too. `roleGroups` returns the active teams that have this one, and every member of those teams gets its roles.

```bash title="cURL"
curl "https://api.kustomerapp.com/v1/teams?roleGroups=$ROLE_GROUP_ID&deleted=false" \
  --header "Authorization: Bearer $KUSTOMER_API_KEY"
```

```bash title="kusty"
kusty api GET /v1/teams --query roleGroups=$ROLE_GROUP_ID --query deleted=false --all \
  | jq -r '.data.attributes.members[]' > via-teams.txt
```

**Step 3.** Combine the two lists. Resolve the IDs to names with [`GET /v1/users/{ids}`](https://developer.kustomer.com/api/access-management/get-multiple-users-by-ids) if you need them.

```bash title="kusty"
sort -u direct.txt via-teams.txt > everyone.txt
```

#### 3. Retire a custom role group

Move people off a role group you no longer want and delete it.

**Step 1.** [`PUT /v1/users/{id}`](https://developer.kustomer.com/api/access-management/update-user-by-id.md). Find the users who have the role group directly, as in the recipe above, and give each one its replacement.

```bash title="cURL"
curl --request PUT "https://api.kustomerapp.com/v1/users/$USER_ID" \
  --header "Authorization: Bearer $KUSTOMER_API_KEY" \
  --header "Content-Type: application/json" \
  --data "{\"roleGroups\": [\"$NEW_ROLE_GROUP_ID\"]}"
```

```bash title="kusty"
while read -r USER_ID; do
  kusty api PUT /v1/users/$USER_ID --field "roleGroups:=[\"$NEW_ROLE_GROUP_ID\"]"
done < direct.txt
```

**Step 2.** [`GET /v1/teams`](https://developer.kustomer.com/api/access-management/get-teams.md). Check for teams that still carry it. The team endpoints don't change a team's role groups, so update any teams listed here in Kustomer's team settings.

```bash title="cURL"
curl "https://api.kustomerapp.com/v1/teams?roleGroups=$ROLE_GROUP_ID&deleted=false" \
  --header "Authorization: Bearer $KUSTOMER_API_KEY"
```

```bash title="kusty"
kusty api GET /v1/teams --query roleGroups=$ROLE_GROUP_ID --query deleted=false \
  | jq -r '.data[].attributes.name'
```

**Step 3.** [`DELETE /v1/role-groups/{id}`](https://developer.kustomer.com/api/access-management/delete-a-role-group.md). Delete the role group. If any user or team still has it, the API answers `409` and nothing is deleted, so go back and find who's left. System role groups can't be deleted at all.

```bash title="cURL"
curl --request DELETE "https://api.kustomerapp.com/v1/role-groups/$ROLE_GROUP_ID" \
  --header "Authorization: Bearer $KUSTOMER_API_KEY"
```

```bash title="kusty"
kusty api DELETE /v1/role-groups/$ROLE_GROUP_ID --confirm --yes
```

#### 4. Limit which brands' From addresses a role group sees

Show members of a role group only the email addresses of the brands they work on, for example in a multi-brand support team.

**Step 1.** [`GET /v1/brands`](https://developer.kustomer.com/api/core-resources/get-brands.md). Find the IDs of the brands this role group should send as.

```bash title="cURL"
curl "https://api.kustomerapp.com/v1/brands?pageSize=100" \
  --header "Authorization: Bearer $KUSTOMER_API_KEY"
```

```bash title="kusty"
kusty api GET /v1/brands --all | jq -r '[.data.id, .data.attributes.name] | @tsv'
```

**Step 2.** [`PUT /v1/role-groups/{id}`](https://developer.kustomer.com/api/access-management/update-a-role-group.md). Set `meta.outboundBrandVisibility` on a custom role group. `brandIds` lists the visible brands, and `includeUnassigned` also shows addresses that aren't mapped to any brand. An empty `brandIds` with `includeUnassigned: false` hides every email address, which is different from not setting it at all.

```bash title="cURL"
curl --request PUT "https://api.kustomerapp.com/v1/role-groups/$ROLE_GROUP_ID" \
  --header "Authorization: Bearer $KUSTOMER_API_KEY" \
  --header "Content-Type: application/json" \
  --data "{\"meta\": {\"outboundBrandVisibility\": {\"brandIds\": [\"$BRAND_ID\"], \"includeUnassigned\": false}}}"
```

```bash title="kusty"
kusty api PUT /v1/role-groups/$ROLE_GROUP_ID \
  --field "meta.outboundBrandVisibility.brandIds:=[\"$BRAND_ID\"]" \
  --field meta.outboundBrandVisibility.includeUnassigned:=false
```

**Step 3.** [`GET /v1/outboundAccounts`](https://developer.kustomer.com/api/core-resources/get-outbound-accounts.md). Check the result as a member of the role group with `applyOutboundBrandVisibility=true`. Email accounts for other brands are left out, and accounts for other channels are always returned. People who can edit role groups always see the full list, so test with an ordinary member.

```bash title="cURL"
curl "https://api.kustomerapp.com/v1/outboundAccounts?applyOutboundBrandVisibility=true" \
  --header "Authorization: Bearer $MEMBER_TOKEN"
```

```bash title="kusty"
kusty api GET /v1/outboundAccounts --query applyOutboundBrandVisibility=true \
  | jq -r '.data[].attributes | [.channel, .name, .account] | @tsv'
```

> Send `"outboundBrandVisibility": null` inside `meta` to remove the restriction. The filter applies only to clients that ask for it with `applyOutboundBrandVisibility`.

### Example object

A real record from [`GET /v1/role-groups/{id}`](https://developer.kustomer.com/api/access-management/get-a-role-group-by-id.md):

```json
{
  "type": "role_group",
  "id": "5afee08eb06db6d51b8cf61e",
  "attributes": {
    "name": "Administrator",
    "description": "Has full access to everything in Kustomer.",
    "display": true,
    "system": true,
    "roles": [
      "org.admin",
      "org.user",
      "org.tracking"
    ],
    "createdAt": "2018-06-22T13:14:57.123Z",
    "updatedAt": "2018-06-22T13:14:57.123Z"
  },
  "relationships": {
    "org": {
      "links": {
        "self": "/v1/orgs/581392b55ac7a2110099d9c8"
      },
      "data": {
        "type": "org",
        "id": "581392b55ac7a2110099d9c8"
      }
    }
  }
}
```

Fields:

- `attributes.name` (string): Up to 255 characters. For system role groups, Kustomer sets the name and description.
- `attributes.description` (string): Optional, up to 1,024 characters.
- `attributes.system` (boolean): `true` for the role groups Kustomer provides, such as Administrator. Updating or deleting one fails with `409`.
- `attributes.roles` (array): Role strings the group grants, such as `org.admin`. Sending `roles` on `PUT` replaces the whole list, and you can only include roles you hold yourself.

### Relationships

- Referenced by **Teams** via `relationships.roleGroups` (list): Role groups assigned to a team add to every member's permissions. Find the teams that carry a role group with `roleGroups` on `GET /v1/teams`.
- Referenced by **Users** via `relationships.roleGroups` (list): The role group assigned directly to a user, in the user's `roleGroups`. Role groups don't list their members, so read users and teams to find who has one.

### Permissions

Fewest roles for a read-only integration: `org.permission.auth_role.read`. For every endpoint: `org.permission.auth_role.read`, `org.permission.role_group.delete`, `org.permission.role_group.update`, `org.permission.role_group.write`.

## Request body

Content type: `application/json`

- `name` (string, required): (min length 1; max length 255)
- `description` (string): (max length 1024)
- `display` (boolean)
- `roles` (array<string>): (unique items)

Example:

```json
{
  "name": "example_name",
  "description": "Example text",
  "display": true,
  "roles": [
    "string"
  ]
}
```

## Responses

### 201

Created

- `data` (object, required)
  - `type` (string, required)
  - `id` (string, required)
  - `attributes` (object, required)
    - `name` (string, required)
    - `description` (string, required)
    - `display` (boolean, required)
    - `system` (boolean, required)
    - `roles` (array<string>, required)
    - `createdAt` (string, required)
    - `updatedAt` (string, required)
  - `relationships` (object, required)
    - `org` (object, required)

```json
{
  "data": {
    "type": "role_group",
    "id": "5afee08eb06db6d51b8cf61e",
    "attributes": {
      "name": "My Custom Administrator Role Group",
      "description": "Has full access to everything in Kustomer.",
      "display": true,
      "system": false,
      "roles": [
        "org.admin",
        "org.user",
        "org.tracking"
      ],
      "createdAt": "2018-06-22T13:14:57.123Z",
      "updatedAt": "2018-06-22T13:14:57.123Z"
    },
    "relationships": {
      "org": {
        "links": {
          "self": "/v1/orgs/581392b55ac7a2110099d9c8"
        },
        "data": {
          "type": "org",
          "id": "581392b55ac7a2110099d9c8"
        }
      }
    }
  }
}
```

### 400

Bad Request - Invalid request parameters or body

### 401

Unauthorized - Authentication required or invalid credentials

### 403

Forbidden - Insufficient permissions

## Example request

```bash
curl --request POST \
  --url 'https://api.kustomerapp.com/v1/role-groups' \
  --header "Authorization: Bearer $KUSTOMER_API_KEY" \
  --header 'Content-Type: application/json' \
  --data '{
  "name": "example_name",
  "description": "Example text",
  "display": true,
  "roles": [
    "string"
  ]
}'
```
