Skip to content
Advertisement

403 Error when setting application command permissions on Discord

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'
    },
  })
User contributions licensed under: CC BY-SA
7 People found this is helpful
Advertisement