> This is a page from the ElevenLabs documentation. For a complete page index, fetch https://elevenlabs.io/docs/llms.txt. For the full documentation in a single file, fetch https://elevenlabs.io/docs/llms-full.txt.

# कस्टम चैनल

## खास जानकारी

Custom Channel किसी बाहरी मैसेजिंग सिस्टम को ElevenLabs एजेंट से जोड़ता है। यूज़र मैसेज को ElevenLabs webhook पर भेजें, फिर अपने HTTPS endpoint पर एजेंट के जवाब पाएं।

> **Warning**
>
> Custom Channel अल्फ़ा में है।

> **Warning**
>
> Zero-retention mode इस्तेमाल करने वाले एजेंट्स या workspaces के लिए Custom Channel उपलब्ध नहीं है।

## क्षमताएं

| क्षमता                    | सहायता                                                          |
| ------------------------- | --------------------------------------------------------------- |
| Zero retention mode (ZRM) | समर्थित नहीं — ZRM workspaces और ZRM एजेंट्स के लिए उपलब्ध नहीं |
| मैसेज में अटैचमेंट्स      | समर्थित नहीं — मैसेज सिर्फ़ टेक्स्ट हो सकते हैं                 |

## सेटअप

#### Custom Channel खोलें

अपना एजेंट खोलें, **Channels** चुनें, **Custom Channel** चुनें, और **Add trigger** पर क्लिक करें।

#### ट्रिगर कॉन्फ़िगर करें

मौजूदा कनेक्शन चुनें या नया बनाएं, फिर **Reply Webhook URL** डालें।

#### क्रेडेंशियल्स कॉपी करें

**Add** पर क्लिक करें, फिर **Inbound Webhook URL**, **Inbound Secret**, और **Outbound Signing Secret** कॉपी करें।

#### अपनी सेवा कॉन्फ़िगर करें

`X-Webhook-Secret` में inbound secret के साथ user messages को inbound webhook URL पर भेजें। हर जवाब को सत्यापित करने के लिए outbound signing secret का इस्तेमाल करें।

## मैसेज भेजें

जनरेट किए गए webhook URL पर `POST` request भेजें:

```text
POST /v1/convai/api-integrations/custom_channel/triggers/{trigger_connection_id}/async_message
X-Webhook-Secret: <inbound-secret>
Content-Type: application/json
```

```json
{
  "data": {
    "type": "user_message",
    "text": "Where is my order?",
    "user_identifier": "customer_8427"
  },
  "user_message_id": "msg_01k1e6z3f4t8n9c2",
  "dynamic_variables": {
    "order_id": "order_72491"
  }
}
```

| फ़ील्ड                 | ज़रूरी | जानकारी                                                                                  |
| ---------------------- | ------ | ---------------------------------------------------------------------------------------- |
| `data.type`            | हाँ    | `user_message` होना चाहिए।                                                               |
| `data.text`            | हाँ    | खाली न होने वाला यूज़र मैसेज।                                                            |
| `data.user_identifier` | नहीं   | बाहरी यूज़र का आइडेंटिफ़ायर।                                                             |
| `user_message_id`      | हाँ    | आपके सिस्टम से दिया गया, खाली न होने वाला idempotency key।                               |
| `conversation_id`      | नहीं   | बातचीत जारी रखने के लिए लौटाई गई ID शामिल करें। नई बातचीत शुरू करने के लिए इसे छोड़ दें। |
| `dynamic_variables`    | नहीं   | इस टर्न के लिए एजेंट को दिए गए dynamic variables।                                        |

ElevenLabs टर्न प्रोसेस करने से पहले `202 Accepted` लौटाता है:

```json
{
  "conversation_id": "conv_01k1e72d4x8p6v3m",
  "status": "queued"
}
```

बातचीत जारी रखने के लिए उस `conversation_id` और नए `user_message_id` के साथ एक और request भेजें।

## जवाब पाएं

हर टर्न के बाद ElevenLabs reply webhook URL पर `POST` request भेजता है:

