Read the change feed
The organisation's public events in commit order: catalogue changes in its own and its licensed catalogues (fields its licences do not cover are left out, and an event with nothing left is skipped) and its sources' health. Pass the page's cursor back to read on; caught_up says nothing committed is left. With wait, a read that finds nothing waits for the next event (long-poll). Events are kept 30 days (fewer when the plan's feed days are fewer): an older cursor answers 400, and the reader starts again from GET /v1/products. Too many waiting reads answer 429 (the organisation's) or 503 (the service's), with Retry-After.
- Scopes
events:read - Rate classread
/v1/changesThe organisation's public events in commit order: catalogue changes in its own and its licensed catalogues (fields its licences do not cover are left out, and an event with nothing left is skipped) and its sources' health. Pass the page's cursor back to read on; caught_up says nothing committed is left. With wait, a read that finds nothing waits for the next event (long-poll). Events are kept 30 days (fewer when the plan's feed days are fewer): an older cursor answers 400, and the reader starts again from GET /v1/products. Too many waiting reads answer 429 (the organisation's) or 503 (the service's), with Retry-After.
Authorization
apiKey An API key (fo_live_… / fo_test_…) as a bearer token
In: header
Query Parameters
Where the previous page ended (its cursor); omit it to read from the oldest retained event
1 <= length <= 512Comma-separated event types to keep (offer.changed,offer.created); all by default
length <= 2000Comma-separated catalogue IDs (1 to 50): only events whose catalogue is one of them (a source health event's is the catalogue the source feeds). All the caller can see by default. A catalogue the caller cannot see adds nothing
length <= 1500Events per page (1 to 1000)
1 <= value <= 1000100Seconds to wait, when nothing is left to read, for an event to commit (0 to 25): the page comes back as soon as one does, or empty and caught_up when the wait runs out. 0 (the default) answers at once
0 <= value <= 250thin (the default): each event's changed fields; fat: also object, the product, variant or offer as of the event's version
"thin"Value in
- "thin"
- "fat"
Header Parameters
Dated API version; pinned per organisation on first use and overridable per request
Value in
- "2026-10-01"
- "2026-10-04"
The data the request acts on: test is the organisation's sandbox. An OAuth token picks it (live by default); an API key's mode is fixed, and naming the other one is refused
Value in
- "live"
- "test"
ETag of a cached representation; a match returns 304
Response Body
application/json
application/problem+json
application/problem+json
application/problem+json
application/problem+json
application/problem+json
application/problem+json
application/problem+json
curl -X GET "https://example.com/v1/changes"{ "object": "change_page", "data": [ { "id": "string", "type": "source.degraded", "spec_version": "1.0", "source": "string", "subject": "string", "time": "2019-08-24T14:15:22Z", "tenant_id": "string", "version": 1, "schema_version": 1, "correlation_id": "string", "causation_id": "string", "livemode": true, "data": { "object": "source", "id": "string", "catalogue": "string", "name": "string", "kind": "api", "connector": "string", "config": { "url": "http://example.com", "platform": "shopify", "format": "csv", "currency": "usd", "decimal": "dot", "role": "supplier", "warehouse": "string", "price_code": "string", "inbound": { "senders": [ "string" ] } }, "schedule": { "interval_minutes": 15, "stock_interval_minutes": 15, "adaptive": true }, "status": "active", "status_reason": { "code": "fetch_refused", "message": "string" }, "licence_basis": "vendor_agreement", "first_party": true, "has_credentials": true, "freshness": { "catalogue": null, "stock": null }, "inbound_address": "[email protected]", "version": 1, "created_at": "2019-08-24T14:15:22Z", "updated_at": "2019-08-24T14:15:22Z" } } ], "cursor": "string", "caught_up": true}List products GET
Products the organisation can see, by ID. With `updated_since`, only those that changed since then (a variant or offer change counts): how a feed reader catches up after its cursor expired. `status`, `brand`, `category`, `availability` and `q` narrow the list further; every filter given must match.
Read the newest changes first GET
The change feed's events newest first, for a recent-changes view: the same events `GET /v1/changes` answers, as the caller's licences let it see them, in reverse commit order. Pass `next_cursor` back as `starting_after` for older ones; a page can hold fewer than `limit` events and still have more. The first page's `cursor` reads on forwards with `GET /v1/changes` or `GET /v1/stream` from just after its newest event. Only events the plan still keeps are listed.