Answering interactions
Every use of a slash command, a menu command, a button, a select, a form or autocomplete reaches your bot as an interaction. This page shows how to answer in time.
You will need
A running gateway connection with the INTERACTIONS intent, or an HTTP address. Commands work in server channels, and in a direct message with the bot for its global commands that need no server permission. Buttons, selects and forms work in that direct message too; server_id and member are then absent.
The time limits
| Limit | Time | What happens after it |
|---|---|---|
| First answer | 3 seconds | The person sees that the bot did not answer. A late callback gets InteractionExpired |
| Edits and follow-ups | 15 minutes | The token stops working: InteractionExpired or UnknownInteraction |
The event carries both as respond_by and expires_at. Follow the event's times, not your own clock.
If the work takes longer than a moment, answer DeferredMessage first. It shows "thinking" and gives you the 15 minutes.
If your bot is not connected when someone uses a command, the event is lost, and the person sees the failure after 3 seconds.
The event
{
"type": "InteractionCreate",
"interaction": {
"_id": "01JC0000000000000000000013",
"version": 1,
"application_id": "01JC0000000000000000000001",
"type": "Command",
"token": "YOUR_INTERACTION_TOKEN",
"user": { "_id": "01JC0000000000000000000012", "username": "example_user" },
"member": { "_id": { "server": "01JC0000000000000000000003", "user": "01JC0000000000000000000012" } },
"server_id": "01JC0000000000000000000003",
"channel_id": "01JC0000000000000000000004",
"user_permissions_string": "2276038022144",
"app_permissions_string": "4398045478879",
"locale": "ar",
"command": { "id": "01JC0000000000000000000014", "name": "ping", "type": "ChatInput", "options": [] },
"respond_by": "2026-11-06T07:04:12.432Z",
"expires_at": "2026-11-06T07:19:09.432Z"
}
}| Field | Meaning |
|---|---|
type | Command, Component, ModalSubmit or Autocomplete |
token | Valid for this interaction only. Treat it like a password until expires_at |
user, member | Who did it |
user_permissions_string | Their permissions in this channel. Use this one in JavaScript, not user_permissions |
app_permissions_string | Your bot's permissions in this channel |
locale | Their language, if the app sent it |
command | With Command and Autocomplete: name, options, resolved, target_id, focused |
component | With Component: custom_id, component_type, values, resolved |
modal | With ModalSubmit: custom_id, fields, resolved |
message_id | The message the component is on |
message_ephemeral | true when that message is private |
The permission numbers are too large for a JavaScript number, so read them as BigInt:
const canTimeout = (BigInt(interaction.user_permissions_string) >> 8n) & 1n;Answer
Send one first answer. No token header is needed: the path holds the token.
curl -X POST "https://api.zrzur.com/interactions/INTERACTION_ID/YOUR_INTERACTION_TOKEN/callback" \
-H "content-type: application/json" \
-d '{ "type": "Message", "data": { "content": "Pong!" } }'Callback type | When | Body |
|---|---|---|
Message | Reply now | data |
DeferredMessage | The work takes longer than 3 seconds. Shows "thinking" | data.ephemeral if it stays private |
UpdateMessage | Buttons and selects: change the message the component is on | data |
DeferredUpdate | Buttons and selects: acknowledge now, change the message later | none |
Modal | Open a form. Not as an answer to a form or to autocomplete | modal |
AutocompleteResult | Suggestions. The only answer to Autocomplete | choices, up to 25 |
data takes content, embeds, components and ephemeral. Answering twice gets InteractionAlreadyAcknowledged.
Private replies
"ephemeral": true shows a reply to that person only. It is never stored in the channel, so it disappears when they reload. The choice is made once: a deferred answer stays as private as you said when deferring.
Deferred replies
# 1. within 3 seconds
curl -X POST "https://api.zrzur.com/interactions/INTERACTION_ID/YOUR_INTERACTION_TOKEN/callback" \
-H "content-type: application/json" \
-d '{ "type": "DeferredMessage", "data": { "ephemeral": true } }'
# 2. within 15 minutes
curl -X PATCH "https://api.zrzur.com/interactions/INTERACTION_ID/YOUR_INTERACTION_TOKEN/original" \
-H "content-type: application/json" \
-d '{ "content": "Done." }'Follow-ups
After the first answer you can send up to 5 more messages for the same interaction, until the token ends:
curl -X POST "https://api.zrzur.com/interactions/INTERACTION_ID/YOUR_INTERACTION_TOKEN/followups" \
-H "content-type: application/json" \
-d '{ "content": "One more thing.", "ephemeral": true }'The answer has the new message's _id. A follow-up has its own ephemeral choice, and cannot come after a Modal answer.
| To | Route |
|---|---|
| Edit the first answer | PATCH /interactions/{interaction_id}/{token}/original |
| Delete the first answer | DELETE /interactions/{interaction_id}/{token}/original |
| Edit a follow-up | PATCH /interactions/{interaction_id}/{token}/messages/{message_id} |
| Delete a follow-up | DELETE /interactions/{interaction_id}/{token}/messages/{message_id} |
Autocomplete
An option with "autocomplete": true asks your bot for suggestions while the person types. command.focused names the option, and its value holds the text so far, up to 100 characters.
{
"type": "AutocompleteResult",
"choices": [{ "name": "Apricot", "value": "apricot" }]
}Answer quickly, as each keystroke can send one. An Autocomplete interaction takes only this answer, and no others take it.
Common errors
| Error | Cause | Fix |
|---|---|---|
InteractionExpired | Over the 3 seconds, or the 15 minutes | Defer first |
InteractionAlreadyAcknowledged | A second first answer | Use a follow-up, or edit |
InvalidOperation | The answer does not fit, such as UpdateMessage on a command | Check the table above |
TooManyFollowups | More than 5 | Edit a message instead |
UnknownInteraction | Wrong id or token | Use the event's values |
Reference
GET /applications/{application_id}/commands
List Global Commands. Commands of this application available in every server it is installed in.
Rate limit: any_dlta, 20 / 10 s
POST /applications/{application_id}/commands
Create Global Command. Register a new command. A command with the same type and name is a conflict.
Rate limit: any_dlta, 20 / 10 s
PUT /applications/{application_id}/commands
Sync Global Commands. Replace every global command with the given list, matched by type and name. The list is validated as a whole before anything changes.
Rate limit: any_dlta, 20 / 10 s
DELETE /applications/{application_id}/commands/{command_id}
Delete Global Command.
Rate limit: any_dlta, 20 / 10 s
GET /applications/{application_id}/commands/{command_id}
Fetch Global Command.
Rate limit: any_dlta, 20 / 10 s
PATCH /applications/{application_id}/commands/{command_id}
Edit Global Command.
Rate limit: any_dlta, 20 / 10 s
GET /applications/{application_id}/servers/{server_id}/commands
List Server Commands. Commands of this application limited to one server it is installed in.
Rate limit: any_dlta, 20 / 10 s
POST /applications/{application_id}/servers/{server_id}/commands
Create Server Command.
Rate limit: any_dlta, 20 / 10 s
PUT /applications/{application_id}/servers/{server_id}/commands
Sync Server Commands.
Rate limit: any_dlta, 20 / 10 s
DELETE /applications/{application_id}/servers/{server_id}/commands/{command_id}
Delete Server Command.
Rate limit: any_dlta, 20 / 10 s
GET /applications/{application_id}/servers/{server_id}/commands/{command_id}
Fetch Server Command.
Rate limit: any_dlta, 20 / 10 s
PATCH /applications/{application_id}/servers/{server_id}/commands/{command_id}
Edit Server Command.
Rate limit: any_dlta, 20 / 10 s
DELETE /channels/{target}/messages/{msg}/reactions
Remove All Reactions from Message. Remove your own, someone else's or all of a given reaction.
Requires ManageMessages permission.
Permissions: Channel:ManageMessages · Rate limit: channels, 15 / 10 s
DELETE /channels/{target}/messages/{msg}/reactions/{emoji}
Remove Reaction(s) to Message. Remove your own, someone else's or all of a given reaction.
Requires ManageMessages if changing others' reactions.
Permissions: Channel:React, Channel:ManageMessages · Rate limit: channels, 15 / 10 s
PUT /channels/{target}/messages/{msg}/reactions/{emoji}
Add Reaction to Message. React to a given message.
Permissions: Channel:React · Rate limit: channels, 15 / 10 s
POST /interactions
Create Interaction. Use an application command, a component on a bot's message, or submit a form the bot opened. The server checks every value and permission, then sends the interaction to the bot only. The answer arrives as InteractionStateUpdate plus a channel message, a message update, EphemeralMessageCreate or InteractionModal, for this user.
Sending the same nonce again returns the first interaction.
Not available to bots.
Rate limit: interactions, 15 / 10 s
POST /interactions/{interaction_id}/{token}/callback
Respond to Interaction. First answer of the bot, authenticated by the interaction token. It must arrive before respond_by and can only happen once.
- Message: reply now; data.ephemeral makes it visible to the invoking user only, and it is never stored as a channel message. - DeferredMessage: show that the bot is working; finish later with PATCH /interactions/<id>/<token>/original before the token expires. - UpdateMessage / DeferredUpdate (components and forms opened from one): change the message the component is on, now or later. - Modal: open a form for the user (not as an answer to a form). - AutocompleteResult (autocomplete only): up to 25 suggestions.
Rate limit: interaction_callbacks, 10 / 10 s
POST /interactions/{interaction_id}/{token}/followups
Send Follow-up. Another message for the same interaction, after the first answer (or while it is deferred). At most 5 per interaction.
Rate limit: interaction_callbacks, 10 / 10 s
DELETE /interactions/{interaction_id}/{token}/messages/{message_id}
Delete Interaction Message. Delete the first answer or a follow-up by its message id. For private messages the invoking user's clients receive EphemeralMessageDelete.
Rate limit: interaction_callbacks, 10 / 10 s
PATCH /interactions/{interaction_id}/{token}/messages/{message_id}
Edit Interaction Message. Edit the first answer or a follow-up by its message id.
Rate limit: interaction_callbacks, 10 / 10 s
DELETE /interactions/{interaction_id}/{token}/original
Delete Original Response.
Rate limit: interaction_callbacks, 10 / 10 s
PATCH /interactions/{interaction_id}/{token}/original
Edit Original Response. Finish a deferred interaction, or edit the answer, until the token expires. After UpdateMessage or DeferredUpdate this edits the component's message.
Rate limit: interaction_callbacks, 10 / 10 s
POST /interactions/autocomplete
Request Autocomplete. Ask the bot for suggestions while the user types into an option with autocomplete. The suggestions arrive as InteractionAutocompleteResult. Clients should wait for a pause in typing and drop answers to older requests.
Not available to bots.
Rate limit: interactions_autocomplete, 30 / 10 s
GET /servers/{server_id}/applications
List Server Apps. Apps installed in this server, who installed them and with which permissions.
Rate limit: servers, 5 / 10 s
DELETE /servers/{server_id}/applications/{application_id}
Uninstall App. Remove an app's bot from the server: its membership, its managed role and its install record go; its server-scoped commands stop showing.
Rate limit: servers, 5 / 10 s
GET /servers/{server_id}/applications/{application_id}/commands
Fetch App Commands In Server. Every command of an app that works in this server, global and limited to this server, without any filtering: for the people who manage the app's rules. Needs Manage Server.
Rate limit: servers, 5 / 10 s
PUT /servers/{server_id}/applications/{application_id}/commands/{command_id}/permissions
Edit Command Permissions. Replace the rules for one command in this server; they come before the app's rules. An empty list removes them. Needs Manage Server and Manage Roles; see the module documentation for which rules an editor may write.
Rate limit: servers, 5 / 10 s
GET /servers/{server_id}/applications/{application_id}/permissions
Fetch Command Permissions. The rules set in this server for an app: the whole app (no command_id) and each command that has its own.
Rate limit: servers, 5 / 10 s
PUT /servers/{server_id}/applications/{application_id}/permissions
Edit App Permissions. Replace the rules for the whole app in this server. An empty list removes them. Needs Manage Server and Manage Roles; see the module documentation for which rules an editor may write.
Rate limit: servers, 5 / 10 s
GET /servers/{server_id}/commands
Fetch Server Commands. Commands a member can pick from in this server: those of every bot installed here, global or limited to this server. Commands that need server permissions the member lacks, or that the server's command permission rules keep from them, are left out. With channel, the channel rules count too (a thread or forum post uses its channel's); the channel is checked again when a command is used.
Rate limit: servers, 5 / 10 s