> ## Documentation Index
> Fetch the complete documentation index at: https://docs.onyx.app/llms.txt
> Use this file to discover all available pages before exploring further.

# Handle Send Search Message

> Executes a search query with optional streaming.

If hybrid_alpha is unset and ONYX_SEARCH_UI_USES_OPENSEARCH_KEYWORD_SEARCH
is True, executes pure keyword search.

Returns:
    StreamingResponse with SSE if stream=True, otherwise SearchFullResponse.

<Info>
  **Required permission:** Search — Read (`read:search`), which `basic` includes, so any signed-in user has it.
  A limited [Personal Access Token](/developers/overview#personal-access-tokens) needs the Search — Read scope.
</Info>

<Note>
  This is the endpoint behind the Onyx Search UI.
  Unlike [`POST /chat/send-chat-message`](/developers/api_reference/chat/handle_send_chat_message),
  `stream` defaults to `false` here, so the default response is the aggregated `SearchFullResponse`.
  See [Search with the API](/developers/guides/search_api_guide) for the streaming packet format.
</Note>

<Warning>
  Requires a vector database: deployments running with `DISABLE_VECTOR_DB` set (Onyx Lite) answer with `501`.
  Every query from a signed-in user is recorded in that user's [search
  history](/developers/api_reference/search/get_search_history).
</Warning>


## OpenAPI

````yaml POST /search/send-search-message
openapi: 3.1.0
info:
  title: Onyx API
  description: Onyx API for AI-powered enterprise search and chat
  version: Development
servers:
  - url: https://cloud.onyx.app/api
security: []
paths:
  /search/send-search-message:
    post:
      tags:
        - public
      summary: Handle Send Search Message
      description: >-
        Executes a search query with optional streaming.


        If hybrid_alpha is unset and
        ONYX_SEARCH_UI_USES_OPENSEARCH_KEYWORD_SEARCH

        is True, executes pure keyword search.


        Returns:
            StreamingResponse with SSE if stream=True, otherwise SearchFullResponse.
      operationId: handle_send_search_message
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/SendSearchQueryRequest'
      responses:
        '200':
          description: >-
            If `stream=true`, returns `text/event-stream`.

            If `stream=false` (the default), returns `application/json`
            (SearchFullResponse).
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SearchFullResponse'
            text/event-stream:
              schema:
                type: string
              examples:
                stream:
                  summary: Stream of NDJSON search packets
                  value: string
        '422':
          description: Validation Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/HTTPValidationError'
      security:
        - BearerAuth: []
