---
title: "Create Message"
method: POST
path: "/v1/omni-ai/threads/{thread_id}/messages"
tags: ["Omni AI"]
---

# Create Message

`POST /v1/omni-ai/threads/{thread_id}/messages`

## Request

- Base URL: `https://api.clearstreet.com`
- URL: `https://api.clearstreet.com/v1/omni-ai/threads/{thread_id}/messages`
- Auth: HTTP bearer

Append a user message to an existing thread and start an assistant response.
Poll the returned `response_id` via `GET /omni-ai/responses/{response_id}`
for assistant output.

A message sent while another response is active is accepted, and its
response is `queued`. Omni reads the message at the next safe point of the
active response. The active response then ends `steered` if it showed
text, or `merged` if it did not, and the response for the newest message
answers everything sent so far. Earlier queued responses that it answers
also end `merged`. Some requests, such as research, do not steer: their
responses, and the responses for messages sent after them, start in order
after the earlier responses end.

The first accepted selected-account message links an unlinked thread.
A linked thread keeps its account regardless of omission or another
selection. A changed scope also returns 409 without accepting a turn.

## Path parameters

- `thread_id` string, uuid, required

## Request body

- CreateMessageRequest: Continue-thread message creation request body.
  - `account_id` integer, nullable: Selected account for creation or the first account-linked turn. Omit for an unlinked conversation. An existing account link remains authoritative even when another account is selected.
  - `capabilities` Capability[]
  - `context` TurnContext: Client snapshots attached to one instant-chat user message. Context is separate from visible message text and does not grant account access. The compact JSON representation must not exceed 64 KiB.
    - `items` ContextItem[], required: One to four snapshots. Each snapshot's data may contain at most 32 levels of nesting.
      - `captured_at` string, date-time, nullable: Client-reported snapshot time. Omit when unknown.
      - `data` object, required: Relevant widget data, selections, and units. Use strings for exact decimals and large IDs.
      - `kind` string, required: Nonblank descriptive kind. New kinds do not require a backend release.
      - `label` string, required: Nonblank attachment label for conversation rendering.
  - `text` string, required

## Response `200`

Message accepted. The response may be `queued` behind an active response.

- object
  - `error` ApiError: A direct mapping of tonic::Status, for use in HTTP responses.
    - `code` integer, required: The error code is used to identify the nature of the error. It corresponds to an HTTP status code.
    - `details` object[]
    - `message` string, required: A human-readable message providing more details about the error.
  - `metadata` ResponseMetadata, required: Metadata for the response. This will always contain a request ID which can be used to identify the request to Clear Street for tracing, and optionally may include pagination data.
    - `next_page_token` string, byte, nullable: Base64URL-encoded pagination token
    - `page_number` integer, nullable: Pagination. Included if this was a GET (list) response
    - `previous_page_token` string, byte, nullable: Base64URL-encoded pagination token
    - `request_id` string, required: A unique ID for this request, generated upon ingestion of the request.
    - `total_items` integer, nullable: Total number of items available (not just in this page).
    - `total_pages` integer, nullable: Total number of pages available.
  - `data` CreateMessageResponse, required: Response payload for continuing a thread with a new message.
    - `response_id` string, uuid, required
    - `thread_id` string, uuid, required
    - `user_message_id` string, uuid, required

## Other responses

- `400`: Invalid request or supplied account ID
- `401`: Authentication required
- `403`: Caller lacks linked-account access
- `404`: Resource not found or not owned by caller
- `409`: Thread scope changed or conflicting retry; refresh before retrying
- `422`: Malformed request payload
- `500`: Internal server error

## Changes

- **2026-10-16** `1bd9eddeffc8`: 8 breaking, 5 warning, 14 info
  - removed the required property `code` from the response with the `400` status
  - removed the required property `code` from the response with the `409` status
  - removed the required property `code` from the response with the `422` status
  - removed the required property `code` from the response with the `500` status
  - …23 more

[Operation history](https://skmtc.dev/clear-street/apis/clear-street-trading-api/changes/v1/omni-ai/threads/:thread_id/messages/post.md)

---

[API](https://skmtc.dev/clear-street/apis/clear-street-trading-api.md) - [All operations](https://skmtc.dev/clear-street/apis/clear-street-trading-api/llms.txt) - [OpenAPI document](https://skmtc.dev/clear-street/apis/clear-street-trading-api/revisions/52e77ea7d731?raw)
