Skip to content

Discord API

Send messages, embeds, polls, forum posts, and threads to Discord servers with Zernio API - No bot hosting, no gateway, no intents approval

Quick Reference

PropertyValue
Content limit2,000 characters (message content)
Embeds per message10 (max 6,000 chars total)
Images per messageUp to 10 attachments
Image formatsJPEG, PNG, GIF, WebP
Image max size25 MB (higher on boosted servers)
Video formatsMP4, MOV, WebM
Video max size25 MB (up to 500 MB on boosted servers)
Post typesMessages, Embeds, Polls, Forum Posts, Threads
SchedulingYes
Inbox (DMs)No
Inbox (Comments)No
AnalyticsNo

Before You Start

Discord integration uses a centralized bot token model. You do NOT need to create a Discord Application, request privileged intents, or host a gateway connection. You add the Zernio bot to your server via OAuth and POST to our REST API.

Key points:

  • No bot hosting required - we manage the bot infrastructure
  • No intents approval - MESSAGE_CONTENT and other privileged intents are handled at the bot level
  • No gateway/sharding - you never connect a WebSocket; everything is REST
  • The bot needs: Send Messages, Embed Links, Attach Files, Send Messages in Threads, Create Public Threads permissions (granted at install time)

Quick Start

Send a message to a Discord channel:

typescript
const { post } = await zernio.posts.createPost({
  content: 'Hello from Zernio API!',
  platforms: [
    {
      platform: 'discord',
      accountId: 'YOUR_ACCOUNT_ID',
      platformSpecificData: {
        channelId: '1234567890'
      }
    }
  ],
  publishNow: true
});
console.log('Posted to Discord!', post._id);
python
result = client.posts.create_post(
    content="Hello from Zernio API!",
    platforms=[
        {
            "platform": "discord",
            "accountId": "YOUR_ACCOUNT_ID",
            "platformSpecificData": {
                "channelId": "1234567890"
            }
        }
    ],
    publish_now=True,
)
print(f"Posted to Discord! {result.post['_id']}")
bash
curl -X POST https://zernio.com/api/v1/posts \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "content": "Hello from Zernio API!",
    "platforms": [
      {
        "platform": "discord",
        "accountId": "YOUR_ACCOUNT_ID",
        "platformSpecificData": {
          "channelId": "1234567890"
        }
      }
    ],
    "publishNow": true
  }'

Connection

Discord uses OAuth2 with our centralized bot:

  1. Call GET /v1/connect/discord?profileId=YOUR_PROFILE_ID to get the bot invite URL
  2. The user authorizes the bot to join their server
  3. After authorization, the user selects which channel to post to via /connect/discord/select-channel
  4. The connected account appears in GET /v1/accounts

Each connected account represents one Discord server. The channelId in platformSpecificData determines which channel receives the message.

Webhook Identity (Bot Customization)

By default, messages are posted as "Zernio" with the bot's avatar. You can customize the display name and avatar at two levels:

Account-level default (applies to every post from this account):

bash
curl -X PATCH https://zernio.com/api/v1/connect/discord \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "accountId": "YOUR_ACCOUNT_ID",
    "webhookUsername": "My Brand",
    "webhookAvatarUrl": "https://example.com/logo.png"
  }'

Per-post override (overrides account default for a single post):

json
{
  "platforms": [{
    "platform": "discord",
    "accountId": "YOUR_ACCOUNT_ID",
    "platformSpecificData": {
      "channelId": "1234567890",
      "webhookUsername": "Special Announcement",
      "webhookAvatarUrl": "https://example.com/special-logo.png"
    }
  }],
  "publishNow": true
}

Webhook usernames must be 1-80 characters and cannot contain "clyde" or "discord". Send an empty string to reset to the default ("Zernio").

Embeds

Send rich embedded content alongside or instead of plain text:

json
{
  "content": "New release shipping today!",
  "platforms": [{
    "platform": "discord",
    "accountId": "YOUR_ACCOUNT_ID",
    "platformSpecificData": {
      "channelId": "1234567890",
      "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 }
        ]
      }]
    }
  }],
  "publishNow": true
}

Each message supports up to 10 embeds with a combined character limit of 6,000 across all embed fields.

Native Polls

Create Discord-native polls (same UX as the Discord client):

