Custom Roles

List, create, update, and delete custom project roles with granular permission and field-level access control.


Custom roles let you define precise permission sets for members of a workspace, beyond the built-in access levels. A role controls which sections a member sees (records, files, chat, docs, …), what they can do (invite, complete, delete), and—optionally—which records, lists, and fields they can view or edit. Roles are ProjectUserRole objects in the API; workspaces are Workspace objects.

You assign a role when you invite someone by passing its roleId with accessLevel: MEMBER. The role must belong to the same workspace as the invite.

This page covers four operations:

  • workspaceUserRoles — list the roles in one or more workspaces.
  • createWorkspaceUserRole — create a role.
  • updateWorkspaceUserRole — change a role.
  • deleteWorkspaceUserRole — delete a role.

Request

Send every request to https://api.blue.app/graphql with your authentication headers. Custom roles are scoped to a workspace, so pass the workspace ID (or slug) in the operation input. Company and project arguments accept either an ID or a slug.

POST https://api.blue.app/graphql
blue-token-id: YOUR_TOKEN_ID
blue-token-secret: YOUR_TOKEN_SECRET
blue-org-id: YOUR_ORG_ID

List the roles in a workspace. The filter argument is required; supply projectId for a single workspace.

query ListProjectRoles {
  workspaceUserRoles(filter: { projectId: "project_123" }) {
    id
    name
    description
    allowInviteOthers
    canDeleteRecords
    isRecordsEnabled
  }
}

To query several workspaces at once, pass projectIds instead. Either field may be null, but you must pass the filter object itself. Roles are only returned for workspaces the calling user belongs to.

query ListRolesAcrossWorkspaces {
  workspaceUserRoles(filter: { projectIds: ["project_123", "project_456"] }) {
    id
    name
    project {
      id
      name
    }
  }
}

Parameters

ProjectUserRoleFilter

The required filter argument for workspaceUserRoles.

ParameterTypeRequiredDescription
projectIdStringNoSingle workspace ID or slug. Takes precedence over projectIds when set.
projectIds[String]NoMultiple workspace IDs or slugs, for a cross-workspace listing.

CreateProjectUserRoleInput

The input for createWorkspaceUserRole. Only projectId and name are required; every other field is optional and falls back to the default shown.

ParameterTypeRequiredDefaultDescription
projectIdString!YesWorkspace the role belongs to (ID or slug).
nameString!YesDisplay name of the role.
descriptionStringNonullOptional description.
Action permissions
allowInviteOthersBooleanNofalseMay invite new users to the workspace.
allowMarkRecordsAsDoneBooleanNofalseMay mark records complete.
canCreateRecordsBooleanNotrueMay create records.
canDeleteRecordsBooleanNotrueMay delete records.
canDeleteFilesBooleanNotrueMay delete files.
canCreateListsBooleanNotrueMay create lists.
canEditListsBooleanNotrueMay rename and reorder lists.
Section access
isRecordsEnabledBooleanNofalseAccess to the records views.
isActivityEnabledBooleanNofalseAccess to the activity feed.
isChatEnabledBooleanNofalseAccess to chat.
isDocsEnabledBooleanNofalseAccess to docs.
isFilesEnabledBooleanNofalseAccess to files.
isFormsEnabledBooleanNofalseAccess to forms.
isWikiEnabledBooleanNofalseAccess to the wiki.
isPeopleEnabledBooleanNofalseAccess to the people/members section.
Visibility filters
showOnlyAssignedTodosBooleanNofalseMembers see only records assigned to them.
showOnlyMentionedCommentsBooleanNofalseMembers see only comments that mention them.
Field-level scoping
recordTagFilterRecordTagFilterInputNodisabledRestrict visible records by tag (allow/deny lists).
recordFilterRecordFilterInputNononeRestrict visible records to those matching a filter.
customFields[CreateProjectUserRoleCustomFieldInput!]NononePer–custom-field view/edit access.
todoLists[CreateProjectUserRoleTodoListInput!]NononePer-list view/edit/delete access.
todoFields[CreateProjectUserRoleTodoFieldInput!]NononePer built-in record field (assignee, due date, …) view/edit access.
Section access defaults to off

Every is*Enabled flag defaults to false. A role created with only projectId and name grants no section access — members assigned to it see nothing until you enable at least one section. The can* permissions, by contrast, default to true. Set the flags you care about explicitly rather than relying on the mixed defaults.

