The CMS Compliance API lets apps request a compliance review of CMS content actions at the site or account level, and apply the review decision. Supported actions include publishing a new draft, publishing a changed or unchanged item, and unpublishing an item with or without pending edits.
With the CMS Compliance API, you can:
For each successful request, the service fetches the required CMS data item versions,
returns a ComplianceReviewRequest for every submitted item, and emits the same objects
in a domain event. Authorized consumers can subscribe to the event as a webhook and
process the requests in their own review workflow, then call back to approve or reject them.
The service is independent of the calling UI.
Call Request Review with the action, data item ID, and collection ID. For
UNPUBLISH_CHANGED, you can also specify which version should remain as the saved draft.
The action determines which CMS data item versions the service reads and returns:
PUBLISH_DRAFT: the proposed draft only, because nothing is live yet.PUBLISH_CHANGED: the current published version and proposed draft.PUBLISH_PUBLISHED: the same published item as both the current and proposed version.UNPUBLISH_PUBLISHED: the current published version only.UNPUBLISH_CHANGED: the current published version and proposed draft, plus the optional version the user wants to preserve as a draft.The currentDataItem is the version that's currently published. The proposedDataItem
is the version submitted for review. Comparing them shows whether the request introduces
a content change.
To submit several data items at once, call Bulk Request Review with a single
collectionId and a list of items. Each item carries the same action, dataItemId, and
versionOnUnpublish fields as a single request, and the actions within one call can differ
from each other. The service applies the matrix above to each item on its own, so a batch
that combines PUBLISH_DRAFT and PUBLISH_CHANGED returns one review request holding only
proposedDataItem and another holding both versions.
A batch is all-or-nothing. The service fetches the data item versions the whole batch needs together, in a single CMS query per collection version, so the outcome is shared by every item in the call: either all the review requests are built and emitted in one Bulk Review Requested event, or the call fails and nothing is emitted. There's no partial success, and no per-item error to inspect.
Once you've reviewed a request, call Bulk Approve Request Review
or Bulk Reject Request Review
with the published collection ID and the compliance review requests you received. Both endpoints take
a list, so you can settle several items in one call, and both record the decision in the data item's
requestReviewStatus field.
The requestReviewStatus field holds one of 3 values: PENDING, APPROVED, or REJECTED. Approving
sets it to APPROVED and rejecting sets it to REJECTED.
Approving applies each item's action to the content. PUBLISH_DRAFT and PUBLISH_CHANGED items are
published from their draft, PUBLISH_PUBLISHED items are already live so only their status is set, and
UNPUBLISH_PUBLISHED and UNPUBLISH_CHANGED items are unpublished. One call can mix publish and
unpublish items. Each UNPUBLISH_CHANGED item must specify its own versionOnUnpublish, which decides
whether the latest draft edits or the live published version is preserved as the saved draft.
Rejecting changes nothing but the status. Whatever an item's action is, its content stays exactly as it is: nothing is published and nothing is unpublished.
Both endpoints check that every item still exists before they change anything. If any item is missing,
the whole call fails with DATA_ITEMS_NOT_FOUND and no item is published, unpublished, or updated.
Past that check, the content and status updates resolve per item, the same way the underlying
Data Items API bulk methods
do, so individual items can fail while the rest succeed. Every result reports its outcomes in a
results array holding 1 entry per item, each with an itemMetadata object giving the item's id,
its originalIndex in the list you sent, whether it succeeded, and an error when it didn't,
alongside bulkActionMetadata with the success and failure totals:
publishResult and unpublishResult for the content changes, and
statusUpdateResults for the status.statusUpdateResults for the status.When approving, the status is set before publishing but after unpublishing. A PUBLISH_* item can
therefore end up APPROVED without having been published, while an UNPUBLISH_* item is set to
APPROVED only once it was unpublished. Read publishResult and unpublishResult, not the status,
to confirm what actually changed.
statusUpdateResults is a list because the status is set in one update per publishing direction, and
it holds one entry per update rather than one per item. Rejecting never publishes or unpublishes, so
it always returns a single entry. Approving returns a single entry too when every action in the batch
starts with PUBLISH, or every action starts with UNPUBLISH, and 2 entries when the batch mixes the
two, the first covering its PUBLISH_* items and the second its UNPUBLISH_* items. An unpublish
that failed isn't covered at all, so a mixed batch whose unpublishes all failed has a single entry.
Treat the entries as the items whose status was set, not as a list of everything you sent.
Both endpoints also return the review requests themselves, in the same shape as the submission
endpoints. Each one is rebuilt from the data items as they stand in CMS when the decision is made,
not from the copy you sent, so currentDataItem and proposedDataItem are always complete. One
consequence is that their requestReviewStatus is the value the items held before the call. To see
the status the call just wrote, read statusUpdateResults.
Each approval and rejection is also emitted as a webhook, carrying exactly what the call returns. Like the bulk submission event, these fire once per call rather than once per data item.
It's important to note the following points before starting to code:
versionOnUnpublish is used only for UNPUBLISH_CHANGED. When submitting a review request it can be omitted, and is ignored for every other action. When approving, each UNPUBLISH_CHANGED item must specify it, or the call fails with INVALID_VERSION_ON_UNPUBLISH.DATA_ITEMS_NOT_FOUND and nothing is emitted.DUPLICATE_ITEM_ID.prodCollectionId. To settle items from several collections, make a call per collection.PUBLISH_PUBLISHED, the same as the current version.UNPUBLISH_CHANGED, whether to preserve the latest draft edits or the live published version as the saved draft.requestReviewStatus field: PENDING, APPROVED, or REJECTED.APPROVED.REJECTED without changing its content.Last updated: 18 October 2026