Docs menu

REST API

Consumer endpoints live under /oi-api/ on your workspace host (https://openx.fathym.com). The full OpenAPI spec, filtered to your access rights, is at GET /oi-api/openapi. Every call takes a Bearer JWT - see Auth & Tokens. There is no GraphQL API; use REST or connect any AI over MCP.

Warm queries

Run a named warm query - GET /oi-api/warm-queries/{lookup}

Runs a saved warm query by its lookup (or its API path). Returns the result rows plus who approved the query and when.

curl -X GET 'https://openx.fathym.com/oi-api/warm-queries/{lookup}' \
  -H 'Authorization: Bearer YOUR_TOKEN'

Run an ad-hoc query - POST /oi-api/warm-queries

Body: { "Query": "ProductData | take 10" } (KQL). For trying an idea before you save it; save the ones your team reuses as warm queries.

Cold-data export

POST /oi-api/downloads/data-connections/{lookup} (also /oi-api/downloads/surfaces/{surface} and .../surfaces/{surface}/connection/{connection})

Body: { "format": "csv" | "jsonl", "from": ISO8601, "to": ISO8601, "page": 1, "pageSize": 1000 }. Returns a ready download URL (15-minute expiry) with row counts and truncated if the export hit the cap. Caps: exports truncate at 25,000 rows; pageSize defaults to 1000, max 5000. Narrow the time window to stay under the cap.

Live stream

GET /oi-api/live-stream (WebSocket) - streams events as they arrive. Optional filters: connection, surface.

Change feed

GET /oi-api/eac-changes/stream (Server-Sent Events) - emits a message after every committed change to your workspace.

Connect an AI (MCP)

/oi-api/mcp (Streamable HTTP) - the MCP endpoint any AI uses to read your warm queries and build via proposals. Per-client setup is in Bring Any AI.

Change history

OpenX records every change to your workspace and every correction to your data. The concept guide is Ship with Confidence; the how-to is Change History & Corrections.

Scope is a filter, not part of the path. Reads pass scopeKey as a query parameter; writes carry ScopeKey in the body. Leave it off an activity-log read and you get the workspace-level Platform-Config records - the platform's own change history, which the earlier per-log URL shape had no way to address. Corrections always describe a change to a scope's data, so scopeKey is required on every corrections endpoint.

Activity log (what changed, when, by whom):

  • POST /oi-api/provenance/events - append an event (ScopeKey in the body; actor and timestamp are server-set, never caller-supplied).
  • GET /oi-api/provenance/events/query - query events (scopeKey, entityType, actionType, userId, startDate, endDate, limit, offset).
  • POST /oi-api/provenance/events/verify - verify the chain, and optionally one record in it (body: ScopeKey, plus an optional RecordID).
  • GET /oi-api/provenance/events/export - export events (format=csv|json, scopeKey, date range).

RecordID is optional, and leaving it off asks a different question. Omit it and you get a whole-chain verification, genesis to tip - which is what a "verify this log" button wants, and what you need when you hold no record id. Supply one and you additionally get that record's own digest recomputed. A supplied id must be the 12-digit zero-padded sequence the platform assigned; a malformed one is rejected rather than treated as "verify everything", because a typo must never come back as a clean bill of health.

verify returns independent verdicts, and the differences matter. Valid is this record's digest, recomputed and compared - and it is null when you did not name a record, because nothing was recomputed. It is never true in that case: that would claim a check that never ran. ChainValid is the whole container's chain. A valid record on a broken chain - Valid: true with ChainValid: false - is a real state, and usually the one an auditor cares about most. Empty tells you whether there was anything to check at all: ChainValid: true with Empty: true means the container is unwritten or does not exist, not that everything checks out. BrokenAt identifies the first bad link, ForkDetected flags a split chain, and Reason puts the verdict in words.

A whole-chain verify reads every record in the container and recomputes every digest. It is authoritative, and it is not cheap - it is a deliberate action, not something to poll.

Corrections (documented edits, original always preserved):

  • POST /oi-api/provenance/amendments - create a correction (reason + before/after, ScopeKey in the body); pending or applied depending on whether approval is required.
  • GET /oi-api/provenance/amendments - query corrections (scopeKey, entityId, entityType, reasonCategory, amendedBy, status, dates, limit, offset).
  • GET /oi-api/provenance/amendments/chain?entityId=... - the full correction chain for one record, oldest first, ordered by chain link rather than by timestamp (scopeKey required).
  • GET /oi-api/provenance/reason-categories - the configurable reason list, workspace-wide and unscoped (defaults include data-entry-error, transcription-error, recalculation, delayed-entry, and others).
  • POST /oi-api/provenance/amendments/{id}/approve - approve a pending correction (a second person, when two-person approval is on; scopeKey on the query string).
  • POST /oi-api/provenance/amendments/{id}/reject - reject one, with a reason.

The OpenAPI spec

GET /oi-api/openapi - the full OpenAPI 3.1 spec for your workspace, filtered to your access rights (you see only the endpoints you can call). The in-product API Explorer is this spec made browsable, with a Try-Me and ready-to-copy snippets.

Responses and errors

A successful query returns the result rows plus the approver and timestamp. Errors come back as an envelope:

{ "HasError": true, "Messages": { "Error": "Warm query \"x\" was not found..." } }

Status codes are set where applicable: 400 invalid input (e.g. no saved query text) · 401 missing/invalid token · 403 outside your access rights · 404 not found · 500 server error · 503 capability not provisioned.

Limits

Per-query caps apply (cold-data 25k-row truncation; pageSize max 5000). There is no per-request rate limiting today.

On this page