Discord API: posting reference
OmniSocials posts to one Discord channel per workspace through an incoming webhook of that channel. No token expires. The workspace connects the channel once in the OmniSocials dashboard (Channels, then Add a channel, then Discord), in one of two ways:
- Continue with Discord (recommended). Discord's own screen asks for the server and the channel; pick a text channel (Discord lists voice channels there too, and a post would land in the voice channel's chat). The person who connects needs the Manage Server permission in that server. OmniSocials keeps the webhook Discord creates, and the server name and icon. Discord gives a webhook no channel name: where the sign-in also adds the OmniSocials bot (with no permissions), the bot reads the channel's name and type and the server's member count, and OmniSocials says so right after connecting when the channel is a voice channel. Without the bot, OmniSocials asks you which channel you picked. The bot never posts and never reads messages; posts always go through the webhook.
- Paste a webhook URL. Make a webhook in Discord (Server Settings, then Integrations, then Webhooks, then New Webhook), pick the channel, press Copy Webhook URL and paste it in OmniSocials. Discord tells a webhook URL no server or channel name, so the account shows the webhook's name, and OmniSocials asks you which channel it is (unless the OmniSocials bot is already in that server).
A post shows the webhook's name and picture as the sender. Change them in Discord, in the webhook's settings. Disconnecting the channel in OmniSocials never deletes the webhook in Discord.
Channel ID: discord
Supported content types
| Type | Supported |
|---|---|
| Text post | ✅ |
| Images, GIFs and videos (up to 10, mixed) | ✅ |
| Native poll | ✅ |
| Forum or media channel post | ✅ (with thread_name) |
| Reel | ✅ (sent as one video message) |
| Story | - |
Minimal example
Terminal
Platform-specific options
| Field | Type | Description |
|---|---|---|
discord.silent | boolean | Send without a push or desktop notification (Discord's @silent). |
discord.link_preview | boolean | false hides the previews of the links in the text. The previews show by default. |
discord.allow_mentions | boolean | Let @everyone, @here, role and user mentions in the text notify people. Off by default. See Mentions. |
discord.spoiler | boolean | Blur every image and video until someone clicks it. |
discord.thread_name | string | The post title in a forum or media channel, 1 to 100 characters. See Forum and media channels. |
discord.buttons | array | Up to 5 link buttons under the message. See Buttons. |
discord.poll | object | A native Discord poll; the post text is the question. See Polls. |
On PATCH /posts/:id, every key merges into the stored options, and a key set to null removes it (for example "discord": { "poll": null }). "discord": null removes every option.
Mentions
Mentions in the text are off by default: @everyone, @here, a role or a user in the text shows as text and notifies nobody, so a scheduled post never pings a whole server by accident. Set discord.allow_mentions: true to let them ping. A role mention is written <@&role_id> and a user mention <@user_id> (in Discord, turn on Developer Mode and copy the id).
Buttons
JSON
Rules:
- At most 5 buttons, in one row under the message.
textis 1 to 80 characters.urlstarts withhttps://orhttp://.- A poll carries no buttons: a request with both is refused with
400 validation_error.
Polls
JSON
| Field | Type | Description |
|---|---|---|
options | array of strings | 2 to 10 answers of up to 55 characters. The answers must differ from each other. |
duration_hours | integer | Hours the poll stays open, 1 to 768 (32 days). Default 24. |
multiple | boolean | Let people pick several answers (default false). |
The question is the post text, 1 to 300 characters. A poll carries no media and no buttons: a request with either is refused with 400 validation_error. The votes come back in analytics under metrics.poll.
Forum and media channels
A forum or media channel holds posts, each with its own title. Discord requires a title there: set discord.thread_name (1 to 100 characters), and the message opens a new post with that title. GET /posts/:id then returns the post's id in discord.result.thread_id.
Leave thread_name out for a text or announcement channel: Discord refuses a title there, so OmniSocials sends the post without it and adds the warning thread_name_ignored to discord.result.warnings. A forum or media channel without a title fails with a message that says what to change.
Media requirements
| Media | Requirement |
|---|---|
| Image | JPEG, PNG, WebP and GIF, up to 40 MB. Discord takes files of up to 20 MB from a webhook; OmniSocials re-encodes a larger image to a JPEG that fits. |
| Video | MP4, MOV or WebM, up to 1 GB. No duration cap. A video of up to 20 MB is attached; a larger one is sent as a link to the file in the message, and Discord shows a player for it. |
| GIF | Up to 20 MB attached; a larger GIF is sent as a link. |
A message holds up to 10 files, and images, GIFs and videos can be mixed. OmniSocials attaches every file from its own servers. Media sent as a link is listed in discord.result.video_links. When the links do not fit in the 2,000-character text, they follow in a second message right after the post (discord.result.link_message_id).
Character limit
2,000 characters per message, counted in UTF-16 code units: most emoji count as 2. A poll question allows 300 characters. Discord shows its own Markdown in the text (**bold**, *italic*, lists, [masked links](https://example.com)).
Published post
GET /posts/:id returns under discord.result:
| Field | Description |
|---|---|
webhook_id | The webhook the post went through. |
guild_id, channel_id | The Discord server and channel. |
thread_id | The forum post the message opened, in a forum or media channel. |
message_id | The id of the message. |
url | The link to the message, which members of the server can open. |
sent_at | When the post went out. |
video_links | Media sent as a link instead of a file. |
link_message_id | The second message that holds the links, when they did not fit in the text. |
warnings | What was sent differently from the request, such as media_sent_as_links or thread_name_ignored (a post title on a channel that is no forum). Empty when everything went as asked. |
published_urls.discord is https://discord.com/channels/<server>/<channel or forum post>/<message>.
Account details
GET /accounts returns the Discord account with platform_details:
| Field | Description |
|---|---|
guild_id, guild_name | The server. The name is known for Continue with Discord, and for a pasted URL in a server the OmniSocials bot is in. |
channel_id | The channel OmniSocials posts to. |
channel_name | The channel name without the #: read by the OmniSocials bot, or given by the person when connecting. null when neither is known. |
channel_type | text, voice, announcement, stage, forum or media, as the bot read it; null when the bot cannot see the channel. A forum or media channel needs discord.thread_name on every post. |
webhook_name | The name posts show as the sender. |
connect_method | oauth (Continue with Discord) or url (a pasted webhook URL). |
url | The link to the channel. |
Analytics
Discord gives webhooks no views. A Discord post carries:
likes: all reactions togetherreactions: the count per emojipoll: the votes per answer, for a poll
When the OmniSocials bot is in the server, the account statistics carry followers: the server's member count, read once a day, together with the channel name. Views, reach and replies are not reported.
Removing a post
A sent message can be removed at any time: "Delete from Discord" on the post in the OmniSocials dashboard removes the message and the message with the links, if there is one. Only the webhook that sent a message can remove it, so after a reconnect with a new webhook, remove older posts in Discord yourself. DELETE /posts/:id removes the post from OmniSocials only and never touches the live message.
Limitations
- One Discord channel per workspace. Connect more channels through more workspaces.
- The sender is the webhook's name and picture; a post cannot set its own.
- A post that was sent cannot be edited through OmniSocials.
- Discord messages are not part of the Social Inbox, and replies are not read. The channel name and the member count come from the OmniSocials bot, so a connection without the bot (a pasted webhook URL) has no member count.
- The OmniSocials bot leaves a server once no workspace posts to it any more. Removing the bot from a server never stops the posts: they go through the webhook.
- Discord is a destination for repost automations, never a source.
When the connection breaks
When someone deletes the webhook in Discord, or resets its URL, the account shows needs_reconnect: true in GET /accounts (reason "The webhook was deleted in Discord") and posts to it fail with a message that says so. Reconnect the channel in OmniSocials: Continue with Discord makes a new webhook, or paste the URL of a new one.