Activity and changes
Prophouse keeps two feeds. The activity feed is history for people: who pushed, reviewed, commented or checked out what. The catalog change feed is for software: a compact list of which records changed, for keeping a local copy of the library up to date. Both need only read scope.
| Method and path | Purpose |
|---|---|
GET /activity |
Activity feed, newest first |
GET /catalog/changes |
Change feed, oldest first |
GET /activity
Section titled “GET /activity”| Parameter | Type | Description |
|---|---|---|
entry_id |
integer | Only events for this entry. |
lineage_id |
string | Only events for this lineage. |
cursor |
integer | Id cursor: pass the previous next_cursor to get older events. |
limit |
integer | 1 to 200, default 50. |
{ "events": [ { "id": 90, "event_type": "push.commit", "actor": { "id": 7, "name": "<user>", "display_name": "Sam Rigger" }, "entry_id": 412, "lineage_id": "guid:6F9619FF8B86D011B42D00C04FC964FF", "object_id": 1880, "batch_key": "0f9a...", "count": 137, "payload": { "name": "SM_Barrel_Rusty", "asset_class": "StaticMesh" }, "created_at": "2026-07-25T12:00:00Z" } ], "next_cursor": 89}Events from one bulk action (a large push, a pull job) share a batch_key and are collapsed into one item with a count; the item carries the newest event’s references. A batch that straddles a page boundary is counted separately on each page. next_cursor: null means there is nothing older.
Event types
Section titled “Event types”| Type | Recorded when |
|---|---|
push.commit |
A push registered a new version. |
push.enrich |
A push filled in missing details on an existing version (payload.fields). |
entry.restore |
An older version was restored (payload.from_object_id, payload.to_object_id). |
lock.acquire, lock.release, lock.expire |
A check-out lock changed. |
review.change |
A version’s review state changed. |
review.request, review.response, review.cancel |
Review request activity. |
comment.create, comment.resolve |
A comment was posted, or a thread resolved or reopened (payload.resolved). |
annotation.create |
An annotation was drawn. |
download.pull |
An entry was downloaded or included in a pull job. |
previews.refresh_requested |
An admin asked for previews to be regenerated. |
The list may grow; ignore types you do not recognize. Events are kept for a year. The same events can be delivered to your systems as they happen with webhooks.
Catalog change feed
Section titled “Catalog change feed”GET /catalog/changes lists every change to entries, versions, locks and review state in order. A client that applies each page and remembers where it stopped can keep a mirror of the catalog current without re-listing it.
| Parameter | Type | Description |
|---|---|---|
cursor |
integer | The seq of the last change you applied. Default 0. |
limit |
integer | 1 to 1,000, default 200. |
{ "changes": [ { "seq": 41, "entity": "object", "entity_id": 1880, "lineage_id": "guid:6F96...64FF", "op": "upsert" }, { "seq": 42, "entity": "entry", "entity_id": 412, "lineage_id": "guid:6F96...64FF", "op": "upsert" }, { "seq": 43, "entity": "lock", "entity_id": 31, "lineage_id": "guid:6F96...64FF", "op": "upsert" } ], "next_cursor": 43, "reset": false}entity |
entity_id is |
Refresh with |
|---|---|---|
entry |
Entry id | GET /entries/{entry_id} (op: "delete" means it was deleted) |
object |
Version id | GET /lineages/{lineage_id} |
lock |
Lock id | GET /locks?lineage_id= |
review |
Version id | GET /entries/{entry_id} for the lineage’s entry (op: "delete" means back to draft) |
op is upsert or delete. Ignore entities you do not recognize.
Mirroring loop
Section titled “Mirroring loop”- On first run, request
cursor=0. If the response hasreset: true(the library has history older than the feed keeps), store itsnext_cursor, list the catalog withGET /entries(passinclude_deprecated=true), and continue from the stored cursor. Otherwise start applying changes. - Fetch a page, apply every change, then store
next_cursor. - Repeat until
changesis empty. Then poll again later from the stored cursor.
Within a page, repeated changes to the same record are collapsed to the latest one. Applying a change twice is harmless, so replaying after a crash is safe.
If reset is true later on, your cursor is older than the feed’s retention window (30 days): the response has no changes and its next_cursor is the current head. Store it, discard the mirror, list the catalog again with GET /entries, and continue from the stored cursor.
This is the efficient way to stay in sync. Polling the change feed every minute costs one small request, where re-listing the library costs one request per page.
