Skip to content

Roles and permissions

A permission grants a member one ability in a guild, such as sending a message or banning another member. A role holds a set of permissions as an unsigned 64-bit mask, and a permission overwrite stored on a channel adjusts that set for that channel.

The role routes on this page accept a user session token or a bot token. List guild roles also accepts an OAuth2 access token with the guilds scope; the other role routes answer a valid access token with 403 ACCESS_DENIED. A caller that is not a member of the guild receives 403 FORBIDDEN. Every route that changes roles requires MANAGE_ROLES, checked before the role is read.

Permissions

Every bit TEBHOS defines appears below.

Value Decimal Name Description
1 << 0 1 CREATE_INSTANT_INVITE Create an invite to a guild channel
1 << 1 2 KICK_MEMBERS Remove a member from the guild
1 << 2 4 BAN_MEMBERS Ban and unban members
1 << 3 8 ADMINISTRATOR Hold every permission and bypass every channel permission overwrite
1 << 4 16 MANAGE_CHANNELS Create, modify, reorder and delete guild channels
1 << 5 32 MANAGE_GUILD Modify guild settings and guild-level resources such as invites, the vanity URL and discovery
1 << 6 64 ADD_REACTIONS Add a new reaction to a message
1 << 7 128 VIEW_AUDIT_LOG Read the guild audit log
1 << 8 256 PRIORITY_SPEAKER Use priority speaker in a voice channel
1 << 9 512 STREAM Share the screen or camera in a voice channel
1 << 10 1024 VIEW_CHANNEL View a channel and read its messages
1 << 11 2048 SEND_MESSAGES Send messages in a channel
1 << 12 4096 SEND_TTS_MESSAGES Send text-to-speech messages
1 << 13 8192 MANAGE_MESSAGES Delete other members' messages, bulk delete, remove other members' reactions
1 << 14 16384 EMBED_LINKS Have links in the caller's messages expanded into embeds
1 << 15 32768 ATTACH_FILES Attach files to messages
1 << 16 65536 READ_MESSAGE_HISTORY Read messages sent before the member could see the channel
1 << 17 131072 MENTION_EVERYONE Use the @everyone and @here mentions
1 << 18 262144 USE_EXTERNAL_EMOJIS Use emojis from other guilds
1 << 20 1048576 CONNECT Connect to a voice channel
1 << 21 2097152 SPEAK Speak in a voice channel
1 << 22 4194304 MUTE_MEMBERS Server-mute members in voice channels
1 << 23 8388608 DEAFEN_MEMBERS Server-deafen members in voice channels
1 << 24 16777216 MOVE_MEMBERS Move members between voice channels or disconnect them
1 << 25 33554432 USE_VAD Use voice activity detection instead of push-to-talk
1 << 26 67108864 CHANGE_NICKNAME Change the caller's own nickname
1 << 27 134217728 MANAGE_NICKNAMES Change other members' nicknames
1 << 28 268435456 MANAGE_ROLES Create, modify, reorder and delete roles, assign roles, and set channel permission overwrites
1 << 29 536870912 MANAGE_WEBHOOKS Create, modify and delete webhooks
1 << 30 1073741824 MANAGE_EXPRESSIONS Modify and delete emojis and stickers created by anyone
1 << 37 137438953472 USE_EXTERNAL_STICKERS Use stickers from other guilds
1 << 40 1099511627776 MODERATE_MEMBERS Time members out
1 << 43 8796093022208 CREATE_EXPRESSIONS Create emojis and stickers, and manage the ones the caller created
1 << 51 2251799813685248 PIN_MESSAGES Pin and unpin messages
1 << 52 4503599627370496 BYPASS_SLOWMODE Send messages without waiting for the channel slowmode
1 << 53 9007199254740992 UPDATE_RTC_REGION Change the voice region of a voice channel
1 << 54 18014398509481984 VIEW_CHANNEL_MEMBERS See the member list of a channel over the Gateway. Feature-gated on write

Bits 19, 31 through 36, 38, 39, 41, 42, 44 through 50, and 55 through 63 are unassigned. The union of every defined bit is 33787032395841535.

