Data operations

Collections of objects, records, key-value pairs, graph edges, views, import and export.

Docs menu

batch

batch.execute

Execute an atomic batch of typed operations.

Route
POST /v1/_batch
Auth
App key or user session; your security rules apply none
CLI
substrio op batch.execute

Parameters

NameInTypeRequiredDescription
atomicbodybooleanNoDefault true.
opsbodyarray of objectYes

Response

FieldTypePresentDescription
okanyAlways
atomicbooleanAlways
countintegerAlways
resultsarray of objectAlways

Errors

A failed call answers the error envelope with a typed code.

Example

curl -X POST "$SUBSTRIO_URL/v1/_batch" \
  -H "Authorization: Bearer $SUBSTRIO_KEY" \
  -H "Content-Type: application/json" \
  -d '{"ops":[]}'

data

data.delete

Delete one record by its _id; 404 when it does not exist, 403 when the key may not delete it.

Route
DELETE /v1/{collection}/{id}
ANY delete
Auth
App key, or a user session your security rules allow tenant_or_rules
MCP tool
substrio_delete
CLI
substrio op data.delete

Parameters

NameInTypeRequiredDescription
collectionpathstringYesThe collection's name, as collection.list names it.
idpathstring or integerYesThe record's id, as data.insert or data.list returned it.

Response

FieldTypePresentDescription
status"deleted"Always

Errors

  • KEY_NOT_FOUND: call data.list to find the right one.

A failed call answers the error envelope with a typed code.

Example

curl -X DELETE "$SUBSTRIO_URL/v1/$COLLECTION/$ID" \
  -H "Authorization: Bearer $SUBSTRIO_KEY"

data.export

Export a collection's records: option format ndjson (the default), json or csv, and limit.

Route
GET /v1/{collection}/_export
Auth
App key or user session; your security rules apply none
MCP tool
substrio_export
CLI
substrio op data.export

Parameters

NameInTypeRequiredDescription
collectionpathstringYesThe collection's name, as collection.list names it.
limitqueryinteger (0 or more)Nothe most items to return.
formatquery"ndjson" | "json" | "csv"Nothe response format (default ndjson).

Response

A JSON object.

Errors

A failed call answers the error envelope with a typed code.

Example

curl "$SUBSTRIO_URL/v1/$COLLECTION/_export" \
  -H "Authorization: Bearer $SUBSTRIO_KEY"

data.get

Read one record by its _id from the route's {collection}: the stored fields plus _id. 404 when it does not exist, 403 when the key may not read it.

Route
GET /v1/{collection}/{id}
Auth
App key or user session; your security rules apply none
MCP tool
substrio_get
CLI
substrio op data.get

Parameters

NameInTypeRequiredDescription
collectionpathstringYesThe collection's name, as collection.list names it.
idpathstring or integerYesThe record's id, as data.insert or data.list returned it.

Response

FieldTypePresentDescription
_idstringWhen setThe record's id.

Errors

  • KEY_NOT_FOUND: call data.list to find the right one.

A failed call answers the error envelope with a typed code.

Example

curl "$SUBSTRIO_URL/v1/$COLLECTION/$ID" \
  -H "Authorization: Bearer $SUBSTRIO_KEY"

data.import

Insert many documents into a collection in one call: the body is a JSON array or NDJSON (option format json or ndjson; by default json when it starts with '['). A document that names _id (a base62 string or a positive whole number) is stored under that id, so an export imports back with the same ids and the references between documents still resolve; one without _id gets a generated id. A document is refused alone and the others are written: a document the collection's schema refuses (the check data.insert makes) fails with SCHEMA_REFUSED and lists its violations, an _id that names no document fails with INVALID_ID, an _id a stored document (or an earlier row) already holds fails with KEY_EXISTS unless option on_conflict says otherwise (error, the default: fails that row with KEY_EXISTS, nothing overwritten; skip: the stored document is left as it is, counted in skipped; replace: the row stores over it whole, counted in replaced; skip and replace refuse, alone, a row with no _id). _createdAt, _updatedAt and _version are the system's and ignored: an imported document is stamped anew. Answers {inserted, skipped, replaced, rejected, errors (the index, code and message of each rejected document), total}.

Route
POST /v1/{collection}/_import
Auth
App key, or a user session your security rules allow tenant_or_rules
MCP tool
substrio_import
CLI
substrio op data.import

Parameters

