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

# Connect a Telegram Bot

> Wire up a Telegram bot to your Chowder instance in under 5 minutes.

Want your agent on Telegram? You're about five minutes and three API calls away from having a bot that responds to DMs with the full power of OpenClaw behind it.

Here's the plan: create a Telegram bot, hand Chowder the token, approve the first user, done.

<Note>
  You need a running Chowder instance. If you don't have one yet, follow [Your First Instance](/guides/your-first-instance) to get set up.
</Note>

## Set up your environment

```bash theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
export CHOWDER_KEY="chd_org_your_key_here"
export INSTANCE_ID="your-instance-id"
```

<Steps>
  ### Create a Telegram bot

  Open Telegram and search for **@BotFather** — it's Telegram's official bot for creating bots (very meta).

  1. Send `/newbot`
  2. Pick a display name (e.g., "My Chowder Agent")
  3. Pick a username ending in `bot` (e.g., `my_chowder_agent_bot`)
  4. BotFather replies with your **bot token** — a string like `7123456789:AAF1k2j3h4g5f6d7s8a9...`

  <Warning>
    Keep this token secret. Anyone with it can control your bot. Don't commit it to version control.
  </Warning>

  ### Copy the bot token

  Grab the token from BotFather's message. You'll pass it to Chowder in the next step.

  ```bash theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
  export BOT_TOKEN="7123456789:AAF1k2j3h4g5f6d7s8a9..."
  ```

  ### Connect the channel

  Call the Telegram connect endpoint with your bot token:

  ```bash theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
  curl -X POST https://api.chowder.dev/v1/instances/$INSTANCE_ID/channels/telegram/connect \
    -H "Authorization: Bearer $CHOWDER_KEY" \
    -H "Content-Type: application/json" \
    -d "{
      \"config\": {
        \"token\": \"$BOT_TOKEN\"
      }
    }"
  ```

  ```json Response theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
  {
    "channel": "telegram",
    "status": "connected",
    "qr_data": null,
    "qr_image_base64": null,
    "message": null
  }
  ```

  That's it — the channel is live. Behind the scenes, Chowder:

  1. Wrote your bot token to the instance's `openclaw.json` config under `channels.telegram`
  2. Set `enabled: true` and `dmPolicy: "pairing"` (more on that next)
  3. Restarted the gateway to pick up the new channel

  <Tip>
    You can verify this by checking the channel status anytime:

    ```bash theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
    curl https://api.chowder.dev/v1/instances/$INSTANCE_ID/channels/telegram/status \
      -H "Authorization: Bearer $CHOWDER_KEY"
    ```

    ```json theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
    {
      "channel": "telegram",
      "enabled": true,
      "connected": true,
      "details": null
    }
    ```
  </Tip>

  ### Understand the DM pairing policy

  OpenClaw uses a **pairing** system for DM channels. Here's how it works:

  1. Someone sends your bot a message on Telegram
  2. OpenClaw generates a **pairing code** and replies with it in the chat
  3. You approve that code through the API (or OpenClaw CLI)
  4. Once approved, that Telegram user can chat freely with your agent

  This prevents random people from racking up your model costs. The first person to message gets a code, and you decide whether to let them in.

  <Note>
    The pairing code is shown to the user directly in Telegram. You need to get it from them (or see it in the logs) and then approve it via the API.
  </Note>

  ### Approve a pairing

  Once someone messages your bot and gets a pairing code, approve it:

  ```bash theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
  curl -X POST https://api.chowder.dev/v1/instances/$INSTANCE_ID/channels/telegram/pair \
    -H "Authorization: Bearer $CHOWDER_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "code": "abc123"
    }'
  ```

  ```json Response theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
  {
    "channel": "telegram",
    "code": "abc123",
    "status": "approved",
    "output": "Pairing approved for user 123456789."
  }
  ```

  Now that user can DM your bot and get full agent responses — tools, memory, the works.

  ### Check channel status

  At any point, you can check whether the Telegram channel is up and healthy:

  ```bash theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
  curl https://api.chowder.dev/v1/instances/$INSTANCE_ID/channels/telegram/status \
    -H "Authorization: Bearer $CHOWDER_KEY"
  ```

  ```json Response theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
  {
    "channel": "telegram",
    "enabled": true,
    "connected": true,
    "details": null
  }
  ```

  You can also list all channels on your instance to see what's connected:

  ```bash theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
  curl https://api.chowder.dev/v1/instances/$INSTANCE_ID/channels \
    -H "Authorization: Bearer $CHOWDER_KEY"
  ```

  ```json Response theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
  [
    {
      "channel": "telegram",
      "connection_type": "token",
      "enabled": true
    },
    {
      "channel": "discord",
      "connection_type": "token",
      "enabled": false
    },
    {
      "channel": "whatsapp",
      "connection_type": "interactive",
      "enabled": false
    }
  ]
  ```

  ### Disconnect when done

  If you want to remove the Telegram channel:

  ```bash theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
  curl -X POST https://api.chowder.dev/v1/instances/$INSTANCE_ID/channels/telegram/disconnect \
    -H "Authorization: Bearer $CHOWDER_KEY"
  ```

  This returns `204 No Content`. Chowder sets `enabled: false` in the config and restarts the gateway. The bot token is still in the config file but the channel is no longer active.
</Steps>

## How it works under the hood

When you call the connect endpoint, Chowder does the following on your instance's sandbox:

1. **Reads** the `openclaw.json` config file
2. **Writes** the bot token to `channels.telegram.botToken`
3. **Enables** the channel: `channels.telegram.enabled = true`
4. **Sets** the DM policy: `channels.telegram.dmPolicy = "pairing"`
5. **Restarts** the gateway process so it picks up the new config

The gateway then starts a Telegram bot listener using the [Telegram Bot API](https://core.telegram.org/bots/api). Incoming DMs are routed to the agent, and responses are sent back through the bot.

## Other channels

Telegram is a "token-based" channel — you give it a token, it connects. Chowder supports a bunch of these:

<Tabs>
  <Tab title="Token-based">
    These work the same way as Telegram — pass credentials via the connect endpoint:

    | Channel         | Required fields                             |
    | --------------- | ------------------------------------------- |
    | **Telegram**    | `token` (bot token from BotFather)          |
    | **Discord**     | `token` (bot token)                         |
    | **Slack**       | `bot_token` + `app_token` (for Socket Mode) |
    | **Signal**      | `account` (E.164 phone number)              |
    | **Matrix**      | `homeserver` + `user_id` + `access_token`   |
    | **MS Teams**    | `app_id` + `app_password` + `tenant_id`     |
    | **Mattermost**  | `bot_token` + `base_url`                    |
    | **LINE**        | `channel_access_token` + `channel_secret`   |
    | **Google Chat** | `audience_type` + `audience`                |
  </Tab>

  <Tab title="Interactive">
    These require a QR code scan or interactive login:

    | Channel      | How it works                                         |
    | ------------ | ---------------------------------------------------- |
    | **WhatsApp** | Call connect, get a QR code back, scan with WhatsApp |

    The connect response for WhatsApp includes `qr_data` and `qr_image_base64` — display the QR and scan it with your phone.
  </Tab>
</Tabs>

## What's next?

<CardGroup cols={2}>
  <Card title="Install Skills" icon="puzzle-piece" href="/guides/install-skills">
    Give your bot web search, browser control, and more.
  </Card>

  <Card title="Scoped API Keys" icon="key" href="/guides/scoped-keys">
    Create restricted keys so your bot management doesn't need your org key.
  </Card>
</CardGroup>
