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

# Channels

> Connect external messaging channels to agents

Channel endpoints use the orchestrator:

```text theme={null}
https://api.runtools.ai/v1
```

## List channels

```bash theme={null}
curl "https://api.runtools.ai/v1/agent-channels?agent=gmail-agent" \
  -H "X-API-Key: $RUNTOOLS_API_KEY"
```

Use `provider=telegram` or `provider=whatsapp` without `agent` to list connected provider accounts in the organization.

## Connect Telegram

```bash theme={null}
curl -X POST https://api.runtools.ai/v1/agent-channels \
  -H "X-API-Key: $RUNTOOLS_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "agent": "gmail-agent",
    "provider": "telegram",
    "mode": "byok",
    "botTokenSecretName": "TELEGRAM_GMAIL_AGENT_BOT_TOKEN"
  }'
```

Then register the webhook:

```bash theme={null}
curl -X POST https://api.runtools.ai/v1/agent-channels/ch_123/register-webhook \
  -H "X-API-Key: $RUNTOOLS_API_KEY"
```

## Connect WhatsApp

Validate the Meta access token and phone number before saving secrets:

```bash theme={null}
curl -X POST https://api.runtools.ai/v1/agent-channels/whatsapp/validate-connection \
  -H "X-API-Key: $RUNTOOLS_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "agent": "gmail-agent",
    "accessToken": "'"$WHATSAPP_ACCESS_TOKEN"'",
    "phoneNumberId": "123456789012345",
    "businessAccountId": "987654321098765"
  }'
```

After storing the access token and app secret as Runtools secrets, connect the channel:

```bash theme={null}
curl -X POST https://api.runtools.ai/v1/agent-channels \
  -H "X-API-Key: $RUNTOOLS_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "agent": "gmail-agent",
    "provider": "whatsapp",
    "mode": "byok",
    "accessTokenSecretName": "WHATSAPP_GMAIL_AGENT_ACCESS_TOKEN",
    "appSecretSecretName": "WHATSAPP_GMAIL_AGENT_APP_SECRET",
    "phoneNumberId": "123456789012345",
    "businessAccountId": "987654321098765"
  }'
```

Register the webhook and copy the returned `setup.webhookUrl` and `setup.verifyToken` into Meta's WhatsApp webhook settings:

```bash theme={null}
curl -X POST https://api.runtools.ai/v1/agent-channels/ch_456/register-webhook \
  -H "X-API-Key: $RUNTOOLS_API_KEY"
```

Each WhatsApp Business phone number can be connected to one agent at a time.

## Privacy

```bash theme={null}
curl https://api.runtools.ai/v1/agent-channels/ch_123/privacy \
  -H "X-API-Key: $RUNTOOLS_API_KEY"
```

```bash theme={null}
curl -X PATCH https://api.runtools.ai/v1/agent-channels/ch_123/privacy \
  -H "X-API-Key: $RUNTOOLS_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "mode": "approved_only",
    "allowPrivateChats": true,
    "allowGroups": true,
    "unauthorizedReply": "message"
  }'
```

Approve a pending request:

```bash theme={null}
curl -X POST https://api.runtools.ai/v1/agent-channels/ch_123/privacy/requests/req_123/approve \
  -H "X-API-Key: $RUNTOOLS_API_KEY"
```

Approve a known conversation directly:

```bash theme={null}
curl -X POST https://api.runtools.ai/v1/agent-channels/ch_123/privacy/grants \
  -H "X-API-Key: $RUNTOOLS_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "scope": "conversation",
    "externalConversationId": "telegram:chat:123456789",
    "conversationType": "private",
    "conversationDisplayName": "Arthur (@ArtKara1)"
  }'
```

Revoke access:

```bash theme={null}
curl -X DELETE https://api.runtools.ai/v1/agent-channels/ch_123/privacy/grants/grant_123 \
  -H "X-API-Key: $RUNTOOLS_API_KEY"
```

## Product channel bindings

Product channel bindings let a developer-owned Telegram, WhatsApp, Slack, Discord, iMessage, or SMS channel serve end users of a product built on Runtools.

The channel credential stays builder-owned. The person chatting is resolved through a separate channel identity link:

```text theme={null}
appId + productExternalUserId + agentChannelId + providerExternalUserId
```

When a linked product user messages the channel, Runtools runs the agent with Hosted Connect end-user scope. Missing Gmail, Stripe, Slack, or other customer data credentials return `connect_required`; product channels never fall back to builder Connected Apps.

### Bind a channel to a product app

```bash theme={null}
curl -X POST https://api.runtools.ai/v1/apps/atlas/channel-bindings \
  -H "X-API-Key: $RUNTOOLS_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "agentChannelId": "ch_123",
    "identityPolicy": "link_required",
    "groupPolicy": "sender_scoped",
    "unknownSenderReply": "Open Atlas to link this chat: {linkUrl}",
    "metadata": {
      "linkUrl": "https://atlas.example.com/settings/channels/link"
    }
  }'
```

```bash theme={null}
curl https://api.runtools.ai/v1/apps/atlas/channel-bindings \
  -H "X-API-Key: $RUNTOOLS_API_KEY"
```

```bash theme={null}
curl -X DELETE https://api.runtools.ai/v1/apps/atlas/channel-bindings/bind_123 \
  -H "X-API-Key: $RUNTOOLS_API_KEY"
```

`identityPolicy` must be `link_required`. `groupPolicy` can be `disabled` or `sender_scoped`.

### Link a channel sender to a product user

Create a link session from your product server:

```bash theme={null}
curl -X POST https://api.runtools.ai/v1/apps/atlas/channel-link-sessions \
  -H "X-API-Key: $RUNTOOLS_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "agentChannelId": "ch_123",
    "externalUserId": "user_123",
    "returnUrl": "https://atlas.example.com/settings/channels"
  }'
```

Complete it after your product verifies the provider sender identity:

```bash theme={null}
curl -X POST https://api.runtools.ai/v1/apps/atlas/channel-link-sessions/sess_123/complete \
  -H "X-API-Key: $RUNTOOLS_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "token": "pcl_...",
    "productExternalUserId": "user_123",
    "providerExternalUserId": "telegram_user_456",
    "externalConversationId": "telegram:chat:789",
    "displayName": "Sam Carter",
    "username": "sam"
  }'
```

For trusted server-side imports, link directly:

```bash theme={null}
curl -X POST https://api.runtools.ai/v1/apps/atlas/channel-links \
  -H "X-API-Key: $RUNTOOLS_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "agentChannelId": "ch_123",
    "externalUserId": "telegram_user_456",
    "productExternalUserId": "user_123",
    "externalConversationId": "telegram:chat:789"
  }'
```

List and revoke links:

```bash theme={null}
curl "https://api.runtools.ai/v1/apps/atlas/channel-links?agentChannelId=ch_123&productExternalUserId=user_123" \
  -H "X-API-Key: $RUNTOOLS_API_KEY"
```

```bash theme={null}
curl -X POST https://api.runtools.ai/v1/apps/atlas/channel-links/link_123/revoke \
  -H "X-API-Key: $RUNTOOLS_API_KEY"
```
