Data

Data stores

Workspace data stores: schema-validated keyed rows written by workflows, browsable in Settings, exportable, and readable over the REST API.

A store is a keyed table your workflows write and read — the durable output of extraction pipelines, the cache in front of slow APIs, the work queue for batch jobs.

Creating a store

Settings → data → stores. A store gets a name, a slug (immutable once created), and a schema — build it field-by-field (name / type / required) or paste JSON Schema. The schema validates every write: a row that doesn't conform fails the writing step with every violation listed.

A store's detail view in Settings Rows newest-first with schema-derived columns, find-by-key, and the copyable API URL.

Rows

  • Every row has a key you choose (an order id, an email, a FIPS code) — unique per store, and the whole write contract: writing an existing key replaces that row.
  • Rows record which run and workflow wrote them — provenance for free.
  • In Settings, rows are deliberately read-only: rows are workflow-written, so a hand-edited value can't paper over a pipeline bug. (Fix the workflow, re-run, the upsert overwrites.)
  • Default capacity is 100,000 rows per store.

Workflows write with save to store and read with get from store — including the list-rows-missing-a-field mode that turns a store into a work queue.

Import & export

From the store's page: export as NDJSON (re-importable, includes the schema), CSV, or JSON. Import takes an NDJSON file (or pasted text) and writes through the same validated upsert path — per-row failures are reported, valid rows land.

The API

External systems read AND write stores over the REST API with an mmx_… token from the developer tab (read-only tokens can read; writes need a build-scoped token):

GET    /api/v1/stores                      # your stores
GET    /api/v1/stores/:id/rows             # rows, paginated
GET    /api/v1/stores/:id/rows/:key        # one row
GET    /api/v1/stores/:id/rows?updated_since=2026-08-01T00:00:00Z
PUT    /api/v1/stores/:id/rows/:key        # insert or replace one row
DELETE /api/v1/stores/:id/rows/:key        # remove one row

A write body is {"data": {"row": {...}}}row must satisfy the store's schema, and the store's row cap applies, exactly as if a workflow's Save-to-store step had written it.

The store's page in Settings shows its copyable URLs. updated_since makes polling cheap — only rows written since your last sync.

Gotchas

  • Upserts replace the whole row — writers must include every field the row should keep.
  • Editing a schema later doesn't rewrite existing rows; they're re-validated on their next write.