json
{
  "platforms": [{
    "platform": "discord",
    "accountId": "YOUR_ACCOUNT_ID",
    "platformSpecificData": {
      "channelId": "1234567890",
      "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
      }
    }
  }],
  "publishNow": true
}
Poll PropertyValue
Max answers10
Duration range1 - 768 hours (32 days)
Default duration24 hours
Multi-selectOptional (default: false)

Polls are standalone messages. You cannot combine a poll with media attachments in the same message (Discord API limitation).

Forum Posts

Post starter messages to forum channels (type 15):

json
{
  "content": "Community call notes for January 15",
  "platforms": [{
    "platform": "discord",
    "accountId": "YOUR_ACCOUNT_ID",
    "platformSpecificData": {
      "channelId": "9999999999",
      "forumThreadName": "Community Call - Jan 15",
      "forumAppliedTags": ["11111111", "22222222"]
    }
  }],
  "publishNow": true
}
  • forumThreadName (required for forum channels) becomes the thread title
  • forumAppliedTags are snowflake IDs of existing forum tags (max 5 tags per post)
  • Use listForumTags(channelId) to discover available tags

Threads

Create a follow-up thread under any published message:

json
{
  "content": "Main announcement here",
  "platforms": [{
    "platform": "discord",
    "accountId": "YOUR_ACCOUNT_ID",
    "platformSpecificData": {
      "channelId": "1234567890",
      "threadFromMessage": {
        "name": "Discussion Thread",
        "autoArchiveDuration": 1440,
        "rateLimitPerUser": 0
      }
    }
  }],
  "publishNow": true
}

autoArchiveDuration options: 60, 1440 (1 day), 4320 (3 days), or 10080 (7 days) minutes. rateLimitPerUser sets slow-mode in seconds (0-21600).

Announcement Crosspost

Auto-crosspost messages from announcement channels (type 5) so followers in other servers receive them:

json
{
  "platformSpecificData": {
    "channelId": "ANNOUNCEMENT_CHANNEL_ID",
    "crosspost": true
  }
}

This is a no-op for regular text channels.

Edit & Delete

  • Edit: PUT /v1/posts/{postId} updates the Discord message content and embeds
  • Delete: DELETE /v1/posts/{postId} deletes the Discord message or cancels a scheduled one

Rate Limits

Discord applies per-channel, per-guild, and global rate limits. Zernio handles 429 responses with exponential backoff and respects the X-RateLimit-Reset-After header automatically. You never need to implement retry logic.

platformSpecificData Reference

FieldTypeRequiredDescription
channelIdstringYesTarget channel snowflake ID
embedsarrayNoUp to 10 Discord embed objects (6,000 chars total)
pollobjectNoNative poll (question, answers, duration). Cannot combine with media
crosspostbooleanNoAuto-crosspost in announcement channels
forumThreadNamestringForum channelsThread title for forum starter message
forumAppliedTagsstring[]NoTag snowflake IDs for forum posts (max 5)
threadFromMessageobjectNoCreate a thread under the published message
threadFromMessage.rateLimitPerUsernumberNoSlow-mode seconds for thread (0-21600)
ttsbooleanNoText-to-speech message
webhookUsernamestringNoOverride display name for this post (1-80 chars)
webhookAvatarUrlstringNoOverride avatar URL for this post

Channel Management

List available channels in the connected guild:

typescript
const { channels } = await zernio.discord.getDiscordChannels({
  path: { accountId: 'YOUR_ACCOUNT_ID' },
});
python
res = client.discord.get_discord_channels(account_id="YOUR_ACCOUNT_ID")
bash
curl https://zernio.com/api/v1/accounts/YOUR_ACCOUNT_ID/discord-channels \
  -H "Authorization: Bearer YOUR_API_KEY"

Switch the connected channel:

bash
curl -X PATCH https://zernio.com/api/v1/connect/discord \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "accountId": "YOUR_ACCOUNT_ID",
    "channelId": "NEW_CHANNEL_ID"
  }'

Only text (0), announcement (5), and forum (15) channels are supported. A new webhook is automatically created in the target channel.

  • Connect Discord Account - OAuth flow and bot installation
  • Create Post - Post creation and scheduling
  • Discord Settings - Update webhook identity and switch channels
  • Discord Channels - List guild channels