A reference guide for building AI agents: every method, how to authenticate, and the permissions each one needs.
The Discord API is how an app or AI agent works with a Discord server: posting messages to a channel, reading message history, managing channels and roles, and updating the members of a server. Access uses a bot token or an OAuth2 token, and Discord's permission system decides, channel by channel, what each call can read or write. A bot also receives activity in real time over a persistent connection, so it learns about new messages and members without polling.
How an app or AI agent connects to Discord determines what it can reach. There is a route for making calls, a route for receiving real-time events, and incoming webhooks for posting into a single channel, and each is governed by the token behind it and the permissions that token carries.
The REST API answers at https://discord.com/api/v10, and a request authenticates with the Authorization header carrying either a bot token (Bot
The Gateway is a persistent WebSocket connection that pushes events to a bot as they happen, like a message being posted or a member joining, so the bot does not poll. Which events arrive is set by the gateway intents the bot enables, and message content and guild members are privileged intents that must be granted.
An incoming webhook posts messages into one channel without a bot user. The webhook id and token in the URL are the only authorization, so a call needs no bot token and no permission once the webhook exists. Anyone holding the token can post to that channel.
Discord does not publish an official Model Context Protocol server as of June 2026. Several community-built MCP servers wrap the Discord API for AI agents, but none is operated or endorsed by Discord, so each carries the security and maintenance posture of its own author.
A bot token authenticates an application's bot user and is sent as 'Authorization: Bot
An OAuth2 bearer token acts on behalf of a user who authorized the app, and is sent as 'Authorization: Bearer
The bot OAuth2 scope adds a bot to a server the authorizing user picks. The install link carries a permissions value, a bitfield where each bit is one permission like SEND_MESSAGES or MANAGE_CHANNELS, that sets the bot's starting permissions in that server. The applications.commands scope, included with bot by default, lets the app register slash commands.
An incoming webhook has its own id and token, and that token alone authorizes posting a message into the webhook's channel. It is not a bot token and carries no other access, so it can post but cannot read or manage anything.
The Discord API is split into areas an agent can act on, like channels, messages, guild members, and roles. Each method needs the right permission in the channel or guild, and some, like managing roles or members, reach far more than posting a message.
Read a channel's details, modify its settings, and delete a channel or close a direct message.
List and read messages, post new ones, edit and delete them, bulk-delete, and add reactions.
Read a guild's details, modify its settings, and list or create the channels inside it.
List members, read a single member, modify a member, and add or remove a member's roles.
List the roles in a guild and create a new role.
Read the current user, read a user by id, modify the current user, list the user's guilds, and open a direct message.
List a channel's or guild's webhooks, create a webhook, read one, and execute a webhook to post a message.
List and create the global or guild slash commands an application registers, and bulk-overwrite the set.
Filter by method, access, or permission, or search any path. Select a row for version detail, rate limits, the related webhook event, and the source.
| Method | Endpoint | What it does | Access | Permission | Version | |
|---|---|---|---|---|---|---|
ChannelsRead a channel's details, modify its settings, and delete a channel or close a direct message.3 | ||||||
| GET | /channels/{channel.id} | Get a channel by id. | read | VIEW_CHANNEL | Current | |
Requires a bot token. The bot must be able to see the channel, which the VIEW_CHANNEL permission controls. Acts onchannel Permission (capability) VIEW_CHANNELVersionAvailable since the API’s base version Webhook eventNone Rate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
| PATCH | /channels/{channel.id} | Modify a channel's settings, such as its name, topic, or permission overwrites. | write | MANAGE_CHANNELS | Current | |
Requires MANAGE_CHANNELS for a guild channel; editing permission overwrites also needs MANAGE_ROLES. Acts onchannel Permission (capability) MANAGE_CHANNELSVersionAvailable since the API’s base version Webhook event channel_updateRate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
| DELETE | /channels/{channel.id} | Delete a guild channel, or close a direct message. | write | MANAGE_CHANNELS | Current | |
Requires MANAGE_CHANNELS for a guild channel, or MANAGE_THREADS for a thread. Deleting a channel cannot be undone. Acts onchannel Permission (capability) MANAGE_CHANNELSVersionAvailable since the API’s base version Webhook eventNone Rate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
MessagesList and read messages, post new ones, edit and delete them, bulk-delete, and add reactions.7 | ||||||
| GET | /channels/{channel.id}/messages | Get messages in a channel. | read | READ_MESSAGE_HISTORY | Current | |
Needs both VIEW_CHANNEL and READ_MESSAGE_HISTORY. Reading the text of a message over the Gateway also needs the message content privileged intent, but the REST read here returns content directly. Acts onmessage Permission (capability) READ_MESSAGE_HISTORYVersionAvailable since the API’s base version Webhook eventNone Rate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
| GET | /channels/{channel.id}/messages/{message.id} | Get a single message by id. | read | READ_MESSAGE_HISTORY | Current | |
Needs both VIEW_CHANNEL and READ_MESSAGE_HISTORY. Acts onmessage Permission (capability) READ_MESSAGE_HISTORYVersionAvailable since the API’s base version Webhook eventNone Rate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
| POST | /channels/{channel.id}/messages | Post a message to a channel. | write | SEND_MESSAGES | Current | |
Requires SEND_MESSAGES, and SEND_MESSAGES_IN_THREADS to post in a thread. The bot must also have VIEW_CHANNEL. Acts onmessage Permission (capability) SEND_MESSAGESVersionAvailable since the API’s base version Webhook event message_createRate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
| PATCH | /channels/{channel.id}/messages/{message.id} | Edit a message. | write | MANAGE_MESSAGES | Current | |
A bot can edit its own messages with no extra permission; editing another author's message flags, or otherwise managing the message, needs MANAGE_MESSAGES. On v10, attachments not listed in the edit are removed. Acts onmessage Permission (capability) MANAGE_MESSAGESVersionAvailable since the API’s base version Webhook event message_updateRate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
| DELETE | /channels/{channel.id}/messages/{message.id} | Delete a message. | write | MANAGE_MESSAGES | Current | |
A bot can delete its own message without MANAGE_MESSAGES; deleting anyone else's needs MANAGE_MESSAGES. Acts onmessage Permission (capability) MANAGE_MESSAGESVersionAvailable since the API’s base version Webhook event message_deleteRate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
| POST | /channels/{channel.id}/messages/bulk-delete | Delete multiple messages in a single request. | write | MANAGE_MESSAGES | Current | |
Requires MANAGE_MESSAGES. Limited to 2 to 100 messages, and it will not delete messages older than two weeks. Acts onmessage Permission (capability) MANAGE_MESSAGESVersionAvailable since the API’s base version Webhook eventNone Rate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
| PUT | /channels/{channel.id}/messages/{message.id}/reactions/{emoji}/@me | Add a reaction to a message as the current user. | write | ADD_REACTIONS | Current | |
Always needs READ_MESSAGE_HISTORY, and additionally ADD_REACTIONS when no one has yet reacted with this emoji. Acts onreaction Permission (capability) ADD_REACTIONSVersionAvailable since the API’s base version Webhook eventNone Rate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
Guilds (servers)Read a guild's details, modify its settings, and list or create the channels inside it.4 | ||||||
| GET | /guilds/{guild.id} | Get a guild (server) by id. | read | — | Current | |
Requires a bot token, and the bot must be a member of the guild. No specific permission is required. Acts onguild Permission (capability)None required VersionAvailable since the API’s base version Webhook eventNone Rate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
| PATCH | /guilds/{guild.id} | Modify a guild's settings, such as its name, icon, or system channel. | write | MANAGE_GUILD | Current | |
Requires the MANAGE_GUILD permission. Acts onguild Permission (capability) MANAGE_GUILDVersionAvailable since the API’s base version Webhook eventNone Rate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
| GET | /guilds/{guild.id}/channels | List the channels in a guild. | read | — | Current | |
Returns channels the bot can see. No specific permission is required beyond guild membership. Acts onchannel Permission (capability)None required VersionAvailable since the API’s base version Webhook eventNone Rate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
| POST | /guilds/{guild.id}/channels | Create a new channel in a guild. | write | MANAGE_CHANNELS | Current | |
Requires MANAGE_CHANNELS. Setting permission overwrites on the new channel also needs MANAGE_ROLES. Acts onchannel Permission (capability) MANAGE_CHANNELSVersionAvailable since the API’s base version Webhook event channel_createRate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
Guild membersList members, read a single member, modify a member, and add or remove a member's roles.5 | ||||||
| GET | /guilds/{guild.id}/members | List the members of a guild. | read | GUILD_MEMBERS intent | Current | |
Requires the guild members privileged intent to be enabled on the application. This intent is the permission this list depends on, not a channel permission. Acts onguild member Permission (capability) GUILD_MEMBERS intentVersionAvailable since the API’s base version Webhook eventNone Rate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
| GET | /guilds/{guild.id}/members/{user.id} | Get a single guild member by user id. | read | — | Current | |
No specific permission is required for a single member by id. Acts onguild member Permission (capability)None required VersionAvailable since the API’s base version Webhook eventNone Rate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
| PATCH | /guilds/{guild.id}/members/{user.id} | Modify a guild member, such as nickname, roles, or voice state. | write | MANAGE_ROLES | Current | |
The permission depends on the field changed: MANAGE_NICKNAMES for nickname, MANAGE_ROLES for roles, and MUTE_MEMBERS, DEAFEN_MEMBERS, MOVE_MEMBERS, or MODERATE_MEMBERS for voice and timeout fields. Acts onguild member Permission (capability) MANAGE_ROLESVersionAvailable since the API’s base version Webhook event guild_member_updateRate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
| PUT | /guilds/{guild.id}/members/{user.id}/roles/{role.id} | Add a role to a guild member. | write | MANAGE_ROLES | Current | |
Requires MANAGE_ROLES, and the bot's own highest role must sit above the role being granted. Acts onguild member Permission (capability) MANAGE_ROLESVersionAvailable since the API’s base version Webhook event guild_member_updateRate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
| DELETE | /guilds/{guild.id}/members/{user.id}/roles/{role.id} | Remove a role from a guild member. | write | MANAGE_ROLES | Current | |
Requires MANAGE_ROLES, and the bot's own highest role must sit above the role being removed. Acts onguild member Permission (capability) MANAGE_ROLESVersionAvailable since the API’s base version Webhook event guild_member_updateRate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
RolesList the roles in a guild and create a new role.2 | ||||||
| GET | /guilds/{guild.id}/roles | List the roles in a guild. | read | — | Current | |
No specific permission is required to read the role list. Acts onrole Permission (capability)None required VersionAvailable since the API’s base version Webhook eventNone Rate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
| POST | /guilds/{guild.id}/roles | Create a new role in a guild. | write | MANAGE_ROLES | Current | |
Requires MANAGE_ROLES. A role's own permissions are a bitfield, so creating one can hand out further access. Acts onrole Permission (capability) MANAGE_ROLESVersionAvailable since the API’s base version Webhook event guild_role_createRate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
UsersRead the current user, read a user by id, modify the current user, list the user's guilds, and open a direct message.5 | ||||||
| GET | /users/@me | Get the current user (the bot, or the authorizing user with a bearer token). | read | identify | Current | |
With a bot token this returns the bot. With an OAuth2 bearer token it needs the identify scope, and the email field requires the email scope. Acts onuser Permission (capability) identifyVersionAvailable since the API’s base version Webhook eventNone Rate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
| GET | /users/{user.id} | Get a user's public account by id. | read | — | Current | |
Requires a bot token. No OAuth2 scope is required for public profile fields. Acts onuser Permission (capability)None required VersionAvailable since the API’s base version Webhook eventNone Rate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
| PATCH | /users/@me | Modify the current user's username or avatar. | write | — | Current | |
Acts on the authenticated account itself, so no extra scope is required. Acts onuser Permission (capability)None required VersionAvailable since the API’s base version Webhook eventNone Rate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
| GET | /users/@me/guilds | List the guilds the current user is in. | read | guilds | Current | |
With a bot token this lists the bot's guilds. With an OAuth2 bearer token it needs the guilds scope. Acts onguild Permission (capability) guildsVersionAvailable since the API’s base version Webhook eventNone Rate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
| POST | /users/@me/channels | Open a direct message channel with another user. | write | — | Current | |
No specific scope is required to open the DM, but the bot still needs to share a guild with the user to message them. Acts onchannel Permission (capability)None required VersionAvailable since the API’s base version Webhook eventNone Rate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
WebhooksList a channel's or guild's webhooks, create a webhook, read one, and execute a webhook to post a message.4 | ||||||
| GET | /channels/{channel.id}/webhooks | List the webhooks in a channel. | read | MANAGE_WEBHOOKS | Current | |
Requires the MANAGE_WEBHOOKS permission. Acts onwebhook Permission (capability) MANAGE_WEBHOOKSVersionAvailable since the API’s base version Webhook eventNone Rate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
| POST | /channels/{channel.id}/webhooks | Create a webhook in a channel. | write | MANAGE_WEBHOOKS | Current | |
Requires the MANAGE_WEBHOOKS permission. Acts onwebhook Permission (capability) MANAGE_WEBHOOKSVersionAvailable since the API’s base version Webhook eventNone Rate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
| GET | /webhooks/{webhook.id} | Get a webhook by id. | read | MANAGE_WEBHOOKS | Current | |
Requires MANAGE_WEBHOOKS, unless the application itself owns the webhook. Acts onwebhook Permission (capability) MANAGE_WEBHOOKSVersionAvailable since the API’s base version Webhook eventNone Rate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
| POST | /webhooks/{webhook.id}/{webhook.token} | Execute a webhook to post a message into its channel. | write | — | Current | |
Does not require a bot token or any permission; the webhook token in the URL is the authorization. Anyone holding that token can post to the channel. Acts onwebhook Permission (capability)None required VersionAvailable since the API’s base version Webhook event message_createRate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
Application commandsList and create the global or guild slash commands an application registers, and bulk-overwrite the set.4 | ||||||
| GET | /applications/{application.id}/commands | List an application's global commands. | read | applications.commands | Current | |
Managing an application's commands is tied to the applications.commands OAuth2 scope under which the app was authorized. Acts onapplication command Permission (capability) applications.commandsVersionAvailable since the API’s base version Webhook eventNone Rate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
| POST | /applications/{application.id}/commands | Create or update a global command (available in every guild). | write | applications.commands | Current | |
Requires the applications.commands scope. Global commands can take up to an hour to roll out to all guilds. Acts onapplication command Permission (capability) applications.commandsVersionAvailable since the API’s base version Webhook eventNone Rate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
| POST | /applications/{application.id}/guilds/{guild.id}/commands | Create or update a command in a single guild. | write | applications.commands | Current | |
Requires the applications.commands scope. Guild commands appear in that guild immediately, unlike global ones. Acts onapplication command Permission (capability) applications.commandsVersionAvailable since the API’s base version Webhook eventNone Rate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
| PUT | /applications/{application.id}/guilds/{guild.id}/commands | Replace all of a guild's commands in one request. | write | applications.commands | Current | |
Requires the applications.commands scope. This overwrites the entire command set for the guild, removing any not included. Acts onapplication command Permission (capability) applications.commandsVersionAvailable since the API’s base version Webhook eventNone Rate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
Discord delivers real-time activity to a bot over a persistent Gateway connection, like a message being posted or a member joining, rather than the bot polling for changes. Which events arrive depends on the gateway intents the bot has enabled, and two of them, message content and guild members, are privileged.
| Event | What it signals | Triggered by |
|---|---|---|
MESSAGE_CREATE | Fires when a message is posted in a channel the bot can see. Reading the message text needs the message content privileged intent, unless the bot is mentioned or it is a direct message. | /channels/{channel.id}/messages/webhooks/{webhook.id}/{webhook.token} |
MESSAGE_UPDATE | Fires when a message is edited. | /channels/{channel.id}/messages/{message.id} |
MESSAGE_DELETE | Fires when a message is deleted from a channel. | /channels/{channel.id}/messages/{message.id} |
CHANNEL_CREATE | Fires when a new guild channel is created. | /guilds/{guild.id}/channels |
CHANNEL_UPDATE | Fires when a channel's settings change. | /channels/{channel.id} |
GUILD_MEMBER_UPDATE | Fires when a guild member changes, like a nickname or role change. Receiving it needs the guild members privileged intent. | /guilds/{guild.id}/members/{user.id}/guilds/{guild.id}/members/{user.id}/roles/{role.id}/guilds/{guild.id}/members/{user.id}/roles/{role.id} |
GUILD_MEMBER_ADD | Fires when a user joins a guild. Receiving it needs the guild members privileged intent. | In-app only |
GUILD_ROLE_CREATE | Fires when a new role is created in a guild. | /guilds/{guild.id}/roles |
INTERACTION_CREATE | Fires when a user runs an interaction, such as a slash command the app has registered. | In-app only |
Discord limits how fast an app or AI agent can call, through a global ceiling on requests per second and separate per-route limits that the response headers report as the agent goes.
Discord applies a global limit of 50 requests per second across the whole API for a bot, on top of separate per-route limits. Per-route limits are grouped into buckets, and endpoints that act on a top-level resource, like a single channel, guild, or webhook, are counted independently per resource id, so the same call on two different channels does not share one quota. Each response carries the current state in headers: X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset, X-RateLimit-Reset-After, and X-RateLimit-Bucket, with X-RateLimit-Global and X-RateLimit-Scope added on a 429. Going over returns HTTP 429 with a retry_after value in the body. Separately, an IP that sends too many invalid requests, the 401, 403, and 429 responses, is temporarily blocked at the edge after 10,000 in 10 minutes.
Message and member lists page by id rather than by page number. Get Channel Messages takes a limit of 1 to 100 (default 50) with before, after, or around an id; List Guild Members takes a limit up to 1000 with after the highest user id from the previous page. There is no total count, so a caller keeps requesting until a short page signals the end.
A single request body is capped at 8 MB for the default upload, and higher for boosted servers. Bulk Delete Messages takes 2 to 100 message ids at once and will not touch messages older than two weeks. A message's text content is limited to 2000 characters, or 4000 with an active Nitro-style boost.
The status codes an agent should handle, and what to do about each.
| Status | Code | Meaning | What to do |
|---|---|---|---|
| 400 | BAD REQUEST | The request was improperly formatted, or the server could not understand it. A common case is JSON error code 50035, an invalid form body, where the errors object names the fields that failed validation. | Read the errors object in the body, correct the named fields, and resend. |
| 401 | UNAUTHORIZED | The Authorization header was missing or invalid. JSON error code 40001 is returned when no valid token is provided. | Send a valid bot token (Bot |
| 403 | FORBIDDEN | The token is valid but does not have permission for the resource. JSON error code 50001 is missing access, and 50013 is missing the permission needed for the action. | Grant the bot the required permission, like SEND_MESSAGES or MANAGE_CHANNELS, in the channel or guild, then retry. |
| 404 | NOT FOUND | The resource does not exist. JSON error codes like 10003 unknown channel, 10004 unknown guild, 10008 unknown message, and 10013 unknown user point to which id was not found. | Confirm the id in the path is correct and that the bot can see the resource. |
| 405 | METHOD NOT ALLOWED | The HTTP method used is not valid for the location specified. | Use the method the endpoint documents, such as POST to create and PATCH to edit. |
| 429 | TOO MANY REQUESTS | A rate limit was hit. The JSON body carries retry_after in seconds and a global flag saying whether the global 50-per-second limit or a per-route limit was reached. | Wait the retry_after seconds before retrying, and read the X-RateLimit headers to pace future calls. |
| 502 | GATEWAY UNAVAILABLE | There was not a gateway available to process the request. This is a transient server-side condition. | Retry the request after a short, increasing wait. |
Discord versions its API by a whole number in the request path, and version 10 is the current stable version that new integrations target.
Version 10 is the current stable version of the Discord API, targeted by new integrations and set in the request path as /api/v10. It made message content a privileged intent, so a bot must enable that intent to receive the text of most messages over the Gateway. It also moved the audit-log reason from the request body to the X-Audit-Log-Reason header, switched message routes to embeds instead of embed, and stopped serving v10 and later on the old discordapp.com domain. It was announced on 14 February 2022.
Version 9 remains available for existing integrations. It predates the v10 change that made message content privileged, and Discord keeps it usable while encouraging new work on v10.
Version 6 is deprecated but remains the default version Discord uses when a request does not specify one in the path. Relying on the default is discouraged; integrations should pin v10 explicitly. Versions 8, 7, and 6 are all deprecated, and 5, 4, and 3 are discontinued.
An integration pins a version in the path and moves up when a newer one is ready.
Discord API changelog ↗Bollard AI sits between a team's AI agents and Discord. Grant each agent exactly the access it needs, read or write, channel by channel, and every call is checked and logged.