Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.superdoc.dev/llms.txt

Use this file to discover all available pages before exploring further.

Diffing compares two DOCX files and produces a third document as a reviewable redline. The workflow uses Document Engine diff operations: diff.capture, diff.compare, and diff.apply. The examples below use the Node and Python SDKs because file-to-file comparison usually runs in backend automation, but the feature isn’t SDK-specific: the same operations are available through the Document API and CLI.

File-to-file workflow

You already have a base document, Doc1. A new document, Doc2, arrives later. You want to produce Doc3, which starts from Doc1 and contains all Doc2 changes as tracked changes. Use two sessions:
  1. Open Doc1 as the base session
  2. Open Doc2 as a temporary target session
  3. Capture a diff snapshot from the target session
  4. Compare the base session against that snapshot
  5. Apply the diff back onto the base session with changeMode: 'tracked'
  6. Save the base session to a new output path as Doc3
Tracked diff apply requires a user identity. Set user on the SDK client so tracked changes are attributed correctly.
If your app already has Doc1 open, keep using that session as the base session and only open the uploaded document as the temporary target session.

Node.js

import { SuperDocClient } from '@superdoc-dev/sdk';

const client = new SuperDocClient({
  user: { name: 'Review Bot', email: 'bot@example.com' },
});

const base = await client.open({
  sessionId: 'base',
  doc: './Doc1.docx',
});

const target = await client.open({
  sessionId: 'target',
  doc: './Doc2.docx',
});

const targetSnapshot = await target.diff.capture({});

await target.close({});

const diff = await base.diff.compare({
  targetSnapshot,
});

await base.diff.apply({
  diff,
  changeMode: 'tracked',
});

await base.save({
  out: './Doc3.docx',
  force: true,
});

await base.close({});

Python

import asyncio

from superdoc import AsyncSuperDocClient


async def main():
    async with AsyncSuperDocClient(
        user={"name": "Review Bot", "email": "bot@example.com"}
    ) as client:
        base = await client.open({
            "sessionId": "base",
            "doc": "./Doc1.docx",
        })

        target = await client.open({
            "sessionId": "target",
            "doc": "./Doc2.docx",
        })

        target_snapshot = await target.diff.capture({})

        await target.close({})

        diff = await base.diff.compare({
            "targetSnapshot": target_snapshot,
        })

        await base.diff.apply({
            "diff": diff,
            "changeMode": "tracked",
        })

        await base.save({
            "out": "./Doc3.docx",
            "force": True,
        })

        await base.close({})


asyncio.run(main())

What this produces

  • Doc3 is based on Doc1, not Doc2
  • Body edits from Doc2 are replayed onto Doc1 as tracked changes
  • Comments, styles, and numbering changes are replayed directly
  • The output stays as a reviewable redline until someone accepts or rejects the tracked changes

Current v1 limits

  • Header and footer content is not diffed in v1
  • The diff payload is opaque and intended for replay, not semantic inspection
  • diff.apply checks that the current base document fingerprint still matches the diff’s baseFingerprint
If the base document changes after diff.compare and before diff.apply, re-run the compare step against the current base document state.

See also