> This page is for For Developers.

> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://whop.ferndocs.com/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://whop.ferndocs.com/_mcp/server.

# Chat

> Send messages, manage channels, and react to events in any Whop community.

Use the Chat API to send messages, manage channels, open support conversations, and read reactions. Channels are identified by `experience_id` or `channel_id`.

> **Tip**
>
> This page covers the **server-side Chat API**, for calling Whop from your backend to post, read, or moderate messages. If you want to render a live Whop chat UI inside your own frontend, see the [embedded chat quickstart](/developer/guides/chat/quickstart) instead.

## Initialize the SDK

**`TypeScript`**

```typescript TypeScript
import Whop from "@whop/sdk";

const client = new Whop({
  appID: "app_xxxxxxxxxxxxx",
  apiKey: process.env.WHOP_API_KEY,
});
```

**`Python`**

```python Python
import os
from whop_sdk import Whop

client = Whop(
    app_id="app_xxxxxxxxxxxxx",
    api_key=os.environ["WHOP_API_KEY"],
)
```

## Send a message

Messages support Markdown and optional attachments uploaded via the [Files API](/developer/guides/upload-files).

**`TypeScript`**

```typescript TypeScript
const message = await client.messages.create({
  channel_id: "chat_feed_xxxxxxxxxxxxx", // or an experience_id
  content: "Hello! **Markdown** is supported.",
  attachments: [
    { id: "file_xxxxxxxxxxxxx" }, // upload via the Files API first
  ],
});
```

**`Python`**

```python Python
message = client.messages.create(
    channel_id="chat_feed_xxxxxxxxxxxxx",
    content="Hello! **Markdown** is supported.",
    attachments=[
        {"id": "file_xxxxxxxxxxxxx"},
    ],
)
```

## Read messages

List operations auto-paginate. Iterate the response and the SDK fetches additional pages for you.

**`TypeScript`**

```typescript TypeScript
for await (const page of client.messages.list({
  channel_id: "chat_feed_xxxxxxxxxxxxx",
  direction: "desc",
  first: 20,
})) {
  console.log(page);
}

const single = await client.messages.retrieve("msg_xxxxxxxxxxxxx");
```

**`Python`**

```python Python
for page in client.messages.list(
    channel_id="chat_feed_xxxxxxxxxxxxx",
    direction="desc",
    first=20,
):
    print(page)

single = client.messages.retrieve("msg_xxxxxxxxxxxxx")
```

## Manage channels

Update moderation settings (banned words, cooldowns, who can post or react) or list every channel on a company.

**`TypeScript`**

```typescript TypeScript
const channel = await client.chatChannels.update("chat_feed_xxxxxxxxxxxxx", {
  ban_media: false,
  ban_urls: false,
  banned_words: ["spam", "scam"],
  user_posts_cooldown_seconds: 10,
  who_can_post: "members_only",
  who_can_react: "everyone",
});

for await (const page of client.chatChannels.list({
  company_id: "biz_xxxxxxxxxxxxx",
  first: 10,
})) {
  console.log(page);
}
```

**`Python`**

```python Python
channel = client.chat_channels.update(
    "chat_feed_xxxxxxxxxxxxx",
    ban_media=False,
    ban_urls=False,
    banned_words=["spam", "scam"],
    user_posts_cooldown_seconds=10,
    who_can_post="members_only",
    who_can_react="everyone",
)

for page in client.chat_channels.list(
    company_id="biz_xxxxxxxxxxxxx",
    first=10,
):
    print(page)
```

`who_can_post` and `who_can_react` accept `everyone`, `members_only`, or `admins_only`.

## React to a message

**`TypeScript`**

```typescript TypeScript
await client.reactions.create({
  resource_id: "msg_xxxxxxxxxxxxx",
  emoji: "😀", // Unicode or ':heart:' shortcode
});
```

**`Python`**

```python Python
client.reactions.create(
    resource_id="msg_xxxxxxxxxxxxx",
    emoji="😀",
)
```

## Support channels

Support channels are 1:1 threads between a user and a company, useful for help desks or concierge flows. `create` returns the existing channel if one already exists for the user.

**`TypeScript`**

```typescript TypeScript
const support = await client.supportChannels.create({
  company_id: "biz_xxxxxxxxxxxxx",
  user_id: "user_xxxxxxxxxxxxx",
});

for await (const page of client.supportChannels.list({
  company_id: "biz_xxxxxxxxxxxxx",
  open: true,
  order: "last_post_sent_at",
  direction: "desc",
  first: 10,
})) {
  console.log(page);
}
```

**`Python`**

```python Python
support = client.support_channels.create(
    company_id="biz_xxxxxxxxxxxxx",
    user_id="user_xxxxxxxxxxxxx",
)

for page in client.support_channels.list(
    company_id="biz_xxxxxxxxxxxxx",
    open=True,
    order="last_post_sent_at",
    direction="desc",
    first=10,
):
    print(page)
```

## Required permissions

Add these from the [Permissions guide](/developer/guides/permissions) before publishing your app.

| Permission            | Needed for                            |
| --------------------- | ------------------------------------- |
| `chat:read`           | Reading messages, channels, reactions |
| `chat:message:create` | Posting messages                      |
| `chat:moderate`       | Updating channel settings             |
| `support_chat:create` | Opening support channels              |
| `support_chat:read`   | Reading support channels              |

#### Message object shape

```typescript
{
  id: string;
  content: string | null;
  created_at: string;
  is_edited: boolean;
  is_pinned: boolean;
  message_type: "text" | "image" | "video" | "poll";
  poll: { options: Array<{ id: string; text: string }> | null } | null;
  poll_votes: Array<{ count: number; option_id: string | null }>;
  reaction_counts: Array<{ count: number; emoji: string | null }>;
  replying_to_message_id: string | null;
  updated_at: string;
  user: { id: string; name: string | null; username: string };
}
```

Full schema: see the [Messages API reference](/api-reference/messages/message).

## Next steps

#### [Listen to events with webhooks](/developer/guides/webhooks)

Receive chat events on your server instead of polling.

#### [Send notifications](/developer/guides/notifications)

Push notifications to users who aren't live in chat.

#### [Upload files](/developer/guides/upload-files)

Attach images and videos to messages.

#### [Embed chat in your app](/developer/guides/chat/quickstart)

Drop-in Whop chat UI for your frontend (separate product).