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

# Chat API

> Use the Chat API to power webchat, in-browser widgets, web SDK implementations, and SMS conversations.

Use the Chat API to integrate PolyAI agents into non-voice channels. It provides a simple set of REST endpoints for starting conversations, sending and receiving messages, and handling handoffs–ideal for webchat widgets, web SDKs, and SMS platforms.

The Chat API powers webchat integrations including in-browser widgets, web SDK implementations, and SMS.

<Note>
  If you need real-time streaming responses, typing indicators, or in-session live-agent handoff events over a persistent connection, use the [Messaging API](/api-reference/messaging/introduction) instead. See [Messaging API vs Chat API](/api-reference/messaging/introduction#messaging-api-vs-chat-api) for guidance on choosing.
</Note>

## Chatting with the API

1. **Start a conversation**
   Call `POST /{version}/{account_id}/{project_id}/chat/create`.
   The response includes a `conversation_id` and the agent's initial `response`.
   You can optionally pass `integration_attributes` to provide custom context to the agent, and `variant_id` to target a specific variant.

2. **Send and receive messages**
   Call `POST /{version}/{account_id}/{project_id}/chat/respond` with the `conversation_id`.
   `message` is optional. The response includes the agent's `response`, an `end_conversation` flag, and may include a `handoff` object.

3. **Close a conversation**
   Call `PUT /{version}/{account_id}/{project_id}/chat/close` with the `conversation_id` in the body.
   The response returns `{ "success": true }` on success.

## Endpoints

### Base URLs

| Region | Base URL                                                                       |
| -----: | ------------------------------------------------------------------------------ |
|     US | [https://api.us-1.platform.polyai.app](https://api.us-1.platform.polyai.app)   |
|     UK | [https://api.uk-1.platform.polyai.app](https://api.uk-1.platform.polyai.app)   |
|    EUW | [https://api.euw-1.platform.polyai.app](https://api.euw-1.platform.polyai.app) |

**Endpoint format:**
`/{version}/{account_id}/{project_id}/chat/{operation}`

* `version`: API version (for example `v1`)
* `account_id`: Your PolyAI account ID (for example `poly-scs-uk` or `ACCOUNT-xxxxxxx`)
* `project_id`: Your PolyAI project ID (for example `PROJECT-191bfa2a`)
* `operation`: `create`, `respond`, or `close`

### Finding your `account_id` and `project_id`

Your `account_id` and `project_id` are the first two path segments of your Agent Studio URL, immediately after the host:

```
https://studio.{region}.poly.ai/{account_id}/{project_id}/...
```

For example, if your Studio URL is `https://studio.uk.poly.ai/acme-uk/acme-team-4/agent`, then:

* `account_id` = `acme-uk`
* `project_id` = `acme-team-4`

Account and project identifiers are also shown as `ACCOUNT-xxxxxxx` and `PROJECT-xxxxxxxx` in some places — both the slug form (visible in the URL) and the prefixed form are accepted in API paths. If you only have the prefixed form, your PolyAI representative can confirm the matching slug.

The same IDs are exposed inside Agent Studio functions as `conv.account_id` and `conv.project_id` — see the [Conversation object reference](/tools/classes/conv-object#account_id).

## Authentication

All requests must include the following headers (case-sensitive):

| Header         | Description                            |
| -------------- | -------------------------------------- |
| `X-API-KEY`    | Your API key for PolyAI                |
| `X-TOKEN`      | Agent authentication token (connector) |
| `Content-Type` | Must be `application/json`             |

### Getting your credentials

Both `X-API-KEY` and `X-TOKEN` are provisioned by PolyAI — there is no self-serve endpoint to create a Chat API connector or generate a connector token.

To request access, contact your PolyAI representative or email [developers@poly.ai](mailto:developers@poly.ai) with:

* Your `account_id`
* Your `project_id`
* The client environment you need (`live`, `pre-release`, or `sandbox`)
* Your `variant_id` (optional, only if targeting a specific variant)

PolyAI will provision a Chat API connector for your project and return:

* An **API key** to use in the `X-API-KEY` header
* A **connector token** to use in the `X-TOKEN` header

<Note>
  The Chat API connector is distinct from the voice/telephony connectors managed under the [Agents API](/api-reference/agents/introduction). You do not need SIP details, phone numbers, or language codes to provision a Chat API connector.
</Note>

## Example: Create chat

**POST** `/v1/{account_id}/{project_id}/chat/create`

<CodeGroup>
  ```bash curl theme={"theme":{"light":"github-light","dark":"github-dark"}}
  curl -X POST \
    "https://api.us-1.platform.polyai.app/v1/ACCOUNT-xxx/PROJECT-xxx/chat/create" \
    -H "X-API-KEY: YOUR_API_KEY" \
    -H "X-TOKEN: YOUR_TOKEN" \
    -H "Content-Type: application/json" \
    -d '{
      "variant_id": "VARIANT-xxxxxxxx",
      "integration_attributes": {
        "user_id": "12345",
        "customer_tier": "premium"
      }
    }'
  ```

  ```python Python theme={"theme":{"light":"github-light","dark":"github-dark"}}
  import requests

  base_url = "https://api.us-1.platform.polyai.app"
  headers = {
      "X-API-KEY": "YOUR_API_KEY",
      "X-TOKEN": "YOUR_TOKEN",
      "Content-Type": "application/json",
  }

  response = requests.post(
      f"{base_url}/v1/ACCOUNT-xxx/PROJECT-xxx/chat/create",
      headers=headers,
      json={
          "variant_id": "VARIANT-xxxxxxxx",
          "integration_attributes": {
              "user_id": "12345",
              "customer_tier": "premium",
          },
      },
  )
  data = response.json()
  conversation_id = data["conversation_id"]
  print(data["response"])
  ```

  ```typescript TypeScript theme={"theme":{"light":"github-light","dark":"github-dark"}}
  const baseUrl = "https://api.us-1.platform.polyai.app";
  const headers = {
    "X-API-KEY": "YOUR_API_KEY",
    "X-TOKEN": "YOUR_TOKEN",
    "Content-Type": "application/json",
  };

  const res = await fetch(
    `${baseUrl}/v1/ACCOUNT-xxx/PROJECT-xxx/chat/create`,
    {
      method: "POST",
      headers,
      body: JSON.stringify({
        variant_id: "VARIANT-xxxxxxxx",
        integration_attributes: {
          user_id: "12345",
          customer_tier: "premium",
        },
      }),
    }
  );
  const data = await res.json();
  const conversationId = data.conversation_id;
  console.log(data.response);
  ```
</CodeGroup>

**Response**

```json theme={"theme":{"light":"github-light","dark":"github-dark"}}
{
  "conversation_id": "CONV-1234567890",
  "response": "Hi, how can I help you today?"
}
```

## Example: Send message

**POST** `/v1/{account_id}/{project_id}/chat/respond`

<CodeGroup>
  ```bash curl theme={"theme":{"light":"github-light","dark":"github-dark"}}
  curl -X POST \
    "https://api.us-1.platform.polyai.app/v1/ACCOUNT-xxx/PROJECT-xxx/chat/respond" \
    -H "X-API-KEY: YOUR_API_KEY" \
    -H "X-TOKEN: YOUR_TOKEN" \
    -H "Content-Type: application/json" \
    -d '{
      "conversation_id": "CONV-1234567890",
      "message": "What'\''s your return policy?"
    }'
  ```

  ```python Python theme={"theme":{"light":"github-light","dark":"github-dark"}}
  response = requests.post(
      f"{base_url}/v1/ACCOUNT-xxx/PROJECT-xxx/chat/respond",
      headers=headers,
      json={
          "conversation_id": "CONV-1234567890",
          "message": "What's your return policy?",
      },
  )
  data = response.json()
  print(data["response"])

  if data.get("end_conversation"):
      print("Conversation ended")
  if data.get("handoff"):
      print(f"Handoff to: {data['handoff']['destination']}")
  ```

  ```typescript TypeScript theme={"theme":{"light":"github-light","dark":"github-dark"}}
  const respondRes = await fetch(
    `${baseUrl}/v1/ACCOUNT-xxx/PROJECT-xxx/chat/respond`,
    {
      method: "POST",
      headers,
      body: JSON.stringify({
        conversation_id: "CONV-1234567890",
        message: "What's your return policy?",
      }),
    }
  );
  const respondData = await respondRes.json();
  console.log(respondData.response);

  if (respondData.end_conversation) {
    console.log("Conversation ended");
  }
  if (respondData.handoff) {
    console.log(`Handoff to: ${respondData.handoff.destination}`);
  }
  ```
</CodeGroup>

**Response**

```json theme={"theme":{"light":"github-light","dark":"github-dark"}}
{
  "conversation_id": "CONV-1234567890",
  "response": "Our return policy is 30 days with proof of purchase.",
  "end_conversation": false
}
```

**Response with handoff**

```json theme={"theme":{"light":"github-light","dark":"github-dark"}}
{
  "conversation_id": "CONV-1234567890",
  "response": "Transferring you to a live agent.",
  "end_conversation": true,
  "handoff": {
    "destination": "live_agent_queue",
    "reason": "billing_question"
  }
}
```

## Example: Close chat

**PUT** `/v1/{account_id}/{project_id}/chat/close`

<CodeGroup>
  ```bash curl theme={"theme":{"light":"github-light","dark":"github-dark"}}
  curl -X PUT \
    "https://api.us-1.platform.polyai.app/v1/ACCOUNT-xxx/PROJECT-xxx/chat/close" \
    -H "X-API-KEY: YOUR_API_KEY" \
    -H "X-TOKEN: YOUR_TOKEN" \
    -H "Content-Type: application/json" \
    -d '{"conversation_id": "CONV-1234567890"}'
  ```

  ```python Python theme={"theme":{"light":"github-light","dark":"github-dark"}}
  response = requests.put(
      f"{base_url}/v1/ACCOUNT-xxx/PROJECT-xxx/chat/close",
      headers=headers,
      json={"conversation_id": "CONV-1234567890"},
  )
  print(response.json())
  ```

  ```typescript TypeScript theme={"theme":{"light":"github-light","dark":"github-dark"}}
  const closeRes = await fetch(
    `${baseUrl}/v1/ACCOUNT-xxx/PROJECT-xxx/chat/close`,
    {
      method: "PUT",
      headers,
      body: JSON.stringify({
        conversation_id: "CONV-1234567890",
      }),
    }
  );
  const closeData = await closeRes.json();
  console.log(closeData);
  ```
</CodeGroup>

**Response**

```json theme={"theme":{"light":"github-light","dark":"github-dark"}}
{
  "success": true
}
```

## Passing custom data with `integration_attributes`

The `integration_attributes` field lets you pass custom data when creating a chat. These attributes are accessible in your project functions at `conv.integration_attributes`.

### When to use

* Pass user context (user ID, session ID, authentication status)
* Include customer information (tier, preferences, history)
* Send external system references (CRM ID, ticket number)
* Provide A/B test parameters or feature flags

### Accessing in project functions

```python theme={"theme":{"light":"github-light","dark":"github-dark"}}
def start(conv):
    # Get integration attributes (always check for None)
    attrs = conv.integration_attributes or {}
    
    user_id = attrs.get("user_id")
    customer_tier = attrs.get("customer_tier", "standard")
    
    # Store in state for use throughout the conversation
    if user_id:
        conv.state.user_id = user_id
    
    # Customize greeting based on tier
    if customer_tier == "premium":
        return "Welcome back! As a premium member, how can I assist you today?"
    return "Hello! How can I help you?"
```

<Note>Pass `integration_attributes` when creating the chat. They're set on the first turn and available throughout the conversation. Store values in `conv.state` to access them in later turns.</Note>

## Targeting a variant with `variant_id`

Pass `variant_id` in the `create` request body to route the conversation to a specific variant. This is useful for multi-site deployments where different variants serve different brands, languages, or regions.

```json theme={"theme":{"light":"github-light","dark":"github-dark"}}
{
  "variant_id": "VARIANT-xxxxxxxx"
}
```

<Note>`variant_id` is only accepted on `POST /chat/create`. It cannot be changed after the conversation starts.</Note>

## Notes

* `create` accepts an optional request body with `variant_id` and `integration_attributes`.
* `respond` requires `conversation_id`; `message` is optional.
* `handoff` may appear in the `respond` response with `destination` and `reason`.
* `close` requires a JSON body containing `conversation_id`.
* Header names are case-sensitive: `X-API-KEY`, `X-TOKEN`.
* Use the regional base URL closest to your deployment.
