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

# Client events

> Events your client can send over the WebSocket.

Your client can send the following five event types. Any other type is rejected with an `EVENT_TYPE_SYSTEM_MESSAGE` error.

## `EVENT_TYPE_REQUEST_POLY_AGENT_JOIN`

Requests the PolyAI agent to join the session. **You must send this to start the conversation.**

```json theme={"theme":{"light":"github-light","dark":"github-dark"}}
{
  "type": "EVENT_TYPE_REQUEST_POLY_AGENT_JOIN",
  "payload": {}
}
```

After sending this, you receive (in order):

1. An echo of your event
2. `EVENT_TYPE_POLY_AGENT_JOINED` — the agent has joined
3. `EVENT_TYPE_POLY_AGENT_THINKING` — the agent is preparing its greeting
4. `EVENT_TYPE_POLY_AGENT_MESSAGE` (or chunks, if streaming) — the greeting message

## `EVENT_TYPE_USER_MESSAGE`

Send a text message from the user.

```json theme={"theme":{"light":"github-light","dark":"github-dark"}}
{
  "type": "EVENT_TYPE_USER_MESSAGE",
  "payload": {
    "text": "I'd like to book a table for tomorrow at 7pm."
  }
}
```

| Field  | Type   | Required | Description      |
| ------ | ------ | -------- | ---------------- |
| `text` | string | Yes      | The message text |

The server echoes this back with a server-assigned `message_id` added to the payload.

## `EVENT_TYPE_USER_TYPING`

Notify the server that the user is typing (or has stopped). Use this to show typing indicators on the live agent side.

```json theme={"theme":{"light":"github-light","dark":"github-dark"}}
{
  "type": "EVENT_TYPE_USER_TYPING",
  "payload": {
    "state": "TYPING_STATE_STARTED"
  }
}
```

| Field   | Type   | Values                                           |
| ------- | ------ | ------------------------------------------------ |
| `state` | string | `TYPING_STATE_STARTED` or `TYPING_STATE_STOPPED` |

## `EVENT_TYPE_USER_END_SESSION`

Send when the user deliberately ends the conversation (e.g. clicks a "Leave" button).

```json theme={"theme":{"light":"github-light","dark":"github-dark"}}
{
  "type": "EVENT_TYPE_USER_END_SESSION",
  "payload": {}
}
```

This triggers a clean shutdown: the server echoes the event, then sends `EVENT_TYPE_SESSION_END` with reason `REASON_USER_END`.

## `EVENT_TYPE_HEARTBEAT`

Keeps the WebSocket alive. Send at regular intervals (typically every 30 seconds). The server echoes it back.

```json theme={"theme":{"light":"github-light","dark":"github-dark"}}
{
  "type": "EVENT_TYPE_HEARTBEAT",
  "payload": {}
}
```

See [WebSocket connection → Keeping the connection alive](/api-reference/messaging/websocket#keeping-the-connection-alive) for details.
