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
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.
- The guild owner receives every defined permission.
- A user who is not a member receives an empty mask.
- Otherwise the base is the union of the
@everyonerole's permissions and the permissions of every role assigned to the member. - If the base contains
ADMINISTRATOR, the member receives every defined permission and no overwrite is applied. - If a channel was named, that channel's own permission overwrites are applied in this order:
- The
@everyonerole overwrite: its denied bits are removed, then its allowed bits added. - 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.
- The member's own overwrite, deny first and then allow.
- The
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.
ADMINISTRATORbypasses permission checks but not the hierarchy.- A caller whose only
MANAGE_ROLEScomes from@everyoneholds 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.
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.