Content review
Someone who cannot publish to the library directly submits their contribution for review instead: a document, a recording, or a proposed fix to a data-quality issue. A content review request is one such submission and its workflow state.
List review requests
Section titled “List review requests”GET /v1/content-review-requests
Cursor-paginated, newest first.
Query parameters
Section titled “Query parameters”| Parameter | Type | Notes |
|---|---|---|
status |
string | PENDING, APPROVED, REJECTED, CHANGES_REQUESTED, CANCELED, or SUPERSEDED. |
kind |
string | content, content-resolves-issue, or issue-only. |
resourceType |
string | document, video, audio, or guide. Applies to the content kinds only. |
submitterId |
string | Restrict to one submitter. Reviewers only; ignored for anyone else, who already sees only their own. |
mine |
boolean | true restricts the list to the token owner’s own submissions. For a reviewer, this narrows the organization-wide queue to their own; for everyone else it is already the case. |
cursor |
string | Pagination cursor from a previous response. |
limit |
number | 1–100. Default 50. |
Request
Section titled “Request”curl "https://api.mereon.ai/v1/content-review-requests?status=PENDING" \ -H "Authorization: Bearer $MEREON_TOKEN"Response
Section titled “Response”{ "data": [ { "id": "crr_5b19...", "requestType": "CREATE", "status": "PENDING", "kind": "content", "resourceType": "document", "contentId": null, "contentTitle": "Winter site access procedure", "resolvesIssueId": null, "resolvesIssueTitle": null, "submittedByUserId": "usr_44de...", "submitterName": "Carla Field", "reviewedByUserId": null, "reviewerName": null, "submitterNote": "Wrote this up after the gate freeze last January.", "reviewNote": null, "reviewedAt": null, "createdAt": "2026-08-02T09:14:00.000Z", "updatedAt": "2026-08-02T09:14:00.000Z", "url": "https://mereon.ai/admin/content-review/crr_5b19" } ], "nextCursor": null}| Field | Type | Notes |
|---|---|---|
requestType |
string | CREATE for new content, UPDATE for a revision of something existing. |
status |
string | One of the six values in the filter table above. A submission does not simply pass or fail: it can come back with changes requested, be cancelled by its submitter, or be superseded by a later submission. |
kind |
string | content is a plain submission, content-resolves-issue is content that also fixes an issue, and issue-only is a fix with no content attached. |
resourceType |
string | null | The content type for the content kinds. null for issue-only. |
contentId |
string | null | Set when the submission targets existing content. Resolve with /v1/content/{id}. |
resolvesIssueId |
string | null | The issue this fixes, when applicable. Resolve with /v1/issues/{id}. |
reviewNote |
string | null | The reviewer’s note, once reviewed. |
url |
string | The review request in the app, or the linked issue for issue-only. |
Get a review request
Section titled “Get a review request”GET /v1/content-review-requests/{id}
The same fields as a list entry.
Get what approving a request would change
Section titled “Get what approving a request would change”GET /v1/content-review-requests/{id}/ontology-plan
What approving the contribution would do to the knowledge base, before anyone decides: the topics and claims it would add, change or retire. Read it to judge a proposal by its effect and not only its wording.
state says whether there is a plan to read.
state |
Meaning |
|---|---|
not-requested |
No plan was ever asked for, as with a proposal older than this feature. |
working |
A plan was asked for and is not finished. Waiting will help. |
failed |
A plan was asked for and the attempt gave up. Waiting will not help. |
ready |
There is a plan. It may still propose no changes, which is a different answer from having no plan. |
Only ready carries a plan; otherwise plan is null. The plan has the same
shape as an announcement’s.
Access is the request’s own: a reviewer reads any request in the organization and everyone else only their own, and anything else answers 404. A request from another organization answers 404 too.
Decide a review
Section titled “Decide a review”These three routes decide a submission that is still pending. Each needs a token
granted the content-review:write scope, which owners and admins hold, and the
person behind the token must be allowed to review submissions. Both are checked
on every call. Each route allows 5 requests a minute and 30 an hour, counted on
its own.
Approving publishes the content or applies the issue fix. Rejecting a submission, or asking for changes, sends your note to the person who submitted it. The response is the request in the same shape as getting one.
A request that has already been decided answers 400. One from another organization answers 404. One decided by someone else while this call was in flight answers 409.
Approve
Section titled “Approve”POST /v1/content-review-requests/{id}/approve
Publishes the submission or applies the issue fix. Every field is optional, and an empty body is a valid approval.
Leaving retrainingIntent out stores none, so nobody is retrained. Ask when
people are already trained on the material. none retrains nobody,
full_retake has them redo the lesson, and changed_material teaches the part
that changed.
Leave visibility out to keep the audience already chosen. A held demo keeps
the audience recorded when it was uploaded, and naming a different one is
refused. everyone shares it with the organization, admins keeps it to
admins, and teams shares it with the teams in teamIds, which is required
for that choice.
Leave onStalePreview out to use rebuild. rebuild refuses the approval when
the knowledge base has moved since the preview was built, answers 409, and
prepares a new preview. extract-afresh approves and works those changes out
again.
curl -X POST "https://api.mereon.ai/v1/content-review-requests/crr_5b19.../approve" \ -H "Authorization: Bearer $MEREON_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "retrainingIntent": "none" }'| Field | Type | Notes |
|---|---|---|
reviewNote |
string | Optional. Plain text, up to 4,000 characters, stored with the decision. |
retrainingIntent |
string | Optional. none, full_retake, or changed_material. Leave it out and nobody is retrained. |
visibility |
string | Optional. everyone, teams, or admins. Leave it out to keep the existing audience. |
teamIds |
string[] | The teams when visibility is teams. Leave it out otherwise. |
forceIfBaseVersionChanged |
boolean | Optional. Approve when the submission was edited again after this review was opened. |
onStalePreview |
string | Optional. rebuild or extract-afresh. Leave it out to use rebuild. |
Reject
Section titled “Reject”POST /v1/content-review-requests/{id}/reject
Rejects the submission and sends reviewNote to the person who submitted it. A
first submission that is rejected releases its source, so it can be submitted
again as something new.
| Field | Type | Notes |
|---|---|---|
reviewNote |
string | Required. Plain text, up to 4,000 characters. What the submitter is told. |
Request changes
Section titled “Request changes”POST /v1/content-review-requests/{id}/request-changes
Asks the submitter to change the submission and sends reviewNote to them. The
submission stays out of the library.
| Field | Type | Notes |
|---|---|---|
reviewNote |
string | Required. Plain text, up to 4,000 characters. What the submitter should change. |