Products in a Collection (public)
PUBLIC endpoint — NO authentication required. Company is resolved from the request subdomain.
The products catalog scoped to one collection, not a second catalog:
the response body, filters, sorting, search, country-relative
pricing, and cursor pagination are identical to
GET /api/v202604/products. Returns ONLY live products (active +
resolved-published) with an active variant in the requested
country.
The collection in the path always wins — a filter[collection_ids] in the
query string cannot widen the listing beyond it. The collection itself
resolves like show — a draft, scheduled, or inactive collection still
lists its live products — so only an archived, deleted, or unknown
collection returns 404.
curl --request GET \
--url https://api.fluid.app/api/v202604/collections/{slug}/productsimport requests
url = "https://api.fluid.app/api/v202604/collections/{slug}/products"
response = requests.get(url)
print(response.text)const options = {method: 'GET'};
fetch('https://api.fluid.app/api/v202604/collections/{slug}/products', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.fluid.app/api/v202604/collections/{slug}/products",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://api.fluid.app/api/v202604/collections/{slug}/products"
req, _ := http.NewRequest("GET", url, nil)
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.get("https://api.fluid.app/api/v202604/collections/{slug}/products")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.fluid.app/api/v202604/collections/{slug}/products")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Get.new(url)
response = http.request(request)
puts response.read_body{
"status": 200,
"meta": {
"request_id": "7f3c9a1e-52d4-4b8e-9c61-2a8e4f0d7b35",
"timestamp": "2026-09-22T14:08:31Z",
"pagination": {
"cursor": null,
"limit": 25,
"prev_cursor": null,
"next_cursor": null
}
},
"products": [
{
"id": 48227,
"slug": "scranton-branch-mug",
"title": "Scranton Branch Mug",
"canonical_url": "https://shop.dundermifflin.com/home/products/scranton-branch-mug",
"images": {
"thumb": {
"url": "https://ik.imagekit.io/fluidapp/tr:w-200,c-at_max,f-auto,q-70/dunder-mifflin/products/scranton-branch-mug.png",
"width": 200
},
"medium": {
"url": "https://ik.imagekit.io/fluidapp/tr:w-600,c-at_max,f-auto,q-75/dunder-mifflin/products/scranton-branch-mug.png",
"width": 600
},
"large": {
"url": "https://ik.imagekit.io/fluidapp/tr:w-1200,c-at_max,f-auto,q-80/dunder-mifflin/products/scranton-branch-mug.png",
"width": 1200
}
},
"active": true,
"status": "published",
"publish_at": null,
"created_at": "2026-09-02T10:20:00Z",
"updated_at": "2026-09-10T16:45:21Z",
"metafields": [],
"languages": [
"en"
],
"sku": "DM-MUG-SCR",
"is_bundle": false,
"in_stock": true,
"has_subscription_plans": false,
"pricing": {
"price": "14.99",
"currency_code": "USD",
"compare_at": null,
"subscription_price": null,
"display_price": "$14.99"
},
"default_variant": {
"id": 97141,
"sku": "DM-MUG-SCR"
},
"skus": [
"DM-MUG-SCR"
]
},
{
"id": 48240,
"slug": "schrute-farms-beet-box",
"title": "Schrute Farms Beet Box",
"canonical_url": "https://shop.dundermifflin.com/home/products/schrute-farms-beet-box",
"images": {
"thumb": {
"url": "https://ik.imagekit.io/fluidapp/tr:w-200,c-at_max,f-auto,q-70/dunder-mifflin/products/schrute-farms-beet-box.png",
"width": 200
},
"medium": {
"url": "https://ik.imagekit.io/fluidapp/tr:w-600,c-at_max,f-auto,q-75/dunder-mifflin/products/schrute-farms-beet-box.png",
"width": 600
},
"large": {
"url": "https://ik.imagekit.io/fluidapp/tr:w-1200,c-at_max,f-auto,q-80/dunder-mifflin/products/schrute-farms-beet-box.png",
"width": 1200
}
},
"active": true,
"status": "published",
"publish_at": null,
"created_at": "2026-09-04T07:55:10Z",
"updated_at": "2026-09-18T11:03:47Z",
"metafields": [],
"languages": [
"en"
],
"sku": "SF-BEET-BOX",
"is_bundle": false,
"in_stock": true,
"has_subscription_plans": true,
"pricing": {
"price": "34.99",
"currency_code": "USD",
"compare_at": null,
"subscription_price": "29.99",
"display_price": "$34.99"
},
"default_variant": {
"id": 97166,
"sku": "SF-BEET-BOX-12"
},
"skus": [
"SF-BEET-BOX-12"
]
},
{
"id": 48255,
"slug": "pied-piper-box",
"title": "Pied Piper Compression Box",
"canonical_url": "https://shop.dundermifflin.com/home/products/pied-piper-box",
"images": {
"thumb": {
"url": "https://ik.imagekit.io/fluidapp/tr:w-200,c-at_max,f-auto,q-70/dunder-mifflin/products/pied-piper-box.png",
"width": 200
},
"medium": {
"url": "https://ik.imagekit.io/fluidapp/tr:w-600,c-at_max,f-auto,q-75/dunder-mifflin/products/pied-piper-box.png",
"width": 600
},
"large": {
"url": "https://ik.imagekit.io/fluidapp/tr:w-1200,c-at_max,f-auto,q-80/dunder-mifflin/products/pied-piper-box.png",
"width": 1200
}
},
"active": true,
"status": "published",
"publish_at": null,
"created_at": "2026-09-07T18:12:04Z",
"updated_at": "2026-09-19T09:27:36Z",
"metafields": [],
"languages": [
"en"
],
"sku": "PP-BOX-01",
"is_bundle": false,
"in_stock": true,
"has_subscription_plans": false,
"pricing": {
"price": "299.00",
"currency_code": "USD",
"compare_at": "349.00",
"subscription_price": null,
"display_price": "$299.00"
},
"default_variant": {
"id": 97190,
"sku": "PP-BOX-01"
},
"skus": [
"PP-BOX-01"
]
}
]
}{
"error": {
"message": "<string>",
"details": {}
},
"status": 123,
"meta": {
"request_id": "<string>",
"timestamp": "2023-11-07T05:31:56Z",
"pagination": {
"cursor": "<string>",
"limit": 25,
"prev_cursor": "<string>",
"next_cursor": "<string>"
}
}
}{
"error": {
"message": "<string>",
"details": {}
},
"status": 123,
"meta": {
"request_id": "<string>",
"timestamp": "2023-11-07T05:31:56Z",
"pagination": {
"cursor": "<string>",
"limit": 25,
"prev_cursor": "<string>",
"next_cursor": "<string>"
}
}
}Path Parameters
The collection's slug, as returned in its slug field.
Query Parameters
Response locale. ISO code (e.g. fr, de). When omitted,
responds in the company's default locale. On reads an
unsupported or unknown locale is ignored — the response comes
back in the default locale, never a 422. Any translated field
with no value in the requested locale falls back to its en
value.
"fr"
ISO-2 country code that selects COUNTRY-RELATIVE Product pricing.
Product-only — Categories and other storefront resources use
filter[country] as an access-list visibility filter instead.
For Products, country drives the pricing block and each
variant's variant_countries: it picks which per-country variant
price and currency are rendered. On the catalog it also drops
products with no active variant in the requested country. When
omitted, falls back to the company's default country.
"GB"
Free-text search over
translation-aware title and description fields, plus slug.
On /products it additionally matches the product-level sku and
every variant SKU.
On /products the match is TIERED: the term is matched first against
the fields that NAME a product — title in every locale, slug, sku
and every variant SKU — and description / metafields answer only when
no name match survives the other filters on the request. A bundle's copy
lists the products it contains, so matching name and copy in one pass
returned every pack that merely mentions a product ahead of the product
itself.
Substring-aware (word_middle), so partial terms match. Results are
returned in the requested sort order, not by relevance — search
resolves to an id set that the ordinary paginated query then filters,
and that id set is capped at 1000 matches per request.
Opaque cursor returned in meta.pagination.next_cursor (or
prev_cursor). Omit on the first page.
Page size. Default 25. Max 100. Requests above 100 return 422.
1 <= x <= 100Stock filter. in_stock restricts to purchasable products;
all (default) imposes no stock constraint.
all, in_stock true returns only bundle products; false returns only
non-bundle products.
true returns only products that have at least one active
subscription plan; false returns only products that have none.
Matches the has_subscription_plans field on each product in the
response exactly — a product whose only plan link is inactive, or
whose only plan has been deactivated, reads false and is
returned by false. Omit the parameter to apply no subscription
constraint.
Single sort key. Prefix with - for descending. Default
priority then id.
priority, -priority, title, -title, created_at, -created_at, updated_at, -updated_at Response
A page of live products in this collection, with country-relative pricing.
Shared success envelope for list / show / create / update
responses: the resource payload is returned alongside a top-level
integer status and meta. Composed onto each resource response
via allOf.
curl --request GET \
--url https://api.fluid.app/api/v202604/collections/{slug}/productsimport requests
url = "https://api.fluid.app/api/v202604/collections/{slug}/products"
response = requests.get(url)
print(response.text)const options = {method: 'GET'};
fetch('https://api.fluid.app/api/v202604/collections/{slug}/products', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.fluid.app/api/v202604/collections/{slug}/products",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://api.fluid.app/api/v202604/collections/{slug}/products"
req, _ := http.NewRequest("GET", url, nil)
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.get("https://api.fluid.app/api/v202604/collections/{slug}/products")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.fluid.app/api/v202604/collections/{slug}/products")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Get.new(url)
response = http.request(request)
puts response.read_body{
"status": 200,
"meta": {
"request_id": "7f3c9a1e-52d4-4b8e-9c61-2a8e4f0d7b35",
"timestamp": "2026-09-22T14:08:31Z",
"pagination": {
"cursor": null,
"limit": 25,
"prev_cursor": null,
"next_cursor": null
}
},
"products": [
{
"id": 48227,
"slug": "scranton-branch-mug",
"title": "Scranton Branch Mug",
"canonical_url": "https://shop.dundermifflin.com/home/products/scranton-branch-mug",
"images": {
"thumb": {
"url": "https://ik.imagekit.io/fluidapp/tr:w-200,c-at_max,f-auto,q-70/dunder-mifflin/products/scranton-branch-mug.png",
"width": 200
},
"medium": {
"url": "https://ik.imagekit.io/fluidapp/tr:w-600,c-at_max,f-auto,q-75/dunder-mifflin/products/scranton-branch-mug.png",
"width": 600
},
"large": {
"url": "https://ik.imagekit.io/fluidapp/tr:w-1200,c-at_max,f-auto,q-80/dunder-mifflin/products/scranton-branch-mug.png",
"width": 1200
}
},
"active": true,
"status": "published",
"publish_at": null,
"created_at": "2026-09-02T10:20:00Z",
"updated_at": "2026-09-10T16:45:21Z",
"metafields": [],
"languages": [
"en"
],
"sku": "DM-MUG-SCR",
"is_bundle": false,
"in_stock": true,
"has_subscription_plans": false,
"pricing": {
"price": "14.99",
"currency_code": "USD",
"compare_at": null,
"subscription_price": null,
"display_price": "$14.99"
},
"default_variant": {
"id": 97141,
"sku": "DM-MUG-SCR"
},
"skus": [
"DM-MUG-SCR"
]
},
{
"id": 48240,
"slug": "schrute-farms-beet-box",
"title": "Schrute Farms Beet Box",
"canonical_url": "https://shop.dundermifflin.com/home/products/schrute-farms-beet-box",
"images": {
"thumb": {
"url": "https://ik.imagekit.io/fluidapp/tr:w-200,c-at_max,f-auto,q-70/dunder-mifflin/products/schrute-farms-beet-box.png",
"width": 200
},
"medium": {
"url": "https://ik.imagekit.io/fluidapp/tr:w-600,c-at_max,f-auto,q-75/dunder-mifflin/products/schrute-farms-beet-box.png",
"width": 600
},
"large": {
"url": "https://ik.imagekit.io/fluidapp/tr:w-1200,c-at_max,f-auto,q-80/dunder-mifflin/products/schrute-farms-beet-box.png",
"width": 1200
}
},
"active": true,
"status": "published",
"publish_at": null,
"created_at": "2026-09-04T07:55:10Z",
"updated_at": "2026-09-18T11:03:47Z",
"metafields": [],
"languages": [
"en"
],
"sku": "SF-BEET-BOX",
"is_bundle": false,
"in_stock": true,
"has_subscription_plans": true,
"pricing": {
"price": "34.99",
"currency_code": "USD",
"compare_at": null,
"subscription_price": "29.99",
"display_price": "$34.99"
},
"default_variant": {
"id": 97166,
"sku": "SF-BEET-BOX-12"
},
"skus": [
"SF-BEET-BOX-12"
]
},
{
"id": 48255,
"slug": "pied-piper-box",
"title": "Pied Piper Compression Box",
"canonical_url": "https://shop.dundermifflin.com/home/products/pied-piper-box",
"images": {
"thumb": {
"url": "https://ik.imagekit.io/fluidapp/tr:w-200,c-at_max,f-auto,q-70/dunder-mifflin/products/pied-piper-box.png",
"width": 200
},
"medium": {
"url": "https://ik.imagekit.io/fluidapp/tr:w-600,c-at_max,f-auto,q-75/dunder-mifflin/products/pied-piper-box.png",
"width": 600
},
"large": {
"url": "https://ik.imagekit.io/fluidapp/tr:w-1200,c-at_max,f-auto,q-80/dunder-mifflin/products/pied-piper-box.png",
"width": 1200
}
},
"active": true,
"status": "published",
"publish_at": null,
"created_at": "2026-09-07T18:12:04Z",
"updated_at": "2026-09-19T09:27:36Z",
"metafields": [],
"languages": [
"en"
],
"sku": "PP-BOX-01",
"is_bundle": false,
"in_stock": true,
"has_subscription_plans": false,
"pricing": {
"price": "299.00",
"currency_code": "USD",
"compare_at": "349.00",
"subscription_price": null,
"display_price": "$299.00"
},
"default_variant": {
"id": 97190,
"sku": "PP-BOX-01"
},
"skus": [
"PP-BOX-01"
]
}
]
}{
"error": {
"message": "<string>",
"details": {}
},
"status": 123,
"meta": {
"request_id": "<string>",
"timestamp": "2023-11-07T05:31:56Z",
"pagination": {
"cursor": "<string>",
"limit": 25,
"prev_cursor": "<string>",
"next_cursor": "<string>"
}
}
}{
"error": {
"message": "<string>",
"details": {}
},
"status": 123,
"meta": {
"request_id": "<string>",
"timestamp": "2023-11-07T05:31:56Z",
"pagination": {
"cursor": "<string>",
"limit": 25,
"prev_cursor": "<string>",
"next_cursor": "<string>"
}
}
}