Skip to content

Selective compare

Compare a range of paragraphs in one document with a range in another, and get the result at once as JSON, Markdown and a PDF.

View as Markdown

POST /v1/compare/selective compares a range of paragraphs in one document with a range in another, or two ranges of the same document, such as one clause in two drafts. It answers in the same response with the comparison as JSON and Markdown, and stores it as a new PDF file. It makes no Word redline; to redline whole documents, use Compare.

Base URLhttps://api.versionstory.com
AuthAuthorization: Bearer vs_.... See Authentication

The flow

  1. Upload each document with POST /v1/files, or use the file_id of a file you have already uploaded.
  2. Pick the ranges. Read each file with GET /v1/files/{file_id}/content and note the index of the first and last paragraph of each range.
  3. Compare with POST /v1/compare/selective. The response carries the comparison and its PDF file.

POST /v1/compare/selective

application/json, with an original and a modified range. Each names its file and its first and last paragraph, either by index or by paragraph id; one side can use indexes while the other uses ids.

FieldRequiredMeaning
file_idYesThe file holding the range
start_paragraph_index, end_paragraph_indexOne pairThe range's first and last paragraph, as the file's content numbers them
start_paragraph_id, end_paragraph_idOne pairInstead of the indexes: the paragraphs' ids from the content's JSON
curl -sS https://api.versionstory.com/v1/compare/selective \
  -H "Authorization: Bearer vs_live_..." \
  -H "Content-Type: application/json" \
  -d '{
    "original": {"file_id": "3f2a9c1e-...", "start_paragraph_index": 12, "end_paragraph_index": 18},
    "modified": {"file_id": "8c41d7b2-...", "start_paragraph_index": 12, "end_paragraph_index": 19}
  }'

Ranges are inclusive and follow document order, including paragraphs inside tables. Each paragraph is read with its tracked changes accepted, and Word's list numbering is compared apart from the text. Paragraphs are lined up first, with identical paragraphs as anchors and the rest paired by how similar their words are, and then each pair is compared word by word.

{
  "comparison": {
    "schema_version": 1,
    "original": { "file_id": "3f2a9c1e-...", "file_name": "v1 NDA.docx", "paragraph_count": 7 },
    "modified": { "file_id": "8c41d7b2-...", "file_name": "v2 NDA.docx", "paragraph_count": 8 },
    "summary": { "unchanged": 5, "modified": 2, "inserted": 1, "deleted": 0 },
    "paragraphs": [
      {
        "status": "modified",
        "original_id": "...",
        "modified_id": "...",
        "original_number": "2.",
        "modified_number": "2.",
        "content": [
          { "text": "through no fault" },
          { "type": "insertion", "text": ", action, or omission" },
          { "text": " of the Recipient;" }
        ]
      }
    ]
  },
  "markdown": "...",
  "file": {
    "file_id": "b4056e05-...",
    "file_name": "Selective Compare - v1 NDA to v2 NDA.pdf",
    "status": "ready",
    "downloads": [
      {
        "format": "pdf",
        "url": "https://documents.versionstory.com/...",
        "file_name": "Selective Compare - v1 NDA to v2 NDA.pdf",
        "expires_at": "2026-10-19T19:30:00+00:00"
      }
    ]
  }
}
  • comparison.paragraphs lists the lined-up paragraphs in reading order. status is unchanged, modified, inserted (with only modified_id) or deleted (with only original_id). A content segment without type is unchanged text: skip the insertions to read the original, and the deletions to read the modified.
  • markdown is the same result with changes marked by <ins> and <del>, each paragraph opened by <p original-unid="..." modified-unid="..."/>.
  • file is a new file holding the same result as a PDF, the one the Selective Compare panel exports in the Version Story app: inserted text blue and underlined, deleted text red and struck through, each paragraph on its own line after its list number.

The PDF file

The PDF is written before the response is sent, so file is always ready. Its download URL is valid for one hour; GET /v1/files/{file_id} with its file_id mints a fresh one. It is served as pdf only, and it cannot be compared, edited or read as content. For an organization with zero-day retention, it is deleted an hour after it is made, or as soon as you call POST /v1/files/{file_id}/acknowledge.

Each request makes a new file, so send it once and keep the file_id. It counts toward your usage as a document with the words of the compared text; downloading its PDF, then or later, does not count again.

Errors

StatusCodeCause
400INVALID_REQUESTA range named both ways or neither, a start after its end, or a file without paragraphs to compare (a redline, a created document, another selective comparison's PDF)
400PARAGRAPH_NOT_FOUNDA paragraph index or id is not in its file
400RANGE_TOO_LARGEThe ranges are too large to compare in one request: more than 40,000 pairs of paragraphs between identical ones, or a comparison of more than 300,000 characters. Compare smaller ranges
400UNSUPPORTED_FILE_TYPEA workbook or presentation, which has no paragraphs
401INVALID_API_KEYMissing, malformed, unknown, revoked, or expired key
404DOCUMENT_NOT_FOUNDNo such file, or it belongs to another organization
409CONFLICTA file is still being prepared (retry after Retry-After), or its preparation failed (upload it again)
410CONTENT_DELETEDA file's content was deleted under zero-day retention
  • Compare: a Word redline of two whole documents
  • Files: upload documents and download the comparison's PDF again
  • Data handling: what is kept, and for how long