Documentation Index
Fetch the complete documentation index at: https://mintlify.com/disgoorg/disgo/llms.txt
Use this file to discover all available pages before exploring further.
HTTP interactions allow you to build Discord bots without maintaining a persistent WebSocket connection. This is perfect for serverless deployments, reduced resource usage, and simpler infrastructure.
How HTTP interactions work
Instead of connecting to Discord’s gateway, your bot receives interactions via HTTP webhooks. Discord sends a POST request to your server when users interact with your bot.
HTTP interactions are ideal for serverless platforms like AWS Lambda, Google Cloud Functions, Cloudflare Workers, and Vercel.
Setting up HTTP interactions
Configure your public key
Get your application’s public key from the Discord Developer Portal and set it as an environment variable:export DISGO_TOKEN="your-bot-token"
export DISGO_PUBLIC_KEY="your-public-key"
Create your bot with HTTP server
package main
import (
"context"
"log/slog"
"os"
"os/signal"
"syscall"
"github.com/disgoorg/snowflake/v2"
"github.com/disgoorg/disgo"
"github.com/disgoorg/disgo/bot"
"github.com/disgoorg/disgo/discord"
"github.com/disgoorg/disgo/events"
"github.com/disgoorg/disgo/httpserver"
)
var (
token = os.Getenv("disgo_token")
publicKey = os.Getenv("disgo_public_key")
guildID = snowflake.GetEnv("disgo_guild_id")
commands = []discord.ApplicationCommandCreate{
discord.SlashCommandCreate{
Name: "say",
Description: "says what you say",
Options: []discord.ApplicationCommandOption{
discord.ApplicationCommandOptionString{
Name: "message",
Description: "What to say",
Required: true,
},
},
},
}
)
func main() {
client, err := disgo.New(token,
bot.WithHTTPServerConfigOpts(publicKey,
httpserver.WithURL("/interactions/callback"),
httpserver.WithAddress(":8080"),
),
bot.WithEventListenerFunc(commandListener),
)
if err != nil {
panic("error while building disgo instance: " + err.Error())
}
defer client.Close(context.TODO())
// Register commands
if _, err = client.Rest.SetGuildCommands(client.ApplicationID, guildID, commands); err != nil {
panic("error while registering commands: " + err.Error())
}
// Start HTTP server
if err = client.OpenHTTPServer(); err != nil {
panic("error while starting http server: " + err.Error())
}
slog.Info("bot is now running. Press CTRL-C to exit.")
s := make(chan os.Signal, 1)
signal.Notify(s, syscall.SIGINT, syscall.SIGTERM, os.Interrupt)
<-s
}
func commandListener(event *events.ApplicationCommandInteractionCreate) {
data := event.SlashCommandInteractionData()
if data.CommandName() == "say" {
if err := event.CreateMessage(discord.MessageCreate{
Content: data.String("message"),
}); err != nil {
event.Client().Logger.Error("error on sending response", slog.Any("err", err))
}
}
}
Configure Discord webhook URL
In the Discord Developer Portal, set your “Interactions Endpoint URL” to:https://your-domain.com/interactions/callback
Discord will verify your endpoint by sending a ping request.
HTTP server configuration
Customize your HTTP server with various options:
client, err := disgo.New(token,
bot.WithHTTPServerConfigOpts(publicKey,
// URL path for interactions
httpserver.WithURL("/interactions"),
// Server address and port
httpserver.WithAddress(":8080"),
// Custom HTTP server
httpserver.WithServer(&http.Server{
Addr: ":8080",
ReadTimeout: 10 * time.Second,
}),
// Custom verifier
httpserver.WithVerifier(customVerifier{}),
),
)
Custom signature verification
You can implement custom signature verification:
type customVerifier struct{}
func (customVerifier) Verify(publicKey httpserver.PublicKey, message, sig []byte) bool {
return ed25519.Verify(publicKey, message, sig)
}
func (customVerifier) SignatureSize() int {
return ed25519.SignatureSize
}
client, err := disgo.New(token,
bot.WithHTTPServerConfigOpts(publicKey,
httpserver.WithVerifier(customVerifier{}),
),
)
Serverless deployment
AWS Lambda example
package main
import (
"context"
"os"
"github.com/aws/aws-lambda-go/events"
"github.com/aws/aws-lambda-go/lambda"
"github.com/disgoorg/disgo"
"github.com/disgoorg/disgo/bot"
"github.com/disgoorg/disgo/httpserver"
)
var client bot.Client
func init() {
var err error
client, err = disgo.New(os.Getenv("DISGO_TOKEN"),
bot.WithHTTPServerConfigOpts(os.Getenv("DISGO_PUBLIC_KEY")),
bot.WithEventListenerFunc(handleCommand),
)
if err != nil {
panic(err)
}
}
func handler(ctx context.Context, request events.APIGatewayProxyRequest) (events.APIGatewayProxyResponse, error) {
// Verify and handle the interaction
return client.HTTPServer().HandleRequest(ctx, request)
}
func main() {
lambda.Start(handler)
}
func handleCommand(event *events.ApplicationCommandInteractionCreate) {
// Handle your commands
}
Cloudflare Workers example
package main
import (
"github.com/disgoorg/disgo"
"github.com/disgoorg/disgo/bot"
"github.com/syumai/workers"
)
var client bot.Client
func init() {
var err error
client, err = disgo.New(workers.Getenv("DISGO_TOKEN"),
bot.WithHTTPServerConfigOpts(workers.Getenv("DISGO_PUBLIC_KEY")),
bot.WithEventListenerFunc(handleCommand),
)
if err != nil {
panic(err)
}
}
func main() {
workers.Serve(client.HTTPServer())
}
func handleCommand(event *events.ApplicationCommandInteractionCreate) {
// Handle your commands
}
Differences from gateway bots
What works with HTTP interactions
- ✅ Slash commands
- ✅ Button and select menu interactions
- ✅ Modal submissions
- ✅ Autocomplete
- ✅ REST API calls
What doesn’t work
- ❌ Gateway events (message create, member join, etc.)
- ❌ Real-time event streaming
- ❌ Voice connections
- ❌ Presence updates
- ❌ Gateway intents
HTTP interactions only receive interaction events. You cannot listen to messages, reactions, or other gateway events.
Responding to interactions
You must respond to interactions within 3 seconds:
func commandListener(event *events.ApplicationCommandInteractionCreate) {
// Option 1: Immediate response
event.CreateMessage(discord.MessageCreate{
Content: "Hello!",
})
// Option 2: Deferred response (for long operations)
event.DeferCreateMessage(false)
// Do long operation...
// Then send followup
event.Client().Rest.CreateFollowupMessage(
event.ApplicationID,
event.Token,
discord.MessageCreate{Content: "Done!"},
)
}
Deferred responses
For operations that take longer than 3 seconds:
func commandListener(event *events.ApplicationCommandInteractionCreate) {
// Tell Discord you're processing (shows "Bot is thinking...")
if err := event.DeferCreateMessage(false); err != nil {
return
}
// Do your long operation
result := performLongOperation()
// Send the result as a followup
_, err := event.Client().Rest.CreateFollowupMessage(
event.ApplicationID,
event.Token,
discord.MessageCreate{Content: result},
)
}
Advantages of HTTP interactions
- Lower costs: No persistent connections mean less resource usage
- Better scaling: Serverless platforms handle scaling automatically
- Simpler infrastructure: No need to manage WebSocket connections
- Faster cold starts: No gateway connection required
- Regional deployment: Deploy to multiple regions easily
Disadvantages
- Limited to interactions: Cannot receive gateway events
- No real-time events: Can’t listen to messages, reactions, etc.
- Startup verification: Discord pings your endpoint on startup
- Public endpoint required: Must be accessible from the internet
Best practices
- Respond quickly: Always respond within 3 seconds or defer
- Use deferred responses: For operations taking more than 1 second
- Validate public key: Ensure signature verification is working
- Handle retries: Discord may retry failed interactions
- Use environment variables: Store tokens and keys securely
- Enable HTTPS: Required for production deployments
- Monitor latency: Keep response times under 1 second when possible
Testing locally
Use a tunnel service to test locally:
# Using ngrok
ngrok http 8080
# Use the ngrok URL as your interactions endpoint
https://abc123.ngrok.io/interactions/callback
Next steps