---
title: "Send a chat message"
description: "Sends a prompt to Mindtickle Copilot and returns the assistant reply as server-sent event chunks, with context retention and citations."
contentType: "api-reference"
url: "https://developer.mindtickle.com/docs/copilot/seller-copilot/send-a-chat-message/"
---

## Prerequisites

1. [Authentication and setup](/docs/getting-started/authentication-and-setup/): A valid access token.

## Endpoint

```http
POST /copilot/chat
```

Base URL: the standard REST host for your region. See [Base URLs](/docs/getting-started/authentication-and-setup/#base-urls).

Headers: `Authorization: Bearer ACCESS_TOKEN`, `Content-Type: application/json`.

## Request

| Parameter | Type | Required | Description |
| --- | --- | --- | --- |
| `username` | string | Required | The username of the Mindtickle user initiating the chat. |
| `input` | array | Required | A list of message exchanges in the conversation, including both user and assistant messages. Each message has the attributes below. |
| `input.role` | string | Required | The role of the persona in the conversation, `user` or `assistant`. |
| `input.content` | string | Required | The content of the message. For user messages this is the user input, and for assistant messages it is the assistant response. |

### Request example

```json
{
  "username": "dummy-user",
  "input": [
    { "role": "user", "content": "Knock, knock." },
    { "role": "assistant", "content": "Who's there?" },
    { "role": "user", "content": "ABC" }
  ]
}
```

## Response

| Field | Type | Description |
| --- | --- | --- |
| `id` | string | A unique identifier for the chat session. |
| `created` | integer | Timestamp value. Confirm its meaning and unit before using it to track session timing. See [Timestamp unit](#notes). |
| `username` | string | The username of the Mindtickle user who initiated the chat. |
| `output` | object or null | Contains the assistant response and metadata. |
| `output.index` | integer | Incremental chunk index, starting at 0. |
| `output.response` | array | An array of assistant responses. |
| `output.response.role` | string | The role of the responder, `assistant`. |
| `output.response.content` | array | Content objects containing response text and annotations. |
| `output.response.content.type` | string | The type of content. See [Content type](#notes) before implementing response handling. |
| `output.response.content.text` | string | The assistant response text. |
| `output.response.content.annotations` | array | Links to reference content used to generate the response. |
| `output.response.content.annotations.type` | string | Type of annotation, currently `link`. |
| `output.response.content.annotations.url` | string | The URL of the annotated content. |
| `output.response.content.annotations.title` | string | The title of the annotated content. |
| `output.tags` | array | Tags associated with the generated response. |
| `output.usage` | object | Reserved for future token usage information. Left blank intentionally. |
| `status` | string | Assistant response status, `in_progress`, `completed`, or `failed`. A successful final chunk has status `completed`; an error chunk has status `failed`. |
| `error` | object | Error details if a chunk response has a `failed` status. |
| `error.code` | string | Error code in the streamed payload, represented as a string. It can differ from the HTTP status. |
| `error.message` | string | Error message in natural language received from the Copilot server. |

### Response example

The following structure illustrates response fields, including `error`. It is not a successful-response example: it contains both `status: "completed"` and an error object. Check both fields when handling a response.

```json
{
  "id": "chatcmpl-123",
  "created": 1700000000,
  "username": "dummy-user",
  "output": {
    "index": 0,
    "response": [
      {
        "role": "assistant",
        "content": [
          {
            "type": "output_text",
            "text": "Sample response text.",
            "annotations": [
              {
                "type": "link",
                "url": "https://example.com",
                "title": "Example citation"
              }
            ]
          }
        ]
      }
    ],
    "tags": ["ai-generated"]
  },
  "status": "completed",
  "error": {
    "code": "500",
    "message": "error"
  }
}
```

Initial chunk:

```json
{
  "id": "dummy-query-1743673664",
  "created": 1743673664179,
  "username": "dummy-user",
  "output": {
    "index": 0,
    "tags": ["ai-generated"],
    "response": [
      {
        "role": "assistant",
        "content": [
          {
            "type": "text",
            "text": "This is dummy streaming message 1 of 10"
          }
        ]
      }
    ]
  },
  "status": "in_progress"
}
```

Final chunk:

```json
{
  "id": "dummy-query-1743673664",
  "created": 1743673669192,
  "username": "dummy-user",
  "output": {
    "index": 11,
    "tags": ["ai-generated"],
    "response": [
      {
        "role": "assistant",
        "content": [
          {
            "type": "text",
            "text": "All 10 streaming messages completed."
          }
        ]
      }
    ]
  },
  "status": "completed"
}
```

Error chunk:

```json
{
  "id": "dummy-query-1743673664",
  "created": 0,
  "username": "dummy-user",
  "output": null,
  "error": {
    "code": "400",
    "message": "Bad Request - Missing required parameter - input.role."
  },
  "status": "failed"
}
```

## Errors

Check both the HTTP status and the streamed event payload. Validation and processing failures can arrive with HTTP 200 and `status: "failed"`; HTTP 200 alone does not indicate a successful chat response.

| Status | Error | Reason | Example message |
| --- | --- | --- | --- |
| `200` | `400` | Bad request due to a validation failure. See Notes for the cases. | `{"id": "", "created": 0, "output": null, "error": {"code": "400", "message": "Bad Request - Missing required parameters: last message must be from user"}, "status": "failed", "username": "copilotuser@example.com"}` |
| `200` | `500` | Any other exception. | `{"id": "", "created": 0, "output": null, "error": {"code": "500", "message": "Internal Server Error - Contact Mindtickle support"}, "status": "failed", "username": "copilotuser@example.com"}` |
| `400` | None | Bad request. | `{"message": "missing 'username' in body"}` |
| `401` | None | Unauthorized. | `{"exp": "token expired"}` or `{"message": "Unauthorized"}` |
| `403` | None | Forbidden. Either Seller Copilot is not enabled, or the user is not authorized to use it. | `{"message": "Access Denied"}` |
| `404` | None | Not found. | `{"message": "User not found"}` |
| `413` | None | Request entity too large. | `{"message": "Request size limit exceeded", "request_id": "xyz"}` |
| `429` | None | Too many requests. Read the `Retry-After` header for the delay. For example, `Retry-After: 7` specifies the retry delay. | `{"message": "API rate limit exceeded", "request_id": "xyz"}` |
| `500` | None | Internal server error. | `{"message": "unknown error"}` |
| `502` | None | Bad gateway. | Connection error page. |
| `503` | None | Service unavailable. | Server overloaded error page. |

## Notes

- **Content type:** Confirm the supported `content.type` values with [Mindtickle Support](mailto:support@mindtickle.com) before implementing response handling. Do not treat `text` and `output_text` as interchangeable values.
- **Validation:** A `400` error code is returned when the JSON is invalid or a subfield has a type mismatch, the `input` field is absent or an empty array, `role` is a value other than `user` and `assistant`, the `content` field is empty in any input message, or the last message is not from `user`.
- **Timestamp unit:** The complete example uses a 10-digit `created` value, while the streaming examples use 13-digit values. Confirm the timestamp unit before converting it to a date.
- **Streaming:** The endpoint supports server-sent events (SSE) for real-time streaming responses. The initial chunk starts the assistant reply incrementally, the final chunk completes the full response, and an error chunk carries a `failed` status with error details. If the connection closes before a terminal `completed` or `failed` chunk, treat the response as incomplete.
- **Rate limits:** 600 requests per minute. The documented payload limit is approximately 200 KB per request. Measure the serialized UTF-8 request in bytes; character count is not equivalent to byte size. Multiple requests can run concurrently as long as the limit per minute is not exceeded.
- **Performance:** The initial chunk timeout is 60 seconds. Average latency between the initial and final chunks is 10 seconds, and may vary with volume and agents. The SLA is 99.9% uptime.
- **Permissions:** The API requires the Seller Copilot feature to be active on your instance, and the caller must be a user an admin has authorized under the **Audience** setting.
