REST API
State Broker REST
Read, list, set, merge, delete and echo states, and configure TTL and size per Main Topic.
All routes are below https://api.thuum.dev/api/{domain}/state. Data routes check the key's State Broker
claim data flags on the topic's Main Topic; config routes check its topic flags.
| Method | Path | Flag | Purpose |
|---|---|---|---|
GET | /state/data/{topic} | data R | List a subtree's states |
GET | /state/data/{topic}/{key} | data R | Read one state |
PUT | /state/data/{topic}/{key} | data P | Set |
PATCH | /state/data/{topic}/{key} | data P | Merge |
DELETE | /state/data/{topic}/{key} | data P | Delete |
POST | /state/data/{topic}/{key}/echo | data P | Echo |
GET | /state/topics | topic R | List TTL and size configs |
GET | /state/topics/{topic} | topic R | A Main Topic's effective config |
PUT | /state/topics/{topic} | topic W | Set a Main Topic's config |
DELETE | /state/topics/{topic} | topic W | Remove it |
A state renders as:
{
"topic": "board:42",
"key": "item:7",
"value": { "title": "Fix login", "column": "doing" },
"version": 2,
"inserted_at": "2026-10-21T13:51:37.599068Z",
"updated_at": "2026-10-21T13:58:02.112907Z"
}Every write notifies the WebSocket subscribers of the topic and of its super topics, exactly like the same operation over the WebSocket.
Read a state#
GET /state/data/{topic}/{key} returns one state, addressed exactly (no subtree). 404 if it
doesn't exist.
curl -s https://api.thuum.dev/api/acme/state/data/board:42/item:7 -H "authorization: Bearer $TOKEN"List states#
GET /state/data/{topic} lists the states of the topic and its sub-topics, ordered by topic,
then key (byte order).
| Query | Meaning |
|---|---|
prefix | Only keys that start with it (literal), in every topic of the subtree. |
limit | Default 100, at most 1000 (larger is capped). |
after | Cursor: the last key of the previous page (exclusive). |
after_topic | Cursor: the last topic of the previous page. Defaults to {topic}; needs after. |
curl -s "https://api.thuum.dev/api/acme/state/data/board:42?prefix=item:&limit=1000" \
-H "authorization: Bearer $TOKEN"const all = [];
let cursor: { after_topic?: string; after?: string } = {};
for (;;) {
const page = await acme.stateBroker.data.list('board:42', { limit: 1000, ...cursor });
all.push(...page);
if (page.length < 1000) break;
const last = page[page.length - 1];
cursor = { after_topic: last.topic, after: last.key };
}Set a state#
PUT /state/data/{topic}/{key} with { "value": … } creates or replaces the value (any JSON except
null, at most 64 KiB). 201 when created, 200 when replaced; the body is the state.
curl -s -X PUT https://api.thuum.dev/api/acme/state/data/orders:1042/status \
-H "authorization: Bearer $TOKEN" -H 'content-type: application/json' \
-d '{"value":{"stage":"shipped","eta":"2026-10-23"}}'const response = await fetch(`${API}/api/acme/state/data/orders:1042/status`, {
method: 'PUT',
headers: { authorization: `Bearer ${token}`, 'content-type': 'application/json' },
body: JSON.stringify({ value: { stage: 'shipped', eta: '2026-10-23' } })
});
const { data: state } = await response.json();const state = await acme.stateBroker.data.set('orders:1042', 'status', {
stage: 'shipped',
eta: '2026-10-23'
});Merge into a state#
PATCH /state/data/{topic}/{key} with { "value": <patch> } applies a JSON Merge Patch. The patch
must be an object; null members remove members. Creates the key if missing (201), else 200.
curl -s -X PATCH https://api.thuum.dev/api/acme/state/data/orders:1042/status \
-H "authorization: Bearer $TOKEN" -H 'content-type: application/json' \
-d '{"value":{"stage":"delivered","eta":null}}'Delete a state#
DELETE /state/data/{topic}/{key} removes the key: 204, also when it didn't exist. Subscribers get
a change with value: null if it existed.
Echo a state#
POST /state/data/{topic}/{key}/echo sends the current value to subscribers again, without writing
it (same version). Returns the state; 404 if it doesn't exist.
TTL and size configs#
A config applies to a Main Topic and all its sub-topics. {topic} must be a Main Topic, else
422.
curl -s -X PUT https://api.thuum.dev/api/acme/state/topics/presence \
-H "authorization: Bearer $TOKEN" -H 'content-type: application/json' \
-d '{"ttl_seconds":120,"max_states":null}'{
"data": {
"topic": "presence",
"ttl_seconds": 120,
"max_states": null,
"default": false,
"inserted_at": "…",
"updated_at": "…"
}
}| Field | Meaning |
|---|---|
ttl_seconds | Remove states not written (set or merge) for this long. null: never. |
max_states | Keep at most this many states in the family, the most recently written. null: unbounded. |
PUTreplaces the whole config; omitted fields arenull.GET /state/topics/{topic}returns the effective config,"default": truewhen nothing is stored (by default, states never expire and are unbounded).- Removals run about once a minute and never notify subscribers.
await acme.stateBroker.topics.put('presence', { ttl_seconds: 120 });