Resource
Document changes
The archive's journal of recorded document and folder change events — owner-scoped, forward-only, never pruned. One endpoint, and the only partner read path on which a deletion is observable.
The endpoint reference below is kept in English in both language trees. It mirrors the API contract verbatim and there is no generator to rebuild it from, so a translated copy would drift from the API the first time an endpoint changes.
Endpoints
One endpoint. It is read-only; nothing on this page writes.
- GET
/document/changes— List recorded document and folder changes (cursor-paginated)
This endpoint can additionally answer the shared errors — 401, 403, 404 (unknown instance) and 500. They are documented once, under Errors and troubleshooting.
What the feed is
A page of this feed is a list of change events, not a list of documents. Each event says what the platform recorded when a change was saved: the operation, the field it concerned, who made it, when it was recorded, and the file names or folder paths on either side of it. Nothing on a page tells you what a document looks like now — read the document for that. Events come back in the order they were recorded, the journal is never pruned, and paging runs forward only.
That is what separates it from GET /document/timeline, and the reason both exist. The timeline is upsert-only and orders on the coalesced modified-or-created timestamp: it reports a document that appeared or was renamed, and says nothing whatsoever about one that was deleted. This feed records the deletion. It is the only read path in the Partner API on which a deletion is observable, and it is what stands behind a nightly change feed into a reporting warehouse.
A complete picture of the archive needs three sources, not one. Upserts come from the document timeline, deletions from this feed, and changes to placement, content and description from a periodic per-owner snapshot diff that you run yourself. Lists, paging and sync works that division through; the completeness limits under the endpoint below say which combined writes record a single event and which changes record nothing at all.
Ordering and resumption are one thing here. Pages come out in the sequence the events were recorded in, and you move forward by handing back the nextCursor the previous page gave you. changed is a reported timestamp, not a position: it is a wall-clock moment on some lanes and a caller-supplied creation time on others, so it is not monotonic with the order the feed pages on, and it is never a resumption watermark. Store the cursor, not the timestamp. limit accepts 1 to 1000 and is 100 when you leave it out.
# First page. entityType and entityId are required; limit is 1..1000, default 100.
curl "https://api.visena.example/acme/api/v1/en/document/changes?entityType=Company&entityId=bQ4wR8&limit=200" \
-H "Authorization: Bearer $TOKEN"
# Next page: hand back nextCursor from the previous response. Never "changed".
curl "https://api.visena.example/acme/api/v1/en/document/changes?entityType=Company&entityId=bQ4wR8&limit=200&cursor=$NEXT_CURSOR" \
-H "Authorization: Bearer $TOKEN"
# A response with no nextCursor is the end of the feed as it stands. Keep the
# last cursor you were given and re-issue it on the next poll.
The feed is owner-scoped, and delivery is at-least-once. entityType and entityId are required — there is no organisation-wide enumeration — so a poller keeps one cursor per owner it follows, and de-duplicates what it reads. A page that comes back without a nextCursor has reached the end of the feed as it stands: keep the last cursor you were handed and re-issue it on the next poll, which is how a nightly job picks up exactly where it stopped. Never treat the absence of an event from a page as proof that no change occurred.
Reading an event
operation says what happened, at the granularity the journal records: DOCUMENT_INSERT, DOCUMENT_UPDATE, DOCUMENT_DELETE, FOLDER_INSERT, FOLDER_UPDATE and FOLDER_DELETE. The two *_DELETE operations are the signal this feed exists for. changedField narrows it: FILE_NAME, FOLDER, FILE_CONTENT, FOLDER_NAME and FOLDER_PARENT are the values observed so far, the column constrains nothing, and an unrecognised value is to be treated as opaque rather than as a failure.
documentId is on a document event and absent from a folder one, so branch on operation rather than assuming the field is there. previousFolderPath and folderPath are folder names from root to leaf, and an empty array means the owner's root level. One event is recorded per placement, so several events carrying the same documentId for one logical change are expected: key your bookkeeping on the cursor, never on documentId.
List recorded document and folder changes (cursor-paginated)
GET /{instanceName}/api/v1/{locale}/document/changes
Owner-scoped feed of recorded document and folder change events — the only partner read path on which a hard deletion is observable. Ordered by recorded INSERTION sequence and paged forward-only: pass the opaque cursor from a previous page's nextCursor, or omit it for the first page. There is no backward cursor and no links.prev. entityType+entityId are REQUIRED — there is no org-wide enumeration. entityType accepts Company, Person, Project and Room (a document share room); Room is a READ owner of this feed ONLY and stays rejected with 400 on every other document operation. No total is available and none will be added: the journal carries no index beyond its primary key and is never pruned, so a count would be a sequential scan of an ever-growing table on every request.
Requires the platform read scope, enforced globally for every safe method; a bearer token that was not granted it is refused with 403 and no rows are disclosed.
Delivery is AT-LEAST-ONCE. A consumer MUST overlap its polling window and de-duplicate events, and MUST NOT treat the absence of an event from a page as proof that no change occurred. Resumption is by cursor only: the reported changed timestamp is NEVER a resumption watermark, because it is the wall-clock moment of the change on some lanes and a caller-supplied creation time on others, and is therefore not monotonic with the insertion order this feed pages on.
An entityId that does not resolve to an existing entity of the declared type is 422. For entityType=Room a room the calling credential's person neither owns nor is a recorded member of — and an expired room read by anyone but its owner — is the SAME 422 with the same message shape, deliberately indistinguishable from a nonexistent room so the feed cannot be used as an existence oracle for room ids.
Completeness limits, published rather than hidden. Only ONE change is recorded when several are saved together: a rename combined with a move or a content replacement records the rename only. Documents that are not archived into a folder record nothing at all, in any direction. Document description and MIME-type changes are never recorded. A folder rename or reparent records the folder change only, never any change to the documents it contains. A relocation records only the gaining owner's side. One event is recorded per PLACEMENT, so several events bearing the same documentId for one logical change are expected — consumers key on the cursor, not on documentId. entityType=Project is NARROWER than GET /document/timeline: the owner predicate is flat, so a change in a sub-project's, phase's or activity's folder does not appear in the parent project's feed — poll this endpoint once per sub-owner you know of for full coverage of a project tree.
Room-specific statements. A room's feed is COMPLETE under the flat owner predicate — a room needs no owner expansion, unlike a project. A documentId on a pointer placement denotes a document whose primary copy belongs to a different owner, because a room commonly holds pointers rather than copies. A rename or a content replacement of such a document reaches the room only as a secondary record of the change to that primary copy. A room's feed MUST be polled while the room still exists: the events recorded by the room's own deletion are no longer retrievable once the room is gone.
Parameters
| Parameter | In | Type | Description |
|---|---|---|---|
entityType required |
query | string, one of Company Person Project Room |
Owning entity type. |
entityId required |
query | string |
Masked id of the owning record. |
cursor |
query | string |
Opaque page cursor from the previous response's links.next; omit for the first page. |
limit |
query | integer |
Maximum items to return per page. |
Responses
| Status | Description |
|---|---|
| 200 | A page of change events with its next cursor and links. DocumentChangeCursorListResponse · application/json |
| 400 | Missing required entityType/entityId, unrecognised entityType, invalid or foreign cursor, limit below 1 or above 1000, or an id is not a valid id. |
| 403 | The bearer token was not granted the platform read scope. |
| 422 | The referenced entityId does not exist for the given entityType; for entityType=Room, also a room the calling identity is not entitled to, with the same message shape. |
Example
curl "https://api.visena.example/acme/api/v1/en/document/changes?entityType=Company&entityId=bQ4wR8" \
-H "Authorization: Bearer $TOKEN"
Object shapes
The response bodies used above, in the order they are first referenced.
DocumentChangeCursorListResponse
| Field | Type | Description |
|---|---|---|
items |
array of DocumentChangeDto | The change events on this page, in recorded insertion order. |
nextCursor |
string |
Opaque cursor for the next page; absent when the feed is exhausted. |
links |
DocumentListLinks |
DocumentChangeDto
The change events on this page, in recorded insertion order.
| Field | Type | Description |
|---|---|---|
operation |
string |
The recorded operation. |
changedField |
string |
Which field the change concerns. Open vocabulary — observed values are FILE_NAME, FOLDER, FILE_CONTENT, FOLDER_NAME and FOLDER_PARENT; treat an unknown value as opaque. |
changed |
string (date-time) |
When the change was recorded (UTC). Not the paging key — it is not monotonic with insertion order. |
changedBy |
string (masked id) |
|
documentId |
string (masked id) |
|
previousFileName |
string |
Previous file name, when the change recorded one. |
fileName |
string |
New file name, when the change recorded one. |
size |
object |
Blob size in bytes, when the change recorded one. |
previousFolderPath |
array of string |
Previous folder path, root to leaf, internal root sentinel removed; empty means root level. |
folderPath |
array of string |
New folder path, root to leaf, internal root sentinel removed; empty means root level. |
DocumentListLinks
RFC 8288 navigation links: self, and next when more events remain.
| Field | Type | Description |
|---|---|---|
self |
string |
URL of the current page. |
first |
string |
URL of the first page (offset endpoint). |
prev |
string |
URL of the previous page, if any. |
next |
string |
URL of the next page, if any. |
last |
string |
URL of the last page (offset endpoint). |