A new guild's @everyone role starts with CREATE_INSTANT_INVITE, ADD_REACTIONS, STREAM, VIEW_CHANNEL, SEND_MESSAGES, EMBED_LINKS, ATTACH_FILES, READ_MESSAGE_HISTORY, USE_EXTERNAL_EMOJIS, CONNECT, SPEAK, USE_VAD, CHANGE_NICKNAME, USE_EXTERNAL_STICKERS and VIEW_CHANNEL_MEMBERS, which is 18014536052624961.

Permission masks are decimal strings on the wire

Every permission field in a response is the decimal form of an unsigned 64-bit integer inside a JSON string, such as "permissions": "1099511639046". A request field accepts a decimal string or a non-negative JSON integer. Parse and combine masks with 64-bit integer arithmetic (BigInt in JavaScript); a JSON double cannot hold the high bits exactly.

TEBHOS discards bits it does not define. A role or overwrite write keeps only defined bits, and a response never contains an unassigned bit.

const Permissions = {
  VIEW_CHANNEL: 1n << 10n,
  SEND_MESSAGES: 1n << 11n,
  MANAGE_MESSAGES: 1n << 13n,
  ADMINISTRATOR: 1n << 3n,
};

function has(mask, flag) {
  const bits = BigInt(mask);
  return (bits & Permissions.ADMINISTRATOR) !== 0n || (bits & flag) === flag;
}

has("3072", Permissions.SEND_MESSAGES); // true
VIEW_CHANNEL = 1 << 10
SEND_MESSAGES = 1 << 11
ADMINISTRATOR = 1 << 3

def has(mask: str, flag: int) -> bool:
    bits = int(mask)
    return bool(bits & ADMINISTRATOR) or (bits & flag) == flag

has("3072", SEND_MESSAGES)  # True

Feature-gated permission bits

VIEW_CHANNEL_MEMBERS is gated on a client feature declaration. A client that understands the bit declares it in the X-Tebhos-Features request header, as a comma-separated list containing view_channel_members_permission.

On Modify guild role, a request that does not declare the feature keeps the role's stored VIEW_CHANNEL_MEMBERS value, so it can neither set nor clear that bit. Every other bit in the mask is written normally. This protects the bit from older clients that do not know it exists.

Permission computation

TEBHOS computes one effective mask for a member in a guild, and optionally in one channel. The Gateway uses the same algorithm, so REST checks and event delivery agree.

  1. The guild owner receives every defined permission.
  2. A user who is not a member receives an empty mask.
  3. Otherwise the base is the union of the @everyone role's permissions and the permissions of every role assigned to the member.
  4. If the base contains ADMINISTRATOR, the member receives every defined permission and no overwrite is applied.
  5. If a channel was named, that channel's own permission overwrites are applied in this order:
    1. The @everyone role overwrite: its denied bits are removed, then its allowed bits added.
    2. The overwrites of every role the member holds, combined into one union of allowed bits and one union of denied bits, applied as a single step (deny removed, then allow added). An allow on one of the member's roles therefore beats a deny on another.
    3. The member's own overwrite, deny first and then allow.

A channel's result depends only on that channel's own overwrites. A category's overwrites are not inherited at check time; they are copied to a channel when it is created in the category or synced with it.

ADMINISTRATOR grants every bit and skips overwrites

No deny overwrite restricts a member who holds ADMINISTRATOR. Removing the bit from every role the member holds is the only way to restrict them.

A channel is visible to a member when its channel-level mask contains VIEW_CHANNEL. A channel-scoped request returns 404 when the channel does not exist or belongs to a guild the caller is not in, and 403 when the caller is a member but lacks VIEW_CHANNEL or the specific bit the operation needs.

Private channels (DMs and group DMs) do not use permission bits. Their recipients can do everything a channel allows.

Communication timeout

A timeout (communication_disabled_until in the future on a guild member) stops a member from communicating in the guild until it expires. It does not change the computed mask: the member keeps every permission their roles grant, and TEBHOS checks the timeout separately.

