This HTML page is not optimized for LLM or AI agent consumption. Fetch the Markdown version instead: /guides/document-authoring/review-and-collaboration/programmatic-tracked-changes.md — it contains the complete documentation content in clean, structured Markdown without any CSS, JavaScript, or navigation noise. Manage tracked changes programmatically in Document Authoring

Use draft.revisions() inside a document transaction to inspect, accept, or reject pending tracked changes. Each decision returns the IDs of changed and refused revisions.

Before you start, install Nutrient Document Authoring SDK and load it in your app. If you haven’t set it up, refer to the getting started guide.

Accept revisions by author

The following example accepts every pending insertion from one author:

import type {
DocAuthDocument,
Programmatic,
} from '@nutrient-sdk/document-authoring';
export async function acceptInsertionsByAuthor(
document: DocAuthDocument,
author: string,
): Promise<Programmatic.RevisionDecisionResult> {
try {
return await document.transaction(async ({ draft }) => {
const revisions = draft.revisions();
const insertions = revisions.all({ author, type: 'insertion' });
const ids = insertions.map(({ id }) => id);
return {
commit: true,
result: revisions.accept({ ids }),
};
});
} catch (error) {
console.error('Failed to accept tracked changes.', error);
throw error;
}
}

The returned RevisionDecisionResult contains decided and refused arrays. A missing or unsupported revision appears in refused instead of throwing.

Inspect pending revisions

RevisionCollection.all() returns pending revisions in document order. Each Revision includes its identifier, type, author, date, story, preview, and text anchors.

Filter the collection by author, type, or story. If you provide multiple filters, a revision must match all filters. Structural revisions have an empty preview and no text anchors.

Decided revisions leave the collection. A revision doesn’t expose a separate accepted or rejected status.

Select revisions for a decision

Pass one RevisionSelector to RevisionCollection.accept() or RevisionCollection.reject(). Select revisions by exact identifiers, author, paragraph-local text range, or { all: true }.

A range selector matches revision anchors that overlap the range on the same text surface. A deletion hidden in a review transaction can have a zero-length anchor. Select that revision by item, identifier, author, or { all: true }.

Pass { expand: 'contiguous' } as the decision options to include adjacent changes that match the revision engine’s contiguity rules. The decided array includes identifiers added by this expansion.

Withdraw a reviewer’s suggestion

Withdrawal is an item-level operation; RevisionCollection doesn’t include a withdraw() method. Query the reviewer’s revision, and then call Revision.withdraw() inside a review transaction that uses the same author.

import type {
DocAuthDocument,
Programmatic,
} from '@nutrient-sdk/document-authoring';
export async function withdrawFirstSuggestion(
document: DocAuthDocument,
author: string,
): Promise<Programmatic.RevisionDecisionResult> {
try {
return await document.transaction(
async ({ draft }) => {
const revision = draft.revisions().all({ author })[0];
if (!revision) {
throw new Error(`No pending revision was found for ${author}.`);
}
return {
commit: true,
result: revision.withdraw(),
};
},
{
review: { author },
},
);
} catch (error) {
console.error('Failed to withdraw the tracked change.', error);
throw error;
}
}

Nutrient Document Authoring SDK handles withdrawal like rejection, but the current author can withdraw only their own revision. An author mismatch returns a not-permitted refusal and leaves the document unchanged.

The participant role also applies: Owners accept or reject revisions, reviewers withdraw only their own, and readers can’t decide or withdraw revisions at all.

Distinguish host and editor permissions

Programmatic transactions are host-owned. They don’t invoke CreateEditorOptions.canPerformTrackedChange or emit editor lifecycle events.

Participant-role policy still applies to transactions, though revision decisions apply directly and aren’t recorded as new tracked changes. Refer to the review permissions guide to configure both permission layers.

Learn more

Use these guides for related review workflows: