> ## Documentation Index
> Fetch the complete documentation index at: https://docs.tckg.factagora.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Search

> POST /v1/search. Time-consistent retrieval: candidates and every expansion hop were known at as_of.

Candidates come from full-text search over `statement` and, when `embedding` is given, cosine similarity over the stored vectors. The two lists are fused with reciprocal rank fusion. Candidates are then expanded along edges of the chosen families up to `depth` hops. The `as_of` and `valid_at` filters apply to **every hop**, not only to the candidates.

## Request

<ParamField body="query" type="string" required>
  Full-text query. Language-agnostic tokens.
</ParamField>

<ParamField body="as_of" type="timestamp or date" required />

<ParamField body="space" type="string">
  Scope to one space. Omit for the whole tenant.
</ParamField>

<ParamField body="valid_at" type="timestamp" />

<ParamField body="depth" type="integer" default="2">
  Expansion hops.
</ParamField>

<ParamField body="family" type="string[]" default="[&#x22;causal&#x22;, &#x22;temporal&#x22;]">
  Edge families to expand along. See [edge types](/concepts#edge-types).
</ParamField>

<ParamField body="limit" type="integer" default="20">
  Caps the **candidates**, not the expanded hits.
</ParamField>

<ParamField body="category" type="string">
  Narrows the **candidates** to one topic label. Expansion hops are not filtered: a causal chain may cross topics, and cutting it at a topic boundary would hide the cause.
</ParamField>

<ParamField body="embedding" type="number[]">
  The query vector. Must come from the same model as the vectors stored on nodes. When absent, only full-text candidates are used.
</ParamField>

## Response

<ResponseField name="hits" type="Hit[]">
  Each hit: `node` (NodeRow), `score`, `depth`, `path` (node ids from the candidate to this node), `via` (the edge type that reached it; null for a candidate), `superseded_by` (the id of the block that superseded it as of `as_of`, or null).
  `score` is the candidate's fused rank score multiplied by 0.5 per hop.
</ResponseField>

<ResponseField name="masked" type="object or null" />

<ResponseField name="certificate" type="object" />

<Tip>
  A superseded block is **returned and flagged**, not dropped. Your agent should see what it used to believe, and that it has been replaced.
</Tip>

<CodeGroup>
  ```bash Request theme={null}
  curl -s -X POST $TCKG/v1/search -H 'content-type: application/json' -d '{
    "query": "interest rates", "space": "user:randy", "as_of": "2024-10-01", "depth": 2
  }'
  ```

  ```json Response theme={null}
  {"hits": [
     {"node": {"id": "c1", "statement": "The Fed raises interest rates", "...": "..."},
      "score": 0.0163, "depth": 0, "path": ["c1"], "via": null, "superseded_by": "c4"},
     {"node": {"id": "c2", "statement": "Bond yields rise after the rate hike", "...": "..."},
      "score": 0.0081, "depth": 1, "path": ["c1", "c2"], "via": "CAUSES", "superseded_by": null},
     {"node": {"id": "c4", "statement": "The Fed cuts interest rates", "...": "..."},
      "score": 0.0161, "depth": 0, "path": ["c4"], "via": null, "superseded_by": null}],
   "masked": null, "certificate": {"as_of": "2024-10-01T23:59:59.999999+00:00", "tx_as_of": "...", "backfill": {"batches": 3, "rows": 7}}}
  ```
</CodeGroup>


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.