FurniOpsDocs
API referenceChanges

Read the newest changes first

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.

  • Scopesevents:read
  • Rate classread
GET/v1/changes/recent

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.

Authorization

apiKey
AuthorizationBearer <token>

An API key (fo_live_… / fo_test_…) as a bearer token

In: header

Query Parameters

limit?integer

Events per page (1 to 100)

Range1 <= value <= 100
Default20
starting_after?string

The previous page's next_cursor, to read older events; omit it for the newest

Match^[A-Za-z0-9_-]{1,512}$
types?string

Comma-separated event types to keep (offer.changed,offer.created); all by default

Lengthlength <= 2000
catalogues?string

Comma-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

Lengthlength <= 1500

Header Parameters

FurniOps-Version?string

Dated API version; pinned per organisation on first use and overridable per request

Value in

  • "2026-10-01"
  • "2026-10-04"
FurniOps-Mode?string

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"
If-None-Match?string

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/recent"
{  "object": "list",  "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"      }    }  ],  "has_more": true,  "next_cursor": "string",  "cursor": "string"}