---
title: "POST /api/v1/{context_id}/query"
method: POST
path: "/api/v1/{context_id}/query"
---

# POST /api/v1/{context_id}/query

`POST /api/v1/{context_id}/query`

Phase 7 unified query: four-tier router + fused ranker over the substrate

## Path parameters

- `context_id` string, required

## Request body

- QueryMemoryRequestJson
  - `asOf` string, nullable — Phase 11.5 — historical query timestamp (known time). When set the retrieval path walks the supersession chain to surface the row that was current as-of this instant.
  - `atInstant` string, nullable — Phase 11.5 — system-time query. Prepends `VERSION d'…'` to the underlying `SELECT` so SurrealDB MVCC returns the substrate state at the supplied instant.
  - `include` string[], nullable — Phase 7 — which families of result to include. Defaults to `["facts", "passages"]` (both). Pass either alone to scope the response.
  - `includeDuplicates` boolean, nullable — When `false` (the default), chunks flagged as near-duplicates of an older chunk are excluded from the fused ranker's chunk recall so the same text does not occupy several ranks. Set `true` to include them (parity with the documents `/query` opt-in).
  - `k` integer — Max hits to return (default 10, max 50).
  - `labels` string[] — Label filter (design §4): `key=value` strings the result rows must **all** carry. Applied after the scope predicate — labels never widen access, only narrow the already-authorised result set. Empty = no label filter.
  - `lens` array[] — A DNF scope selector: an OR of conjunctive clauses. Each clause is an array of scope paths, ALL of which a reader must cover (AND); the outer array is the OR. E.g. [["team/a"],["team/b","clearance/secret"]] means team/a OR (team/b AND clearance/secret). Empty means unscoped (the caller's default region). A bare string is also accepted as a singleton clause.
    - string[]
  - `location` GeoFilterJson — Wire shape for the Phase 6.5 geo filter on `/query`. Mirrors the in-process [`crate::memory::types::GeoFilter`] enum.
    - `near` GeoNearJson
      - `lat` number, double, required
      - `lng` number, double, required
      - `radiusKm` number, double, required
    - `within` string, nullable — Inside a WKT polygon. Mutually exclusive with `near`.
  - `mode` 'hybrid' | 'vector' | 'bm25' | 'graph' — Retrieval mode hint. The default is `Hybrid`, which engages the full fused ranker. The other modes are kept as escape hatches so callers can debug a single signal in isolation.
  - `query` string, required
  - `scopeView` string, nullable — Scope read breadth: `strict` (default) | `merged` | `crossTeam`. Only `strict` is enforced pre-launch; `merged` / `crossTeam` are accepted and behave as `strict` until their region logic ships (design §7.1).
  - `sessionId` string, nullable
  - `source` string, nullable — Phase 7 — free-form source label. Recorded on the trace for audit replay; doesn't affect retrieval today.
  - `validFrom` string, nullable — Phase 11.5 — valid-time (world-time) lower bound. Filters rows whose `valid_from` is ≥ this timestamp.
  - `validUntil` string, nullable — Phase 11.5 — valid-time (world-time) upper bound. Filters rows whose `valid_until` is ≤ this timestamp.

## Response `200`

- QueryMemoryResponseJson
  - `classificationKind` 'direct_lookup' | 'hybrid' | 'full_context', required — What kind of question the query represents. Drives tier selection.
  - `hits` MemoryHitJson[], required
    - `id` string, required
    - `score` number, float, required
    - `source` 'attribute' | 'entity' | 'chunk' | 'memory_chunk' | 'section', required — Coarse-grained result type. Mirrors the row table the hit lives in.
    - `text` string, required
  - `queryMs` integer, required
  - `seedEntities` string[], required
  - `tier` 'direct' | 'cache' | 'hybrid' | 'full_context', required — Which tier resolved the query. Exposed on the response for the CLI's `--tier` flag (Phase 8) and so callers can tell when their query went all the way to tier 4.
  - `trace` QueryTraceJson, required
    - `latencyMs` integer, required
    - `resolutionTier` 'direct' | 'cache' | 'hybrid' | 'full_context', required — Which tier resolved the query. Exposed on the response for the CLI's `--tier` flag (Phase 8) and so callers can tell when their query went all the way to tier 4.
    - `retrievedCount` integer, required
    - `tierReason` string, required
    - `topScores` number[], required
    - `traceId` string, required

## Other responses

- `400` — Invalid request
- `401` — Unauthorized
- `422` — Invalid context id

---

[API](https://skmtc.net/surrealdb/apis/spectron.md) · [All operations](https://skmtc.net/surrealdb/apis/spectron/llms.txt) · [OpenAPI document](https://skmtc-service-staging.skmtc.workers.dev/v1/apis/surrealdb/spectron/versions/52b41ab517b6/schema)
