---
title: "Search with a grounded answer"
method: POST
path: "/org/search"
tags: ["Search"]
---

# Search with a grounded answer

`POST /org/search`

## Request

- Base URL: `https://apiv2.senso.ai/api/v1`
- URL: `https://apiv2.senso.ai/api/v1/org/search`
- Auth: API key in header `X-API-Key`

Runs a retrieval over your compiled knowledge base and returns the matched chunks together with an AI-generated answer grounded on them. The answer also reads up to five chunks either side of each match, so passages are not cut mid-thought; `results` lists only the matched chunks. Every chunk carries the `kb_node_id` of its source document, so a cited passage can be opened in full with `GET /org/kb/nodes/{kb_node_id}`. Each call consumes search credits.

## Headers

- `X-Senso-Signals` string

## Request body

- SearchRequest
  - `query` string, required: The search query. Required and non-empty; there is a maximum length.
  - `max_results` integer: Maximum results to return. Defaults to 5; values ≤ 0 fall back to 5 and values above 20 are capped at 20.
  - `content_ids` string[]: Restrict the search to these content items.
  - `require_scoped_ids` boolean: When true, `content_ids` must be non-empty — the request is rejected with 400 otherwise. Use it to guarantee a scoped search never silently widens.
  - `search_type` string: Retrieval pipeline to use. One of `hybrid` (default), `lexical`, or `vector`. Matching is case-insensitive; an empty or omitted value selects `hybrid`. Any other value is rejected with 400.
  - `neighbor_radius` integer: `/org/search/context` only. Adds up to this many chunks either side of each matched chunk to `results`, marked `inclusion_reason: "neighbor"`, so each match can be read as a passage. Defaults to 0 (matched chunks only); values outside 0–5 are rejected with 400. Total returned text is capped at about 60,000 characters, trimming the farthest neighbours first. Ignored by the other search endpoints, whose answers already include neighbouring chunks.

## Response `200`

The matched chunks and the grounded answer.

- SearchResponse: Matched chunks plus an AI-generated answer.
  - `query` string, required
  - `search_type` 'hybrid' | 'lexical' | 'vector', required: The retrieval pipeline that produced this response — the scale each result's `score` is on.
  - `answer` string, required: The AI-generated answer grounded on the matched content.
  - `results` SearchResultChunk[], required
    - `content_chunk_id` string, uuid, required
    - `content_id` string, uuid, required
    - `kb_node_id` string, uuid, required: The node in the knowledge base tree that the chunk's document lives at. This is the id the `/org/kb/nodes/{kb_node_id}` endpoints take, so a cited chunk can be read in full without a further lookup.
    - `version_id` string, uuid, required
    - `chunk_index` integer, required
    - `chunk_text` string, required
    - `score` number, required: The final relevance score the pipeline ranked and cut on, on the scale named by the response `search_type` (rerank score for hybrid, cosine for vector, document-grain BM25 for lexical). Results from different modes never mix in one response, so scores within a response are comparable.
    - `rank` integer, required: The chunk's 1-based position in the result set.
    - `title` string: The source document's title.
    - `vector_id` string
    - `inclusion_reason` string: Why the chunk is in the result set. Always `matched` on this API.
    - `source_type` 'file' | 'raw' | 'web': The source's kind — `file` (uploaded file), `raw` (raw text/markdown), or `web` (web content).
    - `content_type` string: The source's MIME type (e.g. `application/pdf`, `text/markdown`).
    - `retrieval` ChunkRetrieval: Per-arm retrieval evidence for a chunk. Present on `hybrid` responses only (pure `vector`/`lexical` modes omit it). A key is present only for the arm(s) that found the chunk.
      - `vector` RetrievalArmResult: One retrieval arm's raw score and rank for a chunk.
        - `score` number, required: The arm's own score on the arm's own scale (cosine for vector; document-grain BM25 for lexical).
        - `rank` integer, required: The chunk's 1-based rank in that arm's pool.
      - `lexical` RetrievalArmResult: One retrieval arm's raw score and rank for a chunk.
        - `score` number, required: The arm's own score on the arm's own scale (cosine for vector; document-grain BM25 for lexical).
        - `rank` integer, required: The chunk's 1-based rank in that arm's pool.
  - `total_results` integer, required
  - `max_results` integer, required
  - `processing_time_ms` integer, required

## Other responses

- `400`: The request was malformed — a bad path/query parameter or an invalid value.
- `401`: Missing or invalid credentials — supply a valid org API key in the `X-API-Key` header.
- `402`: The organization is out of credits or has reached its spending limit.
- `403`: The API key is authenticated but not permitted to access this resource.

---

[API](https://skmtc.dev/senso/apis/senso-org-api.md) - [All operations](https://skmtc.dev/senso/apis/senso-org-api/llms.txt) - [OpenAPI document](https://skmtc.dev/senso/apis/senso-org-api/revisions/d789b4fcbe84?raw)
