Base URL
API versioning
Some API and Gateway versions are now non-functioning, and are labeled as discontinued in the table below for posterity. Trying to use these versions will fail and return 400 Bad Request.
Discord exposes different versions of the API. Specify which version to use by including it in the request path like https://discord.com/api/v{version_number}. Omitting the version number routes requests to the current default version. You can find the change log for the newest API version in the change log.
API versions
| Version | Status | Default |
|---|
| 10 | Available | |
| 9 | Available | |
| 8 | Deprecated | |
| 7 | Deprecated | |
| 6 | Deprecated | ✓ |
| 5 | Discontinued | |
| 4 | Discontinued | |
| 3 | Discontinued | |
Error messages
Starting in API v8, error formatting in form error responses was improved. The response will tell you which JSON key contains the error, the error code, and a human-readable error message.
Array error
Object error
Request error
{
"code": 50035,
"errors": {
"activities": {
"0": {
"platform": {
"_errors": [
{
"code": "BASE_TYPE_CHOICES",
"message": "Value must be one of ('desktop', 'android', 'ios')."
}
]
},
"type": {
"_errors": [
{
"code": "BASE_TYPE_CHOICES",
"message": "Value must be one of (0, 1, 2, 3, 4, 5)."
}
]
}
}
}
},
"message": "Invalid Form Body"
}
{
"code": 50035,
"errors": {
"access_token": {
"_errors": [
{
"code": "BASE_TYPE_REQUIRED",
"message": "This field is required"
}
]
}
},
"message": "Invalid Form Body"
}
{
"code": 50035,
"message": "Invalid Form Body",
"errors": {
"_errors": [
{
"code": "APPLICATION_COMMAND_TOO_LARGE",
"message": "Command exceeds maximum size (8000)"
}
]
}
}
Authentication
Authenticating with the Discord API can be done in one of two ways:
- Using a bot token found on the Bot page within your app’s settings. For more information on bots see bots vs user accounts.
- Using an OAuth2 bearer token gained through the OAuth2 API.
For all authentication types, authentication is performed with the Authorization HTTP header in the format Authorization: TOKEN_TYPE TOKEN.
Authorization: Bot MTk4NjIyNDgzNDcxOTI1MjQ4.Cl2FMQ.ZnCjm1XVW7vRze4b7Cq4se7kKWs
Encryption
All HTTP-layer services and protocols (e.g. HTTP, WebSocket) within the Discord API use TLS 1.2.
Snowflakes
Discord utilizes Twitter’s snowflake format for uniquely identifiable descriptors (IDs). These IDs are guaranteed to be unique across all of Discord, except in some unique scenarios in which child objects share their parent’s ID. Because Snowflake IDs are up to 64 bits in size (e.g. a uint64), they are always returned as strings in the HTTP API to prevent integer overflows in some languages.
Snowflake ID broken down in binary
111111111111111111111111111111111111111111 11111 11111 111111111111
64 22 17 12 0
Snowflake ID format structure (left to right)
| Field | Bits | Number of bits | Description | Retrieval |
|---|
| Timestamp | 63 to 22 | 42 bits | Milliseconds since Discord Epoch, the first second of 2015 or 1420070400000 | (snowflake >> 22) + 1420070400000 |
| Internal worker ID | 21 to 17 | 5 bits | | (snowflake & 0x3E0000) >> 17 |
| Internal process ID | 16 to 12 | 5 bits | | (snowflake & 0x1F000) >> 12 |
| Increment | 11 to 0 | 12 bits | For every ID that is generated on that process, this number is incremented | snowflake & 0xFFF |
Snowflake IDs are used in many API routes for pagination. The standardized pagination paradigm lets you specify IDs before and after in combination with limit to retrieve a desired page of results.
Since snowflake IDs are numbers with a timestamp, you can generate a snowflake ID for any point in time when paginating.
Generating a snowflake ID from a timestamp
(timestamp_ms - DISCORD_EPOCH) << 22
ID serialization
Discord stores IDs as integer snowflakes internally. When serializing IDs to JSON, Discord transforms bigints into strings. You should always expect a string when receiving IDs.
However, if you pass a non-bigint value in an id field to the API or Gateway, IDs in the response will be serialized as integers. For example, when requesting GUILD_MEMBERS_CHUNK from the Gateway:
// Send
{
"op": 8,
"d": {
"guild_id": "308994132968210433",
"user_ids": ["123123"]
}
}
// Receive
{
"t": "GUILD_MEMBERS_CHUNK",
"s": 3,
"op": 0,
"d": {
"not_found": [123123],
"members": [],
"guild_id": "308994132968210433"
}
}
The sent user_id (123123) is not a bigint, so Discord serializes it back as an integer rather than a string. This will never happen with IDs that originate from Discord.
ISO8601 date/time
Discord uses the ISO8601 format for most Date/Times returned in models. This format is referred to as type ISO8601 within tables in this documentation.
Nullable and optional resource fields
Resource fields that may contain a null value have types prefixed with a question mark. Resource fields that are optional have names suffixed with a question mark.
| Field | Type |
|---|
optional_field? | string |
nullable_field | ?string |
optional_and_nullable_field? | ?string |
Consistency
Discord operates at a scale where true consistency is impossible. Many operations in the API and between services are eventually consistent. Client actions can never be serialized and may be executed in any order. Events in Discord may:
- Never be sent to a client
- Be sent exactly one time to the client
- Be sent up to N times per client
Clients should operate on events and API results in as idempotent a manner as possible.
HTTP API
User agent
Clients using the HTTP API must provide a valid User Agent specifying information about the client library and version:
User-Agent: DiscordBot ($url, $versionNumber)
Clients may append additional information and metadata to the end of this string.
Client requests that do not have a valid User Agent specified may be blocked and return a Cloudflare error.
Content type
Clients must provide a valid Content-Type header: application/json, application/x-www-form-urlencoded, or multipart/form-data, except where specified. Failing to do so results in a 50035 “Invalid form body” error.
Rate limiting
The HTTP API implements a process for limiting and preventing excessive requests in accordance with RFC 6585. API users that regularly hit and ignore rate limits will have their API keys revoked. For more information, see the Rate Limits section.
Boolean query strings
Discord represents boolean query string parameters using True, true, or 1 for true and False, false, or 0 for false.
Gateway (WebSocket) API
Discord’s Gateway API maintains persistent, stateful WebSocket connections between your client and Discord’s servers. These connections are used for sending and receiving real-time events. The Gateway API uses secure WebSocket connections as specified in RFC 6455. For information on opening Gateway connections, see the Gateway API section.
Discord uses a subset of markdown for rendering message content, with custom functionality for mentioning users and channels.
Formats
| Type | Structure | Example |
|---|
| User | <@USER_ID> | <@80351110224678912> |
| Channel | <#CHANNEL_ID> | <#103735883630395392> |
| Role | <@&ROLE_ID> | <@&165511591545143296> |
| Slash command | </NAME:COMMAND_ID> | </airhorn:816437322781949972> |
| Slash command with subcommand | </NAME SUBCOMMAND:ID> | </foo bar:123456789012345678> |
| Slash command with subcommand group | </NAME SUBCOMMAND_GROUP SUBCOMMAND:ID> | </foo group bar:123456789012345678> |
| Standard emoji | Unicode characters | 🪴 |
| Custom emoji | <:NAME:ID> | <:mmLol:216154654256398347> |
| Animated custom emoji | <a:NAME:ID> | <a:b1nzy:392938283556143104> |
| Unix timestamp | <t:TIMESTAMP> | <t:1618953630> |
| Styled unix timestamp | <t:TIMESTAMP:STYLE> | <t:1618953630:d> |
| Guild navigation | <id:TYPE> | See guild navigation types below |
Timestamps are expressed in seconds and display the given timestamp in the user’s timezone and locale.
Timestamp styles
| Style | Example output | Description |
|---|
t | 16:20 | Short time |
T | 16:20:30 | Medium time |
d | 20/04/2021 | Short date |
D | April 20, 2021 | Long date |
f * | April 20, 2021 at 16:20 | Long date, short time |
F | Tuesday, April 20, 2021 at 16:20 | Full date, short time |
R | 4 years ago | Relative time |
* Default style.
Guild navigation types
Guild navigation types link to the corresponding resource in the current server.
| Full syntax | Linked resource |
|---|
<id:customize> | Channel & Roles tab with Onboarding prompts |
<id:browse> | Browse Channels tab |
<id:guide> | Server Guide tab |
<id:linked-roles> | Linked Roles tab |
<id:linked-roles:id> | Specific linked role, opening the connection modal on click |
Image base URL
https://cdn.discordapp.com/
Discord uses IDs and hashes to render images in the client. The returned format can be changed by changing the extension name at the end of the URL. Image size can be changed by appending ?size=desired_size (any power of two between 16 and 4096).
Animated images uploaded as WebP or AVIF do not convert cleanly to GIF. Request animated images as WebP for maximum compatibility.
Image formats
| Name | Extension |
|---|
| JPEG | .jpg, .jpeg |
| PNG | .png |
| WebP | .webp |
| GIF | .gif |
| Lottie | .json |
CDN endpoints
| Type | Path | Supports |
|---|
| Custom Emoji | emojis/{emoji_id}.png | PNG, JPEG, WebP, GIF |
| Guild Icon | icons/{guild_id}/{guild_icon}.png | PNG, JPEG, WebP, GIF |
| Guild Splash | splashes/{guild_id}/{guild_splash}.png | PNG, JPEG, WebP |
| Guild Discovery Splash | discovery-splashes/{guild_id}/{guild_discovery_splash}.png | PNG, JPEG, WebP |
| Guild Banner | banners/{guild_id}/{guild_banner}.png | PNG, JPEG, WebP, GIF |
| User Banner | banners/{user_id}/{user_banner}.png | PNG, JPEG, WebP, GIF |
| Default User Avatar | embed/avatars/{index}.png | PNG |
| User Avatar | avatars/{user_id}/{user_avatar}.png | PNG, JPEG, WebP, GIF |
| Guild Member Avatar | guilds/{guild_id}/users/{user_id}/avatars/{member_avatar}.png | PNG, JPEG, WebP, GIF |
| Avatar Decoration | avatar-decoration-presets/{avatar_decoration_data_asset}.png | PNG |
| Application Icon | app-icons/{application_id}/{icon}.png | PNG, JPEG, WebP |
| Application Cover | app-icons/{application_id}/{cover_image}.png | PNG, JPEG, WebP |
| Application Asset | app-assets/{application_id}/{asset_id}.png | PNG, JPEG, WebP |
| Team Icon | team-icons/{team_id}/{team_icon}.png | PNG, JPEG, WebP |
| Sticker | stickers/{sticker_id}.png | PNG, Lottie, GIF |
| Role Icon | role-icons/{role_id}/{role_icon}.png | PNG, JPEG, WebP |
| Guild Scheduled Event Cover | guild-events/{scheduled_event_id}/{scheduled_event_cover_image}.png | PNG, JPEG, WebP |
| Guild Member Banner | guilds/{guild_id}/users/{user_id}/banners/{member_banner}.png | PNG, JPEG, WebP, GIF |
| Guild Tag Badge | guild-tag-badges/{guild_id}/{badge_hash}.png | PNG, JPEG, WebP |
Sticker GIFs do not use the CDN base URL, and can be accessed at https://media.discordapp.net/stickers/{sticker_id}.gif.
For endpoints that support GIFs, the hash will begin with a_ if it is available in animated format (e.g. a_1269e74af4df7417b13759eae50c83dc). Animated images can be retrieved as animated WebP using the .webp extension and ?animated=true query parameter.
Image data
Image data is a Data URI scheme that supports JPG, GIF, and PNG formats:
data:image/jpeg;base64,BASE64_ENCODED_JPEG_IMAGE_DATA
Use the proper content type (image/jpeg, image/png, image/gif) that matches the image data being provided.
Signed attachment CDN URLs
Attachments uploaded to Discord’s CDN have signed URLs with a preset expiry time. Discord automatically refreshes attachment CDN URLs that appear within the client.
When passing CDN URLs into API fields (like url in an embed image object or avatar_url for webhooks), pass the CDN URL without any parameters and Discord will automatically render and refresh the URL.
Example attachment CDN URL
https://cdn.discordapp.com/attachments/1012345678900020080/1234567891233211234/my_image.png?ex=65d903de&is=65c68ede&hm=2481f30dd67f503f54d020ae3b5533b9987fae4e55f2b4e3926e08a3fa3ee24f&
Attachment CDN URL parameters
| Parameter | Description |
|---|
ex | Hex timestamp indicating when an attachment CDN URL will expire |
is | Hex timestamp indicating when the URL was issued |
hm | Unique signature that remains valid until the URL’s expiration |
Uploading files
The default file upload size limit is 10 MiB per file. This may be higher depending on the user’s Nitro status or the server’s Boost Tier.
Some endpoints support file attachments, indicated by the files[n] parameter. To add files, replace the standard application/json body with a multipart/form-data body. The JSON message body can optionally be provided using the payload_json parameter.
All files[n] parameters must include a valid Content-Disposition subpart header with a filename and unique name parameter. Each file parameter must be uniquely named in the format files[n] such as files[0], files[1], or files[42].
Example without payload_json
--boundary
Content-Disposition: form-data; name="content"
Hello, World!
--boundary
Content-Disposition: form-data; name="tts"
true
--boundary--
Example with payload_json and file attachments
--boundary
Content-Disposition: form-data; name="payload_json"
Content-Type: application/json
{
"content": "Hello, World!",
"embeds": [{
"title": "Hello, Embed!",
"description": "This is an embedded message.",
"thumbnail": { "url": "attachment://myfilename.png" },
"image": { "url": "attachment://mygif.gif" }
}],
"attachments": [
{ "id": 0, "description": "Image of a cute little cat", "filename": "myfilename.png" },
{ "id": 1, "description": "Rickroll gif", "filename": "mygif.gif" }
]
}
--boundary
Content-Disposition: form-data; name="files[0]"; filename="myfilename.png"
Content-Type: image/png
[image bytes]
--boundary
Content-Disposition: form-data; name="files[1]"; filename="mygif.gif"
Content-Type: image/gif
[image bytes]
--boundary--
Images can be referenced in embeds using the attachment://filename URL:
{
"embeds": [{
"image": {
"url": "attachment://screenshot.png"
}
}]
}
Only .jpg, .jpeg, .png, .webp, and .gif may be used in embeds. Other file types are not supported.
Editing message attachments
When making a PATCH request, only files listed in the attachments parameter will be kept. Any previously-added files not included will be removed.
Locales
| Locale | Language name | Native name |
|---|
| id | Indonesian | Bahasa Indonesia |
| da | Danish | Dansk |
| de | German | Deutsch |
| en-GB | English, UK | English, UK |
| en-US | English, US | English, US |
| es-ES | Spanish | Español |
| es-419 | Spanish, LATAM | Español, LATAM |
| fr | French | Français |
| hr | Croatian | Hrvatski |
| it | Italian | Italiano |
| lt | Lithuanian | Lietuviškai |
| hu | Hungarian | Magyar |
| nl | Dutch | Nederlands |
| no | Norwegian | Norsk |
| pl | Polish | Polski |
| pt-BR | Portuguese, Brazilian | Português do Brasil |
| ro | Romanian | Română |
| fi | Finnish | Suomi |
| sv-SE | Swedish | Svenska |
| vi | Vietnamese | Tiếng Việt |
| tr | Turkish | Türkçe |
| cs | Czech | Čeština |
| el | Greek | Ελληνικά |
| bg | Bulgarian | български |
| ru | Russian | Pусский |
| uk | Ukrainian | Українська |
| hi | Hindi | हिन्दी |
| th | Thai | ไทย |
| zh-CN | Chinese, China | 中文 |
| ja | Japanese | 日本語 |
| zh-TW | Chinese, Taiwan | 繁體中文 |
| ko | Korean | 한국어 |