RecordTagFilterInput

Limit which records a role can see based on their tags. Tags are Tag objects (Tag.title in the API).

ParameterTypeRequiredDescription
enabledBooleanNoTurn tag-based filtering on for the role.
allowedTagIds[String!]NoOnly records carrying one of these tags are visible.
deniedTagIds[String!]NoRecords carrying one of these tags are hidden.

RecordFilterInput

Restrict visible records to those matching a filter, using the same group structure as record queries.

ParameterTypeRequiredDescription
groups[TodoFilterGroupInput!]!YesOne or more filter groups; a record is visible if it matches.
groupLinks[FilterLogicalOperator!]NoAND / OR operators joining the groups. Defaults to an empty list.

CreateProjectUserRoleCustomFieldInput

Per-field access for a custom field (CustomField).

ParameterTypeRequiredDefaultDescription
customFieldIdString!YesThe custom field to scope.
viewableBooleanNotrueMembers can read the field’s value.
editableBooleanNofalseMembers can change the field’s value.

CreateProjectUserRoleTodoListInput

Per-list access for a list (RecordList).

ParameterTypeRequiredDescription
todoListIdString!YesThe list to scope.
viewableBoolean!YesMembers can see the list.
editableBoolean!YesMembers can edit records in the list.
deletableBoolean!YesMembers can delete records in the list.

CreateProjectUserRoleTodoFieldInput

Per-field access for a built-in record field.

ParameterTypeRequiredDefaultDescription
fieldTypeTodoFieldType!YesWhich built-in field (see enum below).
viewableBoolean!YesMembers can read the field.
editableBoolean!YesMembers can edit the field.

TodoFieldType values: DUE_DATE, ASSIGNEE, TAG, DEPENDENCY, CUSTOM_FIELD, DESCRIPTION, CHECKLIST, REFERENCED_BY, CUSTOM_FIELD_GROUP, TIME_TRACKING, CREATED_DATE, UPDATED_DATE, COMPLETED_DATE, PROJECTS, LAST_UPDATED_BY.

UpdateProjectUserRoleInput

The input for updateWorkspaceUserRole. Same fields as CreateProjectUserRoleInput, with two differences:

  • roleId: String! (required) — the role to update.
  • projectId: String! (required) — the workspace the role belongs to, unchanged.
  • name is optional here (String, not String!); omit it to keep the current name.

Any flag you omit keeps its existing value (the update merges over the stored role rather than resetting to defaults).

DeleteProjectUserRoleInput

ParameterTypeRequiredDescription
roleIdString!YesThe role to delete.
projectIdString!YesThe workspace the role belongs to.

Response

workspaceUserRoles returns an array of ProjectUserRole objects.

{
  "data": {
    "workspaceUserRoles": [
      {
        "id": "clm4n8qwx000008l0g4oxdqn7",
        "name": "External Contractor",
        "description": "Limited access for outside collaborators",
        "allowInviteOthers": false,
        "canDeleteRecords": false,
        "isRecordsEnabled": true
      }
    ]
  }
}

createWorkspaceUserRole and updateWorkspaceUserRole both return the ProjectUserRole.

{
  "data": {
    "createWorkspaceUserRole": {
      "id": "clm4n8qwx000008l0g4oxdqn7",
      "name": "External Contractor"
    }
  }
}

deleteWorkspaceUserRole returns a nullable Booleantrue on success.

{ "data": { "deleteWorkspaceUserRole": true } }

Returns — ProjectUserRole

