Discord webhooks
Send messages to a Discord channel from your FlareX app via incoming webhooks — without building a full Discord bot.
Updated
If all you need is "post messages into one specific channel," you don't need a Discord bot. Use an incoming webhook instead. No bot token, no OAuth, no permissions matrix — just a URL you POST JSON to.
If you need a bot that responds to commands, reads messages, or manages roles, that's a full Discord bot instead.
Create the webhook
Open the channel settings in Discord
Right-click the channel → Edit Channel → Integrations → Webhooks → New Webhook.
Configure
Name the webhook (this becomes the "from" name on messages — overrideable per-message). Optionally upload an avatar.
Copy the webhook URL
Click Copy Webhook URL. It looks like:
https://discord.com/api/webhooks/<id>/<token>Treat the URL like a password — anyone with it can post to your channel.
Add to Secrets
DISCORD_WEBHOOK_URL=https://discord.com/api/webhooks/...
Pattern 1: Plain message
On every new signup, post to Discord with:
🎉 New signup: <email> from <country>
await fetch(process.env.DISCORD_WEBHOOK_URL!, {
method: 'POST',
headers: { 'content-type': 'application/json' },
body: JSON.stringify({
content: `🎉 New signup: ${email} from ${country}`,
}),
});
Pattern 2: Embed (rich card)
Embeds give you a title, color bar, fields, footer, timestamp:
await fetch(process.env.DISCORD_WEBHOOK_URL!, {
method: 'POST',
headers: { 'content-type': 'application/json' },
body: JSON.stringify({
embeds: [{
title: 'New paid subscriber',
color: 0x57F287, // green
fields: [
{ name: 'Email', value: email, inline: true },
{ name: 'Plan', value: plan, inline: true },
{ name: 'MRR delta', value: `+$${mrrDelta}`, inline: true },
],
footer: { text: 'flarex.app' },
timestamp: new Date().toISOString(),
}],
}),
});
Tell FlareX:
On invoice.paid webhook from Stripe, post a Discord embed to
DISCORD_WEBHOOK_URL with title "Payment received", green color bar,
fields for email + amount + plan, footer "flarex.app", and current timestamp.
Pattern 3: Override the bot name + avatar per message
Same webhook, different "personas":
await fetch(WEBHOOK_URL, {
method: 'POST',
headers: { 'content-type': 'application/json' },
body: JSON.stringify({
username: 'Stripe',
avatar_url: 'https://stripe.com/img/v3/home/twitter.png',
content: '💳 New payment',
}),
});
Useful for "a single channel that aggregates events from multiple services" — give each its own avatar so they're visually distinct.
Rate limits
Discord caps webhook posts at 30 messages per minute per channel. Above that, requests get 429.
For high-volume channels:
- Batch: collect messages in a 5s buffer and post one combined embed.
- Throttle on your end: post no faster than 1/2s (well under the limit).
- Use multiple webhooks: separate channels = separate buckets.
On post-signup events, batch up to 10 events per minute into one
Discord embed with each signup as a field. If a single batch would
exceed 25 fields, post immediately.
Error handling
Discord returns { "code": 50027, "message": "Invalid Webhook Token" } when the webhook is deleted or its token rotated. Surface this clearly so you know to update the secret rather than retry forever:
const res = await fetch(WEBHOOK_URL, { ... });
if (res.status === 401 || res.status === 404) {
console.error('Discord webhook deleted or token rotated — update DISCORD_WEBHOOK_URL');
// optional: alert yourself via another channel
return;
}
if (res.status === 429) {
const retryAfter = Number(res.headers.get('retry-after') ?? 1);
await new Promise(r => setTimeout(r, retryAfter * 1000));
// retry once
}
Webhooks vs. bots — when to upgrade
You've outgrown an incoming webhook when you need any of:
- React to messages or commands → bot with Discord Gateway
- Read message history → bot
- Add or remove roles → bot
- Slash commands → bot (with interaction webhooks)
- DM users → bot
For one-way notifications, webhooks stay simpler indefinitely.
What's next
- Build a Discord bot — when one-way isn't enough
- Webhooks (incoming) — receive payloads from other services
- Stripe — common source of "post to Discord" events