Change data feed
The change feed, list_changes, lists every change as an event: writes through the engine, hand edits with the rules they break, schema changes and, when asked for, tool calls. It works without history. Poll it from a position, or wait for the next event with wait_ms; a webhook has the engine post each event to a web address instead.
Change feed and webhooks shows how a program follows the feed.
Follow every change with the change feed
Section titled “Follow every change with the change feed”list_changes returns numbered row changes across all tables, oldest first. It includes engine writes and hand edits (source: external). Keep the returned last and pass it as since next time to get only what’s new. wait_ms waits for the next change, a technique called long polling.
list_changes
{ "tables": ["film"], "limit": 3 }Answer (74 lines)
{ "events": [ { "seq": 3, "at": "2026-10-12T16:52:36.274Z", "table": "main.public.film", "kind": "insert", "op": "insert_row", "path": "datanotes/main/public/film/Nosferatu.md", "row_id": "01a13107-c92d-767d-9b60-f4e03575c27e", "changes": { "id": { "after": "01a13107-c92d-767d-9b60-f4e03575c27e" }, "title": { "after": "Nosferatu" }, "status": { "after": "to watch" } }, "source": "engine", "row": { "id": "01a13107-c92d-767d-9b60-f4e03575c27e", "title": "Nosferatu", "status": "to watch" }, "actor": { "session": "history", "harness": "docs-example", "auth": "owner" }, "migration_id": "20261012T165236-insert_row-insert-into-film" }, { "seq": 4, "at": "2026-10-12T16:52:36.280Z", "table": "main.public.film", "kind": "insert", "op": "insert_row", "path": "datanotes/main/public/film/Metropolis.md", "row_id": "01a13107-c934-747a-90f7-3becda86084f", "changes": { "id": { "after": "01a13107-c934-747a-90f7-3becda86084f" }, "title": { "after": "Metropolis" }, "status": { "after": "to watch" } }, "source": "engine", "row": { "id": "01a13107-c934-747a-90f7-3becda86084f", "title": "Metropolis", "status": "to watch" }, "actor": { "session": "history", "harness": "docs-example", "auth": "owner" }, "migration_id": "20261012T165236-insert_row-insert-into-film-2" }, { "seq": 5, "at": "2026-10-12T16:52:36.287Z", "table": "main.public.film", "kind": "update", "op": "update_row", "path": "datanotes/main/public/film/Nosferatu.md", "row_id": "01a13107-c92d-767d-9b60-f4e03575c27e", "changes": { "status": { "before": "to watch", "after": "watched" }, "rating": { "after": 4 }, "watched_on": { "after": "2026-10-03" } }, "source": "engine", "row": { "id": "01a13107-c92d-767d-9b60-f4e03575c27e", "title": "Nosferatu", "status": "watched", "rating": 4, "watched_on": "2026-10-03" }, "actor": { "session": "history", "harness": "docs-example", "auth": "owner" }, "migration_id": "20261012T165236-update_row-update-film" } ], "last": 5, "head": 13}insert_row
{ "table": "film", "values": { "title": "His Girl Friday" } }With since, the answer holds only the newer changes:
list_changes
{ "since": 13 }Answer:
{ "events": [ { "seq": 14, "at": "2026-10-12T16:52:40.870Z", "table": "main.public.film", "kind": "insert", "op": "insert_row", "path": "datanotes/main/public/film/His Girl Friday.md", "row_id": "01a13107-db21-7bf5-942a-c5107eb7fed3", "changes": { "id": { "after": "01a13107-db21-7bf5-942a-c5107eb7fed3" }, "title": { "after": "His Girl Friday" }, "status": { "after": "to watch" } }, "source": "engine", "row": { "id": "01a13107-db21-7bf5-942a-c5107eb7fed3", "title": "His Girl Friday", "status": "to watch" }, "actor": { "session": "history", "harness": "docs-example", "auth": "owner" }, "migration_id": "20261012T165240-insert_row-insert-into-film" } ], "last": 14, "head": 14}Push changes to a web address with webhooks
Section titled “Push changes to a web address with webhooks”create_webhook makes the engine send row changes in batches to a web address (URL), as POST requests. The engine signs each batch with a hash-based message authentication code (HMAC) of the body, in X-Datanotes-Signature. It retries until the receiver answers with a 2xx status. Only this answer returns the secret: give it to the receiver so it can check the signature.
create_webhook
{ "url": "http://127.0.0.1:39785/datanotes-hook", "tables": ["film"] }Answer:
{ "id": "wh_bdde32fd8ee4", "url": "http://127.0.0.1:39785/datanotes-hook", "tables": ["film"], "enabled": true, "cursor": 14, "created_at": "2026-10-12T16:52:40.874Z", "failures": 0, "status": "ok", "secret": "<shown once>"}update_row
{ "table": "film", "path": "datanotes/main/public/film/His Girl Friday.md", "set": { "status": "watched" }}The receiver got this request:
{ "headers": { "x-datanotes-signature": "sha256=d0c9b0450dd3eaec5843de6883d0c16ad058985fa459cff136d0c5035a4ccc1e" }, "body": { "webhook": "wh_bdde32fd8ee4", "events": [ { "seq": 15, "at": "2026-10-12T16:52:40.883Z", "table": "main.public.film", "kind": "update", "op": "update_row", "path": "datanotes/main/public/film/His Girl Friday.md", "row_id": "01a13107-db21-7bf5-942a-c5107eb7fed3", "changes": { "status": { "before": "to watch", "after": "watched" } }, "source": "engine", "row": { "id": "01a13107-db21-7bf5-942a-c5107eb7fed3", "title": "His Girl Friday", "status": "watched" }, "actor": { "session": "history", "harness": "docs-example", "auth": "owner" }, "migration_id": "20261012T165240-update_row-update-film" } ], "last": 15 }}list_webhooks (no arguments)
Answer:
{ "webhooks": [ { "id": "wh_bdde32fd8ee4", "url": "http://127.0.0.1:39785/datanotes-hook", "tables": ["film"], "enabled": true, "cursor": 15, "created_at": "2026-10-12T16:52:40.874Z", "last_delivery": "2026-10-12T16:52:40.886Z", "failures": 0, "status": "ok" } ]}delete_webhook
{ "id": "wh_bdde32fd8ee4" }Answer:
{ "deleted": true }