Discord
#Overview
Post to one Discord channel through a webhook you create yourself. There is no bot to install and no OAuth dance: Discord gives you a webhook URL, you paste it into yeetpost, and posts land in that channel under the name and avatar you gave the webhook.
Discord posts are free to send. The channel counts as one connected account, like LinkedIn or Bluesky. See pricing.
#How to connect
- In Discord, open the channel's settings, then Integrations, then Webhooks.
- Click New Webhook, give it a name and an avatar, and click Copy Webhook URL.
- In yeetpost, click Add connection, then Discord, and paste the URL.
The URL has to be a real Discord webhook URL, so
https://discord.com/api/webhooks/<id>/<token>. yeetpost calls it once to check it exists
and to read back the webhook's name and its channel.
The webhook URL is a credential. It is stored encrypted, never logged and never returned by the API. Anyone holding it can post to that channel, so treat it like an API key. To revoke it, delete the webhook in Discord.
Your first Discord connection gets the slug discord. A second one gets a slug built from
the webhook's name, so a webhook called "Build Bot 2" becomes buildbot2_discord.
GET /connections describes it as Build Bot 2 (Discord).
The connection is identified by the webhook id. Deleting the webhook in Discord and creating a new one means pasting the new URL, which connects a new channel.
#What works
| Thing | Value |
|---|---|
| Text limit | 2000 characters, counted in code points |
| Images | Up to 5 per post |
| Image formats | image/png, image/jpeg, image/gif, image/webp |
| Alt text | Yes, sent as each attachment's description |
| Threads | No, a webhook cannot reply to its own message |
| First comment | No, LinkedIn only |
| Scheduling | Yes |
| Permalink | https://discord.com/channels/<server>/<channel>/<message> |
| Per-post fee | None |
The 2000 is checked before anything is sent, so a long post comes back as a refusal rather than as a Discord rejection.
There is no image size pre-flight for Discord. A webhook on an unboosted server takes
8 MB, and the yeetpost per-image cap is the same 8 MB, so the cap that binds is ours. A
server with a stricter limit answers with its own refusal and the item comes back
media_unsupported.
A rate limit is absorbed once. Discord answers a burst with a retry_after. When that
is 5 seconds or less, yeetpost waits it out and sends again. Anything longer comes back as
platform_rejected rather than holding your request open.
A webhook that lives outside a server has no server id, so its permalinks use @me in
place of one.
#Refusals
Every one of these is a per-item refusal: the other connections on the same post still go out. See the errors reference for the full vocabulary.
| Code | Status | When |
|---|---|---|
invalid_request | 400 | Text over 2000 code points |
media_unsupported | 400 | The server refused the image, usually its own upload limit |
shape_unsupported | 400 | A thread or a firstComment was given. Discord has neither |
platform_rejected | 422 | The webhook no longer exists, is no longer allowed to post, is rate limited past 5 seconds, or Discord refused the message |
internal_server_error | 500 | Our fault. Quote the req_id when you report it |
Discord never answers unauthorized here: a webhook that lost its permission comes back as
platform_rejected with a message saying so.
#Post from curl
curl -X POST https://api.yeetpost.com/api/v2/posts \
-H "x-api-key: $YEETPOST_API_KEY" \
-H "content-type: application/json" \
-H "Idempotency-Key: $(uuidgen)" \
-d '{
"text": "deploy 2.4.0 finished, all checks green",
"connectionSlugs": ["discord"]
}'#Post from Node
const response = await fetch("https://api.yeetpost.com/api/v2/posts", {
method: "POST",
headers: {
"x-api-key": process.env.YEETPOST_API_KEY,
"content-type": "application/json",
"Idempotency-Key": crypto.randomUUID(),
},
body: JSON.stringify({
text: "deploy 2.4.0 finished, all checks green",
connectionSlugs: ["discord", "telegram"],
}),
});
const data = await response.json();
for (const result of data.results) {
console.log(result.connectionSlug, result.status, result.url);
}#FAQ
#Can I post to several channels?
Yes, one webhook per channel and one connection per webhook. Name them in
connectionSlugs and the same call fans out to all of them.
#Why can I not send a thread to Discord?
A webhook posts messages, it cannot reply to one. Ask for a thread on a Discord
connection and that item is refused with shape_unsupported while the connections that do
have threads, X, Bluesky, Telegram and Mastodon, still go out.
#The webhook stopped working. What happened?
Somebody deleted it in Discord, or the channel's permissions changed. Posts come back
platform_rejected with a message naming which of the two it was. Create a new webhook and
paste the new URL.
#Does the post show my name?
No. It shows the name and the avatar you gave the webhook when you created it in Discord. Change them there and every later post follows.
#Is Discord billed per post?
No. Discord costs us nothing per message, so posts are free. Only X carries a per-post fee.