Skip to content

Handling buttons and menus

When someone clicks a button or picks something in a menu, Discord sends your bot an interaction. Your bot must respond within 3 seconds.

  1. Your bot sends a message with a button that has custom_id: "counter".
  2. A user clicks the button.
  3. Discord sends your bot a MESSAGE_COMPONENT (3) interaction with that custom_id.
  4. Your bot looks at the custom_id, decides what to do and responds (new message, edit the message or open a modal).

Inside the interaction, the data field has the component information:

Field Type Description
custom_id string The custom_id you set on the component.
component_type integer Component type (2 = button, 3 = string select…).
values array of strings Menus only: the selected values.
resolved object User/role/channel menus only: full data (users, roles, channels) of the selection.
Received interaction (trimmed)
{
"type": 3,
"id": "1234567890",
"token": "aW50ZXJhY3Rpb24...",
"data": {
"custom_id": "counter",
"component_type": 2,
"id": 3
},
"message": { "id": "...", "flags": 32768, "components": [] }
}
Type Value What it does When to use it
CHANNEL_MESSAGE_WITH_SOURCE 4 Sends a new message. Reply with information (can be ephemeral).
DEFERRED_CHANNEL_MESSAGE_WITH_SOURCE 5 Shows “thinking…” and you reply later. When you need more than 3 s to build the message.
DEFERRED_UPDATE_MESSAGE 6 Acknowledges the click showing nothing; you edit later. Slow work that ends up editing the message.
UPDATE_MESSAGE 7 Edits the message the button is on. Counters, pagination, toggling state.
MODAL 9 Opens a form (modal). Ask the user for text, files or choices.

Every time someone clicks the button, the message is updated with the new number (response type 7).

Preview
My BotAPPToday at 12:00 PM

Counter

You clicked the button 3 times.

Counter message
{
"flags": 32768,
"components": [
{
"type": 17,
"accent_color": 5793266,
"components": [
{
"type": 10,
"content": "### Counter\nYou clicked the button **3** times."
},
{
"type": 1,
"components": [
{
"type": 2,
"style": 1,
"label": "+1",
"custom_id": "counter:3"
},
{
"type": 2,
"style": 4,
"label": "Reset",
"custom_id": "reset"
}
]
}
]
}
]
}

Respond to the interaction with UPDATE_MESSAGE (7). The body is the complete new message:

POST /interactions/{interaction.id}/{interaction.token}/callback
{
"type": 7,
"data": {
"flags": 32768,
"components": [
{
"type": 17,
"accent_color": 5793266,
"components": [
{ "type": 10, "content": "### Counter\nYou clicked the button **4** times." },
{
"type": 1,
"components": [
{ "type": 2, "style": 1, "label": "+1", "custom_id": "counter:4" },
{ "type": 2, "style": 4, "label": "Reset", "custom_id": "reset" }
]
}
]
}
]
}
}

An ephemeral message is only visible to the person who clicked. Combine the IS_COMPONENTS_V2 (32768) and EPHEMERAL (64) flags = 32832.

Preview
My BotAPPToday at 12:00 PM

✅ You're signed up for the event. See you there!

👁 Only you can see this
{
"type": 4,
"data": {
"flags": 32832,
"components": [
{ "type": 10, "content": "✅ You're signed up for the event. See you there!" }
]
}
}

For menus, the selected values arrive in data.values:

Interaction data
{
"custom_id": "pick_color",
"component_type": 3,
"values": ["red", "blue"]
}

If you used DEFERRED_UPDATE_MESSAGE (6) or want to change the response later, edit the original response:

PATCH /webhooks/{application.id}/{interaction.token}/messages/@original

And to send extra messages (follow-ups):

POST /webhooks/{application.id}/{interaction.token}

Learn how to ask users for input with modals.