# How to Integrate External System via Custom Channel

Custom Channel allows integrating ConnectiveOne with any external system that can send and receive HTTP requests. This is useful for connecting existing bots, CRM systems, or new communication channels.

---

## When to Use Custom Channel?

Custom Channel is suitable for such cases:

- Connecting an existing bot from another system to ConnectiveOne
- Extending capabilities of an existing bot thanks to ConnectiveOne (for example, connecting operator panel)
- Connecting correspondence within CRM to ConnectiveOne
- Integrating internal communication systems
- Quickly connecting new channels (messengers) for which there is no official integration yet

---

## Prerequisites

Before starting integration, make sure that:

- [ ] You have a developer team on the external system side with experience in REST API and JSON
- [ ] You can control request formats that your system sends and receives
- [ ] You have tried integration through Postman or another HTTP client
- [ ] You have contacted ConnectiveOne support if you need clarification on request or event formats

---

## How Does Custom Channel Work?

Custom Channel works through a sequence of HTTPS POST requests:

**Incoming flow (from external system to ConnectiveOne):**
- Your system sends POST requests to ConnectiveOne's `input_url`
- ConnectiveOne processes messages through bot scenarios

**Outgoing flow (from ConnectiveOne to external system):**
- ConnectiveOne sends messages and events to your `custom_channel_url`
- Your system processes incoming messages and events

---

## Configuration

### Step 1: Configuration in ConnectiveOne

1. Go to **Bot Settings** → select the needed bot
2. Scroll to the **Custom Channel** section
3. Configure the following parameters:

- **`custom_channel_url`** — address of your server where ConnectiveOne will send messages
  - For testing, you can use services like [https://requestcatcher.com/](https://requestcatcher.com/)
- **`custom_channel x-access-token`** — token that ConnectiveOne will pass in the `x-access-token` header of each message
  - If your service doesn't support this, leave it empty
- **`input_url`** — auto-generated field, address to which you need to send messages
  - This field is generated automatically after configuration
- **`custom_channel kwizbot token`** — token for signing messages sent to ConnectiveOne
  - Specified in the request header as `x-auth-token`
  - If left empty, ConnectiveOne will accept messages without a token

---

## Sending Messages to ConnectiveOne

### URL Format

```
POST https://{{engine_url}}/messengers_host/{{bot_id}}/custom_channel/hooks
```

Where:
- `engine_url` — `engine.instance_name.connectiveone.io` or `engine-instance_name.connectiveone.io`
- `bot_id` — bot ID from the settings page

### Example Request

```json
{
  "update_id": 498995546,
  "message": {
    "from": {
      "id": "wregw3ergwergwergw==",
      "first_name": "",
      "last_name": "",
      "username": "Natalia",
      "language_code": "uk",
      "is_bot": false,
      "phone": "888888888888",
      "channel": "viber",
      "dialog_name": "Natalia"
    },
    "chat": {
      "id": "wregw3ergwergwergw==_viber"
    },
    "date": 1696408917974,
    "text": "Kyiv",
    "type": "text"
  }
}
```

> 🧑‍💻 **Note:** To start the bot, you need to send `/start` as the first message.

### Request Parameters

| Parameter | Type | Description |
|-----------|------|-------------|
| `update_id` | int | Unique value |
| `message.from.id` | string | User ID |
| `message.from.first_name` | string | User first name in operator panel |
| `message.from.last_name` | string | User last name |
| `message.from.username` | string | User nickname |
| `message.from.language_code` | string | Language code (uk, ru, en) |
| `message.chat.id` | string | User chat code |
| `message.text` | string | Message text (for start: `/start`) |
| `message.type` | string | Message type (text) |
| `message.from.dialog_name` | string | Chat name for display in operator panel |

---

## Receiving Messages from ConnectiveOne

Your service will receive a POST request to `custom_channel_url` with these headers:

```http
POST /your_url HTTP/1.1
Host: your-service.com
Content-Type: application/json;charset=utf-8
User-Agent: ConnectiveOne
x-access-token: YOUR_TOKEN
```

**Example request body:**

```json
{
  "reply_markup": {
    "remove_keyboard": false
  },
  "chat_id": "398866",
  "text": "Notifications bot\nMy chat id: 398866,  channel custom_channel",
  "id": "71577138-fe1e-4ce7-b53e-0cec45ee3534",
  "from": "bot",
  "bot_id": 71,
  "type": "text"
}
```

---

## Message Types

### Incoming Messages (Accepted by ConnectiveOne)

- `text` — text
- `image` — image
- `text_image` — text with image in one message
- `video` — video
- `audio` — audio message
- `file` — file

### Outgoing Messages (Sent by ConnectiveOne)

- Text messages
- Messages with keyboard
- Sliders
- Files and images (as links)

---

## Event Types

ConnectiveOne sends the following event types:

- `chat_created` — chat created
- `auto_connected` — auto-connection of operator
- `operator_connected` — operator connected
- `operator_disconnected` — operator disconnected
- `chat_closed_by_operator` — chat closed by operator
- `chat_closed` — chat closed
- `chat_closed_by_timeout` — chat closed by timeout
- `connection_timeout` — connection timeout

### Example `chat_created` Event

```json
{
  "reply_markup": {
    "remove_keyboard": false
  },
  "chat_id": "34122",
  "text": "Chat created",
  "event_name": "chat_created",
  "client": {
    "id": 572338,
    "first_name": "Test",
    "last_name": "Surname",
    "username": "testuername",
    "language_code": "uk",
    "phone": "+380505776464",
    "channel": "telegram"
  },
  "id": "83317aa1-8ea4-4c05-afed-d7437ff88fbf",
  "from": "bot",
  "bot_id": 4,
  "type": "text"
}
```

> 📖 **Documentation:** If you only need events from the operator panel, consider the alternative through [Operator Panel Webhook](/en/integrations/how-to/webhook/configure-operator-panel-webhook.md).

---

## Bot Scenario Configuration

### Step 1: Mark Channel in Blocks

In the bot scenario, after the **"Section Start"** element, you need to mark **custom_channel** in advanced settings for all blocks that will interact with Custom Channel.

### Step 2: Configure Scenario Exit

To end the scenario:

1. Create a **"Message to User"** block with a conditional word for exit (for example, `/exit`)
2. In constants, specify `close_chat_command` with value `/exit`
3. In block advanced settings:
   - Remove marks on all messengers
   - Leave the **custom_channel** mark

---

## Getting Available Operators

### Endpoint

```
POST https://engine-projectname.connectiveone.io/kw/custom_channel/operators_available
```

### Usage Example

```bash
curl --location --request POST 'https://engine-projectname.connectiveone.io/kw/custom_channel/operators_available' \
--data ''
```

### Response Format

```json
{
  "status": "success",
  "data": [
    {
      "id": 56,
      "max_dialogs": 30,
      "rooms_count": 0,
      "max_dialog_id": 498
    }
  ]
}
```

---

## Limitations

- Custom Channel works only through HTTPS
- Webhook endpoint configuration is required on the external system side
- Request timeout depends on system settings
- It is recommended to use retry logic for reliability

---

## Related Articles

- [Configure operator panel webhook](/en/integrations/how-to/webhook/configure-operator-panel-webhook.md)
- [What are integrations](/en/integrations/explanation/what-are-integrations.md)

