Start with install notes or jump straight into the API.

API

Snapshot History

Snapshots are materialized facet histograms for a namespace. They carry facet listings in values[].v and facet counts in values[].n, stored durably in S3 and mirrored into Aerospike for the latest body.

Use POST /snapshots to materialize a field now. Use history and body routes to read the durable chronology written by the consistency watcher.

Configure watched fields

The consistency watcher only materializes snapshots for facet fields it has been told to watch. Configure them with the LAYER_FACET_FIELDS environment variable — a JSON object mapping each namespace to its facet fields (Helm chart: gateway.facetFields):

export LAYER_FACET_FIELDS='{
  "products": ["category", "brand"],
  "reviews": ["sentiment", "language"]
}'

The default is empty, which disables the snapshot writer: with no watched fields, source: stored and eligible source: auto jobs have nothing to read, and the history and activity feeds stay empty. Namespaces discovered through GET /v2/namespaces are registered with the watcher automatically, but only the fields listed here are materialized. LAYER_SNAPSHOT_MIN_INTERVAL_MS (default 300000) sets the floor between writes for a namespace.

Routes

RouteMethodBehavior
POST /v2/namespaces/{ns}/snapshotsPOSTCreate an on-demand snapshot job for one field.
GET /v2/namespaces/{ns}/snapshot-jobsGETList in-memory snapshot jobs.
GET /v2/namespaces/{ns}/snapshot-jobs/{id}GETRead one snapshot job.
GET /v2/namespaces/{ns}/historyGETNewest-first durable snapshot history.
GET /v2/namespaces/{ns}/snapshots/{sha}GETFull snapshot body by full SHA or 7-char prefix.
GET /v2/activity/snapshotsGETCross-namespace snapshot-write activity stream.

Create a snapshot job

POST /v2/namespaces/products/snapshots
Content-Type: application/json

{
  "field": "category",
  "source": "auto",
  "filters": ["brand", "Eq", "Acme"],
  "page_size": 1000
}

Valid sources are auto, stored, cache, and origin.

SourceReads fromNotes
autoStored snapshot when possible, otherwise cache/origin policyDefault. Stored snapshots only support unfiltered configured fields.
storedLatest S3 snapshot body, with Aerospike mirror as a cacheFastest path for configured facet fields.
cacheAerospike document cacheSupports filters the cache can evaluate.
originTurbopuffer paginated scanAuthoritative. Persists the computed snapshot body to S3.

The response is 202 Accepted:

{
  "id": "snapshot-job-uuid",
  "namespace": "products",
  "field": "category",
  "source": "auto",
  "status": "running",
  "progress": 0,
  "documents_scanned": 0,
  "created_at": "2026-05-26T10:00:00Z"
}

Poll the job:

GET /v2/namespaces/products/snapshot-jobs/snapshot-job-uuid

Completed jobs include sha when a body was materialized:

{
  "id": "snapshot-job-uuid",
  "namespace": "products",
  "field": "category",
  "source": "origin",
  "status": "completed",
  "documents_scanned": 12844,
  "sha": "3f9e8b21",
  "stable_as_of": 1747300000123
}

History

GET /v2/namespaces/products/history?limit=20
[
  {"watermark_ms": 1747300000123, "sha": "3f9e8b21..."},
  {"watermark_ms": 1747299600045, "sha": "a1c5b09f..."}
]
Query paramDefaultPurpose
limit50Maximum entries returned. Capped at 500.
beforenoneReturn entries older than this SHA. 7-char prefixes are accepted.

The history endpoint lists S3 keys only; it does not read every snapshot body.

Snapshot body

GET /v2/namespaces/products/snapshots/3f9e8b2
{
  "namespace": "products",
  "watermark_ms": 1747300000123,
  "sha": "3f9e8b21",
  "fields": [
    {
      "name": "category",
      "values": [
        {"v": "books", "n": 1240},
        {"v": "electronics", "n": 873}
      ]
    }
  ],
  "fields_skipped": [
    {
      "name": "tags",
      "reason": "exceeded_cap",
      "distinct_observed": 247000,
      "cap": 10000
    }
  ]
}

fields[].values[].v is the facet listing. fields[].values[].n is the facet count. Fields present in fields[] are complete. Fields above the 10,000 distinct-value cap are listed in fields_skipped[] instead of being partially materialized.

Activity

GET /v2/activity/snapshots?since=1747200000000&limit=50
Query paramRequiredPurpose
sinceyesEpoch-ms lower bound on ts_ms.
limitnoCap 500, default 50.
namespacenoExact namespace filter.
cursornoPagination cursor from next_cursor.

Activity is snapshot lifecycle only. Search history and clickstream events have separate feeds.

esc