> For the complete documentation index, see [llms.txt](https://docs.zipchat.ai/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.zipchat.ai/installation-and-setup/chat-settings/integrations/backend-api.md).

# Backend API

The Backend API lets you programmatically access your Zipchat conversation data and manage your AI's configuration. Use it to sync conversations with your CRM, build custom analytics dashboards, take over conversations from the AI, reply to customers, and update the master prompt, custom tools (skills), and variables — all from your own systems.

### Getting Started

1. Go to **Settings > Integrations** in your Zipchat dashboard
2. Click **Enable** on the Backend API card
3. Copy your API key (prefixed with `zc-`) — store it securely, it is only shown once

### Authentication

Include your API key as a Bearer token in the `Authorization` header:

```
Authorization: Bearer zc-your_api_key_here
```

All requests must be authenticated. Unauthenticated or invalid requests return `401 Unauthorized`.

The API accepts two kinds of token, interchangeably, on every endpoint:

#### Chat-level tokens (`zc-`)

Scoped to a single chat. Generated per chat in **Settings > Integrations > Backend API**. A chat token only authenticates requests whose `:chat_id` matches the chat it belongs to — any other `chat_id` returns `401`.

#### User-level tokens (`zcu-`)

Personal to a user and work against **any chat that user can access** (chats they own or are a member of). Generate or regenerate one under **Account > Settings** (`/account/settings/edit`). Use the same `Authorization: Bearer zcu-...` header. A user token used against a `chat_id` the user cannot access returns `401` and never reveals whether that chat exists.

Both token types can call every endpoint below. Two caveats for user tokens:

* **Role model**: configuration writes (updating the prompt, creating/updating/deleting custom tools and variables) follow the same permissions as the dashboard. A `member`-role (read-only) user's token receives `403 Forbidden` on those endpoints but can still use all read and conversation endpoints.
* **Revocation**: user tokens authenticate independently of the chat's Backend API integration — disabling that integration revokes only the chat-level `zc-` key. To cut off a user token, revoke it in that user's Account > Settings, or remove the user from the chat.

Tokens are environment-specific: a token generated in production only works against production, and vice versa for staging/local environments.

### Base URL

```
https://app.zipchat.ai/api/integrations/backend_api/v1
```

### Endpoints

#### List Chats

```
GET /chats
```

Lists the chats reachable with your credential, so clients can discover chat ids. With a **user token** this returns every chat the user can access; with a **chat token** it returns only that token's chat.

**Parameters**

| Parameter  | Type    | Default | Description                |
| ---------- | ------- | ------- | -------------------------- |
| `page`     | integer | `1`     | Page number                |
| `per_page` | integer | `50`    | Items per page (max `100`) |

**Response**

```json
{
  "chats": [
    {
      "id": 1,
      "name": "Acme Store AI",
      "domain": "acme-store.com",
      "created_at": "2026-01-15T10:30:00Z"
    }
  ],
  "pagination": {
    "page": 1,
    "per_page": 50,
    "total_count": 1,
    "total_pages": 1,
    "has_next_page": false
  }
}
```

***

#### List Conversations

```
GET /chats/:chat_id/conversations
```

Returns a paginated list of conversations for the given chat.

**Parameters**

| Parameter               | Type    | Default | Description                                                                  |
| ----------------------- | ------- | ------- | ---------------------------------------------------------------------------- |
| `page`                  | integer | `1`     | Page number                                                                  |
| `per_page`              | integer | `50`    | Items per page (max `100`)                                                   |
| `last_message_at_since` | string  | —       | ISO 8601 timestamp. Only return conversations with activity since this time. |

**Response**

```json
{
  "conversations": [
    {
      "id": 12345,
      "chat_id": 1,
      "created_at": "2026-01-15T10:30:00Z",
      "last_message_at": "2026-01-15T10:45:00Z",
      "channel": "web",
      "manual_reply_mode": false,
      "last_escalated_at": null,
      "last_escalation_resolved_at": null,
      "assignee": null,
      "share_url": "https://app.zipchat.ai/chats/1/conversations/12345",
      "lead": {
        "id": 100,
        "full_name": "John Doe",
        "email": "john@example.com",
        "phone_number": "+1234567890",
        "email_marketing_consent": true
      }
    },
    {
      "id": 12346,
      "chat_id": 1,
      "created_at": "2026-01-15T11:00:00Z",
      "last_message_at": "2026-01-15T11:20:00Z",
      "channel": "whatsapp",
      "manual_reply_mode": true,
      "last_escalated_at": "2026-01-15T11:10:00Z",
      "last_escalation_resolved_at": "2026-01-15T11:18:00Z",
      "assignee": {
        "id": 42,
        "name": "Stan Marsh",
        "email": "stan@example.com",
        "avatar_url": "https://app.zipchat.ai/rails/active_storage/blobs/redirect/.../avatar.png"
      },
      "share_url": "https://app.zipchat.ai/chats/1/conversations/12346",
      "lead": null
    }
  ],
  "pagination": {
    "page": 1,
    "per_page": 50,
    "total_count": 142,
    "total_pages": 3,
    "has_next_page": true
  }
}
```

The `lead` and `assignee` fields are `null` when not set. `last_escalated_at` is set when the conversation was escalated by the AI; `last_escalation_resolved_at` is set when an agent marked the escalation resolved.

***

#### Get Conversation

```
GET /chats/:chat_id/conversations/:id
```

Returns a single conversation with its messages.

**Parameters**

| Parameter                  | Type    | Default | Description                                                       |
| -------------------------- | ------- | ------- | ----------------------------------------------------------------- |
| `message_page`             | integer | `1`     | Message page number                                               |
| `message_per_page`         | integer | `100`   | Messages per page (max `200`)                                     |
| `message_created_at_since` | string  | —       | ISO 8601 timestamp. Only return messages created since this time. |

**Response**

```json
{
  "conversation": {
    "id": 12345,
    "created_at": "2026-01-15T10:30:00Z",
    "last_message_at": "2026-01-15T10:45:00Z",
    "channel": "web",
    "manual_reply_mode": false,
    "last_escalated_at": null,
    "last_escalation_resolved_at": null,
    "assignee": null,
    "share_url": "https://app.zipchat.ai/chats/1/conversations/12345",
    "lead": {
      "id": 100,
      "first_name": "John",
      "last_name": "Doe",
      "full_name": "John Doe",
      "email": "john@example.com",
      "phone_number": "+1234567890",
      "email_marketing_consent": true,
      "phone_marketing_consent": false,
      "shopify_customer_id": "7890123456",
      "additional_attributes": {},
      "created_at": "2026-01-15T10:31:00Z"
    },
    "messages": [
      {
        "id": 50001,
        "created_at": "2026-01-15T10:30:05Z",
        "role": "user",
        "message": "Do you have this in blue?",
        "count_as_reply": false,
        "manual_reply": false,
        "status": "sent",
        "rate": null,
        "sender_id": null
      },
      {
        "id": 50002,
        "created_at": "2026-01-15T10:30:08Z",
        "role": "assistant",
        "message": "Yes! The Classic Tee is available in blue.",
        "count_as_reply": true,
        "manual_reply": false,
        "status": "sent",
        "rate": "positive",
        "sender_id": null
      }
    ],
    "messages_pagination": {
      "page": 1,
      "per_page": 100,
      "total_count": 2,
      "total_pages": 1,
      "has_next_page": false
    }
  }
}
```

The show endpoint returns expanded lead details (including `first_name`, `last_name`, `shopify_customer_id`, and `additional_attributes`) compared to the list endpoint. The `assignee`, `last_escalated_at`, and `last_escalation_resolved_at` fields follow the same shape as on the list endpoint.

***

#### List Users

```
GET /chats/:chat_id/users
```

Returns the users (the chat owner and any chat participants) who can be assigned to a conversation on this chat.

**Parameters**

| Parameter  | Type    | Default | Description                |
| ---------- | ------- | ------- | -------------------------- |
| `page`     | integer | `1`     | Page number                |
| `per_page` | integer | `50`    | Items per page (max `100`) |

**Response**

```json
{
  "users": [
    {
      "id": 42,
      "name": "Stan Marsh",
      "email": "stan@example.com",
      "avatar_url": "https://app.zipchat.ai/rails/active_storage/blobs/redirect/.../avatar.png"
    }
  ],
  "pagination": {
    "page": 1,
    "per_page": 50,
    "total_count": 1,
    "total_pages": 1,
    "has_next_page": false
  }
}
```

`avatar_url` is `null` when the user has not uploaded an avatar.

***

#### Get User

```
GET /chats/:chat_id/users/:id
```

Returns a single user. Returns `404` if the user is not in the assignable set for this chat — the endpoint will never leak information about users from other chats.

**Response**

```json
{
  "user": {
    "id": 42,
    "name": "Stan Marsh",
    "email": "stan@example.com",
    "avatar_url": null
  }
}
```

***

#### Update Conversation Assignment

```
PATCH /chats/:chat_id/conversations/:id/assignment
```

Takes a conversation over from the AI (manual mode) or hands it back to the AI. This is a single atomic operation: setting `assignee_id` to a user puts the conversation into manual mode; setting it to `null` puts it back into AI mode and unassigns.

Use `GET /chats/:chat_id/users` to discover valid `assignee_id` values.

**Request body**

```json
{ "assignee_id": 42 }
```

Or, to hand back to the AI:

```json
{ "assignee_id": null }
```

**Response**

```json
{
  "conversation": {
    "id": 12345,
    "manual_reply_mode": true,
    "assignee": {
      "id": 42,
      "name": "Stan Marsh",
      "email": "stan@example.com",
      "avatar_url": null
    }
  }
}
```

**Errors**

| Status                     | Error message                                         | Cause                                                  |
| -------------------------- | ----------------------------------------------------- | ------------------------------------------------------ |
| `404 Not Found`            | `Conversation not found`                              | The conversation does not belong to this chat.         |
| `422 Unprocessable Entity` | `assignee_id is required (use null to assign to AI)`  | The body did not include `assignee_id`.                |
| `422 Unprocessable Entity` | `assignee_id is not an assignable user for this chat` | The given user is not the chat owner or a participant. |

***

#### Escalate or Resolve Conversation

```
PATCH /chats/:chat_id/conversations/:id/escalation
```

Updates the conversation's escalation state. It only updates the escalation timestamps — it does not send notifications or assign the conversation.

**Request body**

```json
{ "resolved": false }
```

| Field      | Type    | Description                                                                                                                                                                                                                                                                                                            |
| ---------- | ------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `resolved` | boolean | Optional, defaults to `false`. When `false` (or omitted), **escalates**: sets `last_escalated_at` to now and clears `last_escalation_resolved_at` (so a previously resolved conversation is re-opened). When `true`, **resolves**: sets `last_escalation_resolved_at` to now and leaves `last_escalated_at` untouched. |

Sending no body escalates the conversation.

**Response**

The same shape for both operations:

```json
{
  "conversation": {
    "id": 12345,
    "currently_escalated": true,
    "last_escalated_at": "2026-01-15T11:10:00Z",
    "last_escalation_resolved_at": null
  }
}
```

`currently_escalated` is `true` when `last_escalated_at` is set and not yet resolved.

**Errors**

| Status          | Error message            | Cause                                          |
| --------------- | ------------------------ | ---------------------------------------------- |
| `404 Not Found` | `Conversation not found` | The conversation does not belong to this chat. |

***

#### Send Manual Message

```
POST /chats/:chat_id/conversations/:id/messages
```

Sends a manual reply from a human agent on a conversation that is currently in **manual mode**. The message is sent through whichever channel the conversation uses (web, email, WhatsApp, Instagram, Messenger).

You must take the conversation over first with `PATCH /conversations/:id/assignment` — sending while the conversation is still in AI mode returns `422`.

**Request body**

```json
{
  "message": "Hi! Happy to help with that.",
  "sender_id": 42
}
```

| Field       | Type    | Description                                                                                                   |
| ----------- | ------- | ------------------------------------------------------------------------------------------------------------- |
| `message`   | string  | The reply text. Required.                                                                                     |
| `sender_id` | integer | The user id that should be recorded as the sender. Must be a member of `GET /chats/:chat_id/users`. Required. |

**Response**

```json
{
  "message": {
    "id": 50003,
    "created_at": "2026-01-15T10:45:00Z",
    "role": "assistant",
    "message": "Hi! Happy to help with that.",
    "count_as_reply": false,
    "manual_reply": true,
    "status": "sent",
    "rate": null,
    "sender_id": 42
  }
}
```

**Errors**

| Status                     | Error message                                                                     | Cause                                                                                                              |
| -------------------------- | --------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------ |
| `404 Not Found`            | `Conversation not found`                                                          | The conversation does not belong to this chat.                                                                     |
| `422 Unprocessable Entity` | `message is required`                                                             | Empty or missing `message`.                                                                                        |
| `422 Unprocessable Entity` | `sender_id is required`                                                           | Missing `sender_id`.                                                                                               |
| `422 Unprocessable Entity` | `sender_id is not an assignable user for this chat`                               | Sender is not the chat owner or a participant.                                                                     |
| `422 Unprocessable Entity` | `Conversation is in AI mode; assign it to a user before sending a manual message` | Call the assignment endpoint first.                                                                                |
| `422 Unprocessable Entity` | `Cannot send: customer last messaged more than 24 hours ago on a Meta channel`    | WhatsApp / Instagram / Messenger enforce a 24-hour reply window from Meta. Wait for the customer to message again. |

***

#### Get Master Prompt

```
GET /chats/:chat_id/prompt
```

Returns the chat's current master prompt. Use this to read before modifying (e.g. to append to the existing prompt client-side).

**Response**

```json
{
  "prompt": {
    "chat_id": 1,
    "master_prompt": "You are a helpful support assistant for Acme Co.",
    "master_prompt_max_length": 10000
  }
}
```

***

#### Update Master Prompt

```
PATCH /chats/:chat_id/prompt
```

Replaces the chat's master prompt (the bot's core behavior instructions).

