Query parameters
The list endpoint (GET /m/{project-key}/{resource-name}) accepts a fixed set of query
parameters. It always returns a bare JSON array — no wrapper object — with pagination metadata
riding in response headers instead: X-Total-Count, X-Page, X-Limit, and a Link header
(RFC 5988) carrying first/last/prev/next URLs.
Pagination
page (default 1) and limit (default 10, capped at 100 — a request for more just gets
100, it isn't rejected).
curl "https://mocklab.dev/m/demo7k2m9x/products?page=2&limit=20"Sorting
sort names a field; order is asc (default) or desc.
curl "https://mocklab.dev/m/demo7k2m9x/products?sort=price&order=desc"Sorting is stable — records with equal values on the sort field keep their relative order — and
numeric-aware even for a formatted field like price: sorting by price compares 48.19
correctly against 120.00, not as text.
Filtering
Any query parameter that isn't one of the reserved names above (page, limit, sort,
order, search) is treated as a filter on the field with that name. Plain field=value is an
exact match; four suffixes cover the rest:
| Parameter | Matches |
|---|---|
field=value | exact match |
field_ne=value | not equal |
field_gte=value | greater than or equal (numeric-aware) |
field_lte=value | less than or equal (numeric-aware) |
field_like=value | case-insensitive substring match |
curl "https://mocklab.dev/m/demo7k2m9x/products?inStock=true&price_gte=20&price_lte=100"_gte/_lte strip a currency symbol or other formatting before comparing, so price_gte=20
correctly matches a price field returning "$48.19" — you don't need to know the field's exact
formatting to filter on it numerically.
Search
search matches if any field's value contains the term, case-insensitively — a quick way to
find a record without knowing which field it's in.
curl "https://mocklab.dev/m/demo7k2m9x/products?search=vivid"Invalid parameters
page, limit, and order are the three parameters with a strict, checkable shape — page
and limit must be positive integers, order must be exactly asc or desc. Send something
else and the request never reaches your data: it fails fast with 422 Validation failed and a
body naming exactly which parameter was wrong. Everything else — sort, search, and every
filter — has no fixed vocabulary to validate against, so a typo there (a filter on a field name
that doesn't exist, for instance) isn't an error; it just matches nothing, since the server has
no way to distinguish "wrong field name" from "a field that legitimately has no matching rows."
Combining parameters
All of the above compose in one request — filter, search, sort, and paginate together:
const params = new URLSearchParams({
inStock: "true",
price_gte: "20",
sort: "price",
order: "asc",
page: "1",
limit: "20",
});
const response = await fetch(`https://mocklab.dev/m/demo7k2m9x/products?${params}`);
const products = await response.json();
const totalCount = response.headers.get("X-Total-Count");import { useQuery } from "@tanstack/react-query";
function InStockProducts({ page }) {
const { data: products } = useQuery({
queryKey: ["products", "in-stock", page],
queryFn: async () => {
const params = new URLSearchParams({
inStock: "true",
sort: "price",
order: "asc",
page: String(page),
limit: "20",
});
const res = await fetch(`https://mocklab.dev/m/demo7k2m9x/products?${params}`);
return res.json();
},
});
return (
<ul>
{products?.map((product) => (
<li key={product.id}>{product.title}</li>
))}
</ul>
);
}One limit worth knowing up front: filtering, searching, and sorting only run on resources with 10,000 records or fewer. Above that, only pagination works — see How generation works for why, and how the response tells you when it's happened.