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
| Route | Method | Behavior |
|---|---|---|
POST /v2/namespaces/{ns}/snapshots | POST | Create an on-demand snapshot job for one field. |
GET /v2/namespaces/{ns}/snapshot-jobs | GET | List in-memory snapshot jobs. |
GET /v2/namespaces/{ns}/snapshot-jobs/{id} | GET | Read one snapshot job. |
GET /v2/namespaces/{ns}/history | GET | Newest-first durable snapshot history. |
GET /v2/namespaces/{ns}/snapshots/{sha} | GET | Full snapshot body by full SHA or 7-char prefix. |
GET /v2/activity/snapshots | GET | Cross-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.
| Source | Reads from | Notes |
|---|---|---|
auto | Stored snapshot when possible, otherwise cache/origin policy | Default. Stored snapshots only support unfiltered configured fields. |
stored | Latest S3 snapshot body, with Aerospike mirror as a cache | Fastest path for configured facet fields. |
cache | Aerospike document cache | Supports filters the cache can evaluate. |
origin | Turbopuffer paginated scan | Authoritative. 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 param | Default | Purpose |
|---|---|---|
limit | 50 | Maximum entries returned. Capped at 500. |
before | none | Return 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 param | Required | Purpose |
|---|---|---|
since | yes | Epoch-ms lower bound on ts_ms. |
limit | no | Cap 500, default 50. |
namespace | no | Exact namespace filter. |
cursor | no | Pagination cursor from next_cursor. |
Activity is snapshot lifecycle only. Search history and clickstream events have separate feeds.