NameInTypeRequiredDescription
collectionpathstringYesThe collection's name, as collection.list names it.
formatquery"json" | "ndjson"Nothe body format (default: json when it starts with '[', else ndjson).
on_conflictquery"error" | "skip" | "replace"Nowhat a row whose _id a stored document already holds does (default error): error fails that row alone with KEY_EXISTS; skip leaves the stored document as it is (counted in skipped, no entry in errors); replace stores the row over it whole (counted in replaced). skip and replace refuse, alone, a row with no _id (INVALID_ARGUMENT).
documentsbodyarray of objectYesThe documents (over HTTP, the whole body: a JSON array, or NDJSON with one document per line; format or a leading [ decides).

Response

FieldTypePresentDescription
insertedintegerAlways
skippedintegerAlwaysHow many rows on_conflict=skip left the stored document unchanged for.
replacedintegerAlwaysHow many rows on_conflict=replace stored over the document that held their _id.
rejectedintegerAlwaysHow many documents were refused; each is in errors.
errorsarray of objectAlways
totalintegerAlwaysinserted + skipped + replaced + rejected.

Errors

A failed call answers the error envelope with a typed code.

Example

curl -X POST "$SUBSTRIO_URL/v1/$COLLECTION/_import" \
  -H "Authorization: Bearer $SUBSTRIO_KEY" \
  -H "Content-Type: application/json" \
  -d '{"documents":[]}'

data.insert

Insert one document into a collection: the document is the whole body over HTTP (an object of any fields). The collection assigns _id: a body that names _id is refused with 400 ID_RESERVED and nothing is stored (put(doc) in the function runtime chooses an id); _createdAt, _updatedAt and _version are the system's and ignored. Answers 201 {_id, status:'created'} and runs the collection's insert triggers with that _id. For many documents use data.import.

Route
POST /v1/{collection}
ANY create
Auth
App key, or a user session your security rules allow tenant_or_rules
MCP tool
substrio_insert
CLI
substrio op data.insert

Parameters

NameInTypeRequiredDescription
collectionpathstringYesThe collection's name, as collection.list names it.
documentbodyobjectYesThe document to insert, any field names (over HTTP, the request body with no wrapper). Keys starting with _ are system fields.

Response

FieldTypePresentDescription
_idstringAlways
status"created"Always

Errors

A failed call answers the error envelope with a typed code.

Example

curl -X POST "$SUBSTRIO_URL/v1/$COLLECTION" \
  -H "Authorization: Bearer $SUBSTRIO_KEY" \
  -H "Content-Type: application/json" \
  -d '{"document":{}}'

data.list

List a collection's records in key order: options limit (default 100; a larger value is lowered to 1000), offset and cursor (the previous page's next_cursor, a record _id). Answers data (each record with its _id), count, offset, limit and next_cursor. Records the caller may not read are left out. For filters use data.query or query.chain.

Route
GET /v1/{collection}
Auth
App key or user session; your security rules apply none
MCP tool
substrio_list
CLI
substrio op data.list

Parameters

NameInTypeRequiredDescription
collectionpathstringYesThe collection's name, as collection.list names it.
limitqueryinteger (0 or more)Nothe most items to return.
offsetqueryinteger (0 or more)Noitems to skip before the first one returned.
cursorquerystringNoresume after the previous page: its next_cursor.

Response

A JSON object.

Errors

A failed call answers the error envelope with a typed code.

Example

curl "$SUBSTRIO_URL/v1/$COLLECTION" \
  -H "Authorization: Bearer $SUBSTRIO_KEY"

data.put

