# Discord

Coming soon. Install the bot in a Discord server, publish messages, embeds, polls, forum posts and threads, send DMs, and manage roles, pins and scheduled events.

> **Discord is coming soon:**
> 
> Discord accounts cannot be connected yet. [`GET /v1/connect/discord`](https://pozy.ai/docs/api/getConnectUrl) answers `403` with `code: "feature_not_available"`, so there is no Discord account for the other Discord endpoints to act on. The rest of this page describes how Discord will work once it opens, so you can plan for it. Watch the [changelog](https://pozy.ai/docs/changelog) for the launch.

Discord publishing runs through a hosted bot. The server owner installs it with OAuth, you bind a channel, and from then on you post with `POST /v1/posts` using the platform id `discord`. You never create a Discord application, request privileged intents or keep a gateway connection open. The same bot sends DMs and manages roles, members, pins and scheduled events over plain REST calls.

## What you will be able to do

| Feature | Supported | Where |
| --- | --- | --- |
| Messages with attachments | Up to 10 files | [Post types](#post-types) |
| Embeds | Up to 10 per message | [Embeds](#embeds) |
| Native polls | Yes | [Polls](#polls) |
| Forum posts and threads | Yes | [Forums and threads](#forums-and-threads) |
| Announcement crossposts | Yes | [Platform fields](#platform-fields) |
| Custom name and avatar per post | Yes | [Message identity](#message-identity) |
| Scheduling | Yes | [Scheduling](https://pozy.ai/docs/publishing/scheduling) |
| Edit and delete published messages | Yes | [Edit and delete](#edit-and-delete) |
| DMs | Outbound only | [Inbox](#inbox) |
| Roles, members, pins, scheduled events | Yes | [Server management](#server-management) |
| Reading replies, comments, analytics | No | Not available without a gateway connection |

## Connect

> **Note:**
> 
> Not available yet: these steps return `403 feature_not_available` until Discord opens.

### Install the bot

Request a connect URL with platform `discord` and send the server admin to `authUrl`. They choose a server and authorize the bot.

```bash
curl "https://api.pozy.ai/v1/connect/discord?profileId=66a1f0c2a4b9d3e8f1a2b3c4&redirect_url=https://app.example.com/connected" \
  -H "Authorization: Bearer $POZY_API_KEY"
```

### Bind a channel

Call [Connect a Discord channel](https://pozy.ai/docs/api/connectDiscordChannel) with the `guildId` (server id) and the `channelId` that should receive posts. One connected account serves one channel. Send `channelIds` to connect several at once, or call again to add another.

```bash
curl -X POST https://api.pozy.ai/v1/connect/discord \
  -H "Authorization: Bearer $POZY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "profileId": "66a1f0c2a4b9d3e8f1a2b3c4", "guildId": "1180000000000000000", "channelId": "1180000000000000123" }'
```

The response carries the new `accountId`. [List Discord guild channels](https://pozy.ai/docs/api/getDiscordChannels) shows the channels the bot can see.

The bot asks for these permissions at install: Send Messages, Embed Links, Attach Files, Send Messages in Threads, Create Public Threads, Manage Messages (pins), Manage Roles and Manage Events.

> **Older installs:**
> 
> Servers that installed the bot before Manage Roles and Manage Events were part of the install do not have them, and the role and event endpoints return `502` there. Ask a server admin to re-invite the bot, or grant the permissions to the bot's role under Server Settings, Roles.

## Post types

A post with only `content` becomes a text message in the channel named by `platformSpecificData.channelId`, which is required.

```bash cURL
curl -X POST https://api.pozy.ai/v1/posts \
  -H "Authorization: Bearer $POZY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "content": "Patch 1.8 is live. Full notes below.",
    "platforms": [{
      "platform": "discord",
      "accountId": "66b2e19d8c3f5a7e9d0b1c2d",
      "platformSpecificData": {
        "channelId": "1180000000000000123",
        "embeds": [{
          "title": "Patch 1.8",
          "description": "New maps, faster matchmaking, and 40 bug fixes.",
          "url": "https://example.com/patch-1-8",
          "color": 5793266
        }]
      }
    }],
    "publishNow": true
  }'
```
```ts Node
const res = await fetch("https://api.pozy.ai/v1/posts", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${process.env.POZY_API_KEY}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    content: "Patch 1.8 is live. Full notes below.",
    platforms: [{
      platform: "discord",
      accountId: "66b2e19d8c3f5a7e9d0b1c2d",
      platformSpecificData: {
        channelId: "1180000000000000123",
        embeds: [{
          title: "Patch 1.8",
          description: "New maps, faster matchmaking, and 40 bug fixes.",
          url: "https://example.com/patch-1-8",
          color: 5793266,
        }],
      },
    }],
    publishNow: true,
  }),
});
const data = await res.json();
if (!res.ok) throw new Error(data.error);
console.log(data.post.platforms[0].platformPostUrl);
```
```python Python
import os, requests

resp = requests.post(
    "https://api.pozy.ai/v1/posts",
    headers={"Authorization": f"Bearer {os.environ['POZY_API_KEY']}"},
    json={
        "content": "Patch 1.8 is live. Full notes below.",
        "platforms": [{
            "platform": "discord",
            "accountId": "66b2e19d8c3f5a7e9d0b1c2d",
            "platformSpecificData": {
                "channelId": "1180000000000000123",
                "embeds": [{
                    "title": "Patch 1.8",
                    "description": "New maps, faster matchmaking, and 40 bug fixes.",
                    "url": "https://example.com/patch-1-8",
                    "color": 5793266,
                }],
            },
        }],
        "publishNow": True,
    },
)
print(resp.json()["post"]["platforms"][0]["platformPostUrl"])
```

### Embeds

`embeds` sends up to 10 rich cards with or instead of `content`, with 6,000 characters across all embed fields. Each embed takes `title`, `description`, `url`, `color`, `image`, `thumbnail`, `footer`, `author` and `fields` (each `{ name, value, inline }`). `color` is a decimal integer, so convert hex first (`#5865F2` is `5793266`).

### Polls

`poll` creates a native Discord poll. A poll is a message on its own and cannot carry attachments.

```json
{
  "platform": "discord",
  "accountId": "66b2e19d8c3f5a7e9d0b1c2d",
  "platformSpecificData": {
    "channelId": "1180000000000000123",
    "poll": {
      "question": { "text": "Which map should we rework next?" },
      "answers": [
        { "poll_media": { "text": "Harbor" } },
        { "poll_media": { "text": "Canyon" } },
        { "poll_media": { "text": "Station" } }
      ],
      "duration": 48,
      "allow_multiselect": false
    }
  }
}
```

| Poll property | Value |
| --- | --- |
| Answers | Up to 10 |
| `duration` | 1 to 768 hours (32 days). Default 24 |
| `allow_multiselect` | Default `false` |

### Forums and threads

- **Forum channels** need `forumThreadName`, which becomes the thread title. `content` is the starter message. `forumAppliedTags` takes up to 5 tag ids from the forum's settings (Discord has no API to list them).
- **A thread under the message**: `threadFromMessage` with `name`, plus optional `autoArchiveDuration` (60, 1440, 4320 or 10080 minutes) and `rateLimitPerUser` (slow mode, 0 to 21,600 seconds).
- **A thread later, or with no message**: [Create a Discord public thread](https://pozy.ai/docs/api/createDiscordThread) with `name` and an optional `messageId`.

### Platform fields

| Field | Type | Notes |
| --- | --- | --- |
| `channelId` | string | Required. The target channel |
| `embeds` | array | Up to 10, 6,000 characters combined |
| `poll` | object | Cannot be combined with media |
| `crosspost` | boolean | Publish to every server following an announcement channel. No effect on other channels |
| `forumThreadName` | string | Required on forum channels |
| `forumAppliedTags` | array of string | Up to 5 tag ids |
| `threadFromMessage` | object | Open a thread under the message |
| `tts` | boolean | Discord reads the message aloud |
| `webhookUsername` | string | Display name for this post, 1 to 80 characters |
| `webhookAvatarUrl` | URL | Avatar for this post |

### Message identity

By default, messages post under the bot's own name and avatar. To post under your brand, set an account default once with [Update Discord settings](https://pozy.ai/docs/api/updateDiscordSettings), or override per post with `webhookUsername` and `webhookAvatarUrl`. The per-post values win.

```bash
curl -X PATCH https://api.pozy.ai/v1/accounts/66b2e19d8c3f5a7e9d0b1c2d/discord-settings \
  -H "Authorization: Bearer $POZY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "webhookUsername": "Acme Updates", "webhookAvatarUrl": "https://pozy.ai/media/acme-avatar.png" }'
```

A name must be 1 to 80 characters and cannot contain "clyde" or "discord". An empty string resets it to the default. The same call can move the account to another `channelId`.

### Edit and delete

[Edit published post](https://pozy.ai/docs/api/editPost) replaces the text of a published message, with no time limit, and keeps the message id. To remove a published message, call [Delete a Discord channel message](https://pozy.ai/docs/api/deleteDiscordMessage) with the `accountId`. Deleting a draft or scheduled post in Pozy removes it before it is sent.

## Media requirements

| Type | Formats | Max size |
| --- | --- | --- |
| Images | JPEG, PNG, GIF, WebP | 20 MiB by default, higher on Boosted servers |
| Videos | MP4 | 20 MiB by default, higher on Boosted servers |
| Documents | Any file | 20 MiB by default, higher on Boosted servers |

Up to 10 attachments per message, each a public HTTPS URL. A poll cannot carry attachments. Upload through [Media](https://pozy.ai/docs/publishing/media) for URLs that qualify.

## Limits

| Limit | Value |
| --- | --- |
| Message content | 2,000 characters |
| Embeds | 10 per message, 6,000 characters total |
| Attachments | 10 per message |
| Pinned messages | 50 per channel |
| Poll answers | 10 |

Discord's own rate limits are handled for you: Pozy backs off on Discord's `429` responses, so you do not need retry logic for them.

## Analytics

Discord's bot API reports no message metrics, so Discord has no analytics in Pozy.

## Inbox

Discord is outbound only. [Send a Discord Direct Message](https://pozy.ai/docs/api/sendDiscordDirectMessage) sends a 1:1 message from the bot, for onboarding, reminders or support pings. Replies are not received, because reading DMs needs a gateway connection. There are no comments.

```bash
curl -X POST https://api.pozy.ai/v1/discord/dms \
  -H "Authorization: Bearer $POZY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "accountId": "66b2e19d8c3f5a7e9d0b1c2d", "userId": "1170000000000000456", "content": "Your beta access is ready. Check #welcome to get started." }'
```

`userId` is the recipient's numeric id, not a username. Find it with [Search Discord guild members](https://pozy.ai/docs/api/searchDiscordGuildMembers), which prefix-matches usernames and nicknames. The bot can only DM people who share a server with it and have not turned off DMs from non-friends. Each DM counts as an outbound message on your bill. See [Pricing](https://pozy.ai/docs/billing).

## Server management

| Job | Endpoints |
| --- | --- |
| Roles | List, create, edit and delete roles. Assign and remove a role on a member (not `@everyone`) |
| Members | List with cursor paging, search by name, get one |
| Pins | List, pin and unpin messages (50 per channel) |
| Scheduled events | Create, list, get, update and delete. `entity.type` is `external` (with `location` and `endsAt`), `voice` or `stage` (with `channelId`) |

## Errors you may see

| Error | Cause | Fix |
| --- | --- | --- |
| "Missing Access" | The bot cannot see `channelId` | Give the bot's role access to the channel. Check with List Discord guild channels |
| `502` on a role or event endpoint | Older install without Manage Roles or Manage Events | Re-invite the bot or grant the permission |
| `403` on a DM | The recipient shares no server with the bot or blocks DMs from non-friends | Only DM members of a server the bot is in |
| `400` when pinning | The channel already has 50 pins | Unpin one first |
| `400` on Discord settings | `channelId` is not a text, announcement or forum channel, or the bot cannot see it | Pick a channel of type 0, 5 or 15 that the bot can access |
| Empty member list | The install predates the members permission | Re-invite the bot |
| Webhook username rejected | Empty, over 80 characters, or contains "clyde" or "discord" | Pick another name |

A post can be accepted by Pozy and still fail on Discord. Check `post.status` and `platforms[].errorMessage` in the response. [Errors](https://pozy.ai/docs/getting-started/errors) covers the error format.

## Endpoints

| Endpoint | What it does |
| --- | --- |
| [`GET /v1/accounts/{accountId}/discord-settings`](https://pozy.ai/docs/api/getDiscordSettings) | Get Discord account settings |
| [`PATCH /v1/accounts/{accountId}/discord-settings`](https://pozy.ai/docs/api/updateDiscordSettings) | Update Discord settings |
| [`GET /v1/accounts/{accountId}/discord-channels`](https://pozy.ai/docs/api/getDiscordChannels) | List Discord guild channels |
| [`POST /v1/discord/dms`](https://pozy.ai/docs/api/sendDiscordDirectMessage) | Send a Discord Direct Message |
| [`GET /v1/discord/guilds/{guildId}/roles`](https://pozy.ai/docs/api/listDiscordGuildRoles) | List Discord guild roles |
| [`POST /v1/discord/guilds/{guildId}/roles`](https://pozy.ai/docs/api/createDiscordGuildRole) | Create a Discord guild role |
| [`PATCH /v1/discord/guilds/{guildId}/roles/{roleId}`](https://pozy.ai/docs/api/editDiscordGuildRole) | Edit a Discord guild role |
| [`DELETE /v1/discord/guilds/{guildId}/roles/{roleId}`](https://pozy.ai/docs/api/deleteDiscordGuildRole) | Delete a Discord guild role |
| [`GET /v1/discord/guilds/{guildId}/members`](https://pozy.ai/docs/api/listDiscordGuildMembers) | List Discord guild members |
| [`GET /v1/discord/guilds/{guildId}/members/search`](https://pozy.ai/docs/api/searchDiscordGuildMembers) | Search Discord guild members |
| [`GET /v1/discord/guilds/{guildId}/members/{userId}`](https://pozy.ai/docs/api/getDiscordGuildMember) | Get a Discord guild member |
| [`PUT /v1/discord/guilds/{guildId}/members/{userId}/roles/{roleId}`](https://pozy.ai/docs/api/addDiscordMemberRole) | Assign a role to a guild member |
| [`DELETE /v1/discord/guilds/{guildId}/members/{userId}/roles/{roleId}`](https://pozy.ai/docs/api/removeDiscordMemberRole) | Remove a role from a guild member |
| [`DELETE /v1/discord/channels/{channelId}/messages/{messageId}`](https://pozy.ai/docs/api/deleteDiscordMessage) | Delete a Discord channel message |
| [`POST /v1/discord/channels/{channelId}/messages/{messageId}/crosspost`](https://pozy.ai/docs/api/crosspostDiscordMessage) | Crosspost Discord message |
| [`POST /v1/discord/channels/{channelId}/threads`](https://pozy.ai/docs/api/createDiscordThread) | Create a Discord public thread |
| [`GET /v1/discord/channels/{channelId}/pins`](https://pozy.ai/docs/api/listDiscordPinnedMessages) | List pinned messages |
| [`PUT /v1/discord/channels/{channelId}/pins/{messageId}`](https://pozy.ai/docs/api/pinDiscordMessage) | Pin a Discord message |
| [`DELETE /v1/discord/channels/{channelId}/pins/{messageId}`](https://pozy.ai/docs/api/unpinDiscordMessage) | Unpin a Discord message |
| [`GET /v1/discord/guilds/{guildId}/events`](https://pozy.ai/docs/api/listDiscordScheduledEvents) | List Discord scheduled events |
| [`POST /v1/discord/guilds/{guildId}/events`](https://pozy.ai/docs/api/createDiscordScheduledEvent) | Create a Discord scheduled event |
| [`GET /v1/discord/guilds/{guildId}/events/{eventId}`](https://pozy.ai/docs/api/getDiscordScheduledEvent) | Get a Discord scheduled event |
| [`PATCH /v1/discord/guilds/{guildId}/events/{eventId}`](https://pozy.ai/docs/api/updateDiscordScheduledEvent) | Update a Discord scheduled event |
| [`DELETE /v1/discord/guilds/{guildId}/events/{eventId}`](https://pozy.ai/docs/api/deleteDiscordScheduledEvent) | Delete a Discord scheduled event |

| Endpoint | What it does |
| --- | --- |
| [`GET /v1/connect/{platform}`](https://pozy.ai/docs/api/getConnectUrl) | Get OAuth connect URL |
| [`POST /v1/connect/discord`](https://pozy.ai/docs/api/connectDiscordChannel) | Connect a Discord channel (not available yet) |

## Webhook events

| Event | When it fires |
| --- | --- |
| [`post.published`](https://pozy.ai/docs/webhooks/events#post-published) | Post published. |
| [`post.failed`](https://pozy.ai/docs/webhooks/events#post-failed) | Post failed. |
| [`post.platform.published`](https://pozy.ai/docs/webhooks/events#post-platform-published) | Post platform published. |
| [`post.platform.failed`](https://pozy.ai/docs/webhooks/events#post-platform-failed) | Post platform failed. |
| [`post.platform.deleted`](https://pozy.ai/docs/webhooks/events#post-platform-deleted) | Post platform deleted. |
