> 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.

# Anpassad kanal

## Översikt

Custom Channel ansluter ett externt meddelandesystem till en ElevenLabs-agent. Skicka användarmeddelanden till en ElevenLabs-webhook och ta sedan emot agentsvar på din egen HTTPS-slutpunkt.

> **Warning**
>
> Custom Channel är i alfa.

> **Warning**
>
> Custom Channel är inte tillgänglig för agenter eller arbetsytor som använder nollagringsläge.

## Funktioner

| Funktion              | Stöd                                                              |
| --------------------- | ----------------------------------------------------------------- |
| Nollagringsläge (ZRM) | Stöds inte — inte tillgängligt för ZRM-arbetsytor och ZRM-agenter |
| Bilagor i meddelanden | Stöds inte — meddelanden kan endast innehålla text                |

## Konfiguration

#### Öppna Custom Channel

Öppna din agent, välj **Kanaler**, välj **Custom Channel** och klicka på **Lägg till utlösare**.

#### Konfigurera utlösaren

Välj en befintlig anslutning eller skapa en och ange sedan **Webhook-URL för svar**.

#### Kopiera autentiseringsuppgifterna

Klicka på **Lägg till** och kopiera sedan **Inkommande webhook-URL**, **Inkommande hemlighet** och **Hemlighet för utgående signering**.

#### Konfigurera din tjänst

Skicka användarmeddelanden till den inkommande webhook-URL:en med den inkommande hemligheten i `X-Webhook-Secret`. Använd hemligheten för utgående signering för att verifiera varje svar.

## Skicka ett meddelande

Skicka en `POST`-begäran till den genererade webhook-URL:en:

```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"
  }
}
```

| Fält                   | Krävs | Beskrivning                                                                                      |
| ---------------------- | ----- | ------------------------------------------------------------------------------------------------ |
| `data.type`            | Ja    | Måste vara `user_message`.                                                                       |
| `data.text`            | Ja    | Användarmeddelande som inte är tomt.                                                             |
| `data.user_identifier` | Nej   | Identifierare för den externa användaren.                                                        |
| `user_message_id`      | Ja    | Icke-tom idempotensnyckel som tillhandahålls av ditt system.                                     |
| `conversation_id`      | Nej   | Inkludera det returnerade ID:t för att fortsätta en konversation. Utelämna för att starta en ny. |
| `dynamic_variables`    | Nej   | Dynamiska variabler som tillhandahålls till agenten för denna tur.                               |

ElevenLabs returnerar `202 Accepted` innan turen bearbetas:

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

Fortsätt konversationen genom att skicka en ny begäran med det `conversation_id` och ett nytt `user_message_id`.

## Ta emot svar

ElevenLabs skickar en `POST`-begäran till webhook-URL:en för svar efter varje tur:

```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
}
```

Om bearbetningen misslyckas är `status` `failed`, `data` är `[]` och `error` innehåller en beskrivning.

`data` listar händelser i turordning. Varje objekt har en `type` och en `event`:

* `agent_response` innehåller ett yttrande från agenten. `response_id` identifierar yttrandet unikt, medan `event_id` kopplar det till en tur. Sammanfoga `agent_response`-värdena om din kanal visar en textbubbla per tur.
* `agent_tool_response` rapporterar resultatet från ett verktyg och delar turens `event_id`. Dess `status` är `success`, `error`, `blocked` eller `skipped`. Ett svar med `tool_type: "system"`, `tool_name: "end_call"` och `status: "success"` innebär att agenten avslutade konversationen.

Flera inkommande meddelanden kan slås ihop till en tur. `user_message_ids` listar ID:n för de användarmeddelanden som detta svar besvarar.

## Verifiera svarssignaturer

Varje svar innehåller rubriken `ElevenLabs-Signature`:

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

Sammandraget är en HMAC-SHA256-signatur över `{timestamp}.{raw_request_body}` med hemligheten för utgående signering. Verifiera den råa brödtexten innan du tolkar JSON och avvisa gamla tidsstämplar.

```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");
  }
}
```

## Leveransbeteende

ElevenLabs gör tre leveransförsök i processen, vid ungefär 0, 0,5 och 2 sekunder. Ett `2xx`-svar markerar leveransen som lyckad.

Begärandetexter är begränsade till 256 KiB.