```json
{
  "version": "1",
  "conversation_id": "conv_01k1e72d4x8p6v3m",
  "user_message_ids": ["msg_01k1e6z3f4t8n9c2"],
  "status": "completed",
  "data": [
    {
      "type": "agent_response",
      "event": {
        "agent_response": "Your order is scheduled to arrive tomorrow.",
        "response_id": "9f2c1a7e-4b3d-4e8a-9c1f-2d6b8e0a5f31",
        "event_id": 4
      }
    },
    {
      "type": "agent_tool_response",
      "event": {
        "tool_name": "end_call",
        "tool_call_id": "toolu_01k1e70r4b8y",
        "tool_type": "system",
        "event_id": 4,
        "is_called": true,
        "is_error": false,
        "is_blocked": false,
        "status": "success"
      }
    }
  ],
  "error": null
}
```

अगर प्रोसेसिंग विफल होती है, तो `status` `failed` होता है, `data` `[]` होता है, और `error` में जानकारी होती है।

`data` में टर्न के क्रम में इवेंट्स होते हैं। हर आइटम में एक `type` और एक `event` होता है:

* `agent_response` में एजेंट का एक कथन होता है। `response_id` कथन की विशिष्ट पहचान करता है, जबकि `event_id` उसे एक टर्न से जोड़ता है। अगर आपका चैनल हर टर्न के लिए एक टेक्स्ट बबल दिखाता है, तो `agent_response` वैल्यूज़ को जोड़ दें।
* `agent_tool_response` किसी टूल का परिणाम बताता है और टर्न का `event_id` साझा करता है। इसका `status` `success`, `error`, `blocked`, या `skipped` होता है। `tool_type: "system"`, `tool_name: "end_call"`, और `status: "success"` वाला जवाब बताता है कि एजेंट ने बातचीत खत्म कर दी है।

कई inbound messages को एक टर्न में जोड़ा जा सकता है। `user_message_ids` में उन user message IDs की सूची होती है जिनका जवाब यह reply दे रहा है।

## रिप्लाई सिग्नेचर सत्यापित करें

हर reply में `ElevenLabs-Signature` header शामिल होता है:

```text
t=1753876800,v0=<hex-digest>
```

digest, outbound signing secret का इस्तेमाल करके `{timestamp}.{raw_request_body}` पर बनाया गया HMAC-SHA256 signature है। JSON parse करने से पहले raw body सत्यापित करें और पुराने timestamps अस्वीकार करें।

```python
import hashlib
import hmac
import time


def verify_signature(raw_body: bytes, header: str, secret: str) -> None:
    values = dict(part.split("=", 1) for part in header.split(","))
    timestamp = values["t"]
    if abs(time.time() - int(timestamp)) > 30 * 60:
        raise ValueError("Stale webhook signature")

    expected = hmac.new(
        secret.encode(),
        timestamp.encode() + b"." + raw_body,
        hashlib.sha256,
    ).hexdigest()
    if not hmac.compare_digest(expected, values["v0"]):
        raise ValueError("Invalid webhook signature")
```

```typescript
import { createHmac, timingSafeEqual } from "node:crypto";

export function verifySignature(rawBody: Buffer, header: string, secret: string): void {
  const values = Object.fromEntries(header.split(",").map((part) => part.split("=", 2)));
  const timestamp = values.t;
  if (!timestamp || Math.abs(Date.now() / 1000 - Number(timestamp)) > 30 * 60) {
    throw new Error("Stale webhook signature");
  }

  const expected = createHmac("sha256", secret).update(`${timestamp}.`).update(rawBody).digest();
  const received = Buffer.from(values.v0 ?? "", "hex");
  if (received.length !== expected.length || !timingSafeEqual(expected, received)) {
    throw new Error("Invalid webhook signature");
  }
}
```

## डिलीवरी व्यवहार

ElevenLabs लगभग 0, 0.5 और 2 सेकंड पर इन-प्रोसेस डिलीवरी के तीन प्रयास करता है। `2xx` response डिलीवरी को सफल चिह्नित करता है।

Request body की सीमा 256 KiB है।