Store one whole document under an id the caller chooses (the route's {id}: a base62 id string or a positive whole number): creates it when no document holds the id, replaces the stored document whole when one does (fields the body leaves out are gone; the stamps are made anew). A body that names _id must name the same id, else 400 ID_MISMATCH; an id that is neither form is 400 INVALID_ID. Needs create on the collection for a new document and write for a replacement; honours the tenant's document and storage quotas (507). Answers {_id, created}; runs the collection's insert trigger for a new document and its update trigger for a replaced one.

Route
PUT /v1/{collection}/{id}
ANY put
Auth
App key, or a user session your security rules allow tenant_or_rules
MCP tool
substrio_put
CLI
substrio op data.put

Parameters

NameInTypeRequiredDescription
collectionpathstringYesThe collection's name, as collection.list names it.
idpathstring or integerYesThe id the document is stored under: a base62 id string or a positive whole number (a record's id, as data.insert or data.list returned it, or one the caller chooses).
documentbodyobjectYesThe whole document to store under the route's id, any field names (over HTTP, the request body with no wrapper). A body that names _id must name the route's id. Keys starting with _ are system fields.

Response

FieldTypePresentDescription
_idstringAlwaysThe id the document is stored under.
createdbooleanAlwaystrue when no document held the id and this call created it; false when it replaced the stored document.

Errors

A failed call answers the error envelope with a typed code.

Example

curl -X PUT "$SUBSTRIO_URL/v1/$COLLECTION/$ID" \
  -H "Authorization: Bearer $SUBSTRIO_KEY" \
  -H "Content-Type: application/json" \
  -d '{"document":{}}'

data.update

Change one record in place with operators: $set (fields to values), $unset (fields to remove), $inc (numeric fields to add to) and $push (array fields to append to); at least one, and fields starting with an underscore are skipped. A $set, $unset or $inc key may reach into arrays: "items.0.qty" one element, "items.$[].qty" every element, "items.$[big].qty" the elements the arrayFilters entry for the identifier big selects (arrayFilters: [{identifier, where, scalar?}]; an identifier with no entry, an entry no key uses or two entries for one identifier answer 400 and nothing is written). 404 when the record does not exist, 403 when the key may not write it.

Route
PATCH /v1/{collection}/{id}
ANY update
Auth
App key, or a user session your security rules allow tenant_or_rules
MCP tool
substrio_update
CLI
substrio op data.update

Parameters

NameInTypeRequiredDescription
collectionpathstringYesThe collection's name, as collection.list names it.
idpathstring or integerYesThe record's id, as data.insert or data.list returned it.
$setbodyobjectNoFields set to these values.
$unsetbodyobjectNoFields removed; the values are ignored.
$incbodyobjectNoNumeric fields increased by these amounts.
$pushbodyobjectNoArray fields each value is appended to.
arrayFiltersbodyarray of objectNoWhich elements a $[identifier] step of a $set, $unset or $inc key writes ("items.$[big].qty"): one entry per identifier, and each identifier a key names needs exactly one entry (a missing, unused or repeated one answers 400, nothing written).

Response

FieldTypePresentDescription
status"updated"Always
fieldsUpdatedintegerAlwaysMinimum 0.
fieldsDeletedintegerAlwaysMinimum 0.

Errors

  • KEY_NOT_FOUND: call data.list to find the right one.

A failed call answers the error envelope with a typed code.

Example

curl -X PATCH "$SUBSTRIO_URL/v1/$COLLECTION/$ID" \
  -H "Authorization: Bearer $SUBSTRIO_KEY"

graph

graph.analytics

Run an analytics algorithm over one graph label (the route's {label}); see the schema for the algorithm and its inputs.

Route
GET /v1/_graph/{label}/analytics
POST /v1/_graph/{label}/analytics
Auth
App key or user session; your security rules apply none
MCP tool
substrio_graph_analytics
CLI
substrio op graph.analytics

Parameters

NameInTypeRequiredDescription
labelpathstringYesThe graph label (the edge type).
opquery"common_neighbors" | "common_neighbor_count" | "jaccard" | "adamic_adar" | "preferential_attachment" | "exclusive_neighbors" | "neighbor_union" | "overlap_coefficient" | "cosine_similarity" | "resource_allocation" | "common_neighbors_multi" | "neighbor_union_multi" | "neighbors_in_range" | "neighbors_in_range_count" | "triangle_count_node" | "clustering_coefficient" | "two_hop_neighbors" | "min_neighbor" | "max_neighbor" | "degree_centrality" | "k_hop_neighbors" | "k_hop_count" | "shortest_path_length" | "reachable" | "global_clustering_coefficient" | "neighbor_rank" | "top_k_by_degree" | "degree_histogram" | "neighbors_multi_label" | "neighbors_all_labels" | "triangle_count_global" | "label_stats" | "degree_distribution" | "topological_sort" | "has_cycle" | "connected_components" | "graph_summary" | "pagerank" | "betweenness_centrality" | "closeness_centrality" | "hits" | "scc" | "shortest_path" | "all_shortest_paths" | "eccentricity" | "diameter" | "find_cycle" | "square_count" | "simrank" | "label_propagation" | "louvain" | "graph_coloring" | "min_vertex_cover" | "max_independent_set" | "bipartite_project" | "degree_percentile" | "degree_median" | "nodes_with_degree_gt" | "nodes_with_degree_gte" | "nodes_with_degree_lt" | "nodes_with_degree_in_range" | "neighbor_at_percentile" | "neighbor_degree_facets" | "neighbor_histogram" | "k_hop_labeled" | "influence_spread" | "has_edges" | "add_edges" | "remove_edges" | "degrees" | "pairwise_jaccard"Yes
dirquery"out" | "in"No
aqueryintegerNo
bqueryintegerNo
nodesqueryarray of integerNo
nodequeryintegerNo
loqueryintegerNo
hiqueryintegerNo
kqueryintegerNo
srcqueryintegerNo
dstqueryintegerNo
targetqueryintegerNo
bucket_sizequeryintegerNo
labelsqueryarray of stringNo
iterationsqueryintegerNo
dampingquerynumberNo
samplesqueryintegerNo
decayquerynumberNo
percentilequerynumberNo
thresholdqueryintegerNo
seedsqueryarray of integerNo
probabilityquerynumberNo
simulationsqueryintegerNo
pairsqueryarray of array of integerNo

Response

A JSON object.

Errors

A failed call answers the error envelope with a typed code.

Example

curl "$SUBSTRIO_URL/v1/_graph/$LABEL/analytics" \
  -H "Authorization: Bearer $SUBSTRIO_KEY"

graph.degree

Read the degree (edge count) of one node of a graph label: the route's {label} and {id}.

Route
GET /v1/_graph/{label}/degree/{id}
Auth
App key or user session; your security rules apply none
MCP tool
substrio_graph_degree
CLI
substrio op graph.degree

Parameters

NameInTypeRequiredDescription
labelpathstringYesThe graph label (the edge type).
idpathstring or integerYesThe id of the node.

Response

A JSON object.

Errors

A failed call answers the error envelope with a typed code.

Example

curl "$SUBSTRIO_URL/v1/_graph/$LABEL/degree/$ID" \
  -H "Authorization: Bearer $SUBSTRIO_KEY"

graph.edge.read

Read the edges of one graph label (the route's {label}).

Route
GET /v1/_graph/{label}/edges
POST /v1/_graph/{label}/edges/_check
Auth
App key or user session; your security rules apply none
MCP tool
substrio_graph_edge_read
CLI
substrio op graph.edge.read

Parameters

NameInTypeRequiredDescription
labelpathstringYesThe graph label (the edge type).
srcqueryintegerYes
dstqueryintegerYes

Response

FieldTypePresentDescription
labelstringAlways
srcintegerAlways
dstintegerAlways
existsbooleanAlways

Errors

A failed call answers the error envelope with a typed code.

Example

curl "$SUBSTRIO_URL/v1/_graph/$LABEL/edges" \
  -H "Authorization: Bearer $SUBSTRIO_KEY"

graph.edge.remove

Remove edges of one graph label (the route's {label}); see the schema for the body.

Route
POST /v1/_graph/{label}/edges/_remove
Auth
App key or user session; your security rules apply none
MCP tool
substrio_graph_edge_remove
CLI
substrio op graph.edge.remove

Parameters

NameInTypeRequiredDescription
labelpathstringYesThe graph label (the edge type).
srcbodyintegerYes
dstbodyintegerYes

Response

FieldTypePresentDescription
labelstringAlways
srcintegerAlways
dstintegerAlways
removedbooleanAlways

Errors

A failed call answers the error envelope with a typed code.

Example

curl -X POST "$SUBSTRIO_URL/v1/_graph/$LABEL/edges/_remove" \
  -H "Authorization: Bearer $SUBSTRIO_KEY" \
  -H "Content-Type: application/json" \
  -d '{"src":1,"dst":1}'

graph.edge.write

Write edges of one graph label (the route's {label}); see the schema for the body.

Route
POST /v1/_graph/{label}/edges
Auth
App key or user session; your security rules apply none
MCP tool
substrio_graph_edge_write
CLI
substrio op graph.edge.write

Parameters

NameInTypeRequiredDescription
labelpathstringYesThe graph label (the edge type).
srcbodyintegerYes
dstbodyintegerYes

Response

FieldTypePresentDescription
labelstringAlways
srcintegerAlways
dstintegerAlways
addedbooleanAlways

Errors

A failed call answers the error envelope with a typed code.

Example

curl -X POST "$SUBSTRIO_URL/v1/_graph/$LABEL/edges" \
  -H "Authorization: Bearer $SUBSTRIO_KEY" \
  -H "Content-Type: application/json" \
  -d '{"src":1,"dst":1}'

graph.label.list

List the graph labels (edge types) that exist in the app.

Route
GET /v1/_graph
Auth
App key or user session; your security rules apply none
MCP tool
substrio_graph_label_list
CLI
substrio op graph.label.list

Parameters

No parameters.

Response

A JSON object.

Errors

A failed call answers the error envelope with a typed code.

Example

curl "$SUBSTRIO_URL/v1/_graph" \
  -H "Authorization: Bearer $SUBSTRIO_KEY"

graph.neighbors

Read the neighbors of one node of a graph label: the route's {label} and {id}.

Route
GET /v1/_graph/{label}/neighbors/{id}
POST /v1/_graph/{label}/neighbors/{id}
Auth
App key or user session; your security rules apply none
MCP tool
substrio_graph_neighbors
CLI
substrio op graph.neighbors

Parameters

NameInTypeRequiredDescription
labelpathstringYesThe graph label (the edge type).
idpathstring or integerYesThe id of the node.
dirquery"out" | "in"NoEdge direction; out when absent.

Response

FieldTypePresentDescription
labelstringAlways
node_idintegerAlways
direction"out" | "in"Always
neighborsarray of integerAlways
countintegerAlways

Errors

A failed call answers the error envelope with a typed code.

Example

curl "$SUBSTRIO_URL/v1/_graph/$LABEL/neighbors/$ID" \
  -H "Authorization: Bearer $SUBSTRIO_KEY"

graph.stats

Read the statistics of one graph label (the route's {label}).

Route
GET /v1/_graph/{label}/stats
GET /v1/_graph/{label}
Auth
App key or user session; your security rules apply none
MCP tool
substrio_graph_stats
CLI
substrio op graph.stats

Parameters

NameInTypeRequiredDescription
labelpathstringYesThe graph label (the edge type).

Response

A JSON object.

Errors

A failed call answers the error envelope with a typed code.

Example

curl "$SUBSTRIO_URL/v1/_graph/$LABEL/stats" \
  -H "Authorization: Bearer $SUBSTRIO_KEY"

kv

kv.batch.delete

Delete many keys of a key-value collection in one call: body collection and keys (at least one).

Route
POST /v1/kv/{collection}/_del
Auth
App key tenant
MCP tool
substrio_kv_batch_delete
CLI
substrio op kv.batch.delete

Parameters

NameInTypeRequiredDescription
collectionpathstringYesThe key-value collection.
keysbodyarray of stringYesThe keys.

Response

A JSON array of array.

Errors

A failed call answers the error envelope with a typed code.

Example

curl -X POST "$SUBSTRIO_URL/v1/kv/$COLLECTION/_del" \
  -H "Authorization: Bearer $SUBSTRIO_KEY" \
  -H "Content-Type: application/json" \
  -d '{"keys":[]}'

kv.batch.get

Read many keys of a key-value collection in one call: body collection and keys (at least one).

Route
POST /v1/kv/{collection}/_get
Auth
App key tenant
MCP tool
substrio_kv_batch_get
CLI
substrio op kv.batch.get

Parameters

NameInTypeRequiredDescription
collectionpathstringYesThe key-value collection.
keysbodyarray of stringYesThe keys.

Response

A JSON array of array.

Errors

A failed call answers the error envelope with a typed code.

Example

curl -X POST "$SUBSTRIO_URL/v1/kv/$COLLECTION/_get" \
  -H "Authorization: Bearer $SUBSTRIO_KEY" \
  -H "Content-Type: application/json" \
  -d '{"keys":[]}'

kv.delete

Delete keys from a key-value collection: body collection and keys (at least one).

Route
DELETE /v1/kv/{collection}
Auth
App key tenant
MCP tool
substrio_kv_delete
CLI
substrio op kv.delete

Parameters

NameInTypeRequiredDescription
collectionpathstringYesThe key-value collection.
keysqueryarray of stringYesThe keys.

Response

A JSON array of array.

Errors

  • KEY_NOT_FOUND: call kv.scan to find the right one.

A failed call answers the error envelope with a typed code.

Example

curl -X DELETE "$SUBSTRIO_URL/v1/kv/$COLLECTION" \
  -H "Authorization: Bearer $SUBSTRIO_KEY"

kv.get

Read one key of a key-value collection: the route's {collection} and {key}.

Route
GET /v1/kv/{collection}/{key}
Auth
App key tenant
MCP tool
substrio_kv_get
CLI
substrio op kv.get

Parameters

NameInTypeRequiredDescription
collectionpathstringYes
keypathstringYes

Response

A JSON array of array.

Errors

  • KEY_NOT_FOUND: call kv.scan to find the right one.

A failed call answers the error envelope with a typed code.

Example

curl "$SUBSTRIO_URL/v1/kv/$COLLECTION/$KEY" \
  -H "Authorization: Bearer $SUBSTRIO_KEY"

kv.scan

Scan the keys of a key-value collection in order: options match (only keys with this prefix), count (page size, default 10) and cursor (resume after the previous page's cursor). Answers keys, count and cursor. Values are read with kv.get.

Route
GET /v1/kv/{collection}/_scan
Auth
App key tenant
MCP tool
substrio_kv_scan
CLI
substrio op kv.scan

Parameters

NameInTypeRequiredDescription
collectionpathstringYesThe collection's name, as collection.list names it.
cursorquerystringNoresume after this key (the previous page's cursor).
matchquerystringNoonly keys with this prefix.
countqueryinteger (0 or more)Nothe most keys per page (positive, default 10).
cursorquerystringNo
matchquerystringNo
countqueryintegerNoMinimum 1.

Response

FieldTypePresentDescription
cursorstringAlways
keysarray of stringAlways
countintegerAlways

Errors

A failed call answers the error envelope with a typed code.

Example

curl "$SUBSTRIO_URL/v1/kv/$COLLECTION/_scan" \
  -H "Authorization: Bearer $SUBSTRIO_KEY"

kv.set

Write key-value entries into a collection: body collection and entries, a list of [key, value] string pairs (at least one).

Route
PUT /v1/kv/{collection}
POST /v1/kv/{collection}
Auth
App key tenant
MCP tool
substrio_kv_set
CLI
substrio op kv.set

Parameters

NameInTypeRequiredDescription
collectionpathstringYesThe key-value collection.
entriesbodyarray of array of stringYesThe pairs to write.

Response

A JSON array of array.

Errors

A failed call answers the error envelope with a typed code.

Example

curl -X PUT "$SUBSTRIO_URL/v1/kv/$COLLECTION" \
  -H "Authorization: Bearer $SUBSTRIO_KEY" \
  -H "Content-Type: application/json" \
  -d '{"entries":[]}'

kv.stream

Stream binary key-value operations.

Route
GET /v1/kv/ws
Auth
App key tenant
CLI
substrio op kv.stream

Parameters

No parameters.

Response

A JSON object.

Errors

A failed call answers the error envelope with a typed code.

Example

curl "$SUBSTRIO_URL/v1/kv/ws" \
  -H "Authorization: Bearer $SUBSTRIO_KEY"

ledger

ledger.accounts

Read every account of one kind (the catalog name) in one currency: its pending and cleared amount summed over every organization, voided entries never count; a party with no entry of that kind in that currency is left out, never a zero entry. One walk of that kind's groups of the balance aggregate, no new index. Answers {accounts: [{party, amount}]}.

Route
GET /v1/_ledger/accounts
Auth
App key tenant
MCP tool
substrio_ledger_accounts
CLI
substrio op ledger.accounts

Parameters

NameInTypeRequiredDescription
kindquerystringYes
currencyquerystringYes

Response

A JSON object.

Errors

A failed call answers the error envelope with a typed code.

Example

curl "$SUBSTRIO_URL/v1/_ledger/accounts" \
  -H "Authorization: Bearer $SUBSTRIO_KEY"

ledger.accounts.totals

Read every group of one account kind (the catalog name) in one currency kept by the party totals (the tenant first declares them with ledger.totals.declare by=party): each party's amount sum and row count by category, type and status, and first=true on the groups of the one live positive entry of each (kind, party, reference), whose rows count the references credited to that party. One walk of that kind's groups, no record read. Answers {totals: [{party, type, status, category?, first?, amount, rows}]}.

Route
GET /v1/_ledger/accounts/totals
Auth
App key tenant
MCP tool
substrio_ledger_accounts_totals
CLI
substrio op ledger.accounts.totals

Parameters

NameInTypeRequiredDescription
kindquerystringYes
currencyquerystringYes

Response

A JSON object.

Errors

A failed call answers the error envelope with a typed code.

Example

curl "$SUBSTRIO_URL/v1/_ledger/accounts/totals" \
  -H "Authorization: Bearer $SUBSTRIO_KEY"

ledger.balance

Read one (kind, party, currency) group's balance: pending and cleared amounts and row counts; voided entries never count.

Route
GET /v1/_ledger/balance
Auth
App key tenant
MCP tool
substrio_ledger_balance
CLI
substrio op ledger.balance

Parameters

NameInTypeRequiredDescription
kindquerystringYes
partyquerystringYes
currencyquerystringYes
orgquerystringNo

Response

A JSON object.

Errors

A failed call answers the error envelope with a typed code.

Example

curl "$SUBSTRIO_URL/v1/_ledger/balance" \
  -H "Authorization: Bearer $SUBSTRIO_KEY"

ledger.balances.top

Read the n (default 10, at most 1000) (kind, party) balances with the largest summed amount in one currency, largest first; a party with none of that currency is left out, never a zero entry. One walk of the balance aggregate's own groups, no new index. Answers {balances: [{account_kind, party, amount}]}.

Route
GET /v1/_ledger/balances/top
Auth
App key tenant
MCP tool
substrio_ledger_balances_top
CLI
substrio op ledger.balances.top

Parameters

NameInTypeRequiredDescription
currencyquerystringYes
limitqueryintegerNoMinimum 1. Maximum 1000.

Response

A JSON object.

Errors

A failed call answers the error envelope with a typed code.

Example

curl "$SUBSTRIO_URL/v1/_ledger/balances/top" \
  -H "Authorization: Bearer $SUBSTRIO_KEY"

ledger.catalog.get

Read the tenant's ledger catalog: its declared account kind and category names, in index order.

Route
GET /v1/_ledger/catalog
Auth
App key tenant
MCP tool
substrio_ledger_catalog_get
CLI
substrio op ledger.catalog.get

Parameters

No parameters.

Response

A JSON object.

Errors

A failed call answers the error envelope with a typed code.

Example

curl "$SUBSTRIO_URL/v1/_ledger/catalog" \
  -H "Authorization: Bearer $SUBSTRIO_KEY"

ledger.catalog.set

Declare the tenant's ledger catalog: kinds and categories, each the tenant's whole list in order, either omitted meaning that list stands. Append only: a list that is not a strict prefix of what's stored is refused (409) and changes nothing. Answers the catalog.

Route
POST /v1/_ledger/catalog
Auth
App key tenant
MCP tool
substrio_ledger_catalog_set
CLI
substrio op ledger.catalog.set

Parameters

NameInTypeRequiredDescription
kindsbodyarray of stringNo
categoriesbodyarray of stringNo

Response

A JSON object.

Errors

A failed call answers the error envelope with a typed code.

Example

curl -X POST "$SUBSTRIO_URL/v1/_ledger/catalog" \
  -H "Authorization: Bearer $SUBSTRIO_KEY"

ledger.clear_due

Clear every pending entry whose clear_at has passed, oldest first, at most limit entries (default 1000, at most 10000) in this call; the cutoff is always now, on the server, never caller supplied. Answers {cleared, more}: more is true when entries past the cutoff remain.

Route
POST /v1/_ledger/clear-due
Auth
App key tenant
MCP tool
substrio_ledger_clear_due
CLI
substrio op ledger.clear_due

Parameters

NameInTypeRequiredDescription
limitbodyintegerNoMinimum 1. Maximum 10000.

Response

A JSON object.

Errors

A failed call answers the error envelope with a typed code.

Example

curl -X POST "$SUBSTRIO_URL/v1/_ledger/clear-due" \
  -H "Authorization: Bearer $SUBSTRIO_KEY"

ledger.entries

List posted entries by one index (party, reference, scope or org) and its value, or by=all for the whole ledger (value absent), newest first. before pages older than the entry of that id (default: the newest); limit caps the page (default 50, at most 1000); org (by=party only) narrows a party's entries to one organization. Answers {entries, next_before}: next_before is the id to page from next, or 0 at the end.

Route
GET /v1/_ledger/entries
Auth
App key tenant
MCP tool
substrio_ledger_entries
CLI
substrio op ledger.entries

Parameters

NameInTypeRequiredDescription
byquery"party" | "reference" | "scope" | "org" | "all"Yes
valuequerystringNo
beforequeryintegerNoMinimum 0.
limitqueryintegerNoMinimum 1. Maximum 1000.
orgquerystringNo

Response

A JSON object.

Errors

A failed call answers the error envelope with a typed code.

Example

curl "$SUBSTRIO_URL/v1/_ledger/entries" \
  -H "Authorization: Bearer $SUBSTRIO_KEY"

ledger.entry.annotate

Set an administrator's note and tags on one entry by its id; never a money or index field. Answers {outcome: CHANGED}; an unknown id is refused (404).

Route
POST /v1/_ledger/entries/{id}/annotate
Auth
App key tenant
MCP tool
substrio_ledger_entry_annotate
CLI
substrio op ledger.entry.annotate

Parameters

NameInTypeRequiredDescription
idpathstring or integerYesThe entry's id, as ledger.post or ledger.entries returned it.
admin_notesbodystringNo
tagsbodyarray of stringNo

Response

A JSON object.

Errors

A failed call answers the error envelope with a typed code.

Example

curl -X POST "$SUBSTRIO_URL/v1/_ledger/entries/$ID/annotate" \
  -H "Authorization: Bearer $SUBSTRIO_KEY"

ledger.entry.clear

Clear one pending entry by its id: moves it from pending to cleared. Answers {outcome: CHANGED or UNCHANGED}; an already cleared entry is UNCHANGED, a voided or reversal entry is refused (409).

Route
POST /v1/_ledger/entries/{id}/clear
Auth
App key tenant
MCP tool
substrio_ledger_entry_clear
CLI
substrio op ledger.entry.clear

Parameters

NameInTypeRequiredDescription
idpathstring or integerYesThe entry's id, as ledger.post or ledger.entries returned it.

Response

A JSON object.

Errors

A failed call answers the error envelope with a typed code.

Example

curl -X POST "$SUBSTRIO_URL/v1/_ledger/entries/$ID/clear" \
  -H "Authorization: Bearer $SUBSTRIO_KEY"

ledger.entry.clear_at

Set (clear_at > 0) or take away (clear_at == 0) one pending entry's own clear time by its id; never a money field. Answers {outcome: CHANGED or UNCHANGED}; a cleared or voided entry is refused (409); an unknown id is 404.

Route
POST /v1/_ledger/entries/{id}/clear-at
Auth
App key tenant
MCP tool
substrio_ledger_entry_clear_at
CLI
substrio op ledger.entry.clear_at

Parameters

NameInTypeRequiredDescription
idpathstring or integerYesThe entry's id, as ledger.post or ledger.entries returned it.
clear_atbodyintegerYesMinimum 0.

Response

A JSON object.

Errors

A failed call answers the error envelope with a typed code.

Example

curl -X POST "$SUBSTRIO_URL/v1/_ledger/entries/$ID/clear-at" \
  -H "Authorization: Bearer $SUBSTRIO_KEY" \
  -H "Content-Type: application/json" \
  -d '{"clear_at":0}'

ledger.entry.get

Read one posted entry by its id (the route's {id}, as ledger.post or ledger.entries answered it).

Route
GET /v1/_ledger/entries/{id}
Auth
App key tenant
MCP tool
substrio_ledger_entry_get
CLI
substrio op ledger.entry.get

Parameters

NameInTypeRequiredDescription
idpathstring or integerYesThe entry's id, as ledger.post or ledger.entries returned it.

Response

A JSON object.

Errors

A failed call answers the error envelope with a typed code.

Example

curl "$SUBSTRIO_URL/v1/_ledger/entries/$ID" \
  -H "Authorization: Bearer $SUBSTRIO_KEY"

ledger.entry.reverse

Post a REVERSAL entry that offsets one original entry by its id. Answers {outcome: POSTED or EXISTING, ids}; reversing the same original again answers EXISTING with the same id and writes nothing. A voided original, or an original that is itself a reversal, is refused (409); an unknown id is 404.

Route
POST /v1/_ledger/entries/{id}/reverse
Auth
App key tenant
MCP tool
substrio_ledger_entry_reverse
CLI
substrio op ledger.entry.reverse

Parameters

NameInTypeRequiredDescription
idpathstring or integerYesThe original entry's id, as ledger.post or ledger.entries returned it.

Response

A JSON object.

Errors

A failed call answers the error envelope with a typed code.

Example

curl -X POST "$SUBSTRIO_URL/v1/_ledger/entries/$ID/reverse" \
  -H "Authorization: Bearer $SUBSTRIO_KEY"

ledger.entry.void

Void one pending entry by its id: it stops counting toward its balance. Answers {outcome: CHANGED or UNCHANGED}; an already voided entry is UNCHANGED, a cleared or reversal entry is refused (409).

Route
POST /v1/_ledger/entries/{id}/void
Auth
App key tenant
MCP tool
substrio_ledger_entry_void
CLI
substrio op ledger.entry.void

Parameters

NameInTypeRequiredDescription
idpathstring or integerYesThe entry's id, as ledger.post or ledger.entries returned it.

Response

A JSON object.

Errors

A failed call answers the error envelope with a typed code.

Example

curl -X POST "$SUBSTRIO_URL/v1/_ledger/entries/$ID/void" \
  -H "Authorization: Bearer $SUBSTRIO_KEY"

ledger.import

Import 1 to 1000 ledger entries from an older system's own history, whole or not at all: each entry keeps its own created_at and its own id, and may already be VOIDED or a REVERSAL (naming the original it reverses by original_key). Answers {posted, existing}; an import of the same keys again answers every entry existing and writes nothing.

Route
POST /v1/_ledger/import
Auth
App key tenant
MCP tool
substrio_ledger_import
CLI
substrio op ledger.import

Parameters

NameInTypeRequiredDescription
entriesbodyarray of objectYes

Response

A JSON object.

Errors

A failed call answers the error envelope with a typed code.

Example

curl -X POST "$SUBSTRIO_URL/v1/_ledger/import" \
  -H "Authorization: Bearer $SUBSTRIO_KEY" \
  -H "Content-Type: application/json" \
  -d '{"entries":[]}'

ledger.post

Post 1 to 1000 ledger entries, whole or not at all: each entry's kind and category (when given) are the tenant's declared catalog names. balanced (default false) refuses the whole post unless every currency's amounts sum to zero. Answers {outcome: POSTED or EXISTING, ids}; a post of the same keys again answers EXISTING with the same ids and writes nothing.

Route
POST /v1/_ledger/entries
Auth
App key tenant
MCP tool
substrio_ledger_post
CLI
substrio op ledger.post

Parameters

NameInTypeRequiredDescription
entriesbodyarray of objectYes
balancedbodybooleanNo

Response

A JSON object.

Errors

A failed call answers the error envelope with a typed code.

Example

curl -X POST "$SUBSTRIO_URL/v1/_ledger/entries" \
  -H "Authorization: Bearer $SUBSTRIO_KEY" \
  -H "Content-Type: application/json" \
  -d '{"entries":[]}'

ledger.totals

Read one scope's, one reference's or (all=true) the whole ledger's totals in one currency, maintained by account kind, category, type and status (the tenant must first declare them with ledger.totals.declare): each group's amount sum and row count; category is left out for the entries that named none. Exactly one of scope/reference/all.

Route
GET /v1/_ledger/totals
Auth
App key tenant
MCP tool
substrio_ledger_totals
CLI
substrio op ledger.totals

Parameters

NameInTypeRequiredDescription
scopequerystringNo
referencequerystringNo
allquerystringNo
currencyquerystringYes

Response

A JSON object.

Errors

A failed call answers the error envelope with a typed code.

Example

curl "$SUBSTRIO_URL/v1/_ledger/totals" \
  -H "Authorization: Bearer $SUBSTRIO_KEY"

ledger.totals.declare

Declare the tenant's scope, reference, all or party totals (idempotent, by defaults to scope): once declared, every post and status change keeps that totals current and ledger.totals reads them with no record read. Answers {outcome: DECLARED or EXISTING}.

Route
POST /v1/_ledger/totals/declare
Auth
App key tenant
MCP tool
substrio_ledger_totals_declare
CLI
substrio op ledger.totals.declare

Parameters

NameInTypeRequiredDescription
bybody"scope" | "reference" | "all" | "party"No

Response

A JSON object.

Errors

A failed call answers the error envelope with a typed code.

Example

curl -X POST "$SUBSTRIO_URL/v1/_ledger/totals/declare" \
  -H "Authorization: Bearer $SUBSTRIO_KEY"

live_view

live_view.create

Create a live view; see the schema for its definition.

Route
POST /v1/_live_views
Auth
App key tenant
MCP tool
substrio_live_view_create
CLI
substrio op live_view.create

Parameters

NameInTypeRequiredDescription
namebodystringYes
source_collectionbodystringYes
querybodyobjectYes
min_interval_msbodyintegerNoMinimum 0. Default 50.

Response

A JSON object.

Errors

A failed call answers the error envelope with a typed code.

Example

curl -X POST "$SUBSTRIO_URL/v1/_live_views" \
  -H "Authorization: Bearer $SUBSTRIO_KEY" \
  -H "Content-Type: application/json" \
  -d '{"name":"name","source_collection":"source_collection","query":{}}'

live_view.delete

Delete one live view by its name (the route's {name}); live_view.list shows the live views.

Route
DELETE /v1/_live_views/{name}
Auth
App key tenant
MCP tool
substrio_live_view_delete
CLI
substrio op live_view.delete

Parameters

NameInTypeRequiredDescription
namepathstringYesThe live view's name, as live_view.list shows it.

Response

A JSON object.

Errors

A failed call answers the error envelope with a typed code.

Example

curl -X DELETE "$SUBSTRIO_URL/v1/_live_views/$NAME" \
  -H "Authorization: Bearer $SUBSTRIO_KEY"

live_view.get

Read the current data of one live view by name.

Route
GET /v1/_live_views/{name}/data
Auth
App key tenant
MCP tool
substrio_live_view_get
CLI
substrio op live_view.get

Parameters

NameInTypeRequiredDescription
namepathstringYesThe live view's name, as live_view.list shows it.

Response

A JSON object.

Errors

A failed call answers the error envelope with a typed code.

Example

curl "$SUBSTRIO_URL/v1/_live_views/$NAME/data" \
  -H "Authorization: Bearer $SUBSTRIO_KEY"

live_view.list

List the app's live views: their names are what live_view.get and live_view.delete take.

Route
GET /v1/_live_views
Auth
App key tenant
MCP tool
substrio_live_view_list
CLI
substrio op live_view.list

Parameters

No parameters.

Response

A JSON object.

Errors

A failed call answers the error envelope with a typed code.

Example

curl "$SUBSTRIO_URL/v1/_live_views" \
  -H "Authorization: Bearer $SUBSTRIO_KEY"

live_view.update

Enable or disable one live view by name: body name and enabled.

Route
PATCH /v1/_live_views/{name}
Auth
App key tenant
MCP tool
substrio_live_view_update
CLI
substrio op live_view.update

Parameters

NameInTypeRequiredDescription
namepathstringYesThe view's id, as its create call returned it.
enabledbodybooleanYes

Response

A JSON object.

Errors

A failed call answers the error envelope with a typed code.

Example

curl -X PATCH "$SUBSTRIO_URL/v1/_live_views/$NAME" \
  -H "Authorization: Bearer $SUBSTRIO_KEY" \
  -H "Content-Type: application/json" \
  -d '{"enabled":true}'

view

view.create

Create a view; see the schema for its definition. The id it answers is what view.update, view.delete and view.refresh take.

Route
POST /v1/_views
Auth
App key tenant
MCP tool
substrio_view_create
CLI
substrio op view.create

Parameters

NameInTypeRequiredDescription
namebodystringYes
collectionbodystringYes
querybodyobjectNoA query over the collection; this or pipeline.
pipelinebodyarrayNoAn aggregation pipeline; this or query.
modebody"scheduled" | "live"NoDefault "scheduled".
cronbodystringNoWhen a scheduled view refreshes. Default "*/5 * * * *".
ttl_secondsbodyintegerNoMinimum 0. Default 300.
debounce_msbodyintegerNoMinimum 0. Default 100.

Response

A JSON object.

Errors

A failed call answers the error envelope with a typed code.

Example

curl -X POST "$SUBSTRIO_URL/v1/_views" \
  -H "Authorization: Bearer $SUBSTRIO_KEY" \
  -H "Content-Type: application/json" \
  -d '{"name":"name","collection":"collection"}'

view.delete

Delete one view by its id (the route's {name}, as view.create returned it); view.list shows the views.

Route
DELETE /v1/_views/{name}
Auth
App key tenant
MCP tool
substrio_view_delete
CLI
substrio op view.delete

Parameters

NameInTypeRequiredDescription
namepathstringYesThe view's id, as view.create returned it.

Response

A JSON object.

Errors

A failed call answers the error envelope with a typed code.

Example

curl -X DELETE "$SUBSTRIO_URL/v1/_views/$NAME" \
  -H "Authorization: Bearer $SUBSTRIO_KEY"

view.get

Read materialized view data.

Route
GET /v1/_views/{name}/data
Auth
App key or user session; your security rules apply none
CLI
substrio op view.get

Parameters

NameInTypeRequiredDescription
namepathstringYes

Response

A JSON object.

Errors

A failed call answers the error envelope with a typed code.

Example

curl "$SUBSTRIO_URL/v1/_views/$NAME/data" \
  -H "Authorization: Bearer $SUBSTRIO_KEY"

view.list

List the app's views: materialized and live.

Route
GET /v1/_views
Auth
App key tenant
MCP tool
substrio_view_list
CLI
substrio op view.list

Parameters

No parameters.

Response

A JSON object.

Errors

A failed call answers the error envelope with a typed code.

Example

curl "$SUBSTRIO_URL/v1/_views" \
  -H "Authorization: Bearer $SUBSTRIO_KEY"

view.refresh

Recompute one materialized view now, by its id.

Route
POST /v1/_views/{name}/refresh
Auth
App key tenant
MCP tool
substrio_view_refresh
CLI
substrio op view.refresh

Parameters

NameInTypeRequiredDescription
namepathstringYesThe view's id, as its create call returned it.

Response

A JSON object.

Errors

A failed call answers the error envelope with a typed code.

Example

curl -X POST "$SUBSTRIO_URL/v1/_views/$NAME/refresh" \
  -H "Authorization: Bearer $SUBSTRIO_KEY"

view.update

Enable or disable one view: body name and enabled.

Route
PATCH /v1/_views/{name}
Auth
App key tenant
MCP tool
substrio_view_update
CLI
substrio op view.update

Parameters

NameInTypeRequiredDescription
namepathstringYesThe view's id, as its create call returned it.
enabledbodybooleanYes

Response

A JSON object.

Errors

A failed call answers the error envelope with a typed code.

Example

curl -X PATCH "$SUBSTRIO_URL/v1/_views/$NAME" \
  -H "Authorization: Bearer $SUBSTRIO_KEY" \
  -H "Content-Type: application/json" \
  -d '{"enabled":true}'