**Request body**

```json
{ "master_prompt": "You are a helpful support assistant for Acme Co." }
```

| Field           | Type   | Description                                                                                                                     |
| --------------- | ------ | ------------------------------------------------------------------------------------------------------------------------------- |
| `master_prompt` | string | The new master prompt. Required. Leading/trailing whitespace is stripped. Must not exceed the chat's configured maximum length. |

**Response**

```json
{
  "prompt": {
    "chat_id": 1,
    "master_prompt": "You are a helpful support assistant for Acme Co.",
    "master_prompt_max_length": 10000
  }
}
```

**Errors**

| Status                     | Error message                                     | Cause                                                                                                               |
| -------------------------- | ------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------- |
| `403 Forbidden`            | `Your role does not allow configuration changes`  | User token belongs to a read-only (`member`-role) user.                                                             |
| `422 Unprocessable Entity` | `master_prompt is required`                       | The body did not include `master_prompt`.                                                                           |
| `422 Unprocessable Entity` | `master_prompt cannot be blank`                   | The value was `null`, empty, or whitespace-only. Blank values are rejected rather than silently erasing the prompt. |
| `422 Unprocessable Entity` | `Master prompt must be at most N characters long` | The prompt exceeded `master_prompt_max_length`.                                                                     |

***

#### Custom Tools (Skills)

