Skip to content

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
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.

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.

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.

  1. On first run, request cursor=0. If the response has reset: true (the library has history older than the feed keeps), store its next_cursor, list the catalog with GET /entries (pass include_deprecated=true), and continue from the stored cursor. Otherwise start applying changes.
  2. Fetch a page, apply every change, then store next_cursor.
  3. Repeat until changes is 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.