# JSON format

> The structured redline behind format=json: blocks, segments, and deterministic change positions.

Every comparison and merge can also be fetched as JSON — the same redline as the Word
document, shaped for code. Request it with `format=json` on
[`GET /v1/compare/{id}`](/developers/rest/compare) or
[`GET /v1/merge/{id}`](/developers/rest/merge) and download it like any other format.

Where the [markdown rendering](/developers/reference/redline-format) is for reading, this is
for programs: no markup to parse, no escaping rules, and every change located
deterministically — a change *is* an element of its paragraph's content list, so its position
is structural, never a text match or a character offset you have to keep in sync.

## The shape

Three levels, and only three:

- **`blocks`** — the document in order. Each block is a `paragraph`, `heading`, or `table`.
- **`content`** — a block's text as an ordered list of segments.
- **Segments** — a segment without a `type` is unchanged text; a segment with one is a change.

```json
{
  "schema_version": 1,
  "kind": "comparison",
  "blocks": [
    {
      "type": "paragraph",
      "id": "c38d5f0184dc41d79720a3f118526380",
      "content": [
        { "text": "… to protect the confidentiality of certain " },
        {
          "type": "insertion",
          "text": "valuable ",
          "id": "18",
          "author": "Dana Reyes",
          "revision": "v2.docx",
          "date": "2026-08-17T22:00:39Z"
        },
        { "text": "confidential information of the Company …" }
      ]
    }
  ]
}
```

Block `id`s are the document's own paragraph identifiers — stable across renderings of the
same comparison, so you can reference a paragraph and find it again.

## Reconstructing either version

The two sides of the comparison fall out of the segment list:

- **Base document** — concatenate everything except `insertion` segments.
- **Revised document** — concatenate everything except `deletion` segments (and skip
  table rows whose `change` is a deletion).

## Segment types

| `type` | Meaning |
| --- | --- |
| *(absent)* | Unchanged text |
| `insertion` | Text the revision added |
| `deletion` | Text the revision removed |
| `moved_from` / `moved_to` | The two halves of one relocation, tied by a shared integer `move_id` |
| `conflict` | Competing changes over the same span — merges only |

Every change carries `author`, `revision` (which document version introduced it), and `date`
(ISO 8601, UTC as `Z`). When several revisions made the identical change, `author` and
`revision` are comma-separated lists.

Every change also carries `id`: the tracked revision's own identifier in the source document.
Each change segment corresponds to exactly one of the document's revision records, and the
[markdown rendering](/developers/reference/redline-format) carries the same value in its `id`
attribute, so a change can be cross-referenced between the two renderings.

Changes nest: a revision that edits inside another revision's text carries a `content` list
instead of `text`, so both attributions survive.

```json
{
  "type": "insertion",
  "id": "21",
  "author": "counsel@firm.com",
  "date": "2026-08-17T22:00:39Z",
  "content": [
    { "text": "kept " },
    { "type": "deletion", "text": "then cut", "id": "22", "author": "legal@acme.com", "date": "2026-08-18T09:12:00Z" }
  ]
}
```

## Numbering and headings

A numbered paragraph carries the document's own numeral, verbatim, plus its outline level:

```json
{ "type": "paragraph", "number": "2.4(a)", "level": 2, "content": [ … ] }
```

A paragraph with a heading style becomes `{ "type": "heading", "level": 1, … }`.

## Tables

Tables nest rows and cells; each cell holds its own `blocks`, so cell content is read
exactly like the document body. A whole row that was inserted or deleted carries a `change`
on the row itself — one edit, not one per cell.

```json
{
  "type": "table",
  "id": "5b9331372a6c4dbb9c39d8f78d10f0f2",
  "rows": [
    {
      "id": "fa55704b8f4e4babb15335a5f2f81b8a",
      "change": { "type": "deletion", "id": "12", "author": "Dana Reyes", "revision": "v2.docx", "date": "2026-08-17T21:27:16Z" },
      "cells": [
        { "id": "895ba24a", "blocks": [ { "type": "paragraph", "content": [ { "type": "deletion", "text": "Products", "id": "13", "author": "Dana Reyes", "revision": "v2.docx", "date": "2026-08-17T21:27:16Z" } ] } ] }
      ]
    }
  ]
}
```

## Merge conflicts

When two revisions edit the same span, the competing changes are wrapped in a `conflict`
segment. Each `insertion` is one revision's proposed replacement; the `deletion` is the
original they each replaced, and its `revision` lists every revision that removed it.
Surface these to a person — don't resolve them automatically.

```json
{
  "type": "conflict",
  "id": 1,
  "content": [
    { "type": "deletion",  "text": "April 15 2023",    "id": "41", "author": "Version Story", "revision": "v3.docx, v2.docx", "date": "2026-08-17T22:07:00Z" },
    { "type": "insertion", "text": "[•]",              "id": "42", "author": "Version Story", "revision": "v2.docx",          "date": "2026-08-17T22:07:01Z" },
    { "type": "insertion", "text": "December 31 2022", "id": "43", "author": "Version Story", "revision": "v3.docx",          "date": "2026-08-17T22:07:00Z" }
  ]
}
```

## What it does not carry

Bold and italic are not represented — use the markdown rendering when formatting matters.
Content inside text boxes and footnotes is not included. Spreadsheet comparisons have no
JSON rendering. Comparisons generated before this format shipped report `json` as pending
until they are regenerated; the Word redline always carries the same change set.
