Roles
Manage roles and their permissions.
A role is a named set of permissions shared by users and applications. Every user and every application has exactly one role, referred to by its slug. How roles are evaluated together with per-user permissions is described in Authorization.
The role object#
{
"_id": "66f1c0d2a4b5c6d7e8f90131",
"name": "Support Agent",
"slug": "support",
"description": "Can read and edit customers, but not delete them",
"permissions": [
"users.read",
"users.update",
"user-types.read",
"roles.read"
],
"forbidden": [
"users.delete"
],
"membership_id": "66f1c0d2a4b5c6d7e8f90123",
"sys": { "created_at": "2026-01-01T12:00:00Z", "created_by": "admin" }
}| Field | Required | Description |
|---|---|---|
name | yes | Display name. |
slug | no | Unique in the membership; derived from the name when omitted. Users and applications refer to the role by its slug. |
description | no | |
permissions | no | What the role allows, as permission expressions. |
forbidden | no | What the role denies. A forbidden entry always wins over a permission of the same role. |
The same expression can't be in both lists.
The admin role#
The setup creates the admin role, which has create, read, update and delete on every resource of the ErtisAuth API. Its slug is reserved: no other role can be created with it, and it can't be deleted.
Endpoints#
All routes are under /memberships/{membershipId}.
| Method | Route | Description | Permission |
|---|---|---|---|
GET | /roles/{id} | Get a role (id or slug) | roles.read.{id} |
GET | /roles | List roles | roles.read |
POST | /roles/_query | Query roles | roles.read |
GET | /roles/search?keyword= | Search roles | roles.read |
POST | /roles | Create a role | roles.create |
PUT | /roles/{id} | Update a role | roles.update.{id} |
DELETE | /roles/{id} | Delete a role | roles.delete.{id} |
DELETE | /roles | Delete several roles | roles.delete |
GET | /roles/{id}/check-permission?permission= | Check a permission of a role | roles.read |
GET | /roles/check-permission?permission= | Check a permission of the caller | any valid token |
Create a role#
curl -X POST https://auth.example.com/memberships/<membership_id>/roles \
-H 'Authorization: Bearer <access_token>' \
-H 'Content-Type: application/json' \
-d '{
"name": "Support Agent",
"slug": "support",
"permissions": [ "users.read", "users.update", "roles.read" ],
"forbidden": [ "users.delete" ]
}'Response 201 Created: the role.
| Error | When |
|---|---|
400 ModelValidationError | Missing name, invalid slug, or the same expression in both lists |
400 InvalidRbac | An expression is not valid |
404 MembershipNotFound | The membership does not exist |
409 RoleAlreadyExists | The slug is taken |
409 ReservedRole | The slug is admin |
Update a role#
PUT /memberships/{membershipId}/roles/{id}The body has the same fields as the create request and replaces the role's permissions and forbidden lists. The change applies to every user and application with the role without reissuing their tokens. When you run several ErtisAuth instances, each instance caches roles for up to 5 minutes, so a change can take that long to reach all of them (see Operations).
An update without any change answers 409 IdenticalDocumentError.
Delete a role#
DELETE /memberships/{membershipId}/roles/{id}Response 204 No Content. The admin role can't be deleted (409 SystemRolesCannotBeDeleted). Several roles can be deleted at once with bulk delete.
403 AccessDenied ("role is not found").Check permissions#
See Authorization.
Events#
RoleCreated, RoleUpdated and RoleDeleted. See Events.
Found a mistake in the docs? Open an issue