yeetpost

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

  1. In Discord, open the channel's settings, then Integrations, then Webhooks.
  2. Click New Webhook, give it a name and an avatar, and click Copy Webhook URL.
  3. 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

ThingValue
Text limit2000 characters, counted in code points
ImagesUp to 5 per post
Image formatsimage/png, image/jpeg, image/gif, image/webp
Alt textYes, sent as each attachment's description
ThreadsNo, a webhook cannot reply to its own message
First commentNo, LinkedIn only
SchedulingYes
Permalinkhttps://discord.com/channels/<server>/<channel>/<message>
Per-post feeNone

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.

CodeStatusWhen
invalid_request400Text over 2000 code points
media_unsupported400The server refused the image, usually its own upload limit
shape_unsupported400A thread or a firstComment was given. Discord has neither
platform_rejected422The webhook no longer exists, is no longer allowed to post, is rate limited past 5 seconds, or Discord refused the message
internal_server_error500Our 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.

Other platforms