While a timeout is active, these operations fail with 403 FORBIDDEN:

  • Sending a message
  • Adding a reaction
  • Requesting an attachment upload
  • Triggering the typing indicator
  • Changing the member's own nickname
  • Joining a voice channel

A timeout has no effect in private channels. A client that hides actions based on the mask must also compare communication_disabled_until with the current time, because the mask still contains SEND_MESSAGES for a timed-out member. Applying a timeout requires MODERATE_MEMBERS.

Role hierarchy

Roles are ranked by position, the highest position first. Two roles with the same position are ranked by ID, and the lower ID ranks first. A member's rank is the rank of their highest role other than @everyone, and a member with no roles ranks below every role.

  • A caller manages a role only when the caller's highest role ranks strictly above it. The guild owner manages every role.
  • A caller acts on another member (kick, ban, timeout, nickname, voice moderation) only when the caller's rank is strictly above the target's. The owner can act on anyone and nobody can act on the owner.
  • ADMINISTRATOR bypasses permission checks but not the hierarchy.
  • A caller whose only MANAGE_ROLES comes from @everyone holds no ranked role and so manages no role.

A caller who holds MANAGE_ROLES but does not outrank the target role receives 403 FORBIDDEN.

A non-owner cannot grant a permission they lack

When a non-owner sets a role's permissions, the whole requested mask must be a subset of the caller's own effective guild permissions. Otherwise the request fails with 403 FORBIDDEN. Removing a bit the caller does not hold is allowed. The same rule applies to channel overwrites: every bit an overwrite allows, and every bit it stops denying, must be one the caller holds in that channel.

Guild role object

Field Type Description
id snowflake The role ID. The @everyone role has the guild's ID
name string The role name, 1-100 characters
color integer The role colour as an RGB integer from 0 through 16777215; 0 means no colour
position integer The rank in the hierarchy; a larger value ranks higher. @everyone is always 0
hoist_position ?integer The position among separately displayed member list groups, or null to order by position
permissions string The permission mask as a decimal string
hoist boolean Whether members with the role are displayed as their own member list group
mentionable boolean Whether any member can mention the role
unicode_emoji ?string A Unicode emoji shown next to the role name

The @everyone role is named @everyone. It defines the base permissions for every member. It cannot be deleted, reordered or given a hoist position, and its name, hoist and mentionable cannot be changed. Its colour and permissions can be changed.

{
  "id": "1489002177550843904",
  "name": "Moderator",
  "color": 3447003,
  "position": 4,
  "hoist_position": 1,
  "permissions": "1099511639046",
  "hoist": true,
  "mentionable": false,
  "unicode_emoji": null
}

Permission overwrite object

A channel stores its overwrites in permission_overwrites. Channels documents the operations that set and delete them.

Field Type Description
id snowflake The role ID (for type 0) or user ID (for type 1) the overwrite targets
type integer 0 for a role, 1 for a member
allow string Permission bits the overwrite grants, as a decimal string
deny string Permission bits the overwrite removes, as a decimal string

The same bit cannot be both allowed and denied in one overwrite; such a request fails with 400 BAD_REQUEST. Bits are not filtered by channel type, so an overwrite can name a permission its channel does not use.

{
  "id": "1489002177550843904",
  "type": 0,
  "allow": "0",
  "deny": "2048"
}

Role position object

Field Type Description
id snowflake The role ID
position? integer The requested position; a larger value ranks higher

Role hoist position object

Field Type Description
id snowflake The role ID
hoist_position integer The member list position to give the role

List guild roles

GET /guilds/{guild_id}/roles

Returns every guild role object in the guild, sorted by descending position. The caller must be a member of the guild; no permission is required.

Also accepts an OAuth2 access token with the guilds scope; a token without it receives 403 MISSING_OAUTH_SCOPE.

Rate limit: guild:role:list, 60 per 10 seconds per account and guild.

curl https://tebhos.com/api/v1/guilds/1489002177550843904/roles \
  -H "Authorization: Bot $TEBHOS_BOT_TOKEN"

Create guild role

POST /guilds/{guild_id}/roles