Custom tools (labeled "skills" in the dashboard) are per-chat actions the AI can invoke.

**List**

```
GET /chats/:chat_id/custom_tools
```

Paginated (`page`, `per_page`, max `100`).

```json
{
  "custom_tools": [
    {
      "id": 12,
      "name": "Order lookup",
      "instructions": "Fetch orders from the API",
      "active": true,
      "channels": ["all channels"],
      "icon_id": null,
      "custom_tool_template_id": null,
      "variable_ids": [5, 7],
      "created_at": "2026-01-15T10:30:00Z",
      "updated_at": "2026-01-15T10:30:00Z"
    }
  ],
  "pagination": { "page": 1, "per_page": 50, "total_count": 1, "total_pages": 1, "has_next_page": false }
}
```

**Create**

```
POST /chats/:chat_id/custom_tools
```

```json
{
  "custom_tool": {
    "name": "Order lookup",
    "instructions": "Fetch orders from the API",
    "channels": ["all channels"],
    "active": true,
    "variable_ids": [5, 7]
  }
}
```

| Field          | Type    | Description                                                                                                                                                    |
| -------------- | ------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `name`         | string  | Required, max 255 chars.                                                                                                                                       |
| `instructions` | string  | Required, max 10000 chars.                                                                                                                                     |
| `channels`     | array   | Channels the tool is active on. When omitted, defaults to the template's install channels if `custom_tool_template_id` is given, otherwise `["all channels"]`. |
| `active`       | boolean | Optional, defaults to `true`.                                                                                                                                  |
| `variable_ids` | array   | Optional. IDs of existing pool variables to attach to this tool. Must be an array of ids (`422` otherwise).                                                    |

