---
title: "Diff current scrape content against a previous snapshot"
method: POST
path: "/v1/change-tracking/diff"
tags: ["change-tracking"]
---

# Diff current scrape content against a previous snapshot

`POST /v1/change-tracking/diff`

## Request

- Base URL: `https://api.fastcrw.com`
- URL: `https://api.fastcrw.com/v1/change-tracking/diff`
- Auth: one of:
  - HTTP bearer
  - none

Stateless: opencore stores nothing — the caller supplies the `previous` snapshot. Accepts a single body or a `batch` array (presence of `batch` selects batch mode). The crawl-path workhorse for monitors.

## Request body

- ChangeTrackingDiffRequest: Single body (provide 'current') OR batch (provide 'batch'). Top-level modes/schema/prompt/contentType act as shared defaults in batch mode.
  - `batch` ChangeTrackingDiffItem[]
    - `url` string, uri
    - `current` object, required
      - `markdown` string
      - `json` object
    - `previous` ChangeTrackingSnapshot
      - `markdown` string: Present for gitDiff/mixed mode
      - `json` object: Present for json/mixed mode
      - `contentHash` string: Mode-aware hash; persist + supply on the next check
      - `capturedAt` string: Caller-stamped capture time, echoed untouched
    - `modes` string[]
    - `schema` object
    - `prompt` string
    - `contentType` string
    - `tag` string
  - `current` object
    - `markdown` string
    - `json` object
  - `previous` ChangeTrackingSnapshot
    - `markdown` string: Present for gitDiff/mixed mode
    - `json` object: Present for json/mixed mode
    - `contentHash` string: Mode-aware hash; persist + supply on the next check
    - `capturedAt` string: Caller-stamped capture time, echoed untouched
  - `modes` string[]
  - `schema` object
  - `prompt` string
  - `contentType` string

## Response `200`

Diff result (object for single, array for batch) wrapped in the standard envelope

- object
  - `success` boolean, required
  - `data` union, required
    - ChangeTrackingResult
      - `status` 'same' | 'changed', required: Per-page status. Set-level new/removed are computed by the caller's reconciler.
      - `firstObservation` boolean: True when no previous was supplied — caller maps to 'new'
      - `contentHash` string, required
      - `snapshot` ChangeTrackingSnapshot
        - `markdown` string: Present for gitDiff/mixed mode
        - `json` object: Present for json/mixed mode
        - `contentHash` string: Mode-aware hash; persist + supply on the next check
        - `capturedAt` string: Caller-stamped capture time, echoed untouched
      - `diff` ChangeDiff
        - `text` string: Unified markdown diff (gitDiff/mixed)
        - `json` object: Parse-diff AST (gitDiff-only) OR per-field path map {previous,current} (json/mixed)
      - `judgment` ChangeJudgment
        - `meaningful` boolean, required
        - `confidence` 'low' | 'medium' | 'high', required
        - `reason` string, required
        - `meaningfulChanges` object[]
          - `type` 'added' | 'removed' | 'changed'
          - `before` string
          - `after` string
          - `reason` string
      - `tag` string
      - `truncated` boolean
    - ChangeTrackingResult[]
      - `status` 'same' | 'changed', required: Per-page status. Set-level new/removed are computed by the caller's reconciler.
      - `firstObservation` boolean: True when no previous was supplied — caller maps to 'new'
      - `contentHash` string, required
      - `snapshot` ChangeTrackingSnapshot
        - `markdown` string: Present for gitDiff/mixed mode
        - `json` object: Present for json/mixed mode
        - `contentHash` string: Mode-aware hash; persist + supply on the next check
        - `capturedAt` string: Caller-stamped capture time, echoed untouched
      - `diff` ChangeDiff
        - `text` string: Unified markdown diff (gitDiff/mixed)
        - `json` object: Parse-diff AST (gitDiff-only) OR per-field path map {previous,current} (json/mixed)
      - `judgment` ChangeJudgment
        - `meaningful` boolean, required
        - `confidence` 'low' | 'medium' | 'high', required
        - `reason` string, required
        - `meaningfulChanges` object[]
          - `type` 'added' | 'removed' | 'changed'
          - `before` string
          - `after` string
          - `reason` string
      - `tag` string
      - `truncated` boolean

## Other responses

- `400`: Invalid request body
- `401`: Missing or invalid bearer token (hosted only)

---

[API](https://skmtc.dev/fastcrw/apis/crw-rest-api.md) · [All operations](https://skmtc.dev/fastcrw/apis/crw-rest-api/llms.txt) · [OpenAPI document](https://skmtc.dev/fastcrw/apis/crw-rest-api/revisions/9bc1842aa048?raw)
