> ## Documentation Index
> Fetch the complete documentation index at: https://danswer-mintlify-deep-research-1773355783.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Send Message (Deprecated)

> Guide to send a message to Onyx

<Note>
  This API is being deprecated in favor of the [/chat/send-chat-message](/developers/guides/chat_new_guide) API,
  it will be removed by end of Jan 2026.
</Note>

## Simple Chat Flow

*Send Message Simple API* is the quickest way to interact with Onyx programmatically.

This endpoint has fewer required parameters and returns a concise JSON payload described by `ChatBasicResponse`.

<Note>
  You must specify either a `chat_session_id` or a `persona_id` in your request.
</Note>

<CodeGroup>
  ```python Python expandable theme={null}
  import requests

  API_BASE_URL = "https://cloud.onyx.app/api" # or your own domain
  API_KEY = "YOUR_KEY_HERE"

  headers = {
    "Authorization": f"Bearer {API_KEY}",
    "Content-Type": "application/json"
  }

  '''
  - To create a chat session, see the Full-featured Chat Flow guide below.
  - To find your persona_id, see the List Agents endpoint in the Agents API Reference.
  '''

  response = requests.post(
    f"{API_BASE_URL}/chat/send-message-simple-api",
    headers=headers,
    json={
      "message": "What is Onyx?",
      "persona_id": 0  # The default Onyx Search Agent (int)
    }
  )

  data = response.json()
  answer = data.get("answer")
  answer_citationless = data.get("answer_citationless")
  message_id = data.get("message_id")
  docs = data.get("top_documents") or []
  top_documents = [
    {
      "id": doc.get("document_id"),
      "title": doc.get("semantic_identifier"),
      "link": doc.get("link")
    } for doc in docs
  ]
  cited_docs_map = data.get("cited_documents") or {}

  print(f"Answer: {answer}")
  print(f"Answer (citationless): {answer_citationless}")
  print(f"Message ID: {message_id}")
  print(f"Top Documents: {top_documents[:5]}") # Print top 5 documents
  print(f"Citations map: {cited_docs_map}")
  ```

  ```bash Shell expandable theme={null}
  #!/bin/bash

  API_BASE_URL="https://cloud.onyx.app/api"
  API_KEY="YOUR_KEY_HERE"

  echo "Sending message to Onyx..."
  RESPONSE=$(curl -s -X POST "${API_BASE_URL}/chat/send-message-simple-api" \
    -H "Authorization: Bearer ${API_KEY}" \
    -H "Content-Type: application/json" \
    -d '{
      "message": "What is Onyx?",
      "persona_id": 0
    }'
  )

  echo "Answer:"
  echo $RESPONSE | jq -r '.answer'

  echo -e "\nAnswer (citationless):"
  echo $RESPONSE | jq -r '.answer_citationless'

  echo -e "\nMessage ID:"
  echo $RESPONSE | jq -r '.message_id'

  echo -e "\nTop Documents:"
  echo $RESPONSE | jq '.top_documents | .[] | {id: .document_id, title: .semantic_identifier, link: .link}'
  ```
</CodeGroup>

## Advanced Chat Flow

The `/send-message` endpoint is what the Onyx frontend uses to send and receive messages.
Responses are streamed back in packets of JSON objects.

