Stream the change feed
The change feed as server-sent events (text/event-stream), for dashboards and consoles: each event's event is its type, its data the event as GET /v1/changes shows it, and its id a feed cursor. A reconnecting client sends the last id as Last-Event-ID and carries on after it. Without a cursor the stream starts with events committed from now on. A comment line is sent every 15 s while it is quiet. The server ends a stream after a while (the client reconnects, and its access is checked again). Webhooks or the feed, not the stream, are for systems that must not miss an event.
- Scopes
events:read - Rate classstream
/v1/streamThe change feed as server-sent events (text/event-stream), for dashboards and consoles: each event's event is its type, its data the event as GET /v1/changes shows it, and its id a feed cursor. A reconnecting client sends the last id as Last-Event-ID and carries on after it. Without a cursor the stream starts with events committed from now on. A comment line is sent every 15 s while it is quiet. The server ends a stream after a while (the client reconnects, and its access is checked again). Webhooks or the feed, not the stream, are for systems that must not miss an event.
Authorization
apiKey An API key (fo_live_… / fo_test_…) as a bearer token
In: header
Query Parameters
Start after this feed cursor (a page's cursor, or the id of a stream event); omit it to start with events committed from now on
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 <= 1500thin (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
text/event-stream
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/stream"{ "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" }}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.
Start an export POST
Queues an export in the caller's mode, written as gzip JSON Lines. `products`: the catalogue the caller can see, one product per line as `GET /v1/products` returns it; needs `products:read` beside `exports:write` and the plan's bulk exports (403 `feature_unavailable`), and exported products count against the `export_rows` quota (429 `quota_exceeded`). `organisation`: everything the organisation holds, one file per dataset, each line as its API read returns it, closed by a manifest; needs every dataset's read permission (403 `insufficient_scope`), takes no filters (422), and is neither plan-gated nor metered. Follow it with `GET /v1/exports/{id}` or the `export.completed` event. An organisation may have at most 3 open (`pending` or `running`) exports per mode, test and live counted apart; one more answers 409 `conflict`.