A custom role is an access control resource defined at the organization level. Custom roles allow individual organizations to create roles tailored to their specific needs, in addition to the environment roles that apply across all organizations.
Like environment roles, custom roles can be assigned to organization memberships, directory users, and SSO profiles. Each custom role has a unique slug identifier within the organization and can have permissions assigned to it.
When listing roles for an organization, both environment roles and custom roles are returned in priority order. Environment roles are included because they apply to all organizations in your environment.
Get a list of all roles that apply to an organization. This includes both environment roles and custom roles, returned in priority order.
curl "https://api.workos.com/authorization/organizations/org_01EHZNVPK3SFK441A1RGBFSHRT/roles" \ --header "Authorization: Bearer sk_example_123456789"
{ "object": "list", "data": [ { "slug": "admin", "object": "role", "id": "role_01EHQMYV6MBK39QC5PZXHY59C3", "name": "Admin", "description": "Can manage all resources", "type": "EnvironmentRole", "resource_type_slug": "organization", "permissions": [ "posts:read", "posts:write" ], "created_at": "2026-01-15T12:00:00.000Z", "updated_at": "2026-01-15T12:00:00.000Z" } ] }
| curl "https://api.workos.com/authorization/organizations/org_01EHZNVPK3SFK441A1RGBFSHRT/roles" \ | |
| --header "Authorization: Bearer sk_example_123456789" |
| import { WorkOS } from '@workos-inc/node'; | |
| const workos = new WorkOS('sk_example_123456789'); | |
| const roles = await workos.authorization.listOrganizationRoles( | |
| 'org_01EHZNVPK3SFK441A1RGBFSHRT', | |
| ); |
| from workos import WorkOSClient | |
| workos_client = WorkOSClient( | |
| api_key="sk_example_123456789", client_id="client_123456789" | |
| ) | |
| roles = workos_client.authorization.list_organization_roles( | |
| organization_id="org_01EHZNVPK3SFK441A1RGBFSHRT", | |
| ) |
| { | |
| "object": "list", | |
| "data": [ | |
| { | |
| "slug": "admin", | |
| "object": "role", | |
| "id": "role_01EHQMYV6MBK39QC5PZXHY59C3", | |
| "name": "Admin", | |
| "description": "Can manage all resources", | |
| "type": "EnvironmentRole", | |
| "resource_type_slug": "organization", | |
| "permissions": [ | |
| "posts:read", | |
| "posts:write" | |
| ], | |
| "created_at": "2026-01-15T12:00:00.000Z", | |
| "updated_at": "2026-01-15T12:00:00.000Z" | |
| } | |
| ] | |
| } |
GET/authorization /organizations /:organizationId /rolesParameters Returns Create a new custom role. The role will be specific to the organization and can be assigned to organization memberships.
The slug must be unique within the organization, begin with org-, and contain only lowercase letters, numbers, hyphens, and underscores.
New roles are placed at the bottom of the organization’s priority order.
curl --request POST \ --url "https://api.workos.com/authorization/organizations/org_01EHZNVPK3SFK441A1RGBFSHRT/roles" \ --header "Authorization: Bearer sk_example_123456789" \ --header "Content-Type: application/json" \ -d @- <<'BODY' { "slug": "org-billing-admin", "name": "Billing Administrator", "description": "Can manage billing and invoices" } BODY
{ "slug": "org-billing-admin", "object": "role", "id": "role_01EHQMYV6MBK39QC5PZXHY59C3", "name": "Billing Administrator", "description": "Can manage billing and invoices", "type": "OrganizationRole", "resource_type_slug": "organization", "permissions": [ "posts:read", "posts:write" ], "created_at": "2026-01-15T12:00:00.000Z", "updated_at": "2026-01-15T12:00:00.000Z" }
| curl --request POST \ | |
| --url "https://api.workos.com/authorization/organizations/org_01EHZNVPK3SFK441A1RGBFSHRT/roles" \ | |
| --header "Authorization: Bearer sk_example_123456789" \ | |
| --header "Content-Type: application/json" \ | |
| -d @- <<'BODY' | |
| { | |
| "slug": "org-billing-admin", | |
| "name": "Billing Administrator", | |
| "description": "Can manage billing and invoices" | |
| } | |
| BODY |
| import { WorkOS } from '@workos-inc/node'; | |
| const workos = new WorkOS('sk_example_123456789'); | |
| const role = await workos.authorization.createOrganizationRole( | |
| 'org_01EHZNVPK3SFK441A1RGBFSHRT', | |
| { | |
| slug: 'org-billing-admin', | |
| name: 'Billing Administrator', | |
| description: 'Can manage billing and invoices', | |
| }, | |
| ); |
| from workos import WorkOSClient | |
| workos_client = WorkOSClient( | |
| api_key="sk_example_123456789", client_id="client_123456789" | |
| ) | |
| role = workos_client.authorization.create_organization_role( | |
| organization_id="org_01EHZNVPK3SFK441A1RGBFSHRT", | |
| slug="org-billing-admin", | |
| name="Billing Administrator", | |
| description="Can manage billing and invoices", | |
| ) |
| { | |
| "slug": "org-billing-admin", | |
| "object": "role", | |
| "id": "role_01EHQMYV6MBK39QC5PZXHY59C3", | |
| "name": "Billing Administrator", | |
| "description": "Can manage billing and invoices", | |
| "type": "OrganizationRole", | |
| "resource_type_slug": "organization", | |
| "permissions": [ | |
| "posts:read", | |
| "posts:write" | |
| ], | |
| "created_at": "2026-01-15T12:00:00.000Z", | |
| "updated_at": "2026-01-15T12:00:00.000Z" | |
| } |
POST/authorization /organizations /:organizationId /rolesParameters Returns Retrieve a role that applies to an organization by its slug. This can return either an environment role or a custom role.
curl "https://api.workos.com/authorization/organizations/org_01EHZNVPK3SFK441A1RGBFSHRT/roles/org-billing-admin" \ --header "Authorization: Bearer sk_example_123456789"
{ "slug": "org-billing-admin", "object": "role", "id": "role_01EHQMYV6MBK39QC5PZXHY59C3", "name": "Billing Manager", "description": "Can view and export billing reports", "type": "OrganizationRole", "resource_type_slug": "organization", "permissions": [ "posts:read", "posts:write" ], "created_at": "2026-01-15T12:00:00.000Z", "updated_at": "2026-01-15T12:00:00.000Z" }
| curl "https://api.workos.com/authorization/organizations/org_01EHZNVPK3SFK441A1RGBFSHRT/roles/org-billing-admin" \ | |
| --header "Authorization: Bearer sk_example_123456789" |
| import { WorkOS } from '@workos-inc/node'; | |
| const workos = new WorkOS('sk_example_123456789'); | |
| const role = await workos.authorization.getOrganizationRole( | |
| 'org_01EHZNVPK3SFK441A1RGBFSHRT', | |
| 'org-billing-admin', | |
| ); |
| from workos import WorkOSClient | |
| workos_client = WorkOSClient( | |
| api_key="sk_example_123456789", client_id="client_123456789" | |
| ) | |
| role = workos_client.authorization.get_organization_role( | |
| organization_id="org_01EHZNVPK3SFK441A1RGBFSHRT", | |
| slug="org-billing-admin", | |
| ) |
| { | |
| "slug": "org-billing-admin", | |
| "object": "role", | |
| "id": "role_01EHQMYV6MBK39QC5PZXHY59C3", | |
| "name": "Billing Manager", | |
| "description": "Can view and export billing reports", | |
| "type": "OrganizationRole", | |
| "resource_type_slug": "organization", | |
| "permissions": [ | |
| "posts:read", | |
| "posts:write" | |
| ], | |
| "created_at": "2026-01-15T12:00:00.000Z", | |
| "updated_at": "2026-01-15T12:00:00.000Z" | |
| } |
GET/authorization /organizations /:organizationId /roles /:slugParameters Returns Update an existing custom role. Only the fields provided in the request body will be updated.
curl --request PATCH \ --url "https://api.workos.com/authorization/organizations/org_01EHZNVPK3SFK441A1RGBFSHRT/roles/org-billing-admin" \ --header "Authorization: Bearer sk_example_123456789" \ --header "Content-Type: application/json" \ -d @- <<'BODY' { "name": "Finance Administrator", "description": "Can manage all financial operations" } BODY
{ "slug": "org-billing-admin", "object": "role", "id": "role_01EHQMYV6MBK39QC5PZXHY59C3", "name": "Finance Administrator", "description": "Can manage all financial operations", "type": "OrganizationRole", "resource_type_slug": "organization", "permissions": [ "posts:read", "posts:write" ], "created_at": "2026-01-15T12:00:00.000Z", "updated_at": "2026-01-15T12:00:00.000Z" }
| curl --request PATCH \ | |
| --url "https://api.workos.com/authorization/organizations/org_01EHZNVPK3SFK441A1RGBFSHRT/roles/org-billing-admin" \ | |
| --header "Authorization: Bearer sk_example_123456789" \ | |
| --header "Content-Type: application/json" \ | |
| -d @- <<'BODY' | |
| { | |
| "name": "Finance Administrator", | |
| "description": "Can manage all financial operations" | |
| } | |
| BODY |
| import { WorkOS } from '@workos-inc/node'; | |
| const workos = new WorkOS('sk_example_123456789'); | |
| const role = await workos.authorization.updateOrganizationRole( | |
| 'org_01EHZNVPK3SFK441A1RGBFSHRT', | |
| 'org-billing-admin', | |
| { | |
| name: 'Finance Administrator', | |
| description: 'Can manage all financial operations', | |
| }, | |
| ); |
| from workos import WorkOSClient | |
| workos_client = WorkOSClient( | |
| api_key="sk_example_123456789", client_id="client_123456789" | |
| ) | |
| role = workos_client.authorization.update_organization_role( | |
| organization_id="org_01EHZNVPK3SFK441A1RGBFSHRT", | |
| slug="org-billing-admin", | |
| name="Finance Administrator", | |
| description="Can manage all financial operations", | |
| ) |
| { | |
| "slug": "org-billing-admin", | |
| "object": "role", | |
| "id": "role_01EHQMYV6MBK39QC5PZXHY59C3", | |
| "name": "Finance Administrator", | |
| "description": "Can manage all financial operations", | |
| "type": "OrganizationRole", | |
| "resource_type_slug": "organization", | |
| "permissions": [ | |
| "posts:read", | |
| "posts:write" | |
| ], | |
| "created_at": "2026-01-15T12:00:00.000Z", | |
| "updated_at": "2026-01-15T12:00:00.000Z" | |
| } |
PATCH/authorization /organizations /:organizationId /roles /:slugParameters Returns Delete an existing custom role. The role must not have any active assignments or IdP group role mappings.
If the role has active assignments, you will receive a 409 Conflict error with code role_has_assignments. If the role has group role mappings, you will receive a 409 Conflict error with code role_has_group_role_mappings.
curl --request DELETE \ --url https://api.workos.com/authorization/organizations/org_01EHZNVPK3SFK441A1RGBFSHRT/roles/org-billing-admin \ --header "Authorization: Bearer sk_example_123456789"
import { WorkOS } from '@workos-inc/node'; const workos = new WorkOS('sk_example_123456789'); await workos.authorization.deleteOrganizationRole( 'org_01EHZNVPK3SFK441A1RGBFSHRT', 'org-billing-admin', );
from workos import WorkOSClient workos_client = WorkOSClient( api_key="sk_example_123456789", client_id="client_123456789" ) workos_client.authorization.delete_organization_role( organization_id="org_01EHZNVPK3SFK441A1RGBFSHRT", slug="org-billing-admin", )
DELETE/authorization /organizations /:organizationId /roles /:slugParameters Returns Replace all permissions assigned to a custom role. This operation removes any existing permissions and assigns the provided permissions.
To remove all permissions from a role, pass an empty array.
curl --request PUT \ --url "https://api.workos.com/authorization/organizations/org_01EHZNVPK3SFK441A1RGBFSHRT/roles/org-admin/permissions" \ --header "Authorization: Bearer sk_example_123456789" \ --header "Content-Type: application/json" \ -d @- <<'BODY' { "permissions": [ "billing:read", "billing:write", "invoices:manage", "reports:view" ] } BODY
{ "slug": "org-admin", "object": "role", "id": "role_01EHQMYV6MBK39QC5PZXHY59C3", "name": "Organization Admin", "description": "Can manage all resources", "type": "OrganizationRole", "resource_type_slug": "organization", "permissions": [ "billing:read", "billing:write", "invoices:manage", "reports:view" ], "created_at": "2026-01-15T12:00:00.000Z", "updated_at": "2026-01-15T12:00:00.000Z" }
| curl --request PUT \ | |
| --url "https://api.workos.com/authorization/organizations/org_01EHZNVPK3SFK441A1RGBFSHRT/roles/org-admin/permissions" \ | |
| --header "Authorization: Bearer sk_example_123456789" \ | |
| --header "Content-Type: application/json" \ | |
| -d @- <<'BODY' | |
| { | |
| "permissions": [ | |
| "billing:read", | |
| "billing:write", | |
| "invoices:manage", | |
| "reports:view" | |
| ] | |
| } | |
| BODY |
| import { WorkOS } from '@workos-inc/node'; | |
| const workos = new WorkOS('sk_example_123456789'); | |
| const role = await workos.authorization.setOrganizationRolePermissions( | |
| 'org_01EHZNVPK3SFK441A1RGBFSHRT', | |
| 'org-billing-admin', | |
| { | |
| permissions: [ | |
| 'billing:read', | |
| 'billing:write', | |
| 'invoices:manage', | |
| 'reports:view', | |
| ], | |
| }, | |
| ); |
| from workos import WorkOSClient | |
| workos_client = WorkOSClient( | |
| api_key="sk_example_123456789", client_id="client_123456789" | |
| ) | |
| role = workos_client.authorization.set_organization_role_permissions( | |
| organization_id="org_01EHZNVPK3SFK441A1RGBFSHRT", | |
| slug="org-billing-admin", | |
| permissions=["billing:read", "billing:write", "invoices:manage", "reports:view"], | |
| ) |
| { | |
| "slug": "org-admin", | |
| "object": "role", | |
| "id": "role_01EHQMYV6MBK39QC5PZXHY59C3", | |
| "name": "Organization Admin", | |
| "description": "Can manage all resources", | |
| "type": "OrganizationRole", | |
| "resource_type_slug": "organization", | |
| "permissions": [ | |
| "billing:read", | |
| "billing:write", | |
| "invoices:manage", | |
| "reports:view" | |
| ], | |
| "created_at": "2026-01-15T12:00:00.000Z", | |
| "updated_at": "2026-01-15T12:00:00.000Z" | |
| } |
PUT/authorization /organizations /:organizationId /roles /:slug /permissionsParameters Returns Add a single permission to a custom role. If the permission is already assigned to the role, this operation has no effect.
curl --request POST \ --url "https://api.workos.com/authorization/organizations/org_01EHZNVPK3SFK441A1RGBFSHRT/roles/org-admin/permissions" \ --header "Authorization: Bearer sk_example_123456789" \ --header "Content-Type: application/json" \ -d @- <<'BODY' { "slug": "reports:export" } BODY
{ "slug": "org-admin", "object": "role", "id": "role_01EHQMYV6MBK39QC5PZXHY59C3", "name": "Organization Admin", "description": "Can manage all resources", "type": "OrganizationRole", "resource_type_slug": "organization", "permissions": [ "reports:export" ], "created_at": "2026-01-15T12:00:00.000Z", "updated_at": "2026-01-15T12:00:00.000Z" }
| curl --request POST \ | |
| --url "https://api.workos.com/authorization/organizations/org_01EHZNVPK3SFK441A1RGBFSHRT/roles/org-admin/permissions" \ | |
| --header "Authorization: Bearer sk_example_123456789" \ | |
| --header "Content-Type: application/json" \ | |
| -d @- <<'BODY' | |
| { | |
| "slug": "reports:export" | |
| } | |
| BODY |
| import { WorkOS } from '@workos-inc/node'; | |
| const workos = new WorkOS('sk_example_123456789'); | |
| const role = await workos.authorization.addOrganizationRolePermission( | |
| 'org_01EHZNVPK3SFK441A1RGBFSHRT', | |
| 'org-billing-admin', | |
| { permissionSlug: 'reports:export' }, | |
| ); |
| from workos import WorkOSClient | |
| workos_client = WorkOSClient( | |
| api_key="sk_example_123456789", client_id="client_123456789" | |
| ) | |
| role = workos_client.authorization.add_organization_role_permission( | |
| organization_id="org_01EHZNVPK3SFK441A1RGBFSHRT", | |
| slug="org-billing-admin", | |
| permission_slug="reports:export", | |
| ) |
| { | |
| "slug": "org-admin", | |
| "object": "role", | |
| "id": "role_01EHQMYV6MBK39QC5PZXHY59C3", | |
| "name": "Organization Admin", | |
| "description": "Can manage all resources", | |
| "type": "OrganizationRole", | |
| "resource_type_slug": "organization", | |
| "permissions": [ | |
| "reports:export" | |
| ], | |
| "created_at": "2026-01-15T12:00:00.000Z", | |
| "updated_at": "2026-01-15T12:00:00.000Z" | |
| } |
POST/authorization /organizations /:organizationId /roles /:slug /permissionsParameters Returns Remove a single permission from a custom role by its slug.
curl --request DELETE \ --url "https://api.workos.com/authorization/organizations/org_01EHZNVPK3SFK441A1RGBFSHRT/roles/org-admin/permissions/documents:read" \ --header "Authorization: Bearer sk_example_123456789"
{ "slug": "admin", "object": "role", "id": "role_01EHQMYV6MBK39QC5PZXHY59C3", "name": "Admin", "description": "Can manage all resources", "type": "EnvironmentRole", "resource_type_slug": "organization", "permissions": [ "posts:read", "posts:write" ], "created_at": "2026-01-15T12:00:00.000Z", "updated_at": "2026-01-15T12:00:00.000Z" }
| curl --request DELETE \ | |
| --url "https://api.workos.com/authorization/organizations/org_01EHZNVPK3SFK441A1RGBFSHRT/roles/org-admin/permissions/documents:read" \ | |
| --header "Authorization: Bearer sk_example_123456789" |
| import { WorkOS } from '@workos-inc/node'; | |
| const workos = new WorkOS('sk_example_123456789'); | |
| const role = await workos.authorization.removeOrganizationRolePermission( | |
| 'org_01EHZNVPK3SFK441A1RGBFSHRT', | |
| 'org-billing-admin', | |
| 'reports:export', | |
| ); |
| from workos import WorkOSClient | |
| workos_client = WorkOSClient( | |
| api_key="sk_example_123456789", client_id="client_123456789" | |
| ) | |
| role = workos_client.authorization.remove_organization_role_permission( | |
| organization_id="org_01EHZNVPK3SFK441A1RGBFSHRT", | |
| slug="org-billing-admin", | |
| permission_slug="reports:export", | |
| ) |
| { | |
| "slug": "admin", | |
| "object": "role", | |
| "id": "role_01EHQMYV6MBK39QC5PZXHY59C3", | |
| "name": "Admin", | |
| "description": "Can manage all resources", | |
| "type": "EnvironmentRole", | |
| "resource_type_slug": "organization", | |
| "permissions": [ | |
| "posts:read", | |
| "posts:write" | |
| ], | |
| "created_at": "2026-01-15T12:00:00.000Z", | |
| "updated_at": "2026-01-15T12:00:00.000Z" | |
| } |
DELETE/authorization /organizations /:organizationId /roles /:slug /permissions /:permissionSlugParameters Returns