Working with Data¶
Getting data in¶
Direct writes¶
POST /v1/records (single or batch, with inline relationships) and POST /v1/relationships for edges. Structured JSON ingestion (format: "json") applies synchronously and infers schema as it goes: no upfront modeling, ever. Property types are observed per label and queryable historically (GET /v1/schema?at=<time>&label=<label>).
Document ingestion¶
POST /v1/ingest with a format hint. Workers parse and project:
| Format | Handles | Projection |
|---|---|---|
docling | PDF, DOCX, PPTX | Document, sections, paragraphs, tables as nodes with CONTAINS edges, page/bbox metadata |
tabular | CSV, XLSX | Rows as nodes, typed columns, cross-reference columns become edges |
web | URLs, SPAs | Markdown projection, headings as hierarchy, links as REFERENCES edges |
email | .eml, .msg | Threading edges (SENT_BY, TO, IN_REPLY_TO), attachments fan out as child ingests |
code | rs, py, js/ts | Files, functions, classes as nodes; imports and calls as edges |
json | Structured records | Direct node projection, nested objects flatten or become child nodes |
Duplicate content is detected by hash: re-ingesting the same bytes is a no-op, changed bytes create a new source version.
Connectors (the usual way)¶
Connectors sync continuously, read-only, preserving authorship, ownership, ACLs, and deletions:
- SharePoint / OneDrive (files by extension)
- Exchange / Outlook (mailbox allowlists, attachments included)
- Slack (thread-aware conversation documents per allowlisted channel)
- Salesforce (allowlisted objects as records)
- Entra ID (people, groups, managers: the identity backbone for routing and SSO)
Configure per connection under [connectors.<source>.<connection>] with credentials by environment-variable name, an explicit scope allowlist (nothing syncs by default), and an interval. telha connector ls|status|run <name> shows cursor age, processed/skipped/failed counts, and last error. Source deletions tombstone in Telha; history before the deletion stays queryable.
Querying¶
The query language is JSON. The important parts:
{
"find": "CONTRACT_VERSION", // label
"where": { // operator objects, always
"riskScore": { "$gte": 3 }, // $eq $ne $gt $gte $lt $lte $in $exists
"$or": [ { "region": { "$eq": "EU" } }, { "region": { "$eq": "UK" } } ]
},
"atValidTime": "2026-03-01T00:00:00Z", // world-time pin
"atTxTime": "2026-04-01T00:00:00Z", // knowledge-time pin
"expand": { // graph traversal from results
"types": ["AMENDS"], "direction": "out", "depth": 2
},
"vector": { // semantic stage (hybrid ranking)
"text": "supply chain delay risk", "model": "default", "k": 20, "minScore": 0.3
},
"limit": 100, // + opaque cursor for pagination
"trace": true // persist an execution trace
}
Notes that save time:
wherevalues are always operator objects:{"$eq": 5}, never a bare5.- Expanded results arrive in a
relatedsection and never repeat nodes already in the primary results. - Datetimes serialize as microsecond integers in responses; bytes as base64.
- Vector plus cursor do not compose (vector results are ranked, not scan-ordered).
- Scores: hybrid queries return a similarity-and-decay fused score per result.
Snapshots and compare¶
POST /v1/snapshot exports a consistent subgraph pinned at exact coordinates: the state of everything matching a query, as of a moment, as known at a moment.
POST /v1/compare diffs two coordinate pairs: added, removed, and modified nodes and edges, with property-level diffs, paginated for large deltas. This is the "what changed in our risk assessment between Q1 and Q2" call, and it is also available as the compareSnapshots MCP tool and in chat.