> ## Documentation Index
> Fetch the complete documentation index at: https://docs.whop.com/llms.txt
> Use this file to discover all available pages before exploring further.

# 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.
</Tip>

## Initialize the SDK

<CodeGroup>
  ```typescript TypeScript theme={null}
  import Whop from "@whop/sdk";

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

  ```python Python theme={null}
  import os
  from whop_sdk import Whop

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

## Send a message

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

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

  ```python Python theme={null}
  message = client.messages.create(
      channel_id="channel_xxxxxxxxxxxxx",
      content="Hello! **Markdown** is supported.",
      attachments=[
          {"id": "file_xxxxxxxxxxxxx"},
      ],
  )
  ```
</CodeGroup>

## Read messages

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

<CodeGroup>
  ```typescript TypeScript theme={null}
  for await (const page of client.messages.list({
    channel_id: "channel_xxxxxxxxxxxxx",
    direction: "desc",
    first: 20,
  })) {
    console.log(page);
  }

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

  ```python Python theme={null}
  for page in client.messages.list(
      channel_id="channel_xxxxxxxxxxxxx",
      direction="desc",
      first=20,
  ):
      print(page)

  single = client.messages.retrieve("msg_xxxxxxxxxxxxx")
  ```
</CodeGroup>

## Manage channels

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

<CodeGroup>
  ```typescript TypeScript theme={null}
  const channel = await client.chatChannels.update("channel_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 theme={null}
  channel = client.chat_channels.update(
      "channel_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)
  ```
</CodeGroup>

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

## React to a message

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

  ```python Python theme={null}
  client.reactions.create(
      resource_id="msg_xxxxxxxxxxxxx",
      emoji="😀",
  )
  ```
</CodeGroup>

## 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.

<CodeGroup>
  ```typescript TypeScript theme={null}
  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 theme={null}
  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)
  ```
</CodeGroup>

## 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              |

<Accordion title="Message object shape">
  ```typescript theme={null}
  {
    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).
</Accordion>

## Next steps

<CardGroup cols={2}>
  <Card title="Listen to events with webhooks" href="/developer/guides/webhooks">
    Receive chat events on your server instead of polling.
  </Card>

  <Card title="Send notifications" href="/developer/guides/notifications">
    Push notifications to users who aren't live in chat.
  </Card>

  <Card title="Upload files" href="/developer/guides/upload-files">
    Attach images and videos to messages.
  </Card>

  <Card title="Embed chat in your app" href="/developer/guides/chat/quickstart">
    Drop-in Whop chat UI for your frontend (separate product).
  </Card>
</CardGroup>
