# Discord Integration


The Discord integration lets your VM post messages to a Discord channel with
a plain HTTP request — no webhook URL on the VM, no Discord library required.
It's handy for build notifications, long-running job completions, or anything
an agent wants to tell you about.

If you want a bot that can *act* on Discord — read message history, react,
manage roles, call the full Discord Bot API — see the
[Discord Bot Integration](integrations-discord-bot) instead.

## Setup

Click the **Discord** tile on the [Integrations page](/integrations), or run:

```
exe.dev ▶ integrations setup discord
```

Either way, you'll be sent to Discord to authorize the exe.dev app. Discord
shows a server and channel picker: choose where the integration should post,
then click **Authorize**. That's the whole dance — Discord hands exe.dev an
incoming webhook for that channel, exe.dev stores it server-side, and the
integration is created for you.

Each integration posts to exactly one channel. To post to a second channel,
run setup again and pick a different channel.

## Sending messages

Attach the integration to a VM, then POST JSON to the integration hostname:

```
exe.dev ▶ integrations attach discord-hook vm:my-vm
Attached discord-hook to vm:my-vm

exe.dev ▶ ssh my-vm curl --json '{"content":"build finished ✅"}' https://discord-hook.int.exe.xyz/
```

The request body is Discord's [webhook execute
payload](https://discord.com/developers/docs/resources/webhook#execute-webhook),
so `content`, `embeds`, `components`, and friends all work:

```
curl --json '{"embeds":[{"title":"deploy done","description":"v42 is live 🚀","color":5763719}]}' \
  https://discord-hook.int.exe.xyz/
```

Two query parameters pass through: `wait=true` to get the created message
back in the response, and `thread_id=<id>` to post into a thread.

## Notes

- The webhook URL is a secret, and it never touches your VM. exe.dev holds it
  server-side and injects it when proxying your request.
- Messages are rate limited to 5 per minute per user, and exe.dev also
  honors Discord's own per-webhook rate limit headers proactively — when a
  limit is hit you get a 429 with a `Retry-After` header.
- The payload must be JSON (`Content-Type: application/json`), at most
  256 KiB. File uploads (multipart) are not supported.
- The `username` and `avatar_url` override fields are rejected, and mass
  mentions (`@everyone`, role and user pings) are neutralized — a VM can't
  impersonate someone else or ping your whole server.
- If the webhook is deleted on the Discord side (Server Settings →
  Integrations → Webhooks), requests return 404 — re-run
  `integrations setup discord`.

## Manual webhook

Already have a Discord webhook URL? Create one in Discord under
**Server Settings → Integrations → Webhooks → New Webhook**, pick the
channel, **Copy Webhook URL**, then skip OAuth and add it directly:

```
exe.dev ▶ integrations add discord --name my-discord --webhook-url https://discord.com/api/webhooks/1234567890/XXXX
```
