Create an organization's own role
/api/v1/organizations/{id}/rolesCreates a role the organization owns, with its permissions, held only at the organization node or beneath it. The name is unique within the organization and may not repeat one of the Environment's roles (409 role.name_taken). An identity may give only permissions it holds at the organization node (403 organization.role_permission_not_held, with the keys in data). An organization owns at most 50 roles (409 organization.role_limit). copy_from_role_id records the role it was copied from. Requires rbac.manage_roles or the organization's roles delegation.
Authentication
Authorization Option A JWT access token. Never send alongside X-API-Key: a request carrying both is refused.
X-API-Key Option B API key for management-tier access. Never send alongside an Authorization header: a request carrying both is refused.
Path Parameters
idstring Required Request body
application/json
namestring Required Unique within the organization, and not the name of one of the Environment's roles
descriptionobject Optional permission_keysstring[] Required The permission keys the role carries. A caller signed in as an identity may give only keys it holds at the organization node
copy_from_role_idstring Optional The role this one was copied from, recorded for provenance: one of the Environment's or the organization's own. The permissions are the ones sent in `permission_keys`
Responses
application/json
data *RoleResponseDto
application/json
error *ApiErrorBodyDto
application/json
error *ApiErrorBodyDto
application/json
error *ApiErrorBodyDto
application/json
error *ApiErrorBodyDto
application/json
error *ApiErrorBodyDto
Errors
When the request can't be completed, the response body includes a stable error code you can branch on, and a correlation_id (also sent as the X-Correlation-Id header). Quote the correlation id when you contact support: it identifies the exact request in Canopy's logs.
organization.role_permission_not_heldForbiddenThe role would carry a permission the editor does not hold at the organization node. <code>data.permission_keys</code> names each one. A permission the role already carries may stay; only one being added must be held.
Leave those permissions out, or ask someone who holds them, or the developer, to add them.
role.name_takenConflictAnother role in the same tier already has this name (the Environment's roles, or the same organization's own), or an organization's role was given the name of one of the Environment's.
Choose another name, or rename the role that holds it.
organization.role_limitConflictThe organization already owns 50 roles of its own, the most one organization may have. The Environment's roles do not count.
Delete a role the organization no longer uses, then create the new one.
Returned object
curl -X POST "https://auth.canopy-io.com/api/v1/organizations/value/roles" \ -H "X-API-Key: $CANOPY_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "name": "string", "description": {}, "permission_keys": [ "string" ], "copy_from_role_id": "string" }'
{ "data": { "id": "string", "name": "string", "scope": "environment", "organization_node_id": "string", "organization_name": "string", "template_id": "string", "description": "string", "is_system_role": false, "system_key": "string", "is_active": false, "created_at": "2026-04-20T12:00:00.000Z", "updated_at": "2026-04-20T12:00:00.000Z", "version": 0, "permission_count": 0, "member_count": 0, "administers": false } }
Tell us how we can improve this guide.