To understand the response format, see the [Core Concepts documentation](/developers/core_concepts/#chat).

<Steps>
  <Step title="Prepare your request">
    <CodeGroup>
      ```python Python theme={null}
      import requests

      API_BASE_URL = "https://cloud.onyx.app/api" # or your own domain
      API_KEY = "YOUR_KEY_HERE"

      headers = {
        "Authorization": f"Bearer {API_KEY}",
        "Content-Type": "application/json"
      }
      ```

      ```bash Shell theme={null}
      API_BASE_URL="https://cloud.onyx.app/api"
      API_KEY="YOUR_KEY_HERE"
      ```
    </CodeGroup>
  </Step>

  <Step title="Create a chat session">
    <CodeGroup>
      ```python Python theme={null}
      session_response = requests.post(
        f"{API_BASE_URL}/chat/create-chat-session",
        headers=headers,
        json={
          "persona_id": 0, # The default Onyx Search Agent
          "description": "Onyx API Guide Chat Session"
        }
      )

      chat_session_id = session_response.json()["chat_session_id"]
      ```

      ```bash Shell theme={null}
      CHAT_SESSION_RESPONSE=$(curl -s -X POST "${API_BASE_URL}/chat/create-chat-session" \
        -H "Authorization: Bearer ${API_KEY}" \
        -H "Content-Type: application/json" \
        -d '{
          "persona_id": 0,
          "description": "Onyx API Guide Chat Session"
        }'
      )

      # Extract chat session ID (requires jq for JSON parsing)
      CHAT_SESSION_ID=$(echo $CHAT_SESSION_RESPONSE | jq -r '.chat_session_id')
      ```
    </CodeGroup>
  </Step>

  <Step title="Send message">
    <CodeGroup>
      ```python Python theme={null}
      payload = {
        "chat_session_id": chat_session_id,
        "parent_message_id": None,
        "message": "What is Onyx?",
        "file_descriptors": [],
        "search_doc_ids": [],
        "retrieval_options": {}
      }

      # Consume the streamed packets fully and then print a summary
      # NOTE: The first packet always contains message IDs:
      #   {"user_message_id": int, "reserved_assistant_message_id": int}
      with requests.post(
        f"{API_BASE_URL}/chat/send-message",
        headers=headers,
        json=payload,
        stream=True,
      ) as resp:
        resp.raise_for_status()

        full_text = []
        docs_raw = None
        citations_map = {}
        user_message_id = None
        reserved_assistant_message_id = None

        # Each line is a JSON Packet: { ind: int, obj: { type: "...", ... } }
        for line in resp.iter_lines(decode_unicode=True):
          if not line:
            continue
          try:
            packet = json.loads(line)
          except Exception:
            continue

          # First packet: message IDs
          if "user_message_id" in packet and "reserved_assistant_message_id" in packet:
            user_message_id = packet.get("user_message_id")
            reserved_assistant_message_id = packet.get("reserved_assistant_message_id")
            continue

          obj = packet.get("obj", {})
          ptype = obj.get("type")

          if ptype == "message_start":
            # Includes final search documents per API spec
            docs_raw = obj.get("final_documents") or docs_raw
          elif ptype == "message_delta":
            delta = obj.get("content", "")
            full_text.append(delta)
          elif ptype == "citation_delta":
            # Update citation map using citation_num -> document_id pairs
            if isinstance(obj.get("citations"), list):
              for c in obj["citations"]:
                cnum = c.get("citation_num")
                did = c.get("document_id")
                if cnum is not None and did is not None:
                  citations_map[str(cnum)] = str(did)
          elif ptype == "stop":
            break

      # Prepare documents (id/title/link) if present
      top_documents = []
      if isinstance(docs_raw, list):
        for d in docs_raw:
          top_documents.append(
            {
              "id": d.get("document_id") or d.get("id"),
              "title": d.get("semantic_identifier") or d.get("title"),
              "link": d.get("link") or d.get("url"),
            }
          )

      print("Final Answer:\n" + "".join(full_text))
      if user_message_id is not None:
        print(f"\nUser message ID: {user_message_id}")
      if reserved_assistant_message_id is not None:
        print(f"Reserved assistant message ID: {reserved_assistant_message_id}")
      print("\nTop Documents:")
      print(json.dumps(top_documents, indent=2))
      print("\nCitations map (citation_num -> document_id):")
      print(json.dumps(citations_map, indent=2))
      ```

      ```bash Shell theme={null}
      # Read streamed response to completion (no live token rendering)
      curl -s -N -X POST "${API_BASE_URL}/chat/send-message" \
        -H "Authorization: Bearer ${API_KEY}" \
        -H "Content-Type: application/json" \
        -d "{
          \"chat_session_id\": \"${CHAT_SESSION_ID}\",
          \"parent_message_id\": null,
          \"message\": \"What is Onyx?\",
          \"file_descriptors\": [],
          \"search_doc_ids\": [],
          \"retrieval_options\": {}
        }" \
        | (
          TEXT=""
          DOCS_JSON=""
          CITS_JSON='{}'
          USER_MSG_ID=""
          RESERVED_ASST_ID=""
          while IFS= read -r line; do
            [ -z "$line" ] && continue
            # First packet contains message IDs
            uid=$(echo "$line" | jq -r '.user_message_id // empty')
            rid=$(echo "$line" | jq -r '.reserved_assistant_message_id // empty')
            if [ -n "$uid" ] || [ -n "$rid" ]; then
              [ -n "$uid" ] && USER_MSG_ID="$uid"
              [ -n "$rid" ] && RESERVED_ASST_ID="$rid"
              continue
            fi

            type=$(echo "$line" | jq -r '.obj.type // empty')
            if [ "$type" = "message_start" ]; then
              docs=$(echo "$line" | jq -c '(.obj.final_documents) // empty')
              if [ -n "$docs" ] && [ -z "$DOCS_JSON" ]; then
                DOCS_JSON="$docs"
              fi
            elif [ "$type" = "message_delta" ]; then
              delta=$(echo "$line" | jq -r '.obj.content // empty')
              TEXT+="$delta"
            elif [ "$type" = "citation_delta" ]; then
              newmap=$(echo "$line" | jq -c '
                if (.obj.citations // empty) then
                  (reduce (.obj.citations // [])[] as $c ({}; .[($c.citation_num|tostring)] = ($c.document_id|tostring)))
                else
                  {}
                end')
              CITS_JSON=$(jq -c --argjson A "$CITS_JSON" --argjson B "$newmap" '$A * $B' <<< '{}')
            elif [ "$type" = "stop" ]; then
              break
            fi
          done

          echo "Final Answer:"
          printf "%s\n" "$TEXT"

          echo
          if [ -n "$USER_MSG_ID" ]; then
            echo "User message ID: $USER_MSG_ID"
          fi
          if [ -n "$RESERVED_ASST_ID" ]; then
            echo "Reserved assistant message ID: $RESERVED_ASST_ID"
          fi

          echo
          echo "Top Documents:"
          if [ -z "$DOCS_JSON" ]; then
            echo "[]"
          else
            echo "$DOCS_JSON" | jq -c '[.[] | {id: (.document_id // .id), title: (.semantic_identifier // .title), link: (.link // .url)}]'
          fi

          echo
          echo "Citations map (citation_num -> document_id):"
          echo "$CITS_JSON" | jq '.'
        )
      ```
    </CodeGroup>
  </Step>
</Steps>

## Next Steps

<CardGroup cols={2}>
  <Card title="Guide: Use the Ingestion API" icon="upload" href="/developers/guides/index_files_ingestion_api">
    Use the lightweight ingestion API to index documents
  </Card>

  <Card title="Guide: Create a Connector" icon="link" href="/developers/guides/create_connector">
    Learn how to create and configure Connectors programmatically
  </Card>
</CardGroup>
