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

# Messaging API

> Embed real-time text conversations into your application using WebSockets, with handoff to live agents.

The Messaging API lets you embed real-time text conversations into your application. End users chat with a PolyAI agent, and the conversation can be handed off to a live human agent inside the same session when needed.

Communication happens over a WebSocket connection after a short HTTP handshake. All messages are JSON-encoded events.

> [!NOTE]
>
> The Messaging API is a **real-time, event-driven** protocol. If you only need simple turn-based request/response (for example for SMS), use the [Chat API](https://docs.poly.ai/api-reference/chat/introduction.md) instead. See [Messaging API vs Chat API](#messaging-api-vs-chat-api) below.

## Base URL

```
https://messaging.poly.ai
```

For cluster-specific deployments, the pattern is `https://messaging.<cluster>.poly.ai`:

| Cluster | Base URL | Description |
| - | - | - |
| `us-1` | `https://messaging.us-1.poly.ai` | US Mainland |
| `uk-1` | `https://messaging.uk-1.poly.ai` | UK |
| `euw-1` | `https://messaging.euw-1.poly.ai` | EU West |

Your PolyAI contact will confirm which base URL to use.

## Prerequisites

Before integrating, you need two values:

| Value | What it is | Where to find it |
| - | - | - |
| **Connector token** | A secret token that identifies your integration | Provisioned by PolyAI — contact your PolyAI representative to request one |
| **Host identifier** | The domain (e.g. `https://www.yourcompany.com`) or app namespace (e.g. `com.yourcompany.app`) registered against the connector token | Set when the token is provisioned. The server rejects requests where `X-Host` doesn't match. |

> [!NOTE]
>
> The self-serve **Messaging → API Configuration** page in Agent Studio is not fully built out yet. For now, your PolyAI representative will provision a connector token and register the host identifier on your behalf.

> [!TIP]
>
> If you already have a PolyAI webchat widget configured, you can reuse its credentials:
>
> * **Connector token**: the value between the last `/` and `.js` in the widget embed script URL.
> * **Host identifier**: the same domain you set in the widget configuration.

> [!TIP]
>
> Subdomains are matched against the registered host — for example, a connector registered to `yourcompany.com` accepts requests from `app.yourcompany.com`.

## Getting started

Every conversation follows this sequence:

**1. Obtain an access token**

`POST /api/v1/access-token` with your connector token. Returns a short-lived JWT.

**2. Create a session**

`POST /api/v1/sessions` with the access token. Returns a `session_id`.

**3. Open a WebSocket connection**

`wss://<base-url>/ws?access_token=...&session_id=...`

**4. Request the agent to join**

Send `EVENT_TYPE_REQUEST_POLY_AGENT_JOIN` to start the conversation.

**5. Exchange messages**

Send and receive events over the WebSocket.

> [!WARNING]
>
> The PolyAI agent does not join the session automatically. On a **new session**, after opening the WebSocket and receiving the session history, your client must explicitly send `EVENT_TYPE_REQUEST_POLY_AGENT_JOIN` to start the conversation. On a **reconnect** to an existing session, the agent has already joined — check the replayed history for `EVENT_TYPE_POLY_AGENT_JOINED` and skip the join request if present.

### Minimal JavaScript example

```javascript theme={"theme":{"light":"github-light","dark":"github-dark"}}
// 1. Get an access token
const tokenRes = await fetch("https://messaging.us-1.poly.ai/api/v1/access-token", {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
    "X-Token": "<your-connector-token>",
    "X-Host": "https://www.yourcompany.com",
  },
  body: "{}",
});
const { access_token } = await tokenRes.json();

// 2. Create a session
const sessionRes = await fetch("https://messaging.us-1.poly.ai/api/v1/sessions", {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
    "Authorization": `Bearer ${access_token}`,
  },
  body: JSON.stringify({ streaming_enabled: false }),
});
const { session_id } = await sessionRes.json();

// 3. Open the WebSocket
const ws = new WebSocket(
  `wss://messaging.us-1.poly.ai/ws?session_id=${session_id}&access_token=${access_token}`
);

ws.onmessage = (event) => {
  const msg = JSON.parse(event.data);
  console.log(msg.type, msg.payload);
};

ws.onopen = () => {
  // Wait for EVENT_TYPE_EVENT_BATCH (history replay), then:

  // 4. Request the agent to join
  ws.send(JSON.stringify({
    type: "EVENT_TYPE_REQUEST_POLY_AGENT_JOIN",
    payload: {},
  }));
};
```

## Messaging API vs Chat API

PolyAI offers two APIs for non-voice channels. Pick the one that matches your integration model.

| | [Messaging API](https://docs.poly.ai/api-reference/messaging/introduction.md) | [Chat API](https://docs.poly.ai/api-reference/chat/introduction.md) |
| - | - | - |
| **Protocol** | WebSocket (real-time, event-driven) | REST (turn-based request/response) |
| **Streaming responses** | Yes (incremental chunks) | No |
| **Typing indicators** | Yes | No |
| **Live-agent handoff** | Yes (full event flow over the WebSocket) | Yes (via `handoff` in the respond response) |
| **Reconnection / history replay** | Built-in (`cursor` query param) | Client manages turns |
| **Auth** | Connector token + host domain → short-lived JWT | API key + connector token |
| **Best for** | Web apps, iOS/Android apps, custom SDKs | SMS, server-to-server, simple webchat |

## Reference

> [card] [Sessions and authentication](https://docs.poly.ai/api-reference/messaging/sessions.md)
>
> Obtain an access token and create a session

> [card] [WebSocket connection](https://docs.poly.ai/api-reference/messaging/websocket.md)
>
> Connect, reconnect, and keep the connection alive

> [card] [Event format](https://docs.poly.ai/api-reference/messaging/events.md)
>
> Common envelope, echo behavior, delivery receipts

> [card] [Client events](https://docs.poly.ai/api-reference/messaging/events-send.md)
>
> Events your client can send

> [card] [Server events](https://docs.poly.ai/api-reference/messaging/events-receive.md)
>
> Events your client receives

> [card] [Streaming](https://docs.poly.ai/api-reference/messaging/streaming.md)
>
> Receive agent responses as incremental chunks

> [card] [Handoff to live agent](https://docs.poly.ai/api-reference/messaging/handoff.md)
>
> Server-managed and client-managed handoff flows

> [card] [Session lifecycle](https://docs.poly.ai/api-reference/messaging/lifecycle.md)
>
> Every event in order, from connect to session end

> [card] [Errors](https://docs.poly.ai/api-reference/messaging/errors.md)
>
> HTTP codes and system-message error catalog

> [card] [Best practices](https://docs.poly.ai/api-reference/messaging/best-practices.md)
>
> Connection management, dedup, ordering, UX, security
