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.
DisGo provides a dedicated webhook client for sending messages through Discord webhooks without requiring a bot token. This is useful for notifications, logging, and integrations.
Creating a webhook client
You can create a webhook client using either the webhook ID and token, or by parsing a webhook URL.
Using ID and token
import (
" github.com/disgoorg/disgo/webhook "
" github.com/disgoorg/snowflake/v2 "
)
webhookID := snowflake . MustParse ( "YOUR_WEBHOOK_ID" )
webhookToken := "YOUR_WEBHOOK_TOKEN"
client := webhook . New ( webhookID , webhookToken )
defer client . Close ( context . TODO ())
Using webhook URL
If you have a webhook URL from Discord, you can parse it directly:
webhookURL := "https://discord.com/api/webhooks/123456789/abcdefghijklmnop"
client , err := webhook . NewWithURL ( webhookURL )
if err != nil {
// Handle invalid URL
}
defer client . Close ( context . TODO ())
Webhook tokens are sensitive credentials. Never expose them in client-side code or public repositories.
Sending messages
The webhook client provides several methods for sending messages.
Basic message
messageCreate := discord . NewWebhookMessageCreateBuilder ().
SetContent ( "Hello from DisGo!" ).
Build ()
message , err := client . CreateMessage (
messageCreate ,
rest . CreateWebhookMessageParams { Wait : true },
)
if err != nil {
// Handle error
}
Setting Wait: true returns the created message. Without it, the method returns nil for the message.
Content shorthand
For simple text messages, use the convenience method:
message , err := client . CreateContent ( "Simple text message" )
if err != nil {
// Handle error
}
Messages with embeds
embed := discord . NewEmbedBuilder ().
SetTitle ( "Alert" ).
SetDescription ( "Something important happened" ).
SetColor ( 0x FF0000 ).
SetTimestamp ( time . Now ()).
AddField ( "Status" , "Critical" , true ).
AddField ( "Count" , "42" , true ).
Build ()
messageCreate := discord . NewWebhookMessageCreateBuilder ().
AddEmbeds ( embed ).
Build ()
message , err := client . CreateMessage (
messageCreate ,
rest . CreateWebhookMessageParams { Wait : true },
)
Embeds shorthand
embeds := [] discord . Embed {
discord . NewEmbedBuilder ().
SetTitle ( "First Embed" ).
Build (),
discord . NewEmbedBuilder ().
SetTitle ( "Second Embed" ).
Build (),
}
message , err := client . CreateEmbeds ( embeds )
Username and avatar overrides
Webhooks can override the username and avatar for each message:
messageCreate := discord . NewWebhookMessageCreateBuilder ().
SetContent ( "Custom identity message" ).
SetUsername ( "Custom Bot Name" ).
SetAvatarURL ( "https://cdn.example.com/avatar.png" ).
Build ()
message , err := client . CreateMessage (
messageCreate ,
rest . CreateWebhookMessageParams { Wait : true },
)
Username changes are rate limited. Don’t change the username with every message or you may be rate limited.
Thread support
Webhooks can post messages to threads within the webhook’s channel.
Post to existing thread
messageCreate := discord . NewWebhookMessageCreateBuilder ().
SetContent ( "Message in thread" ).
Build ()
message , err := client . CreateMessageInThread (
messageCreate ,
threadID ,
)
Create thread with message
messageCreate := discord . NewWebhookMessageCreateBuilder ().
SetContent ( "First message in new thread" ).
Build ()
message , err := client . CreateMessage (
messageCreate ,
rest . CreateWebhookMessageParams {
Wait : true ,
ThreadName : "New Thread Name" ,
},
)
Editing and deleting messages
Edit a message
content := "Updated content"
messageUpdate := discord . NewWebhookMessageUpdateBuilder ().
SetContent ( content ).
Build ()
updatedMessage , err := client . UpdateMessage (
message . ID ,
messageUpdate ,
rest . UpdateWebhookMessageParams {},
)
Update shortcuts
// Update content only
message , err := client . UpdateContent ( messageID , "New content" )
// Update embeds only
message , err := client . UpdateEmbeds ( messageID , [] discord . Embed { embed })
Delete a message
err := client . DeleteMessage ( messageID )
if err != nil {
// Handle error
}
Thread message operations
// Update message in thread
message , err := client . UpdateMessageInThread (
messageID ,
messageUpdate ,
threadID ,
)
// Delete message in thread
err := client . DeleteMessageInThread ( messageID , threadID )
Managing the webhook
webhook , err := client . GetWebhook ()
if err != nil {
// Handle error
}
fmt . Printf ( "Webhook: %s \n " , webhook . Name )
fmt . Printf ( "Channel: %s \n " , webhook . ChannelID )
Update webhook
name := "New Webhook Name"
avatar := "https://cdn.example.com/new-avatar.png"
webhookUpdate := discord . WebhookUpdateWithToken {
Name : & name ,
Avatar : & avatar ,
}
updatedWebhook , err := client . UpdateWebhook ( webhookUpdate )
if err != nil {
// Handle error
}
Delete webhook
err := client . DeleteWebhook ()
if err != nil {
// Handle error
}
Deleting a webhook is permanent and cannot be undone. Make sure you really want to delete it.
Rate limiting and delays
DisGo automatically handles Discord’s rate limits, but you can add additional delays:
message , err := client . CreateMessage (
messageCreate ,
rest . CreateWebhookMessageParams { Wait : true },
rest . WithDelay ( 2 * time . Second ), // Wait 2 seconds before sending
)
Concurrent webhook requests
Webhooks are perfect for concurrent operations since they don’t share global rate limits with bot operations:
var wg sync . WaitGroup
for i := 1 ; i <= 10 ; i ++ {
wg . Add ( 1 )
go func ( num int ) {
defer wg . Done ()
messageCreate := discord . NewWebhookMessageCreateBuilder ().
SetContentf ( "Message # %d " , num ).
Build ()
_ , err := client . CreateMessage (
messageCreate ,
rest . CreateWebhookMessageParams { Wait : true },
rest . WithDelay ( time . Duration ( num ) * time . Second ),
)
if err != nil {
slog . Error ( "failed to send message" ,
slog . Int ( "num" , num ),
slog . Any ( "err" , err ),
)
}
}( i )
}
wg . Wait ()
Complete notification example
Here’s a complete example for sending server notifications:
package main
import (
" context "
" fmt "
" log/slog "
" os "
" time "
" github.com/disgoorg/disgo/discord "
" github.com/disgoorg/disgo/rest "
" github.com/disgoorg/disgo/webhook "
)
func main () {
webhookURL := os . Getenv ( "WEBHOOK_URL" )
client , err := webhook . NewWithURL ( webhookURL )
if err != nil {
slog . Error ( "invalid webhook URL" , slog . Any ( "err" , err ))
return
}
defer client . Close ( context . TODO ())
// Send startup notification
sendNotification ( client , "Server Started" , "Application is now running" , 0x 00FF00 )
// Simulate some work
time . Sleep ( 5 * time . Second )
// Send status update
sendNotification ( client , "Status Update" , "Processing 1000 items" , 0x 0000FF )
// Send error notification
sendNotification ( client , "Error Occurred" , "Failed to connect to database" , 0x FF0000 )
}
func sendNotification ( client * webhook . Client , title , description string , color int ) {
embed := discord . NewEmbedBuilder ().
SetTitle ( title ).
SetDescription ( description ).
SetColor ( color ).
SetTimestamp ( time . Now ()).
SetFooter ( "Server Monitor" , "" ).
Build ()
messageCreate := discord . NewWebhookMessageCreateBuilder ().
AddEmbeds ( embed ).
Build ()
message , err := client . CreateMessage (
messageCreate ,
rest . CreateWebhookMessageParams { Wait : true },
)
if err != nil {
slog . Error ( "failed to send notification" , slog . Any ( "err" , err ))
return
}
fmt . Printf ( "Sent notification: %s (ID: %s ) \n " , title , message . ID )
}
Configuration options
You can customize the webhook client with configuration options:
import (
" github.com/disgoorg/disgo/rest "
" github.com/disgoorg/disgo/webhook "
)
client := webhook . New ( webhookID , webhookToken ,
webhook . WithLogger ( logger ),
webhook . WithRestClient ( customRestClient ),
webhook . WithRestClientConfigOpts (
rest . WithHTTPClient ( httpClient ),
rest . WithUserAgent ( "CustomBot/1.0" ),
),
)
Available options:
WithLogger(*slog.Logger) - Set custom logger
WithRestClient(rest.Client) - Use custom REST client
WithRestClientConfigOpts(...rest.ClientConfigOpt) - Configure REST client
Best practices
The webhook client maintains a connection pool. Always close it when done: client := webhook . New ( webhookID , webhookToken )
defer client . Close ( context . TODO ())
Use Wait parameter appropriately
Set Wait: true only when you need the returned message object: // Need message ID for later operations
message , err := client . CreateMessage (
messageCreate ,
rest . CreateWebhookMessageParams { Wait : true },
)
// Fire and forget
_ , err := client . CreateMessage (
messageCreate ,
rest . CreateWebhookMessageParams { Wait : false },
)
Handle rate limits gracefully
Even with automatic rate limiting, be mindful of Discord’s limits: // Bad: Sending too many messages too quickly
for i := 0 ; i < 1000 ; i ++ {
client . CreateContent ( fmt . Sprintf ( "Message %d " , i ))
}
// Good: Add delays between messages
for i := 0 ; i < 1000 ; i ++ {
client . CreateMessage (
messageCreate ,
rest . CreateWebhookMessageParams { Wait : true },
rest . WithDelay ( time . Second ),
)
}
Treat webhook tokens like passwords: // Good: Load from environment or secret manager
webhookURL := os . Getenv ( "WEBHOOK_URL" )
// Bad: Hardcode in source code
webhookURL := "https://discord.com/api/webhooks/..."