Returns `201` with the serialized custom tool. Validation failures return `422` with an `error` message — including an unknown `icon_id` or `custom_tool_template_id` (`icon_id does not exist` / `custom_tool_template_id does not exist`).

**Update**

```
PATCH /chats/:chat_id/custom_tools/:id
```

Same body shape as create (all fields optional; `custom_tool_template_id` is create-only and ignored here). `variable_ids`, when present, is the **full desired set** of attached variables: missing ones are attached and absent ones detached (detaching only removes the link — the pooled variable itself is untouched). Omit the key to leave attachments unchanged. Returns `200`, or `404` if the tool does not belong to this chat.

**Delete**

```
DELETE /chats/:chat_id/custom_tools/:id
```

Returns `204 No Content`, or `404` if the tool does not belong to this chat.

***

#### Variables

Variables are a per-chat pool of secrets (e.g. API keys) that custom tools reference. **Values are write-only** — they are encrypted at rest and never returned by the API; responses expose only a `has_value` flag.

**List**

```
GET /chats/:chat_id/variables
```

Paginated (`page`, `per_page`, max `100`).

```json
{
  "variables": [
    {
      "id": 5,
      "name": "API_KEY",
      "kind": "user",
      "has_value": true,
      "usage_count": 2,
      "custom_tool_ids": [12],
      "created_at": "2026-01-15T10:30:00Z",
      "updated_at": "2026-01-15T10:30:00Z"
    }
  ],
  "pagination": { "page": 1, "per_page": 50, "total_count": 1, "total_pages": 1, "has_next_page": false }
}
```

