Create a role
create_workspace_role
Creates a custom role in a workspace with a chosen set of permissions.
Roles are how a workspace gives people less than full access. Every custom role grants workspace.access whether you list it or not, and api.access is what lets a member use an access token at all, from an MCP client or the HTTP API. Every permission explains what each one allows.
Deleting the workspace and managing billing belong to the owner alone, so workspace.delete and billing.manage are not among the values the tool accepts. A role with no permissions is refused. The answer is the new role, with the _id that assign_member_role and the roles of invite_workspace_member take.
It needs the Manage roles permission (roles.manage) and the workspace on Pro or Enterprise, otherwise it is refused with You must upgrade to the Pro plan to manage roles! A workspace holds up to 10 custom roles, and past that the call is refused with You can create up to 10 roles per workspace! See Members and roles.
Request
Call it with a POST to https://api.modulify.ai/v1/create_workspace_role, sending the inputs below as a JSON object. The token needs the workspaces:write scope.
It makes changes, so send an Idempotency-Key header whenever you might retry it. A retry with the same key gets the first answer back instead of running again.
curl -X POST https://api.modulify.ai/v1/create_workspace_role \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{"workspaceId":"WORKSPACE_ID","name":"NAME","permissions":[]}'Over MCP, the same method is the create_workspace_role tool.
Inputs
| Input | Type | Required | Description |
|---|---|---|---|
workspaceId |
string | Yes | The workspace id. |
name |
string | Yes | What to call the role, 2 to 32 characters. |
permissions |
array of strings | Yes | The permissions it grants, at least one of workspace.access, workspace.update, members.manage, roles.manage, projects.delete, projects.transfer, projects.move, projects.domains, folders.edit, folders.delete, folders.move and api.access. |
Response
Every call answers with the JSON envelope of success, message, data, code and version. data holds the result described above, and on a method that returns a total, count carries it. The response headers carry the call's X-Request-Id and what is left of your per-minute budget in X-RateLimit-Limit, X-RateLimit-Remaining and X-RateLimit-Reset. Errors explains every status code a call can answer with.