# Chat channels

## What this covers

Connect a channel of your own to one of your agents, and the agent answers everyone who writes to it: a Telegram bot made with @BotFather (its webhook is set for you), or a WhatsApp number or Instagram professional account on your own Meta app (paste the response's `webhook_url` and `meta.verify_token` into the app's webhook settings). Tokens and secrets are sent once and never returned. WhatsApp and Instagram replies go out only within Meta's 24-hour window.

Every example below runs as written once these are exported:

```bash
export DVAARIK_API_KEY="dvk_..."        # project API key, server side only
export DVAARIK_TOKEN="<account access token>"   # console session, from POST /console/auth/login
export CHANNEL_ID="<uuid>"
export PROJECT_ID="<uuid>"
```

A `<value>` inside a JSON body is a value you supply. Responses are JSON; every error body is `{ "detail": … }`. Each schema is expanded once per page, where it first appears.

### Machine door errors

Raised by the project-key dependency before any handler on this page runs.

| Status | Cause |
| --- | --- |
| `401` | `Missing API key` or `Invalid API key` — the `X-Api-Key` header is absent, unknown, or revoked. |
| `403` | `API key is not scoped to a project`, `Project unavailable`, or `API key is missing the required scope '<scope>'`. |
| `429` | The project's `api_rpm` ceiling was exceeded. Honour `Retry-After`; `X-RateLimit-*` headers are on every response. |

Scopes used on this page: `channel:read`, `channel:write`. Mint a key with only these.

### Account door errors

| Status | Cause |
| --- | --- |
| `401` | No account session was presented, or it is invalid or expired. Refresh once, then re-authenticate. |
| `403` | The account is suspended or its email is not verified. |

## Operations — project API key

Call these from your own server with a project key. Never from a browser or a mobile bundle.

### GET `/v2/chat-channels`

List the project's channels with their state, webhook address, limits and, for WhatsApp and Instagram, what to paste into the Meta app. Never a token or a secret.

| Detail | Value |
| --- | --- |
| Door | Project API key — `X-Api-Key: $DVAARIK_API_KEY` |
| Scope | `channel:read` |
| Operation | `listChatChannels` |
| Success | `200` `ChatChannelPage` |

#### `ChatChannelPage`

| Field | Type | Required | Notes |
| --- | --- | --- | --- |
| `data` | ChatChannelInfo[] | yes |  |

#### `ChatChannelInfo`

| Field | Type | Required | Notes |
| --- | --- | --- | --- |
| `account_id` | string or null | yes |  |
| `account_name` | string or null | yes |  |
| `agent_id` | uuid or null | yes |  |
| `checked_at` | date-time or null | yes |  |
| `created_at` | date-time | yes |  |
| `disconnected_at` | date-time or null | yes |  |
| `id` | uuid | yes |  |
| `last_error` | string or null | yes |  |
| `last_error_at` | date-time or null | yes |  |
| `meta` | ChatChannelMeta or null | no |  |
| `name` | string | yes |  |
| `pending_updates` | integer or null | yes |  |
| `provider` | "telegram" or "whatsapp" or "instagram" or "api" | yes |  |
| `replies_per_day` | integer | yes |  |
| `replies_per_minute` | integer | yes |  |
| `status` | "active" or "error" or "disconnected" | yes |  |
| `turns_per_hour` | integer | yes |  |
| `updated_at` | date-time | yes |  |
| `webhook_url` | string | yes |  |

#### `ChatChannelMeta`

WhatsApp and Instagram: what to paste into your Meta app, and what Meta says about the account.

| Field | Type | Required | Notes |
| --- | --- | --- | --- |
| `display_phone_number` | string or null | no |  |
| `subscription` | ChatChannelSubscription or null | no |  |
| `token_expires_at` | date-time or null | no |  |
| `token_refreshed_at` | date-time or null | no |  |
| `username` | string or null | no |  |
| `verified_name` | string or null | no |  |
| `verify_token` | string | yes |  |
| `waba_id` | string or null | no |  |
| `webhook_fields` | string[] | yes |  |
| `webhook_object` | "whatsapp_business_account" or "instagram" | yes |  |

