Publish
Publish messages, embeds, polls, forum posts and threads to a Discord channel, and edit or delete them.
A plain post becomes a text message in the channel named by channelId.
Fields in platformSpecificData add embeds and polls, target forum channels, open a thread under the message and change the name it is posted under.
Message
const { data: published } = await zernio.posts.createPost({
body: {
content: 'Release 2.3 is live. Changelog in the thread below.',
platforms: [
{
platform: 'discord',
accountId: '66b2e19d8c3f5a7e9d0b1c2d',
platformSpecificData: { channelId: '1234567890123456789' }
}
],
publishNow: true
}
});
console.log(published.post.platforms[0].platformPostUrl);Response (201):
{
"post": {
"_id": "65f1c0a9e2b5af0012ab34cd",
"status": "published",
"platforms": [
{
"platform": "discord",
"status": "published",
"platformPostUrl": "https://discord.com/channels/1098765432109876543/1234567890123456789/4455667788990011223"
}
]
}
}Every sample below changes only the platforms entry of this request.
Embeds
embeds sends rich cards alongside or instead of content.
A message takes up to 10 embeds, with 6,000 characters combined across every embed field. color is a decimal integer, so convert hex first.
{
"platform": "discord",
"accountId": "66b2e19d8c3f5a7e9d0b1c2d",
"platformSpecificData": {
"channelId": "1234567890123456789",
"embeds": [{
"title": "v2.3.0 release notes",
"description": "Dark mode, new API endpoints, faster uploads.",
"color": 5814783,
"url": "https://example.com/changelog",
"footer": { "text": "Shipped today" },
"fields": [
{ "name": "New features", "value": "3", "inline": true },
{ "name": "Bug fixes", "value": "12", "inline": true }
]
}]
}
}Polls
poll creates a native Discord poll, the same one the Discord client makes.
A poll is a standalone message. Discord does not allow media attachments in the same message.
{
"platform": "discord",
"accountId": "66b2e19d8c3f5a7e9d0b1c2d",
"platformSpecificData": {
"channelId": "1234567890123456789",
"poll": {
"question": { "text": "Ship it now or wait until Monday?" },
"answers": [
{ "poll_media": { "text": "Ship now" } },
{ "poll_media": { "text": "Wait for Monday" } }
],
"duration": 24,
"allow_multiselect": false
}
}
}| Poll property | Value |
|---|---|
| Max answers | 10 |
| Duration | 1 to 768 hours (32 days) |
| Default duration | 24 hours |
| Multi-select | Optional (default false) |
Forum posts
A forum channel (type 15) needs forumThreadName, which becomes the thread title. content is the starter message.
forumAppliedTags takes up to 5 snowflake ids of the forum's existing tags. There is no discovery endpoint for tags: read the ids from the forum channel's settings in Discord.
{
"platform": "discord",
"accountId": "66b2e19d8c3f5a7e9d0b1c2d",
"platformSpecificData": {
"channelId": "1122334455667788990",
"forumThreadName": "Community call, 15 January",
"forumAppliedTags": ["7788990011223344556", "8899001122334455667"]
}
}Threads
threadFromMessage opens a thread under the published message.
autoArchiveDurationis 60, 1440 (1 day), 4320 (3 days) or 10080 (7 days) minutes.rateLimitPerUsersets slow mode in seconds, 0 to 21600.
Later or standalone threads. To open one later, or a standalone thread with no message under it, call POST /v1/discord/channels/{channelId}/threads with name and an optional messageId (Create thread).
It returns 403 when the bot lacks Create Public Threads.
{
"platform": "discord",
"accountId": "66b2e19d8c3f5a7e9d0b1c2d",
"platformSpecificData": {
"channelId": "1234567890123456789",
"threadFromMessage": {
"name": "Discussion",
"autoArchiveDuration": 1440,
"rateLimitPerUser": 0
}
}
}Announcement crosspost
crosspost: true publishes the message to every server that follows an announcement channel (type 5). On a regular text channel it does nothing.
To crosspost a message you already published, call POST /v1/discord/channels/{channelId}/messages/{messageId}/crosspost (Crosspost message). It returns 400 when the channel is not an announcement channel.
{
"platform": "discord",
"accountId": "66b2e19d8c3f5a7e9d0b1c2d",
"platformSpecificData": {
"channelId": "1011121314151617181",
"crosspost": true
}
}Webhook identity
Messages post as "Zernio" with the bot's avatar unless you change the name and avatar.
An account-level default applies to every post from the account. Set it with PATCH /v1/accounts/{accountId}/discord-settings (Update Discord settings):
curl -X PATCH https://zernio.com/api/v1/accounts/66b2e19d8c3f5a7e9d0b1c2d/discord-settings \
-H "Authorization: Bearer $ZERNIO_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"webhookUsername": "My Brand",
"webhookAvatarUrl": "https://cdn.example.com/logo.png"
}'Response (200):
{
"message": "Discord settings updated",
"account": {
"_id": "66b2e19d8c3f5a7e9d0b1c2d",
"channelId": "1234567890123456789",
"webhookUsername": "My Brand",
"webhookAvatarUrl": "https://cdn.example.com/logo.png"
}
}A per-post override in platformSpecificData wins over the account default for that post only:
{
"platform": "discord",
"accountId": "66b2e19d8c3f5a7e9d0b1c2d",
"platformSpecificData": {
"channelId": "1234567890123456789",
"webhookUsername": "Special announcement",
"webhookAvatarUrl": "https://cdn.example.com/special-logo.png"
}
}A webhook username is 1 to 80 characters and cannot contain "clyde" or "discord". An empty string resets to the default ("Zernio").
Edit and delete
Edit post (POST /v1/posts/{postId}/edit) replaces the text of a published message with no time limit. The message id does not change.
DELETE /v1/posts/{postId} deletes a draft or cancels a scheduled post.
To delete a message that is already published, call DELETE /v1/discord/channels/{channelId}/messages/{messageId} with accountId.