components:
  schemas:
    SendSearchQueryRequest:
      properties:
        search_query:
          type: string
          title: Search Query
          description: The query to search for.
        filters:
          anyOf:
            - $ref: '#/components/schemas/BaseFilters'
            - type: 'null'
          description: >-
            Restrict which documents are searched. All fields are optional and
            combine with AND.
        num_docs_fed_to_llm_selection:
          anyOf:
            - type: integer
            - type: 'null'
          title: Num Docs Fed To Llm Selection
          description: >-
            When set to 1 or more, the top N merged sections are handed to an
            LLM that picks the most relevant ones, and their document ids come
            back in `llm_selected_doc_ids`. Omit it (or send `null`) to skip LLM
            selection and the extra LLM call it costs.
        run_query_expansion:
          type: boolean
          title: Run Query Expansion
          default: false
          description: >-
            When true, an LLM generates extra keyword queries from
            `search_query`. Every query runs in parallel and the results are
            merged with weighted reciprocal-rank fusion, with the original query
            weighted twice as heavily as each expansion. The queries that
            actually ran come back in `all_executed_queries`. Expansion failures
            are non-fatal: the original query still runs on its own.
        num_hits:
          type: integer
          title: Num Hits
          default: 30
          description: Maximum number of merged sections to return.
        hybrid_alpha:
          anyOf:
            - type: number
            - type: 'null'
          title: Hybrid Alpha
          description: >-
            Balance between vector and keyword matching, from `0.0` (pure
            keyword) to `1.0` (pure vector). Leave unset to use the deployment's
            `HYBRID_ALPHA` (`0.5` by default) — except on deployments configured
            for OpenSearch keyword search, where leaving it unset runs a pure
            keyword search.
        include_content:
          type: boolean
          title: Include Content
          default: false
          description: >-
            When true, each returned document carries the full text of the
            matched section in `content`. When false, `content` is `null` and
            only `blurb` is populated.
        stream:
          type: boolean
          title: Stream
          default: false
          description: >-
            When true, responds with a stream of newline-delimited JSON packets.
            When false (the default), returns the aggregated
            `SearchFullResponse`.
      type: object
      required:
        - search_query
      title: SendSearchQueryRequest
    SearchFullResponse:
      properties:
        all_executed_queries:
          items:
            type: string
          type: array
          title: All Executed Queries
          description: >-
            Every query that was run, starting with the original. Contains more
            than one entry only when `run_query_expansion` was set.
        search_docs:
          items:
            $ref: '#/components/schemas/SearchDocWithContent'
          type: array
          title: Search Docs
          description: Matched sections, most relevant first.
        doc_selection_reasoning:
          anyOf:
            - type: string
            - type: 'null'
          title: Doc Selection Reasoning
          description: >-
            Reserved for the LLM's document-selection reasoning. Not currently
            populated — always `null` on this endpoint.
        llm_selected_doc_ids:
          anyOf:
            - items:
                type: string
              type: array
            - type: 'null'
          title: Llm Selected Doc Ids
          description: >-
            Document ids the LLM picked out of `search_docs`. `null` when LLM
            selection was not requested or failed, an empty list when it ran and
            chose nothing.
        error:
          anyOf:
            - type: string
            - type: 'null'
          title: Error
          description: >-
            Set when the search failed partway through; the other fields hold
            whatever was gathered before the failure.
      type: object
      required:
        - all_executed_queries
        - search_docs
      title: SearchFullResponse
    HTTPValidationError:
      properties:
        detail:
          items:
            $ref: '#/components/schemas/ValidationError'
          type: array
          title: Detail
      type: object
      title: HTTPValidationError
    BaseFilters:
      properties:
        source_type:
          anyOf:
            - items:
                $ref: '#/components/schemas/DocumentSource'
              type: array
            - type: 'null'
          title: Source Type
        document_set:
          anyOf:
            - items:
                type: string
              type: array
            - type: 'null'
          title: Document Set
        created_at_range:
          anyOf:
            - $ref: '#/components/schemas/TimeRange'
            - type: 'null'
        updated_at_range:
          anyOf:
            - $ref: '#/components/schemas/TimeRange'
            - type: 'null'
        tags:
          anyOf:
            - items:
                $ref: '#/components/schemas/Tag'
              type: array
            - type: 'null'
          title: Tags
        time_cutoff:
          anyOf:
            - type: string
              format: date-time
            - type: 'null'
          title: Time Cutoff
      type: object
      title: BaseFilters
    SearchDocWithContent:
      properties:
        document_id:
          type: string
          title: Document Id
        chunk_ind:
          type: integer
          title: Chunk Ind
        semantic_identifier:
          type: string
          title: Semantic Identifier
        link:
          anyOf:
            - type: string
            - type: 'null'
          title: Link
        blurb:
          type: string
          title: Blurb
        source_type:
          $ref: '#/components/schemas/DocumentSource'
        boost:
          type: integer
          title: Boost
        hidden:
          type: boolean
          title: Hidden
        metadata:
          additionalProperties:
            anyOf:
              - type: string
              - items:
                  type: string
                type: array
          type: object
          title: Metadata
        score:
          anyOf:
            - type: number
            - type: 'null'
          title: Score
        is_relevant:
          anyOf:
            - type: boolean
            - type: 'null'
          title: Is Relevant
        relevance_explanation:
          anyOf:
            - type: string
            - type: 'null'
          title: Relevance Explanation
        match_highlights:
          items:
            type: string
          type: array
          title: Match Highlights
        updated_at:
          anyOf:
            - type: string
              format: date-time
            - type: 'null'
          title: Updated At
        primary_owners:
          anyOf:
            - items:
                type: string
              type: array
            - type: 'null'
          title: Primary Owners
        secondary_owners:
          anyOf:
            - items:
                type: string
              type: array
            - type: 'null'
          title: Secondary Owners
        is_internet:
          type: boolean
          title: Is Internet
          default: false
        file_id:
          anyOf:
            - type: string
            - type: 'null'
          title: File Id
        content:
          anyOf:
            - type: string
            - type: 'null'
          title: Content
      type: object
      required:
        - document_id
        - chunk_ind
        - semantic_identifier
        - blurb
        - source_type
        - boost
        - hidden
        - metadata
        - match_highlights
        - content
      title: SearchDocWithContent
    ValidationError:
      properties:
        loc:
          items:
            anyOf:
              - type: string
              - type: integer
          type: array
          title: Location
        msg:
          type: string
          title: Message
        type:
          type: string
          title: Error Type
        input:
          title: Input
        ctx:
          type: object
          title: Context
      type: object
      required:
        - loc
        - msg
        - type
      title: ValidationError
    DocumentSource:
      type: string
      enum:
        - ingestion_api
        - slack
        - web
        - google_drive
        - gmail
        - github
        - gitbook
        - gitlab
        - guru
        - bookstack
        - outline
        - confluence
        - jira
        - slab
        - productboard
        - file
        - coda
        - canvas
        - notion
        - zulip
        - linear
        - hubspot
        - document360
        - gong
        - google_sites
        - zendesk
        - loopio
        - box
        - dropbox
        - sharepoint
        - teams
        - salesforce
        - discourse
        - axero
        - clickup
        - mediawiki
        - wikipedia
        - asana
        - s3
        - r2
        - google_cloud_storage
        - oci_storage
        - xenforo
        - not_applicable
        - discord
        - freshdesk
        - fireflies
        - egnyte
        - airtable
        - highspot
        - drupal_wiki
        - imap
        - bitbucket
        - testrail
        - braintrust
        - lumapps
        - mock_connector
        - user_file
        - craft_file
      title: DocumentSource
    TimeRange:
      properties:
        start:
          anyOf:
            - type: string
              format: date-time
            - type: 'null'
          title: Start
        end:
          anyOf:
            - type: string
              format: date-time
            - type: 'null'
          title: End
      type: object
      title: TimeRange
      description: |-
        An inclusive [start, end] window; either bound may be None (open).
        Naive (timezone-less) bounds are treated as UTC.
    Tag:
      properties:
        tag_key:
          type: string
          title: Tag Key
        tag_value:
          type: string
          title: Tag Value
      type: object
      required:
        - tag_key
        - tag_value
      title: Tag
  securitySchemes:
    BearerAuth:
      type: http
      scheme: bearer
      description: Authorization header with Bearer token

````