All paths are relative to
http://localhost:3333/api/kiwi. For DQL queries and the link graph, see Metadata and graph.
Full-text search
Run a BM25-ranked keyword search over page content.GET /api/kiwi/search
string
required
Search query. See query syntax.
integer
default:"50"
Maximum results to return. Capped at
200.integer
default:"0"
Number of results to skip.
string
Restrict results to paths that start with this prefix, for example
runbooks/. pathPrefix is accepted as an alias.string
default:"fts"
fts for BM25 only, or hybrid to fuse BM25 with vector search. See hybrid search. Any other value returns 400.string
Set to
none or off to disable the default trust boost.string
Keep only pages whose frontmatter
scope equals this value.boolean
default:"false"
Include pages with
memory_status: superseded. They are excluded by default.number
default:"0"
Blend recency into ranking, from
0.0 (relevance only) to 1.0 (recency only). Values outside that range return 400.string
RFC 3339 timestamp. Keep only pages modified after it, for example
2026-09-01T00:00:00Z.integer
default:"3"
Maximum edit distance for “did you mean” title suggestions when the first page of results is empty. Capped at
10.string
The query as received.
integer
The effective limit after defaults and caps.
integer
The effective offset.
object[]
Ranked results.
object[]
Present only when the query returned nothing at
offset=0. Each entry has query, path, title, and distance.Response
400 when q is missing or a parameter is malformed. Returns 501 when scope is used on a non-SQLite search backend.
By default results get a soft trust boost:
status: verified, source-of-truth: true, and a confidence between 0 and 1 nudge a page up, while status: deprecated or outdated nudge it down. Requests that set scope, include_superseded, or recency_weight skip the boost.Query syntax
Plain words are matched as an implicit AND, and punctuation such as hyphens is handled for you. If the query contains FTS5 syntax (quotes, parentheses,*, ^, :, or uppercase AND/OR/NOT), KiwiFS passes it to FTS5 unchanged.
Hybrid search
Fuse BM25 and vector rankings with Reciprocal Rank Fusion (RRF) on the same endpoint.GET /api/kiwi/search?mode=hybrid
Hybrid mode accepts q, limit, offset, path_prefix, and boost from full-text search, plus:
number
default:"60"
RRF rank constant. Must be greater than 0. Smaller values let one engine’s top hit dominate; larger values flatten rank differences.
string
Always
hybrid.string[]
Engines that contributed:
["fts", "semantic"], or ["fts"] when no vector index is configured. The request still succeeds with 200 in that case.number
The RRF constant used.
object[]
Each result has
path, matches, score (the RRF score), snippet, permalink, fts_rank, and semantic_rank. A rank of 0 means that engine did not return the page.Response
Trust-ranked search
Run the same BM25 search, then re-rank hard by trust signals in frontmatter.GET /api/kiwi/search/verified
Compared with the default soft boost, status: verified pages get a 2x multiplier, source-of-truth: true pages 3x, status: outdated 0.3x, and status: deprecated 0.1x. Results are re-ranked, not filtered: every BM25 hit is still returned.
integer
default:"50"
Maximum results. Capped at
200.integer
default:"0"
Number of results to skip.
Response
501 when the search backend is not SQLite.
Semantic search
Find pages by meaning using vector embeddings.GET /api/kiwi/search/semantic or POST /api/kiwi/search/semantic
Send parameters as query parameters, or as a JSON body on POST. Body values win over query parameters.
string
required
Natural-language query. On
GET, pass it as q.integer
default:"10"
Maximum results to return.
integer
default:"0"
Number of results to skip.
string
Keep only pages whose frontmatter
scope equals this value.string
RFC 3339 timestamp. Keep only pages modified after it. Body only.
string
The query as received.
integer
The effective result cap.
integer
The effective offset.
object[]
Ranked chunks.
Response
400 when no query is given or modifiedAfter is not RFC 3339. Returns 503 when semantic search is not enabled.
Semantic search needs an embedder and vector store. Configure them under
[search.vector] in .kiwi/config.toml. See Configuration.Context pack
Retrieve the most relevant pages and pack them, whole or by section, into a token budget.POST /api/kiwi/brief
The pack uses hybrid retrieval and counts real BPE tokens. Content is never summarized or rewritten. Anything that did not fit is listed in dropped with its token cost, so you can fetch it explicitly or raise the budget.
string
required
Retrieval query. You can also pass it as the
q query parameter.integer
default:"4000"
Hard token ceiling. A negative value returns an empty pack whose
dropped list still names every candidate, which lets you ask what a query would cost.integer
default:"20"
Maximum candidate pages considered before packing.
string
Restrict retrieval to paths under this prefix.
string
default:"cl100k_base"
BPE vocabulary used to count tokens.
string
The query as received.
integer
The effective budget.
integer
Tokens used by
items.string
Encoding used to count tokens.
integer
Pages retrieval offered before budgeting.
object[]
Packed content in relevance order.
object[]
Content that did not make it in. Each entry has
path, optional heading, tokens, score, and reason: budget exhausted, page truncated to fit budget, page could not be read, or page has no content.Response
Frontmatter query
Filter pages by frontmatter values using JSON path expressions.GET /api/kiwi/meta
Each filter is <field><op><value>, where field is a JSON path starting with $. (for example $.status or $.tags[*]). Operators are =, !=, <>, <, <=, >, >=, LIKE, and NOT LIKE.
string
AND filter. Repeat the parameter to combine several, for example
where=$.status=draft&where=$.priority>2.string
OR filter. Repeat for several alternatives.
string
Shorthand for
where=$.scope=<value>.string
JSON path to sort by, for example
$.updated.string
default:"asc"
asc or desc.integer
default:"50"
Maximum results. Capped at
200.integer
default:"0"
Number of results to skip.
integer
Number of results in this response.
integer
The effective limit.
integer
The effective offset.
object[]
Each result has
path, frontmatter (the full frontmatter object), and permalink when a public URL is configured.Response
400 for a malformed filter or a field that does not start with $.. Returns 501 when the search backend is not SQLite.
Similar pages
Rank pages by how close their frontmatter is to a given page or to an inline field vector.GET /api/kiwi/similar
Similarity uses Gower distance over the numeric and categorical fields named in a [[similarity.profiles]] block in .kiwi/config.toml. Pass vector to ask about a case that is not in the knowledge base yet.
string
Page to find neighbors of. Required unless
vector is set.string
JSON object of field values, for example
{"format":"csv","stats.rows":12000}. With path, these values override the page’s own.string
Similarity profile name. Optional when exactly one profile is configured.
integer
default:"5"
Number of neighbors to return.
.kiwi/config.toml
string
Profile used.
string
The
path you passed, if any.object
The resolved field vector that was compared.
string[]
Fields in the profile.
integer
Pages compared.
boolean
true when the candidate set hit its cap, so ranking covers only part of the corpus.object[]
Ranked neighbors.
Response
400 when neither path nor vector is given, the profile is unknown, k is not a positive integer, or vector is not a JSON object. Returns 503 when no similarity profiles are configured.
Related
Search concepts
How the three search tiers fit together.
Metadata and graph
DQL queries, aggregations, backlinks, and the link graph.
Configuration
Search engine and vector settings.
Analytics
Search analytics and failed queries.