#### `ChatChannelSubscription`

How subscribing your app to the account's webhooks went (Meta's `subscribed_apps`).

| Field | Type | Required | Notes |
| --- | --- | --- | --- |
| `at` | date-time or null | no |  |
| `error` | string or null | no |  |
| `ok` | boolean | yes |  |

#### `FieldErrors`

A 422 from a route that names its fields: every field that failed validation, or one sentence when the request validated and was then refused.

| Field | Type | Required | Notes |
| --- | --- | --- | --- |
| `detail` | string or FieldError[] | yes | The fields that failed validation (each named), or a sentence for the developer. |

| Error | When |
| --- | --- |
| `401` | No API key was sent in X-Api-Key, or it is invalid or revoked. |
| `403` | The API key lacks the scope this route needs, or its account or project is unavailable. |
| `422` | The request body or query is not valid. `detail` is an array of `{loc, msg, type}` and `loc` names the offending field. |
| `429` | The project's requests-per-minute limit is reached; Retry-After says when to try again. |

Plus the machine-door errors above. Full list on the [errors page](/docs/errors).

```bash
curl -sS -X GET "https://api.developers.dvaarik.com/v2/chat-channels" \
  -H "X-Api-Key: $DVAARIK_API_KEY"
```

### POST `/v2/chat-channels`

Connect a Telegram bot, a WhatsApp number or an Instagram account to an agent. The token is checked with the provider first and a refused one is never stored. A Telegram webhook is set for you; for WhatsApp and Instagram, paste `webhook_url` and `meta.verify_token` into your Meta app.

| Detail | Value |
| --- | --- |
| Door | Project API key — `X-Api-Key: $DVAARIK_API_KEY` |
| Scope | `channel:write` |
| Operation | `createChatChannel` |
| Success | `201` `ChatChannelInfo` |

Request body: `ChatChannelCreate`.

#### `ChatChannelCreate`

