My bot got a 403 error, even though it never happened before, and the code hasn’t changed at all.
throw new DiscordAPIError(data, res.status, request); ^ DiscordAPIError: Bots cannot use this endpoint --- { method: 'put', path: '/applications/---/guilds/---/commands/---/permissions', code: 20001, httpStatus: 403, requestData: { json: { permissions: [Array] }, files: [] } }
Trying to set fullPermissions
gives me a 405 Error instead
DiscordAPIError: 405: Method Not Allowed --- { method: 'put', path: '/applications/---/guilds/---/commands/permissions', code: 0, httpStatus: 405, requestData: { json: [ [Object], [Object], [Object], [Object], [Object], [Object], [Object], [Object], [Object], [Object], [Object], [Object], [Object], [Object], [Object], [Object], [Object], [Object], [Object], [Object], [Object], [Object] ], files: [] } }
The paths /applications/{applicationId}/guilds/{guildId}/commands/{commandId}/permissions
and /applications/{applicationId}/guilds/{guildId}/commands/permissions
worked perfectly fine before, why wouldn’t they work now?
Advertisement
Answer
Discord has released Permissions V2 to all guilds yesterday (April 27, 2022). Bots can no longer control the permissions, only server administrators can. It’s better to put simple permission/role/user checks in the code instead if you want to restrict it, and remove the code that would be setting the command permissions.
// only run for specific user if (interaction.user.id !== "userId") return; // only run for specific role if (!interaction.member.roles.cache.has("roleId")) return; // only run for specific permission if (!interaction.member.permissions.has("BAN_MEMBERS")) return; // You can use any permission flag of course
Admins can set it by going to Server Settings --> Integerations
, but you are able to programmatically edit the command permissions using a Bearer Token with a scope called applications.commands.permissions.update
, which you can get from a URL like this
https://discord.com/api/oauth2/authorize?client_id=CLIENT_ID&redirect_uri=REDIRECT_URI&response_type=token&scope=applications.commands.permissions.update
And you will get redirected to what you set the redirect_uri
as, with URL parameters. You can copy the access_token
part
PUT COMMAND PERMISSIONS
const applicationId = "APPLICATION_ID" const guildId = "GUILD_ID" const commandId = "COMMAND_ID" // Set this as your application ID to set default permissions const url = `https://discord.com/api/v9/applications/${applicationId}/guilds/${guildId}/commands/${commandId}/permissions` // requires the user that the bearer token belongs to have used applications.commands.permissions.update scope and have manage guild/roles permission const token = "Bearer {token}" // replace {token} with what you copied from access_token const payload = { permissions: [ { id: "ID", // role/user/channel ID type: 1, // 1 for role, 2 for user, and 3 for channel permission: false // whether or not that role/user can use the command or you can use the command in the channel } ] } await fetch(url, { method: "PUT", body: JSON.stringify(payload), headers: { Authorization: `${token}`, Accept: 'application/json', 'Content-Type': 'application/json' }, })
GET COMMAND PERMISSIONS
const applicationId = "APPLICATION_ID" const guildId = "GUILD_ID" const commandId = "COMMAND_ID" // Set this as your application ID to get default permissions const url = `https://discord.com/api/v9/applications/${applicationId}/guilds/${guildId}/commands/${commandId}/permissions` const token = "Bearer {token}" await fetch(url, { method: "GET", headers: { Authorization: `${token}`, Accept: 'application/json', 'Content-Type': 'application/json' }, })
GET ALL COMMAND PERMISSIONS
const applicationId = "APPLICATION_ID" const guildId = "GUILD_ID" const url = `https://discord.com/api/v9/applications/${applicationId}/guilds/${guildId}/commands/permissions` const token = "Bearer {token}" await fetch(url, { method: "GET", headers: { Authorization: `${token}`, Accept: 'application/json', 'Content-Type': 'application/json' }, })