Search and ask
Retrieve passages with no model, or get a cited answer: request bodies, filters, the fields of a result and of an answer, streaming, and what an out-of-coins or out-of-evidence response looks like.
Two operations find knowledge. Search returns ranked passages and calls no model. Ask returns an answer with its evidence.
Search#
POST /api/v1/search/query (scope: read){ "query": "data retention policy", "filters": { "source_providers": ["notion"], "date_from": "2026-01-01" } }| Field | Meaning |
|---|---|
query | Required. What to find. |
mode | Retrieval mode. Automatic when omitted. |
filters | See below. |
The response is a list of passages, best first.
| Result field | Meaning |
|---|---|
document_id, title, url | The item the passage came from, and an app link to it. A passage on its own is not citable, so the item is always named. |
text | The passage. |
method | Which arm found it: semantic, keyword, graph or metadata. |
semantic_score, keyword_score, graph_score, freshness_score, confidence_score, final_score | How it ranked. |
source | Provenance, when the item was synced from a source. |
Search costs no coins.
Filters#
Filters narrow retrieval before each search takes its top results, never after, so you get the best passages within the filter rather than the best overall minus what you excluded. Several values in one field are alternatives (OR); several fields all apply (AND).
| Filter | Meaning |
|---|---|
space_ids | Only items in these spaces. |
source_providers | Only items synced from these providers (slack, google_drive, notion, github, …). |
source_types | upload, note, link, meeting, voice, photo, import, connector. |
mime_types | For example application/pdf. |
tags | Only items carrying every one of these tags. |
owner_ids | Only items saved by these users. |
visibility | workspace or private. |
date_from, date_to | Items changed in this range (a date, or an RFC 3339 instant). |
Ask#
POST /api/v1/search/ask (scope: ask){ "question": "What did we decide about the Q3 launch?", "filters": { "date_from": "2026-07-01" } }| Field | Meaning |
|---|---|
question | Required. |
sources | knowledge (default), web or both. |
document_id | Answer from this one item only. |
conversation_id | Groups turns into one conversation. |
filters | As above. |
mode | Retrieval mode. |
The answer#
| Field | Meaning |
|---|---|
answer | The text, with numbered markers. |
evidence | The cited passages, each as a search result above (with source for synced items). |
confidence | How strongly the evidence supports the answer. |
insufficient_evidence | True when the knowledge did not support an answer. The answer then says so. |
suggestions | Follow-up questions. |
history_id | The stored conversation turn. |
context | What the workspace remembered that the answer used (facts with validity, changes, decisions, conflicts). Absent when nothing was. |
processing_time_ms, search_mode, model_version, retrieval_version, prompt_version | How it was produced. |
Asking spends coins. A workspace with none returns 402. See Billing and coins.
Streamed answers#
GET /api/v1/search/ask/stream (scope: ask)Takes the same parameters as query-string values (question, mode, sources, document_id, conversation_id) and returns server-sent events: chunk events carrying {"text": "…"} as the answer is generated, then one done event whose data is the full answer, produced after the grounding check, or one error event. It is switched by a workspace feature flag; when off it returns 403 FEATURE_DISABLED.
Example#
curl -s -H "Authorization: Bearer $TOKEN" -H 'Content-Type: application/json' \
-d '{"question":"What is our refund policy?"}' "$BRENO/search/ask" \
| jq '.data | {answer, confidence, sources: [.evidence[] | {title, url: .source.url}]}'