Skip to main content

Roles API

CRUD operations for RBAC roles within an application, plus endpoints to assign and revoke roles on users and retrieve a user's computed permissions.

Authentication

All endpoints require a valid JWT access token:

text
Authorization: Bearer {access_token}

Role read operations require the roles:read permission on the token. Role write operations require roles:manage.

List Roles

GET /api/v1/applications/{applicationId}/roles

List all roles for the application. Supports search and pagination.

Authentication

Requires jwt.permission:roles:read.

Query Parameters

ParameterTypeDescription
searchstringFilter by role name or display_name
include_permissionsbooleanWhen true, includes the full permissions array for each role
per_pageintegerRecords per page. Default 15, max 100.
pageintegerPage number

Response

200 OK

json
{
  "data": [
    {
      "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
      "name": "admin",
      "display_name": "Administrator",
      "description": "Full access to all resources",
      "is_system_role": true,
      "permissions_count": 12,
      "created_at": "2026-01-01T00:00:00Z"
    }
  ],
  "current_page": 1,
  "last_page": 1,
  "per_page": 15,
  "total": 3
}

Create Role

POST /api/v1/applications/{applicationId}/roles

Create a new role and attach a set of permissions to it. Permission names follow resource:action format.

Authentication

Requires jwt.permission:roles:manage.

Request Body

FieldTypeRequiredDescription
namestringYesUnique machine-readable identifier within the application. Max 100 characters.
display_namestringYesHuman-readable name shown in the UI. Max 255 characters.
descriptionstringNoOptional description of the role's purpose.
permissionsarray of stringsYesAt least one permission in resource:action format. Wildcards supported: posts:*, *:read.
is_system_rolebooleanNoMarks role as system-managed. System roles cannot be deleted. Default false.

Response

201 Created

json
{
  "data": {
    "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
    "name": "editor",
    "display_name": "Editor",
    "description": "Can create and edit content",
    "is_system_role": false,
    "permissions": ["posts:read", "posts:create", "posts:update"],
    "permissions_count": 3,
    "created_at": "2026-02-25T12:00:00Z"
  }
}

Error Responses

StatusCodeDescription
400VALIDATION_MULTIPLE_ERRORSOne or more fields are invalid
409RESOURCE_ALREADY_EXISTSA role with that name already exists in this application

Get Role

GET /api/v1/applications/{applicationId}/roles/{role}

Retrieve a single role with its full permissions list and user count.

Authentication

Requires jwt.permission:roles:read.

Response

200 OK

json
{
  "data": {
    "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
    "name": "editor",
    "display_name": "Editor",
    "description": "Can create and edit content",
    "is_system_role": false,
    "permissions": [
      {
        "id": "a1b2c3d4-...",
        "name": "posts:read"
      },
      {
        "id": "e5f6g7h8-...",
        "name": "posts:create"
      }
    ],
    "permissions_count": 2,
    "users_count": 14,
    "created_at": "2026-02-25T12:00:00Z",
    "updated_at": "2026-02-25T12:00:00Z"
  }
}

Error Responses

StatusCodeDescription
404RESOURCE_NOT_FOUNDRole not found

Update Role

PUT /api/v1/applications/{applicationId}/roles/{role}

Update a role's display name, description, and permissions. The role name is immutable after creation. System roles cannot be modified.

PATCH /api/v1/applications/{applicationId}/roles/{role} is also accepted.

Authentication

Requires jwt.permission:roles:manage.

Request Body

FieldTypeRequiredDescription
display_namestringNoNew display name
descriptionstringNoNew description
permissionsarray of stringsNoReplaces the entire permissions set for this role

Response

200 OK

json
{
  "data": {
    "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
    "name": "editor",
    "display_name": "Content Editor",
    "description": "Updated description",
    "is_system_role": false,
    "permissions_count": 5,
    "created_at": "2026-02-25T12:00:00Z",
    "updated_at": "2026-02-25T14:00:00Z"
  }
}

Error Responses

StatusCodeDescription
403Role is a system role and cannot be modified
404RESOURCE_NOT_FOUNDRole not found

Delete Role

DELETE /api/v1/applications/{applicationId}/roles/{role}

Delete a role. System roles and roles that are currently assigned to users cannot be deleted.

Authentication

Requires jwt.permission:roles:manage.

Response

204 No Content

Error Responses

StatusCodeDescription
403Role is a system role
404RESOURCE_NOT_FOUNDRole not found
409Role is currently assigned to one or more users

List User Roles

GET /api/v1/applications/{applicationId}/users/{userId}/roles

List all roles assigned to a specific user. Optionally filter by scope.

Authentication

Requires jwt.permission:roles:read.

Query Parameters

ParameterTypeDescription
scopestringFilter by assignment scope (e.g., org_123)

Response

200 OK

json
{
  "data": [
    {
      "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
      "name": "editor",
      "display_name": "Editor",
      "scope": null,
      "expires_at": null,
      "assigned_at": "2026-02-20T10:00:00Z"
    }
  ],
  "user_id": "550e8400-e29b-41d4-a716-446655440000",
  "scope": null
}

Assign Role to User

POST /api/v1/applications/{applicationId}/users/{userId}/roles

Assign a role to a user. Optionally scoped and with an expiry date.

Authentication

Requires jwt.permission:roles:manage.

Request Body

FieldTypeRequiredDescription
role_idstring (UUID)YesThe ID of the role to assign
scopestringNoOptional scope string (e.g., a resource ID or organization ID)
expires_atstring (ISO 8601)NoOptional expiry date for the role assignment. Must be in the future.

Response

201 Created

json
{
  "data": {
    "user_id": "550e8400-e29b-41d4-a716-446655440000",
    "role_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
    "scope": null,
    "expires_at": null,
    "assigned_at": "2026-02-25T12:00:00Z"
  }
}

Error Responses

StatusCodeDescription
409AUTHZ_ROLE_ALREADY_ASSIGNEDThe role is already assigned to this user (with the same scope)

Revoke Role from User

DELETE /api/v1/applications/{applicationId}/users/{userId}/roles/{roleId}

Remove a role assignment from a user. If the role was assigned with a scope, pass the same scope as a query parameter.

Authentication

Requires jwt.permission:roles:manage.

Query Parameters

ParameterTypeDescription
scopestringRequired if the role was assigned with a scope

Response

204 No Content

Error Responses

StatusCodeDescription
404AUTHZ_ROLE_ASSIGNMENT_NOT_FOUNDNo matching role assignment found

Get User Permissions

GET /api/v1/applications/{applicationId}/users/{userId}/permissions

Get the full set of permissions computed from all roles assigned to a user. Optionally filtered by scope.

Authentication

Requires jwt.permission:roles:read.

Query Parameters

ParameterTypeDescription
scopestringFilter by assignment scope

Response

200 OK

json
{
  "data": {
    "user_id": "550e8400-e29b-41d4-a716-446655440000",
    "scope": null,
    "permissions": [
      "posts:read",
      "posts:create",
      "posts:update",
      "comments:read"
    ],
    "roles": [
      {
        "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
        "name": "editor"
      }
    ]
  }
}