Application commands
An application command is a slash command a bot registers so that people can run it from the message composer. Every bot can register commands; no review is required. A user runs a command through Invoke a bot command, and the bot receives it as an interaction.
The field names, type numbers, and routes match Discord’s, so a discord.js or discord.py bot registers commands without changes beyond its API base and version. Differences from Discord lists what is not the same.
Command scopes
Section titled “Command scopes”A command is either global or belongs to one guild. A global command is available in every guild the bot is in and, when dm_permission is true, in a one-to-one direct message with the bot. A guild command is available in that guild alone and never in a direct message. When a guild command and a global command share a name, the guild command hides the global one in that guild.
Each scope holds one command set with a version. Every write replaces the set atomically and gives it a new version, which is returned as the ETag header of every registration route.
Registration rules
Section titled “Registration rules”- Only the application’s own bot token is accepted. Any other credential is refused with 403
ACCESS_DENIED, and a bot token for a different application with 403MISSING_ACCESS. - A guild route requires the bot to be a member of that guild, and one that is not receives 403
MISSING_ACCESS. - The bot’s
feature_bot_interactionslimit key must be1andfeature_bot_interactions_blockedmust be0. Otherwise every registration route returns 403APPLICATION_COMMAND_FEATURE_DISABLED. - A request body with a declared length over 540,672 bytes is refused with 413
FILE_SIZE_TOO_LARGEbefore it is parsed.
Write preconditions
Section titled “Write preconditions”A write with If-Match set to the ETag of an earlier read fails with 412 APPLICATION_COMMAND_VERSION_CONFLICT when the set has changed since. A malformed tag matches no version and fails the same way. A write with If-None-Match: * fails with 412 when the scope already has commands.
Without either header the server applies the change to the newest set. Concurrent writers to the same scope can still receive 412 when every attempt loses. discord.js and discord.py send neither header.
Application command object
Section titled “Application command object”Structure
Section titled “Structure”| Field | Type | Description |
|---|---|---|
| id | snowflake | The ID of the command, kept while its name stays the same |
| application_id | snowflake | The ID of the application that owns the command |
| version | snowflake | Changes whenever the command itself changes |
| guild_id? | snowflake | The guild of a guild command, absent on a global command |
| type | integer | Always 1, a chat input command |
| name | string | Command name |
| description | string | 1 through 100 characters |
| options | array[command option object] | Up to 25 options |
| default_member_permissions | ?string | The permission bits a member needs to see and run the command, as a decimal string, or null for none |
| dm_permission | boolean | Whether a global command works in a direct message with the bot |
| contexts? | array[integer] | The contexts sent with the command, absent when none were sent |
The request body takes type, name, description, options, default_member_permissions, and dm_permission. type defaults to 1, options to an empty array, default_member_permissions to null, and dm_permission to false. A guild command can only have dm_permission false.
name_localizations, description_localizations, default_permission, and a false nsfw are accepted and discarded, so discord.js and discord.py can register commands unchanged; the default name shows in every locale. nsfw true is refused. integration_types is accepted and discarded, because user-installed applications do not exist. Any other field is refused with 400 INVALID_FORM_BODY.
Command contexts
Section titled “Command contexts”contexts works as on Discord: 0 is a guild, 1 the direct message with the bot, and 2 (private channels) has no effect. When it is sent, it is stored and returned, a global command’s dm_permission becomes whether it holds 1, and a command without 0 is neither offered nor run in guilds. Without it, a command is available in guilds and dm_permission decides direct messages.
Example
Section titled “Example”{ "id": "1558000000000000001", "application_id": "1557753609842589699", "version": "1558000000000000002", "type": 1, "name": "yardım", "description": "Komutları kategoriye göre gösterir", "options": [ { "type": 3, "name": "kategori", "description": "Gösterilecek kategori", "required": false, "autocomplete": true } ], "default_member_permissions": null, "dm_permission": true}Command names
Section titled “Command names”A command, option, subcommand, or group name has 1 through 32 Unicode code points after NFC normalisation. It may contain lowercase letters of any script, digits, -, and _, so yardım and seviye-ödül are valid. An uppercase letter or any other character is refused with 400 INVALID_FORM_BODY.
Application command option object
Section titled “Application command option object”Structure
Section titled “Structure”| Field | Type | Description |
|---|---|---|
| type | integer | Option type |
| name | string | Name, unique among its siblings |
| description | string | 1 through 100 characters |
| required? | boolean | Whether the user must fill the option, default false |
| choices? | array[option choice object] | Up to 25 fixed values for a string, integer, or number option |
| autocomplete? | boolean | Whether the bot suggests values while the user types |
| min_value? | number | Smallest value of an integer or number option |
| max_value? | number | Largest value of an integer or number option |
| min_length? | integer | Shortest value of a string option, 0 through 6000 |
| max_length? | integer | Longest value of a string option, 1 through 6000 |
| channel_types? | array[integer] | Up to 25 channel types a channel option offers |
| options? | array[command option object] | The children of a subcommand or group |
Only the fields of an option’s own type are accepted. autocomplete is limited to string, integer, and number options, and an option cannot have both autocomplete and choices. min_value cannot exceed max_value, and min_length cannot exceed max_length. Required options come before optional ones.
A string value has at most 6000 code points. Integer and number values are bounded by the safe integer range of JSON numbers.
Subcommands
Section titled “Subcommands”A command’s options are either all value options or all subcommands and groups. A group holds 1 through 25 subcommands, a subcommand holds value options, and nothing nests deeper. A subcommand has no required field.
Application command option types
Section titled “Application command option types”| Value | Name | Description |
|---|---|---|
| 1 | SUB_COMMAND | A subcommand |
| 2 | SUB_COMMAND_GROUP | A group of subcommands |
| 3 | STRING | Text |
| 4 | INTEGER | A whole number |
| 5 | BOOLEAN | True or false |
| 6 | USER | A user, resolved in the interaction |
| 7 | CHANNEL | A channel, resolved in the interaction |
| 8 | ROLE | A role, resolved in the interaction |
| 10 | NUMBER | A number with a fraction |
Type 9 (mentionable) and type 11 (attachment) are not offered and are refused with 400 INVALID_FORM_BODY.
Application command option choice object
Section titled “Application command option choice object”Structure
Section titled “Structure”| Field | Type | Description |
|---|---|---|
| name | string | The label the user sees, 1 through 100 characters |
| value | string | number | The value the bot receives, a string of at most 100 characters for a string option |
Command limits
Section titled “Command limits”| Limit | Value |
|---|---|
| Commands in one scope | 100 |
| Options on a command or subcommand | 25 |
| Choices on an option | 25 |
| Serialised size of one command | 32,768 bytes |
| Serialised size of one command set | 524,288 bytes |
The sizes count the UTF-8 JSON of each command together with the fields the server adds.
List global application commands
Section titled “List global application commands”GET/v1/applications/{application_id}/commandsReturns the application’s global commands, with the set’s version as ETag.
Path parameters
Section titled “Path parameters”| Field | Type | Description |
|---|---|---|
| application_id | snowflake | The ID of the application |
Response
Section titled “Response”| Status | Body | Condition |
|---|---|---|
| 200 | array[application command object] | The set was read |
| 403 | error response | The registration rules refuse the caller |
Rate limit
Section titled “Rate limit”30 requests per 10 seconds for each application ID, on the application:commands:read::application_id bucket.
Bulk overwrite global application commands
Section titled “Bulk overwrite global application commands”PUT/v1/applications/{application_id}/commandsReplaces the whole global set in one write and returns the new set. A command keeps its ID while its name stays the same, and an unchanged command keeps its version. An unchanged set is not rewritten.
Path parameters
Section titled “Path parameters”| Field | Type | Description |
|---|---|---|
| application_id | snowflake | The ID of the application |
JSON body
Section titled “JSON body”An array of up to 100 application command objects with unique names.
Response
Section titled “Response”| Status | Body | Condition |
|---|---|---|
| 200 | array[application command object] | The set was replaced |
| 400 | error response | The body is invalid |
| 403 | error response | The registration rules refuse the caller |
| 412 | error response | A precondition failed with APPLICATION_COMMAND_VERSION_CONFLICT |
| 413 | error response | The body is too large and the request returns FILE_SIZE_TOO_LARGE |
Rate limit
Section titled “Rate limit”5 requests per 1 minute for each application ID, on the application:commands:write::application_id bucket.
Create global application command
Section titled “Create global application command”POST/v1/applications/{application_id}/commandsCreates one global command, or replaces the command with the same name, which keeps its ID. Returns 201 for a new command and 200 for a replaced one.
Path parameters
Section titled “Path parameters”| Field | Type | Description |
|---|---|---|
| application_id | snowflake | The ID of the application |
JSON body
Section titled “JSON body”One application command object.
Response
Section titled “Response”| Status | Body | Condition |
|---|---|---|
| 200 | application command object | A command with the same name was replaced |
| 201 | application command object | The command was created |
| 400 | error response | The body is invalid |
| 403 | error response | The registration rules refuse the caller |
| 412 | error response | A precondition failed with APPLICATION_COMMAND_VERSION_CONFLICT |
Rate limit
Section titled “Rate limit”Shares the application:commands:write::application_id bucket with Bulk overwrite global application commands.
Delete all global application commands
Section titled “Delete all global application commands”DELETE/v1/applications/{application_id}/commandsEmpties the global set. Returns 204 with an empty body.
Path parameters
Section titled “Path parameters”| Field | Type | Description |
|---|---|---|
| application_id | snowflake | The ID of the application |
Response
Section titled “Response”| Status | Body | Condition |
|---|---|---|
| 204 | empty | The set was emptied |
| 403 | error response | The registration rules refuse the caller |
| 412 | error response | A precondition failed with APPLICATION_COMMAND_VERSION_CONFLICT |
Rate limit
Section titled “Rate limit”Shares the application:commands:write::application_id bucket.
Get global application command
Section titled “Get global application command”GET/v1/applications/{application_id}/commands/{command_id}Returns one global command.
Path parameters
Section titled “Path parameters”| Field | Type | Description |
|---|---|---|
| application_id | snowflake | The ID of the application |
| command_id | snowflake | The ID of the command |
Response
Section titled “Response”| Status | Body | Condition |
|---|---|---|
| 200 | application command object | The command exists |
| 403 | error response | The registration rules refuse the caller |
| 404 | error response | No such command, and the request returns NOT_FOUND |
Rate limit
Section titled “Rate limit”Shares the application:commands:read::application_id bucket.
Edit global application command
Section titled “Edit global application command”PATCH/v1/applications/{application_id}/commands/{command_id}Replaces the given fields of one global command. The result must be a valid command, and the ID stays.
Path parameters
Section titled “Path parameters”| Field | Type | Description |
|---|---|---|
| application_id | snowflake | The ID of the application |
| command_id | snowflake | The ID of the command |
JSON body
Section titled “JSON body”Any subset of the application command request fields.
Response
Section titled “Response”| Status | Body | Condition |
|---|---|---|
| 200 | application command object | The command was changed |
| 400 | error response | The resulting command is invalid |
| 403 | error response | The registration rules refuse the caller |
| 404 | error response | No such command, and the request returns NOT_FOUND |
| 412 | error response | A precondition failed with APPLICATION_COMMAND_VERSION_CONFLICT |
Rate limit
Section titled “Rate limit”Shares the application:commands:write::application_id bucket.
Delete global application command
Section titled “Delete global application command”DELETE/v1/applications/{application_id}/commands/{command_id}Deletes one global command. Returns 204 with an empty body.
Path parameters
Section titled “Path parameters”| Field | Type | Description |
|---|---|---|
| application_id | snowflake | The ID of the application |
| command_id | snowflake | The ID of the command |
Response
Section titled “Response”| Status | Body | Condition |
|---|---|---|
| 204 | empty | The command was deleted |
| 403 | error response | The registration rules refuse the caller |
| 404 | error response | No such command, and the request returns NOT_FOUND |
| 412 | error response | A precondition failed with APPLICATION_COMMAND_VERSION_CONFLICT |
Rate limit
Section titled “Rate limit”Shares the application:commands:write::application_id bucket.
Guild application command routes
Section titled “Guild application command routes”The guild routes take the same bodies and return the same objects as the global routes, for one guild. The bot must be a member of the guild, dm_permission must be false, and each successful write sends Application Commands Update to the guild’s active sessions so their clients reload the catalog. A global write reaches no session.
Their writes are limited to 2 requests per 1 minute for each application and guild, on the application:commands:guild:write::application_id::guild_id bucket. Their reads share the application:commands:read::application_id bucket.
Guild path parameters
Section titled “Guild path parameters”| Field | Type | Description |
|---|---|---|
| application_id | snowflake | The ID of the application |
| guild_id | snowflake | The ID of the guild |
| command_id | snowflake | The ID of the command, on the single command routes |
List guild application commands
Section titled “List guild application commands”GET/v1/applications/{application_id}/guilds/{guild_id}/commandsReturns the application’s commands for the guild, as List global application commands does for the global set.
Bulk overwrite guild application commands
Section titled “Bulk overwrite guild application commands”PUT/v1/applications/{application_id}/guilds/{guild_id}/commandsReplaces the guild’s whole set, as Bulk overwrite global application commands does.
Create guild application command
Section titled “Create guild application command”POST/v1/applications/{application_id}/guilds/{guild_id}/commandsCreates or replaces one guild command by name, as Create global application command does.
Delete all guild application commands
Section titled “Delete all guild application commands”DELETE/v1/applications/{application_id}/guilds/{guild_id}/commandsEmpties the guild’s set. Returns 204 with an empty body.
Get guild application command
Section titled “Get guild application command”GET/v1/applications/{application_id}/guilds/{guild_id}/commands/{command_id}Returns one guild command, or 404 NOT_FOUND.
Edit guild application command
Section titled “Edit guild application command”PATCH/v1/applications/{application_id}/guilds/{guild_id}/commands/{command_id}Replaces the given fields of one guild command, as Edit global application command does.
Delete guild application command
Section titled “Delete guild application command”DELETE/v1/applications/{application_id}/guilds/{guild_id}/commands/{command_id}Deletes one guild command. Returns 204 with an empty body, or 404 NOT_FOUND.
Command catalog object
Section titled “Command catalog object”The commands a user may run in one channel, as the client’s composer lists them.
Structure
Section titled “Structure”| Field | Type | Description |
|---|---|---|
| applications | array[catalog application object] | The bots whose commands are on this page |
| application_commands | array[application command object] | At most 50 commands |
| next_cursor | ?string | The cursor of the next page, or null on the last one |
A page holds at most 50 commands and at most 131,072 bytes. Every page carries the same weak ETag, which covers the whole catalog, so a change on a later page changes it too. A first-page request with a matching If-None-Match returns 304. The tag does not change when only a bot’s name, avatar, or channel permissions change, so a client can show those for up to 10 minutes; a command run from an outdated list returns 409 APPLICATION_COMMAND_STALE.
Catalog application object
Section titled “Catalog application object”| Field | Type | Description |
|---|---|---|
| id | snowflake | The ID of the application |
| name | string | The application name |
| bot | partial user object | The bot user |
List guild command catalog
Section titled “List guild command catalog”GET/v1/guilds/{guild_id}/application-commandsReturns, page by page, the commands of the guild’s bots that the caller may run in the channel. A command whose default_member_permissions the caller does not hold is left out.
Limitations
Section titled “Limitations”- This is a user-only operation, and a bot credential is refused with 403
ACCESS_DENIED. - An unknown channel, one the caller cannot view, or one in another guild returns 404
UNKNOWN_CHANNEL. - An account whose
feature_app_commandslimit key is0receives an empty page.
Path parameters
Section titled “Path parameters”| Field | Type | Description |
|---|---|---|
| guild_id | snowflake | The ID of the guild |
Query parameters
Section titled “Query parameters”| Field | Type | Description |
|---|---|---|
| channel_id | snowflake | The channel the commands would run in |
| cursor? | string | The next_cursor of the previous page |
Response
Section titled “Response”| Status | Body | Condition |
|---|---|---|
| 200 | command catalog object | The page was built |
| 304 | empty | The first page matches If-None-Match |
| 403 | error response | Caller is a bot and the request returns ACCESS_DENIED |
| 404 | error response | The channel cannot be used and the request returns UNKNOWN_CHANNEL |
Rate limit
Section titled “Rate limit”30 requests per 1 minute for each authenticated user, on the application:commands:catalog bucket.
List direct message command catalog
Section titled “List direct message command catalog”GET/v1/channels/{channel_id}/application-commandsIn a one-to-one direct message with a bot, returns that bot’s global commands with dm_permission true and no default_member_permissions. Any other private channel returns an empty page, and a guild channel returns 404 UNKNOWN_CHANNEL.
Limitations
Section titled “Limitations”- This is a user-only operation, and a bot credential is refused with 403
ACCESS_DENIED.
Path parameters
Section titled “Path parameters”| Field | Type | Description |
|---|---|---|
| channel_id | snowflake | The ID of the direct message channel |
Query parameters
Section titled “Query parameters”| Field | Type | Description |
|---|---|---|
| cursor? | string | The next_cursor of the previous page |
Response
Section titled “Response”| Status | Body | Condition |
|---|---|---|
| 200 | command catalog object | The page was built |
| 304 | empty | The first page matches If-None-Match |
| 403 | error response | Caller is a bot and the request returns ACCESS_DENIED |
| 404 | error response | The channel is a guild channel and the request returns UNKNOWN_CHANNEL |
Rate limit
Section titled “Rate limit”Shares the application:commands:catalog bucket with List guild command catalog.