Valori LogoValori
POST/v1/searchREAD

Vector search

K-nearest-neighbour search over a collection, with optional recency decay, term-frequency reranking, and metadata filtering.

query must have the same dimension as the collection; k must be between 1 and 5000 (enforced server-side — the OpenAPI schema's own k property currently declares only a minimum: 0, without the upper bound, so don't rely on client-side JSON Schema validation alone to catch an oversized k). A collection with fewer than k live records returns as many results as exist — never an error.

Request body

querynumber[]required

Query vector.

kintegerrequired

Maximum number of results to return. 15000.

collectionstringoptional

Collection to search. Optional at the HTTP level — pass it explicitly.

rerankbooleanoptional

BM25 hybrid reranking. When true (the default), the server fetches a wider candidate pool by vector similarity and re-ranks it by a 50/50 blend of normalised vector score and BM25 term-frequency score before returning the top k. Requires query_text. Set false for pure vector ranking.

query_textstringoptional

The raw query string used for BM25 scoring. Required when rerank is true (the default); ignored when rerank: false.

decay_half_life_secsintegeroptional

When set, older records rank lower: a record one half-life old has its distance doubled. score itself stays the true, undecayed distance — see the response fields below.

metadata_filterobjectoptional

Restricts results to records whose metadata matches every given key. Numeric fields accept range operators, e.g. {"year": {"gte": 2020}}.

graph_rerankobjectoptional

Nudges ranking by graph proximity to the query's own top vector hits: adjusted = score * (1 + weight * hop_distance). weight clamps to [0, 1], seed_count (how many top hits become graph seeds) clamps to [1, 10], max_depth clamps to 4 — all silently, never rejected. Full Graph documentation is a later phase; this field only makes sense once the collection has graph nodes linked to its records.

as_ofstringoptional

ISO 8601 UTC timestamp — search the vector state as it existed at this moment. Requires the node's event log to be enabled.

as_of_log_indexintegeroptional

Search the state after exactly this many committed events. Takes precedence over as_of if both are given.

Response fields

resultsarrayrequired

Ranked hits, closest first.

results[].idintegerrequired

The matched record's id.

results[].scorenumberrequired

Distance under the collection's configured metric — lower is closer, 0 is an exact match. Always the true, undecayed distance, even when decay_half_life_secs changed the ranking order.

results[].decay_factornumberoptional

Applied decay factor in (0, 1]. Present only when decay_half_life_secs was set.

results[].age_secsintegeroptional

Record age in seconds at query time. Present only when decay is active.

results[].graph_distanceintegeroptional

Hop distance to the nearest graph_rerank seed. Present only when graph_rerank was requested; null within that means no graph node or unreachable within max_depth — never causes a candidate to be dropped.

Errors

StatuscodeMeaning
400validation_error, dimension_mismatchk out of range, query doesn't match the collection's dimension, or a bad filter.
401unauthorizedMissing or invalid API key.
403forbiddenThe key's scope doesn't include read_only.
404collection_not_foundThe target collection doesn't exist.
500internal_errorIndex or state failure.

Related endpoints

POST /v1/search
curl -X POST "https://app.valori.systems/v1/search" \
  -H "Authorization: Bearer vlk_your_project_api_key" \
  -H "Content-Type: application/json" \
  -d '{
    "collection": "documents",
    "query": [0.12, 0.34, 0.56, 0.78, 0.11, 0.22, 0.33, 0.44],
    "k": 5
  }'
200
{
  "results": [
    { "id": 42, "score": 0.0 },
    { "id": 17, "score": 0.043 }
  ]
}