Planned.
/v1/changes is specified here so you can design against it;
it returns 404 until launch. Availability requires the incremental
feature (Builder and Commercial). Follow the
changelog for the release date.This is not
/v1/updates. /v1/updates returns recently added
models within a 1–30 day lookback, has no cursor, and does not report
score, ranking, pricing, or removal changes. Keep using it for a “what’s new”
list; use /v1/changes for synchronization.Sync model
1
Seed from a snapshot
Import the latest snapshot and keep its
change_cursor.2
Pull changes
Call
GET /v1/changes?cursor=<saved> and apply every event in order.3
Advance the cursor
Persist
next_cursor only after the page is applied. Repeat while has_more is true.4
Repeat on a schedule
The feed has daily granularity, so a daily job is enough. Each page costs one data response.
Endpoint
Response
integer
required
Monotonically increasing sequence number across the whole feed. The cursor is the base64url encoding of the last
seq you applied.date
required
UTC day the change was published. The feed has daily granularity: several changes to one entity on the same day are collapsed into one event carrying the end-of-day state.
string
required
model, score, ranking, or pricing.string
required
Stable identifier for the record. Composite for
score (model_id:benchmark_id), ranking (model_id:category), and pricing (model_id:provider).string
required
upsert or delete. There is no separate create: the first upsert for an entity_id is a create.object | null
required
Full current record for
upsert, using the same fields as the corresponding snapshot dataset. null for delete (a tombstone).string
required
Pass as
cursor on the next call. Present even when has_more is false, so you can resume later.boolean
required
true when more events exist after this page. Keep paging until false.date
required
Earliest day still in the feed. Cursors before it are expired.
Guarantees
Retention and cursor expiry
Events are retained for 13 months. If you pass a cursor older thanretained_from, the API returns 410 with error.code: "cursor_expired". Recover by re-importing the latest snapshot and continuing from its change_cursor. A daily or weekly sync will never hit this; it exists to protect against jobs that were paused for a year.
Omitting cursor starts from retained_from. That is 13 months of events — fine for a one-off, but a snapshot is cheaper for the initial load.
Schema changes
Eventdata follows the snapshot schema_version in effect on occurred_on. Minor versions add optional fields; ignore unknown keys. Major versions are announced in the changelog 30 days ahead, and the feed emits a synthetic upsert for every affected entity on the cutover day so that consumers on the new schema converge without a resync.
Filtering and quota
entity_type reduces the volume you pull but does not change cursors: seq values are global, so you can switch filters between calls without losing position. Each page is one data response regardless of limit, so always request limit=1000.
Full resynchronization
Resync from a snapshot when:- You receive
cursor_expired. - Your local checksums disagree with the manifest for a dataset you rebuilt.
- A major
schema_versionbump changes fields you cannot migrate in place.