Skip to content

Reviews

Review state belongs to an exact version, not to the entry. Each version is draft until someone reviews it; the entry’s review_status shows the state of its current version, so pushing a new version resets the badge to draft and restoring an approved version brings approved back.

There are two ways to set it:

  • A direct decision with PUT /entries/{entry_id}/review.
  • A review request: one round in which up to 20 reviewers each respond. The version’s state is derived from their responses.
Method and path Scope Purpose
PUT /entries/{entry_id}/review write Set the state directly
POST /entries/{entry_id}/review-requests write Open a review round
GET /entries/{entry_id}/review-requests read An entry’s rounds
GET /review-requests read The review queue across entries
GET /review-requests/waiting-count read How many rounds wait on you
GET /review-requests/{request_id} read One round
POST /review-requests/{request_id}/respond write Respond as a reviewer
PATCH /review-requests/{request_id} write Add or remove reviewers
POST /review-requests/{request_id}/cancel write Cancel a round

Every review write names the version as object_id, which must be the entry’s current version. Otherwise it fails with 409 CONFLICT and details.current_object_id, so a review can never land on the wrong version. To review an older version, restore it first.

{ "state": "approved", "object_id": 1880, "assignee_id": 12, "note": "LODs look right" }
Field Type Description
state string, required draft, in_review, changes_requested or approved.
object_id integer, required The entry’s current version.
assignee_id integer or null Omit to keep the current assignee; null clears it. Not allowed with draft.
note string Up to 1,000 characters. Replaces the previous note (omitting it clears it). Not allowed with draft.

Response:

{
"entry_id": 412,
"object_id": 1880,
"review_status": "approved",
"review": {
"object_id": 1880,
"state": "approved",
"assignee": { "id": 12, "name": "<user>", "display_name": "Lee Lead" },
"decided_by": { "id": 7, "name": "<user>", "display_name": "Sam Rigger" },
"decided_at": "2026-07-25T12:00:00Z",
"note": "LODs look right",
"request_id": null
}
}

draft removes the review record (review: null). request_id is set when the record came from a review request.

Rules:

  • While a review has an assignee, only the assignee or an admin can change it (403 FORBIDDEN). Unassigned reviews are open to anyone.
  • While a review request is open on the version, only its requester or an admin can set the state directly, which closes the round as superseded. Anyone else gets 409 CONFLICT with details.open_request_id and should respond through the request.
  • Unknown assignee: 404 USER_NOT_FOUND. Disabled assignee: 422.
{ "object_id": 1880, "reviewer_ids": [12, 15], "note": "First pass please, @lee", "attachment_ids": [301] }
Field Type Description
object_id integer, required The entry’s current version.
reviewer_ids array, required 1 to 20 distinct library user ids (see Members). Must be active people, not API-only identities.
note string Up to 1,000 characters. @name mentions notify those people.
attachment_ids array Up to 10 of your own uploaded attachments.

Returns 201 with {"request": <request>}. The version goes to in_review immediately. Only one round can be open per version (409 CONFLICT with details.open_request_id); opening a round on the current version closes rounds still open on older versions. Each reviewer gets a notification.

Write endpoints return it wrapped as {"request": {...}}.

{
"id": 3,
"entry_id": 412,
"object_id": 1880,
"lineage_id": "guid:6F9619FF8B86D011B42D00C04FC964FF",
"status": "open",
"requested_by": { "id": 7, "name": "<user>", "display_name": "Sam Rigger" },
"note": "First pass please, @lee",
"attachments": [{ "id": 301, "width": 1920, "height": 1080, "size": 402113, "has_strokes": true }],
"mentions": [{ "id": 12, "name": "<user>", "display_name": "Lee Lead" }],
"created_at": "2026-07-25T12:00:00Z",
"closed_at": null,
"closed_by": null,
"reviewers": [
{
"user": { "id": 12, "name": "<user>", "display_name": "Lee Lead" },
"response": "pending",
"note": null,
"attachments": [],
"mentions": [],
"assign_to": null,
"responded_at": null
}
]
}

status is open, completed (everyone approved), cancelled or superseded (a newer round, or a direct decision). The version’s state follows the responses: any changes_requested wins, all approved completes the round, anything else is in_review.

Endpoint Parameters Response
GET /entries/{entry_id}/review-requests status (optional) {"requests": [request]}, newest first
GET /review-requests/{request_id} {"request": request, "entry": entry}
GET /review-requests view, status, cursor, limit {"requests": [request with an extra entry field], "next_cursor"}
GET /review-requests/waiting-count {"waiting": 2}

view for the queue is waiting_on_me (open rounds where your response is pending), requested_by_me, or all (default). The queue uses an id cursor: pass next_cursor back as cursor; null means the end.

Queue rows and the single-request read include entry: {id, name, entry_type, asset_class, status, has_thumbnail, preview_status, preview_kind, review_status, face_object_id, date_updated}. When face_object_id differs from the round’s object_id, the round reviews an older version.

POST /review-requests/{request_id}/respond

Section titled “POST /review-requests/{request_id}/respond”
{ "response": "changes_requested", "note": "Pivot is off; see markup", "assign_to": 7, "attachment_ids": [302] }
Field Type Description
response string, required approved or changes_requested.
note string Up to 1,000 characters, with @name mentions.
assign_to integer Only with changes_requested: who should make the fix (defaults to the requester). 422 with approved.
attachment_ids array Up to 10. Replaces the attachments on your previous response.

Only listed reviewers can respond (403 FORBIDDEN, including admins who are not listed). You can respond again while the round is open; the new response replaces the old one. Closed rounds return 409. Returns {"request": <request>}.

{ "add_reviewer_ids": [18], "remove_reviewer_ids": [15] }

Requester or admin, open rounds only. Up to 20 ids per list. The reviewer list can never become empty (422). Returns {"request": <request>}.

No body. Requester or admin, open rounds only. If nobody has responded yet, the version goes back to draft; otherwise its derived state stays as it is. Returns {"request": <request>}.

Unknown request ids return 404 REVIEW_REQUEST_NOT_FOUND.

Review changes appear in the activity feed as review.change, review.request, review.response and review.cancel, in the catalog change feed as entity review, and can be sent to webhooks.