`kind` is `user` for normal variables or `managed_shopify` for the reserved, auto-managed `SHOPIFY_API_KEY`.

**Create**

```
POST /chats/:chat_id/variables
```

```json
{
  "skill_variable": {
    "name": "API_KEY",
    "value": "sk_live_...",
    "custom_tool_ids": [12]
  }
}
```

| Field             | Type   | Description                                                                                  |
| ----------------- | ------ | -------------------------------------------------------------------------------------------- |
| `name`            | string | Required. Uppercase letters, digits, and underscores only (e.g. `API_KEY`). Unique per chat. |
| `value`           | string | Required. Stored encrypted; never returned.                                                  |
| `custom_tool_ids` | array  | Optional. Custom tools to attach this variable to.                                           |

Returns `201`. Validation failures (bad name format, duplicate, reserved name) return `422`.

**Update**

```
PATCH /chats/:chat_id/variables/:id
```

Updates the value only. The change propagates to every custom tool the variable is attached to.

```json
{ "skill_variable": { "value": "sk_live_new..." } }
```

Returns `200`. Returns `422` if `value` is blank, `404` if the variable is not on this chat, or `422` when targeting the managed `SHOPIFY_API_KEY` (it cannot be edited via the API).

**Delete**

```
DELETE /chats/:chat_id/variables/:id
```

Returns `204 No Content`. Returns `404` if the variable is not on this chat, or `422` for the managed `SHOPIFY_API_KEY` (it cannot be deleted).

### Rate Limiting

The API allows **120 requests per 60-second window** per credential (per chat integration for chat tokens, per user for user tokens).

Every response includes rate limit headers:

| Header                  | Description                              |
| ----------------------- | ---------------------------------------- |
| `X-RateLimit-Limit`     | Maximum requests per window (`120`)      |
| `X-RateLimit-Remaining` | Requests remaining in the current window |
| `X-RateLimit-Reset`     | Unix timestamp when the window resets    |

When the limit is exceeded, the API returns `429 Too Many Requests`.

### Error Codes

| Status                     | Description                                                                              |
| -------------------------- | ---------------------------------------------------------------------------------------- |
| `401 Unauthorized`         | Missing or invalid API key                                                               |
| `403 Forbidden`            | User token's role does not allow configuration changes (prompt, custom tools, variables) |
| `404 Not Found`            | Conversation, user, custom tool, or variable not found                                   |
| `422 Unprocessable Entity` | Invalid parameter (e.g., malformed timestamp, missing field, ineligible assignee)        |
| `429 Too Many Requests`    | Rate limit exceeded                                                                      |

### Examples

#### Discover your chats with a user token

```bash
curl -H "Authorization: Bearer zcu-your_user_token" \
  "https://app.zipchat.ai/api/integrations/backend_api/v1/chats"
```

#### Read, then append to the master prompt

```bash
# 1. Read the current prompt
curl -H "Authorization: Bearer zcu-your_user_token" \
  "https://app.zipchat.ai/api/integrations/backend_api/v1/chats/1/prompt"

# 2. Send back the full prompt with your addition appended
curl -X PATCH \
  -H "Authorization: Bearer zcu-your_user_token" \
  -H "Content-Type: application/json" \
  -d '{"master_prompt": "<existing prompt>\n\nAlways mention our 30-day return policy."}' \
  "https://app.zipchat.ai/api/integrations/backend_api/v1/chats/1/prompt"
```

