List products
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.
- Scopes
products:read - Rate classread
/v1/productsProducts 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.
Authorization
apiKey An API key (fo_live_… / fo_test_…) as a bearer token
In: header
Query Parameters
Only products that changed at or after this time, their variants and offers included (UTC)
^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d:[0-5]\d(?:\.\d+)?(?:Z))$date-timeOnly products with this lifecycle status
Value in
- "active"
- "probably_discontinued"
- "discontinued"
Only products of this brand, ignoring case and spacing
1 <= length <= 200Only products filed under this category or below it
^ctg_[0-9A-Za-z]{22}$Only products with at least one offer of this availability
Value in
- "in_stock"
- "low_stock"
- "out_of_stock"
- "backorder"
- "preorder"
- "discontinued"
- "unknown"
Only products in this catalogue (the organisation's own, or a licensed one); a catalogue it cannot see lists nothing
^cat_[0-9A-Za-z]{22}$Only products this source feeds or fed: one of its records is grouped into the product, or it states one of the product's offers. A record is never deleted for going missing, so the products it stopped listing stay in the list with their lifecycle status (narrow with status)
^src_[0-9A-Za-z]{22}$Search: products whose title or brand holds every word (ignoring case; at most 8 words), or with a variant whose SKU or MPN is this text (ignoring case and punctuation)
2 <= length <= 100Page size
1 <= value <= 10020Opaque position returned by a previous page
^[A-Za-z0-9_-]{1,512}$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/products"{ "object": "list", "data": [ { "object": "product", "id": "string", "catalogue": "string", "status": "active", "version": 1, "data": { "title": "string", "brand": "string", "collection": "string", "description": "string", "category_path": [ "string" ], "category": "string", "tags": [ "string" ], "gpc_brick": "string", "features": [ "string" ], "compliance": { "tsca_title_vi": true, "sturdy_act": true, "stability_rating": 0, "ca_tb117_2013": true, "prop65_warning": true, "prop65_chemicals": [ "string" ], "country_of_origin": "string" }, "media": [ { "url": "http://example.com", "role": "hero", "alt": "string", "position": 0, "id": "string", "stored_url": "http://example.com" } ] }, "variants": [ { "object": "variant", "id": "string", "status": "active", "version": 1, "data": { "sku": "string", "gtin": "string", "mpn": "string", "title": "string", "axes": { "property1": "string", "property2": "string" }, "colour": "string", "finish": "string", "materials": [ "string" ], "dimensions": { "width": { "hundredths_in": 0, "given": { "value": 0, "unit": "mm" } }, "depth": { "hundredths_in": 0, "given": { "value": 0, "unit": "mm" } }, "height": { "hundredths_in": 0, "given": { "value": 0, "unit": "mm" } }, "diameter": { "hundredths_in": 0, "given": { "value": 0, "unit": "mm" } }, "seat_height": { "hundredths_in": 0, "given": { "value": 0, "unit": "mm" } }, "seat_depth": { "hundredths_in": 0, "given": { "value": 0, "unit": "mm" } }, "arm_height": { "hundredths_in": 0, "given": { "value": 0, "unit": "mm" } }, "clearance": { "hundredths_in": 0, "given": { "value": 0, "unit": "mm" } } }, "weight": { "hundredths_lb": 0, "given": { "value": 0, "unit": "g" } }, "components": [ { "name": "string", "sku": "string", "quantity": 1, "dimensions": { "width": { "hundredths_in": 0, "given": { "value": 0, "unit": "mm" } }, "depth": { "hundredths_in": 0, "given": { "value": 0, "unit": "mm" } }, "height": { "hundredths_in": 0, "given": { "value": 0, "unit": "mm" } }, "diameter": { "hundredths_in": 0, "given": { "value": 0, "unit": "mm" } }, "seat_height": { "hundredths_in": 0, "given": { "value": 0, "unit": "mm" } }, "seat_depth": { "hundredths_in": 0, "given": { "value": 0, "unit": "mm" } }, "arm_height": { "hundredths_in": 0, "given": { "value": 0, "unit": "mm" } }, "clearance": { "hundredths_in": 0, "given": { "value": 0, "unit": "mm" } } }, "weight": { "hundredths_lb": 0, "given": { "value": 0, "unit": "g" } } } ], "cartons": [ { "width": { "hundredths_in": 0, "given": { "value": 0, "unit": "mm" } }, "depth": { "hundredths_in": 0, "given": { "value": 0, "unit": "mm" } }, "height": { "hundredths_in": 0, "given": { "value": 0, "unit": "mm" } }, "weight": { "hundredths_lb": 0, "given": { "value": 0, "unit": "g" } }, "count": 1 } ], "assembly_required": true, "white_glove": true, "freight_class": "string", "rug": { "shape": "rectangle", "size_text": "string", "nominal": "string", "construction": "hand_knotted", "pile_height": { "hundredths_in": 0, "given": { "value": 0, "unit": "mm" } }, "indoor_outdoor": "indoor" }, "media": [ { "url": "http://example.com", "role": "hero", "alt": "string", "position": 0, "id": "string", "stored_url": "http://example.com" } ], "discontinued": true, "replacement_sku": "string" }, "offers": [ { "object": "offer", "id": "string", "source": "string", "location": "string", "currency": "usd", "cost": 0, "msrp": 0, "map": 0, "price": 0, "compare_at": 0, "quantity": 0, "incoming": [ { "quantity": 1, "eta": "2019-08-24" } ], "availability": "in_stock", "lead_time_days": 0, "version": 1, "observed_at": "2019-08-24T14:15:22Z", "withdrawn_at": "2019-08-24T14:15:22Z" } ], "updated_at": "2019-08-24T14:15:22Z" } ], "visibility": "listed", "created_at": "2019-08-24T14:15:22Z", "updated_at": "2019-08-24T14:15:22Z" } ], "has_more": true, "next_cursor": "string"}List offers GET
Every source's price and stock the organisation can see, newest first: filter by variant, product, source, availability or `updated_since`. Each offer shows only the fields its licences cover, as in `GET /v1/products`, and names its variant and catalogue; its product, title and SKU only where the licences show them.
Read the change feed GET
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`.