Bi-temporal queries: as_of, valid_during, recorded_during, plus natural-language phrases.
Temporal Queries
Time is a first-class dimension in CortexDB. Every derived record carries four time fields (valid_from, valid_to, recorded_from, recorded_to), and every read endpoint accepts a temporal block that clips both axes.
For the full model, see Bi-temporal Model.
On /v1/recall and /v1/answer
pack = client.recall(
scope="org:acme/dept:eng",
query="What database are we using for payments?",
view="holistic",
temporal={
"as_of": "2026-04-15T00:00:00Z", # both axes ≤ this instant
"natural": "last 30 days", # parsed against reference_date
"reference_date": "2026-05-16T00:00:00Z",
},
)
| Field | Effect |
|---|---|
as_of | Clips both axes — recorded_* ≤ as_of AND valid_from ≤ as_of < valid_to |
valid_during | [start, end] two-element array on the world-time axis (RFC 3339 datetimes or date-only strings; a date-only end is inclusive) |
recorded_during | [start, end] two-element array on the ingest-time axis |
natural | Phrase like "last week", "this quarter", "fiscal Q3" (register custom phrases via /v1/temporal/phrases) |
reference_date | Anchor for natural; defaults to request time |
On layer reads
GET /v1/events accepts since (ISO-8601), and GET /v1/facts accepts as_of, min_confidence, and include_superseded:
# Events observed since March 1
events = client.events(
scope="org:acme/dept:eng",
since="2026-03-01T00:00:00Z",
limit=200,
)
The Python SDK's client.facts() exposes subject / predicate only, so pass the temporal parameters over REST:
import requests, os
H = {"Authorization": f"Bearer {os.environ['CORTEX_TOKEN']}", "X-Cortex-Actor": os.environ["CORTEX_ACTOR"]}
# Facts as the system saw them on April 15
facts = requests.get(
"https://api-v1.cortexdb.ai/v1/facts",
headers=H,
params={
"scope": "org:acme/dept:eng",
"subject": "ent_payments_service",
"as_of": "2026-04-15T00:00:00Z",
"include_superseded": "false", # only the value that was current then
},
).json()
The supersession chain
GET /v1/facts/timeline?subject=…&predicate=… returns every value the system has held for that (subject, predicate) pair, with the validity window for each:
timeline = requests.get(
"https://api-v1.cortexdb.ai/v1/facts/timeline",
headers=H,
params={"subject": "ent_payments_service", "predicate": "database"},
).json()
for row in timeline["timeline"]:
print(f" {row['value']:>12} valid {row['valid_from']} → {row['valid_to'] or 'now'}")
postgres valid 2024-01-01T00:00:00Z → 2026-03-15T10:00:00Z
cockroachdb valid 2026-03-15T10:00:00Z → now
This is what lets you ask "What database did we use for payments before the migration?" — pass as_of set to the day before the migration and the right value comes back.
Why two axes
Single-axis systems can answer either "what was true at time T" or "what did the system know at time T", but not both. CortexDB tracks valid_* (world time) and recorded_* (ingest time) independently, so you can reconstruct historical model state — what did the system believe about X on April 15, as observed from May 1?
Custom temporal phrases
Register tenant-specific phrases via POST /v1/temporal/phrases:
import requests, os
requests.post(
"https://api-v1.cortexdb.ai/v1/temporal/phrases",
headers={"Authorization": f"Bearer {os.environ['CORTEX_TOKEN']}", "X-Cortex-Actor": os.environ["CORTEX_ACTOR"], "Content-Type": "application/json"},
json={
"name": "fiscal_q3",
"pattern": "fiscal Q3",
"resolves_to": {"valid_during": ["2026-07-01", "2026-10-01"]},
},
)
Then temporal: {"natural": "fiscal Q3"} on recall/answer is parsed against that window.