Competitor Tracker & Co. Docs

Detected changes

Read the changes Competitor Tracker & Co. detects on competitors you track: pricing, product and messaging, filtered per competitor, per snapshot or org-wide.

Whenever we ingest a fresh snapshot of a tracked page, an agent compares it to the most recent prior one and writes down anything meaningful that's different. The change endpoints expose those notes three ways: scoped to a single competitor, scoped to a single snapshot or as a unified org-wide feed.

Concepts

A change is a single short description (≤ 240 chars) of something that differs between two snapshots, classified into a category and assigned a priority.

A change run is one analysis pass against a snapshot. Every snapshot has at most one run, ending in one of these terminal states:

  • completed — analysis finished. Zero or more changes attributed to the snapshot.
  • skipped_no_diff — the new snapshot was byte-identical to the prior one. Nothing to read.
  • skipped_first_snapshot — no prior snapshot to diff against (first capture of the tracked page).
  • errored — the run failed. The response includes a phase and summary describing what went wrong.

Run states are durable. A skipped_no_diff run is how the API tells you "the pack checked at this time. Nothing moved."

Two ways we file a change

Every change carries two independent labels that answer different questions.

  • Category — the nature of what moved: pricing, product, messaging, corporate or geography. It rides on the change and shows up as category.
  • Page type — the kind of page the change was spotted on. It rides on the page rather than the change — you read it as pageType on a tracked page and on a snapshot's trackedPage.

Category is what moved. Page type is where we were looking. A pricing-category change can surface on a pricing page or, now and then, on the homepage — the two axes stay separate on purpose.

We read the page type from the page's URL, so treat it as a good first guess rather than gospel. The buckets:

  • pricing — plans, tiers and price points
  • product — capability and feature pages
  • marketing — use-case and customer-facing pitch pages
  • docs — help, reference and guides
  • changelog — release notes and what's-new timelines
  • integrations — marketplace and integration listings
  • security — trust and compliance pages
  • legal — terms, privacy and agreements
  • corporate — about, careers and press
  • updates — blog and news
  • homepage — the site's front door
  • other — anything the read can't place into a sharper bucket

Changes for one competitor

GET /v1/competitors/{id}/changes

A page of changes detected on the competitor across all its tracked pages, newest first. Returns 404 CompetitorNotFound when the org has no subscription, 403 CompetitorAccessRevoked when the subscription has been removed.

curl "$CT_API/competitors/01HF.../changes?limit=20" \
  -H "Authorization: Bearer $CT_TOKEN"

Changes for one snapshot

GET /v1/snapshots/{id}/changes

Changes attributed to a single snapshot. Useful paired with GET /v1/snapshots/{id} — the snapshot's signed URLs let you show the artifact alongside the diff. Same access rules as GET /v1/snapshots/{id}.

curl "$CT_API/snapshots/01HF.../changes" \
  -H "Authorization: Bearer $CT_TOKEN"

The org-wide feed

GET /v1/changes

Changes across every competitor your organization is actively tailing. Built for digest-style consumers. A daily or weekly job calls this with since=<lastRunISO> and processes the new items. One short report every Monday.

curl "$CT_API/changes?since=2026-05-01T00:00:00.000Z&limit=100" \
  -H "Authorization: Bearer $CT_TOKEN"

Filters

All three endpoints accept the same query parameters:

  • cursor — opaque cursor returned in nextCursor from a prior call. Stable under newest-first ordering by detectedAt, with id as a tiebreaker.
  • limit — 1–200, default 50.
  • category — repeat or comma-separate to filter (?category=pricing_changes&category=product_changes or ?category=pricing_changes,product_changes). Unknown ids match nothing.
  • priorityhigh, medium or low. Same multi-value shape as category.
  • since — ISO-8601 timestamp with offset. Excludes changes detected before that moment.

Response shape

{
  "items": [
    {
      "id": "01HF...",
      "competitorId": "01HF...",
      "snapshotId": "01HF...",
      "priorSnapshotId": "01HE...",
      "category": "pricing_changes",
      "priority": "high",
      "description": "Basic plan price increased from $9 to $12 per month.",
      "detectedAt": "2026-05-04T10:23:00.000Z",
      "createdAt": "2026-05-04T10:23:00.000Z"
    }
  ],
  "nextCursor": "eyJkIjoi..."
}

priorSnapshotId is null when the change was detected on the first analyzed snapshot for that page. Rare. Typically only on backfills.

Admin reanalyze

POST /v1/admin/snapshots/{id}/reanalyze

Force a fresh run against a snapshot. Use when the prior run errored or you want a re-read after the catalog was updated. The existing analysis is cleared and a new run is scheduled. The new results replace the old transactionally.

Authentication is via a static admin bearer token (separate from the user-level token):

curl -X POST "$CT_API/admin/snapshots/01HF.../reanalyze" \
  -H "Authorization: Bearer $CT_ADMIN_TOKEN"

Returns 202 Accepted with { "snapshotId": "...", "enqueued": true }. Returns 404 NotFound for an unknown snapshot id and — deliberately — for any caller whose admin token is missing or wrong, so the endpoint is indistinguishable from a non-existent path to unauthenticated probes. Reprocessing runs asynchronously. Poll GET /v1/snapshots/{id}/changes to watch the new result set land.

On this page