#### Create a custom tool with a secret variable

```bash
# 1. Create the variable (value is write-only; it is never returned)
curl -X POST \
  -H "Authorization: Bearer zcu-your_user_token" \
  -H "Content-Type: application/json" \
  -d '{"skill_variable": {"name": "ORDERS_API_KEY", "value": "sk_live_..."}}' \
  "https://app.zipchat.ai/api/integrations/backend_api/v1/chats/1/variables"

# 2. Create the tool and attach the variable (use the id from step 1)
curl -X POST \
  -H "Authorization: Bearer zcu-your_user_token" \
  -H "Content-Type: application/json" \
  -d '{"custom_tool": {"name": "Order lookup", "instructions": "Call GET https://api.example.com/orders/{id} with the ORDERS_API_KEY header...", "variable_ids": [5]}}' \
  "https://app.zipchat.ai/api/integrations/backend_api/v1/chats/1/custom_tools"
```

#### Copy a custom tool to another chat

```bash
# 1. List tools on the source chat, pick the one to copy
curl -H "Authorization: Bearer zcu-your_user_token" \
  "https://app.zipchat.ai/api/integrations/backend_api/v1/chats/1/custom_tools"

# 2. POST its name/instructions/channels to the destination chat
curl -X POST \
  -H "Authorization: Bearer zcu-your_user_token" \
  -H "Content-Type: application/json" \
  -d '{"custom_tool": {"name": "Order lookup", "instructions": "...", "channels": ["all channels"]}}' \
  "https://app.zipchat.ai/api/integrations/backend_api/v1/chats/2/custom_tools"
```

#### Fetch the latest conversations

```bash
curl -H "Authorization: Bearer zc-your_api_key" \
  "https://app.zipchat.ai/api/integrations/backend_api/v1/chats/1/conversations"
```

#### Fetch conversations updated in the last hour

```bash
curl -H "Authorization: Bearer zc-your_api_key" \
  "https://app.zipchat.ai/api/integrations/backend_api/v1/chats/1/conversations?last_message_at_since=2026-01-15T09:30:00Z"
```

#### Fetch a single conversation with messages

```bash
curl -H "Authorization: Bearer zc-your_api_key" \
  "https://app.zipchat.ai/api/integrations/backend_api/v1/chats/1/conversations/12345"
```

#### Paginate through messages

```bash
curl -H "Authorization: Bearer zc-your_api_key" \
  "https://app.zipchat.ai/api/integrations/backend_api/v1/chats/1/conversations/12345?message_page=2&message_per_page=50"
```

#### Take over a conversation, reply, and hand it back to the AI

```bash
# 1. Take the conversation over and assign it to user 42
curl -X PATCH \
  -H "Authorization: Bearer zc-your_api_key" \
  -H "Content-Type: application/json" \
  -d '{"assignee_id": 42}' \
  "https://app.zipchat.ai/api/integrations/backend_api/v1/chats/1/conversations/12345/assignment"

# 2. Send a manual reply on behalf of user 42
curl -X POST \
  -H "Authorization: Bearer zc-your_api_key" \
  -H "Content-Type: application/json" \
  -d '{"message": "Hi! Happy to help.", "sender_id": 42}' \
  "https://app.zipchat.ai/api/integrations/backend_api/v1/chats/1/conversations/12345/messages"

# 3. Hand the conversation back to the AI
curl -X PATCH \
  -H "Authorization: Bearer zc-your_api_key" \
  -H "Content-Type: application/json" \
  -d '{"assignee_id": null}' \
  "https://app.zipchat.ai/api/integrations/backend_api/v1/chats/1/conversations/12345/assignment"
```

#### Escalate, then resolve a conversation

```bash
# Escalate (no body needed)
curl -X PATCH \
  -H "Authorization: Bearer zc-your_api_key" \
  "https://app.zipchat.ai/api/integrations/backend_api/v1/chats/1/conversations/12345/escalation"

# Resolve the escalation
curl -X PATCH \
  -H "Authorization: Bearer zc-your_api_key" \
  -H "Content-Type: application/json" \
  -d '{"resolved": true}' \
  "https://app.zipchat.ai/api/integrations/backend_api/v1/chats/1/conversations/12345/escalation"
```


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.zipchat.ai/installation-and-setup/chat-settings/integrations/backend-api.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