Connect a channel to one of your agents: your own Telegram bot (its token from @BotFather), or a WhatsApp number or Instagram professional account on your OWN Meta app (the access token, the app secret that signs its webhooks, and the account's id). For WhatsApp and Instagram, paste the response's `webhook_url` and `meta.verify_token` into your Meta app's webhook settings.

| Field | Type | Required | Notes |
| --- | --- | --- | --- |
| `access_token` | string or null | no |  |
| `agent_id` | uuid | yes |  |
| `app_secret` | string or null | no |  |
| `bot_token` | string or null | no |  |
| `instagram_account_id` | string or null | no |  |
| `instagram_app_secret` | string or null | no |  |
| `name` | string | yes | min length 1; max length 120 |
| `phone_number_id` | string or null | no |  |
| `provider` | "telegram" or "whatsapp" or "instagram" | yes |  |
| `replies_per_day` | integer or null | no |  |
| `replies_per_minute` | integer or null | no |  |
| `turns_per_hour` | integer or null | no |  |
| `waba_id` | string or null | no |  |

| Error | When |
| --- | --- |
| `401` | No API key was sent in X-Api-Key, or it is invalid or revoked. |
| `403` | The API key lacks the scope this route needs, or its account or project is unavailable. |
| `404` | The addressed resource does not exist in this key's project. One in another project is deliberately indistinguishable from one that never existed. |
| `409` | A limit or the resource's state refuses this change; the sentence says which. |
| `422` | The request body or query is not valid. `detail` is an array of `{loc, msg, type}` and `loc` names the offending field. |
| `429` | The project's requests-per-minute limit is reached; Retry-After says when to try again. |

Plus the machine-door errors above. Full list on the [errors page](/docs/errors).

```bash
curl -sS -X POST "https://api.developers.dvaarik.com/v2/chat-channels" \
  -H "X-Api-Key: $DVAARIK_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "agent_id": "<agent uuid>",
    "name": "Support bot",
    "provider": "telegram",
    "bot_token": "<token from @BotFather>"
  }'
```

### DELETE `/v2/chat-channels/{channel_id}`

Disconnect the channel: it stops answering at once and its credentials are forgotten. A Telegram webhook is deleted while it still points here; a Meta app keeps its callback URL until you change it.

| Detail | Value |
| --- | --- |
| Door | Project API key — `X-Api-Key: $DVAARIK_API_KEY` |
| Scope | `channel:write` |
| Operation | `disconnectChatChannel` |
| Success | `200` `ChatChannelInfo` |

| Parameter | In | Type | Required | Notes |
| --- | --- | --- | --- | --- |
| `channel_id` | path | uuid | yes |  |

| Error | When |
| --- | --- |
| `401` | No API key was sent in X-Api-Key, or it is invalid or revoked. |
| `403` | The API key lacks the scope this route needs, or its account or project is unavailable. |
| `404` | The addressed resource does not exist in this key's project. One in another project is deliberately indistinguishable from one that never existed. |
| `422` | The request body or query is not valid. `detail` is an array of `{loc, msg, type}` and `loc` names the offending field. |
| `429` | The project's requests-per-minute limit is reached; Retry-After says when to try again. |

Plus the machine-door errors above. Full list on the [errors page](/docs/errors).

```bash
curl -sS -X DELETE "https://api.developers.dvaarik.com/v2/chat-channels/$CHANNEL_ID" \
  -H "X-Api-Key: $DVAARIK_API_KEY"
```

### GET `/v2/chat-channels/{channel_id}`

Read one channel.

| Detail | Value |
| --- | --- |
| Door | Project API key — `X-Api-Key: $DVAARIK_API_KEY` |
| Scope | `channel:read` |
| Operation | `getChatChannel` |
| Success | `200` `ChatChannelInfo` |

| Parameter | In | Type | Required | Notes |
| --- | --- | --- | --- | --- |
| `channel_id` | path | uuid | yes |  |

| Error | When |
| --- | --- |
| `401` | No API key was sent in X-Api-Key, or it is invalid or revoked. |
| `403` | The API key lacks the scope this route needs, or its account or project is unavailable. |
| `404` | The addressed resource does not exist in this key's project. One in another project is deliberately indistinguishable from one that never existed. |
| `422` | The request body or query is not valid. `detail` is an array of `{loc, msg, type}` and `loc` names the offending field. |
| `429` | The project's requests-per-minute limit is reached; Retry-After says when to try again. |

Plus the machine-door errors above. Full list on the [errors page](/docs/errors).

```bash
curl -sS -X GET "https://api.developers.dvaarik.com/v2/chat-channels/$CHANNEL_ID" \
  -H "X-Api-Key: $DVAARIK_API_KEY"
```

### PATCH `/v2/chat-channels/{channel_id}`

Rename the channel, answer with another agent, change its limits, or give the same account's new credentials: a bot's new token; a new access token, app secret or WABA id. Only the fields you send change; the verify token never does.

| Detail | Value |
| --- | --- |
| Door | Project API key — `X-Api-Key: $DVAARIK_API_KEY` |
| Scope | `channel:write` |
| Operation | `updateChatChannel` |
| Success | `200` `ChatChannelInfo` |

| Parameter | In | Type | Required | Notes |
| --- | --- | --- | --- | --- |
| `channel_id` | path | uuid | yes |  |

Request body: `ChatChannelUpdate`.

#### `ChatChannelUpdate`

Rename, answer with another agent, change the limits, or give the SAME account's new credentials: a bot's new token (Telegram); a new access token, app secret or WABA id (WhatsApp, Instagram). A new token is checked against the account before it is saved.

| Field | Type | Required | Notes |
| --- | --- | --- | --- |
| `access_token` | string or null | no |  |
| `agent_id` | uuid or null | no |  |
| `app_secret` | string or null | no |  |
| `bot_token` | string or null | no |  |
| `instagram_app_secret` | string or null | no |  |
| `name` | string or null | no |  |
| `replies_per_day` | integer or null | no |  |
| `replies_per_minute` | integer or null | no |  |
| `turns_per_hour` | integer or null | no |  |
| `waba_id` | string or null | no |  |

| Error | When |
| --- | --- |
| `401` | No API key was sent in X-Api-Key, or it is invalid or revoked. |
| `403` | The API key lacks the scope this route needs, or its account or project is unavailable. |
| `404` | The addressed resource does not exist in this key's project. One in another project is deliberately indistinguishable from one that never existed. |
| `409` | A limit or the resource's state refuses this change; the sentence says which. |
| `422` | The request body or query is not valid. `detail` is an array of `{loc, msg, type}` and `loc` names the offending field. |
| `429` | The project's requests-per-minute limit is reached; Retry-After says when to try again. |

Plus the machine-door errors above. Full list on the [errors page](/docs/errors).

```bash
curl -sS -X PATCH "https://api.developers.dvaarik.com/v2/chat-channels/$CHANNEL_ID" \
  -H "X-Api-Key: $DVAARIK_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "replies_per_minute": 20
  }'
```

### POST `/v2/chat-channels/{channel_id}/check`

Ask the provider now: Telegram's last error and the messages it still holds, or whether Meta still accepts the token, with your app subscribed again. A refused token turns the channel `error`.

| Detail | Value |
| --- | --- |
| Door | Project API key — `X-Api-Key: $DVAARIK_API_KEY` |
| Scope | `channel:write` |
| Operation | `checkChatChannel` |
| Success | `200` `ChatChannelInfo` |

| Parameter | In | Type | Required | Notes |
| --- | --- | --- | --- | --- |
| `channel_id` | path | uuid | yes |  |

| Error | When |
| --- | --- |
| `401` | No API key was sent in X-Api-Key, or it is invalid or revoked. |
| `403` | The API key lacks the scope this route needs, or its account or project is unavailable. |
| `404` | The addressed resource does not exist in this key's project. One in another project is deliberately indistinguishable from one that never existed. |
| `409` | A limit or the resource's state refuses this change; the sentence says which. |
| `422` | The request body or query is not valid. `detail` is an array of `{loc, msg, type}` and `loc` names the offending field. |
| `429` | The project's requests-per-minute limit is reached; Retry-After says when to try again. |

Plus the machine-door errors above. Full list on the [errors page](/docs/errors).

```bash
curl -sS -X POST "https://api.developers.dvaarik.com/v2/chat-channels/$CHANNEL_ID/check" \
  -H "X-Api-Key: $DVAARIK_API_KEY"
```

## Operations — account session

The same resource through the console door. These are what the web console calls; both doors return the same shapes.

### GET `/console/v2/projects/{project_id}/chat-channels`

List the project's channels with their state, webhook address, limits and, for WhatsApp and Instagram, what to paste into the Meta app. Never a token or a secret.

| Detail | Value |
| --- | --- |
| Door | Account session — `Authorization: Bearer $DVAARIK_TOKEN` |
| Operation | `consoleListChatChannels` |
| Success | `200` `ChatChannelPage` |

| Parameter | In | Type | Required | Notes |
| --- | --- | --- | --- | --- |
| `project_id` | path | uuid | yes |  |

| Error | When |
| --- | --- |
| `401` | No account session was presented, or it is invalid or expired. |
| `403` | The account is suspended or its email is not verified. |
| `404` | The project or the addressed resource does not exist for this owner. A resource owned by another developer is deliberately indistinguishable from one that never existed. |
| `422` | The request body or query is not valid. `detail` is an array of `{loc, msg, type}` and `loc` names the offending field. |

Plus the account-door errors above. Full list on the [errors page](/docs/errors).

```bash
curl -sS -X GET "https://api.developers.dvaarik.com/console/v2/projects/$PROJECT_ID/chat-channels" \
  -H "Authorization: Bearer $DVAARIK_TOKEN"
```

### POST `/console/v2/projects/{project_id}/chat-channels`

Connect a Telegram bot, a WhatsApp number or an Instagram account to an agent. The token is checked with the provider first and a refused one is never stored. A Telegram webhook is set for you; for WhatsApp and Instagram, paste `webhook_url` and `meta.verify_token` into your Meta app.

| Detail | Value |
| --- | --- |
| Door | Account session — `Authorization: Bearer $DVAARIK_TOKEN` |
| Operation | `consoleCreateChatChannel` |
| Success | `201` `ChatChannelInfo` |

| Parameter | In | Type | Required | Notes |
| --- | --- | --- | --- | --- |
| `project_id` | path | uuid | yes |  |

Request body: `ChatChannelCreate`.

| Error | When |
| --- | --- |
| `401` | No account session was presented, or it is invalid or expired. |
| `403` | The account is suspended or its email is not verified. |
| `404` | The project or the addressed resource does not exist for this owner. A resource owned by another developer is deliberately indistinguishable from one that never existed. |
| `409` | The project or resource is in a state that refuses this change. |
| `422` | The request body or query is not valid. `detail` is an array of `{loc, msg, type}` and `loc` names the offending field. |

Plus the account-door errors above. Full list on the [errors page](/docs/errors).

```bash
curl -sS -X POST "https://api.developers.dvaarik.com/console/v2/projects/$PROJECT_ID/chat-channels" \
  -H "Authorization: Bearer $DVAARIK_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "agent_id": "<agent uuid>",
    "name": "Support bot",
    "provider": "telegram",
    "bot_token": "<token from @BotFather>"
  }'
```

### DELETE `/console/v2/projects/{project_id}/chat-channels/{channel_id}`

Disconnect the channel: it stops answering at once and its credentials are forgotten. A Telegram webhook is deleted while it still points here; a Meta app keeps its callback URL until you change it.

| Detail | Value |
| --- | --- |
| Door | Account session — `Authorization: Bearer $DVAARIK_TOKEN` |
| Operation | `consoleDisconnectChatChannel` |
| Success | `200` `ChatChannelInfo` |

| Parameter | In | Type | Required | Notes |
| --- | --- | --- | --- | --- |
| `channel_id` | path | uuid | yes |  |
| `project_id` | path | uuid | yes |  |

| Error | When |
| --- | --- |
| `401` | No account session was presented, or it is invalid or expired. |
| `403` | The account is suspended or its email is not verified. |
| `404` | The project or the addressed resource does not exist for this owner. A resource owned by another developer is deliberately indistinguishable from one that never existed. |
| `409` | The project or resource is in a state that refuses this change. |
| `422` | The request body or query is not valid. `detail` is an array of `{loc, msg, type}` and `loc` names the offending field. |

Plus the account-door errors above. Full list on the [errors page](/docs/errors).

```bash
curl -sS -X DELETE "https://api.developers.dvaarik.com/console/v2/projects/$PROJECT_ID/chat-channels/$CHANNEL_ID" \
  -H "Authorization: Bearer $DVAARIK_TOKEN"
```

### GET `/console/v2/projects/{project_id}/chat-channels/{channel_id}`

Read one channel.

| Detail | Value |
| --- | --- |
| Door | Account session — `Authorization: Bearer $DVAARIK_TOKEN` |
| Operation | `consoleGetChatChannel` |
| Success | `200` `ChatChannelInfo` |

| Parameter | In | Type | Required | Notes |
| --- | --- | --- | --- | --- |
| `channel_id` | path | uuid | yes |  |
| `project_id` | path | uuid | yes |  |

| Error | When |
| --- | --- |
| `401` | No account session was presented, or it is invalid or expired. |
| `403` | The account is suspended or its email is not verified. |
| `404` | The project or the addressed resource does not exist for this owner. A resource owned by another developer is deliberately indistinguishable from one that never existed. |
| `422` | The request body or query is not valid. `detail` is an array of `{loc, msg, type}` and `loc` names the offending field. |

Plus the account-door errors above. Full list on the [errors page](/docs/errors).

```bash
curl -sS -X GET "https://api.developers.dvaarik.com/console/v2/projects/$PROJECT_ID/chat-channels/$CHANNEL_ID" \
  -H "Authorization: Bearer $DVAARIK_TOKEN"
```

### PATCH `/console/v2/projects/{project_id}/chat-channels/{channel_id}`

Rename the channel, answer with another agent, change its limits, or give the same account's new credentials: a bot's new token; a new access token, app secret or WABA id. Only the fields you send change; the verify token never does.

| Detail | Value |
| --- | --- |
| Door | Account session — `Authorization: Bearer $DVAARIK_TOKEN` |
| Operation | `consoleUpdateChatChannel` |
| Success | `200` `ChatChannelInfo` |

| Parameter | In | Type | Required | Notes |
| --- | --- | --- | --- | --- |
| `channel_id` | path | uuid | yes |  |
| `project_id` | path | uuid | yes |  |

Request body: `ChatChannelUpdate`.

| Error | When |
| --- | --- |
| `401` | No account session was presented, or it is invalid or expired. |
| `403` | The account is suspended or its email is not verified. |
| `404` | The project or the addressed resource does not exist for this owner. A resource owned by another developer is deliberately indistinguishable from one that never existed. |
| `409` | The project or resource is in a state that refuses this change. |
| `422` | The request body or query is not valid. `detail` is an array of `{loc, msg, type}` and `loc` names the offending field. |

Plus the account-door errors above. Full list on the [errors page](/docs/errors).

```bash
curl -sS -X PATCH "https://api.developers.dvaarik.com/console/v2/projects/$PROJECT_ID/chat-channels/$CHANNEL_ID" \
  -H "Authorization: Bearer $DVAARIK_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "replies_per_minute": 20
  }'
```

### POST `/console/v2/projects/{project_id}/chat-channels/{channel_id}/check`

Ask the provider now: Telegram's last error and the messages it still holds, or whether Meta still accepts the token, with your app subscribed again. A refused token turns the channel `error`.

| Detail | Value |
| --- | --- |
| Door | Account session — `Authorization: Bearer $DVAARIK_TOKEN` |
| Operation | `consoleCheckChatChannel` |
| Success | `200` `ChatChannelInfo` |

| Parameter | In | Type | Required | Notes |
| --- | --- | --- | --- | --- |
| `channel_id` | path | uuid | yes |  |
| `project_id` | path | uuid | yes |  |

| Error | When |
| --- | --- |
| `401` | No account session was presented, or it is invalid or expired. |
| `403` | The account is suspended or its email is not verified. |
| `404` | The project or the addressed resource does not exist for this owner. A resource owned by another developer is deliberately indistinguishable from one that never existed. |
| `409` | The project or resource is in a state that refuses this change. |
| `422` | The request body or query is not valid. `detail` is an array of `{loc, msg, type}` and `loc` names the offending field. |

Plus the account-door errors above. Full list on the [errors page](/docs/errors).

```bash
curl -sS -X POST "https://api.developers.dvaarik.com/console/v2/projects/$PROJECT_ID/chat-channels/$CHANNEL_ID/check" \
  -H "Authorization: Bearer $DVAARIK_TOKEN"
```

---

Source: https://developers.dvaarik.com/docs/api/chat-channels · every page as one file: https://developers.dvaarik.com/docs.md