FieldTypeDescription
idID!Unique role identifier.
uidString!Stable public identifier.
nameString!Role name.
descriptionStringRole description.
createdAtDateTime!When the role was created.
updatedAtDateTimeWhen the role was last updated.
projectWorkspace!The workspace the role belongs to.
Action permissions
allowInviteOthersBooleanMay invite users.
allowMarkRecordsAsDoneBooleanMay complete records.
canCreateRecordsBooleanMay create records.
canDeleteRecordsBooleanMay delete records.
canDeleteFilesBooleanMay delete files.
canCreateListsBooleanMay create lists.
canEditListsBooleanMay edit lists.
Section access
isRecordsEnabledBooleanRecords access.
isActivityEnabledBooleanActivity access.
isChatEnabledBooleanChat access.
isDocsEnabledBooleanDocs access.
isFilesEnabledBooleanFiles access.
isFormsEnabledBooleanForms access.
isWikiEnabledBooleanWiki access.
isPeopleEnabledBooleanPeople section access.
Visibility filters
showOnlyAssignedTodosBooleanRestricts records to those assigned to the member.
showOnlyMentionedCommentsBooleanRestricts comments to those mentioning the member.
Field-level scoping
recordTagFilterRecordTagFilterTag-based record visibility (enabled, allowedTagIds, deniedTagIds).
recordFilterProjectUserRoleRecordFilterFilter-based record visibility (groups, groupLinks).
customFields[CustomField!]Custom fields scoped by the role.
todoLists[ProjectUserRoleTodoList!]Per-list access (viewable, editable, deletable).
todoFields[ProjectUserRoleTodoField!]!Per built-in field access (fieldType, viewable, editable).

Full example

Create a contractor role: enable the records and files sections, allow completing records but not deleting them, limit visibility to assigned records, and grant view-only access to one custom field.

mutation CreateContractorRole {
  createWorkspaceUserRole(
    input: {
      projectId: "project_123"
      name: "External Contractor"
      description: "Limited access for outside collaborators"
      isRecordsEnabled: true
      isFilesEnabled: true
      allowMarkRecordsAsDone: true
      canDeleteRecords: false
      canDeleteFiles: false
      showOnlyAssignedTodos: true
      customFields: [{ customFieldId: "field_123", viewable: true, editable: false }]
    }
  ) {
    id
    name
    isRecordsEnabled
    canDeleteRecords
  }
}

Restrict a role to records tagged tag_123 only:

mutation CreateScopedRole {
  createWorkspaceUserRole(
    input: {
      projectId: "project_123"
      name: "Client Reviewer"
      isRecordsEnabled: true
      recordTagFilter: { enabled: true, allowedTagIds: ["tag_123"] }
    }
  ) {
    id
    name
  }
}

Rename an existing role and turn off chat without touching its other settings:

mutation UpdateRole {
  updateWorkspaceUserRole(
    input: {
      roleId: "role_123"
      projectId: "project_123"
      name: "Contractor (Phase 2)"
      isChatEnabled: false
    }
  ) {
    id
    name
    isChatEnabled
  }
}

Delete a role:

mutation DeleteRole {
  deleteWorkspaceUserRole(input: { roleId: "role_123", projectId: "project_123" })
}

Assigning a role

A role is attached to a member at invite time. Set accessLevel: MEMBER and pass the role’s roleId to inviteUser. The role’s projectId must match the invite’s workspace, or the call fails with PROJECT_USER_ROLE_NOT_FOUND. Custom roles are treated as MEMBER-level for the access hierarchy.

mutation InviteWithRole {
  inviteUser(
    input: {
      email: "contractor@example.com"
      projectId: "project_123"
      accessLevel: MEMBER
      roleId: "role_123"
    }
  )
}

Errors

CodeWhen
FORBIDDENThe caller is not a workspace OWNER or ADMIN. Mutations require manage-roles access.
PROJECT_NOT_FOUNDThe projectId does not match a workspace.
PROJECT_USER_ROLE_NOT_FOUNDThe roleId does not exist, or belongs to a different workspace than projectId.
PLAN_LIMIT_REACHEDThe workspace has reached its custom-role limit. Message: Custom roles per workspace limit reached (current/limit). Upgrade your plan for more.

The custom-role limit is plan-dependent — roughly 1 on starter plans up to ~50 on enterprise, and unlimited on some plans. Upgrade the organization’s plan to raise it.

{
  "errors": [
    {
      "message": "Custom roles per workspace limit reached (1/1). Upgrade your plan for more.",
      "extensions": {
        "code": "PLAN_LIMIT_REACHED",
        "kind": "over_limit",
        "resource": "Custom roles per workspace",
        "current": 1,
        "limit": 1
      }
    }
  ]
}

Permissions

OperationRequired access
workspaceUserRolesAny member of the queried workspace (roles for workspaces you don’t belong to are silently excluded).
createWorkspaceUserRoleWorkspace OWNER or ADMIN.
updateWorkspaceUserRoleWorkspace OWNER or ADMIN.
deleteWorkspaceUserRoleWorkspace OWNER or ADMIN.