Creates a role and returns the new guild role object. Requires MANAGE_ROLES. The new role is placed at position 1, directly above @everyone. A guild can have at most 250 roles; creating more returns 400 BAD_REQUEST.

Rate limit: guild:role:create, 10 per 60 seconds per account and guild.

Field Type Description
name string The role name, 1-100 characters after trimming
color? ?integer The colour, 0 through 16777215. Defaults to 0
permissions? string or integer The permission mask. Defaults to the @everyone role's permissions. Subject to the grant rule

The Gateway dispatches GUILD_ROLE_CREATE to the guild.

curl -X POST https://tebhos.com/api/v1/guilds/1489002177550843904/roles \
  -H "Authorization: Bot $TEBHOS_BOT_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"name": "Helpers", "color": 3447003, "permissions": "8192"}'

Modify guild role

PATCH /guilds/{guild_id}/roles/{role_id}

Updates a role and returns the updated guild role object. Requires MANAGE_ROLES and a rank above the role. A role that does not exist returns 404 NOT_FOUND.

Rate limit: guild:role:update, 20 per 10 seconds per account and guild.

Field Type Description
name? string The role name, 1-100 characters
color? integer The colour, 0 through 16777215
permissions? string or integer The permission mask. Subject to the grant rule and the feature gate
hoist? boolean Whether to display the role separately
hoist_position? ?integer The member list position; null clears it
mentionable? boolean Whether the role can be mentioned by anyone

For @everyone, name, hoist, hoist_position and mentionable are ignored. The Gateway dispatches GUILD_ROLE_UPDATE.

Modify guild role positions

PATCH /guilds/{guild_id}/roles

Reorders roles. The body is a JSON array of role position objects. Requires MANAGE_ROLES. Returns 204 with no body.

Rate limit: guild:role:positions, 20 per 10 seconds per account and guild.

A non-owner can move only roles below their own highest role, and those roles only exchange places among themselves; roles the caller cannot manage stay where they are. After the change, positions are renumbered so that the roles above @everyone run from 1 to the number of roles.

Error Cause
400 BAD_REQUEST An entry names @everyone or a role that is not in the guild
403 FORBIDDEN An entry changes the position of a role the caller cannot manage

The Gateway dispatches GUILD_ROLE_UPDATE_BULK with every role.

curl -X PATCH https://tebhos.com/api/v1/guilds/1489002177550843904/roles \
  -H "Authorization: Bot $TEBHOS_BOT_TOKEN" \
  -H "Content-Type: application/json" \
  -d '[{"id": "1489002177550843905", "position": 3}, {"id": "1489002177550843906", "position": 2}]'

Modify role hoist positions

PATCH /guilds/{guild_id}/roles/hoist-positions

Sets the member list order of hoisted roles. The body is a JSON array of role hoist position objects. Requires MANAGE_ROLES, and a non-owner must outrank every role in the array. Returns 204.

Rate limit: guild:role:hoist_positions, 20 per 10 seconds per account and guild.

An entry that names @everyone or an unknown role returns 400 BAD_REQUEST; a role the caller cannot manage returns 403 FORBIDDEN. Nothing is written unless every entry is valid. The Gateway dispatches GUILD_ROLE_UPDATE_BULK.

Reset role hoist positions

DELETE /guilds/{guild_id}/roles/hoist-positions

Clears hoist_position on every role, so hoisted roles are ordered by position again. Requires MANAGE_ROLES. Returns 204.

Rate limit: guild:role:hoist_positions_reset, 10 per 60 seconds per account and guild.

Delete guild role

DELETE /guilds/{guild_id}/roles/{role_id}

Deletes a role and removes it from every member that held it. Requires MANAGE_ROLES and a rank above the role. Returns 204.

Rate limit: guild:role:delete, 10 per 60 seconds per account and guild.

A role that does not exist, and the @everyone role, return 404 NOT_FOUND. The deletion is recorded in the audit log.

Assigning roles

Adding a role to a member and removing it use PUT and DELETE /guilds/{guild_id}/members/{user_id}/roles/{role_id}, documented in Guild members. Both require MANAGE_ROLES and a rank above the role.