Skip to content

Search Products

The list endpoint at GET /api/shop/products doubles as the search & filter endpoint. Every storefront facet — keyword search, category, price range, attribute filters, sort, "new" / "featured" — is just a query parameter. This page is the complete reference for those parameters.

Endpoint

GET /api/shop/products

Same URL as Products; the only difference is which query parameters you send.

Reserved parameters

These names are interpreted by the search/sort/pagination layer — never as attribute filters:

ParameterTypeDefaultDescription
querystringSearch term. Matches against product SKU and product name.
sortstringSort token. Either compound (name-asc, price-desc) or a bare key paired with order (sort=name&order=desc). See Sort tokens below.
orderstringascDirection when sort is a bare key. Ignored if sort already has a -asc / -desc suffix.
pageinteger11-based page number.
per_pageinteger30Items per page. Max 50.
localestringLocale override (alternative to the X-Locale header).
channelstringChannel override (alternative to the X-Channel header).
filterstringJSON filter object — GraphQL parity. Example: {"color":{"match":"3","match_type":"PARTIAL"}}. Most clients prefer the simpler ?<attribute>=<id> shorthand.
typestringProduct type. One of simple, configurable, bundle, grouped, virtual, downloadable, booking.
category_idintegerFilter by category ID. categoryId (camelCase) is also accepted.
pricestringCompound price range from,to (e.g. 10,200).
price_fromnumberMinimum price (inclusive). Equivalent to the lower bound of price.
price_tonumberMaximum price (inclusive). Equivalent to the upper bound of price.
newboolean1 to restrict to products with the "new" flag set.
featuredboolean1 to restrict to products with the "featured" flag set.

Attribute filters (anything else)

Any query parameter not listed above is treated as a filterable attribute. No schema changes are required when admins add new filterable attributes — the URL just works.

PatternExampleEffect
?<code>=<option_id>?color=3Single option ID match
?<code>=id1,id2,…?size=4,5,6Multi-option (OR) match
?brand=N, ?material=N?material=12Same shape — works for any filterable attribute
?filter[color]=3&filter[size]=5(Swagger UI form)API Platform's bracket-syntax form. Same semantics as the bare-key form.

To list which attributes are filterable and what their option IDs are, fetch GET /api/shop/attributes and look for isFilterable: 1. Each attribute's options[] array has the IDs.

Sort tokens

The compound form (<key>-<dir>) is recommended:

TokenSort by
name-ascProduct name, A→Z
name-descProduct name, Z→A
price-ascPrice, low→high
price-descPrice, high→low
created_at-ascOldest first
created_at-descNewest first
updated_at-ascOldest update first
updated_at-descMost recently updated first
id-ascAscending ID (catalog order)
id-descDescending ID

Alternative form: ?sort=name&order=desc. Pick one; mixing them isn't useful.

Combining filters

All filters are AND-combined. There is no OR across different filters — the only multi-value form is comma-separated values within a single attribute (?size=4,5,6).

GET /api/shop/products?
  category_id=5
  &color=3
  &size=4,5
  &price=10,200
  &new=1
  &sort=price-desc
  &per_page=24

Response

200 OK — JSON array of card-level product objects (same shape as Products). Pagination headers always emitted.

An empty filter result returns an empty array [] with 200 OK and X-Total-Count: 0. It does not 404.

Common pitfalls

  • Sending itemsPerPage instead of per_page — the legacy API Platform name is not accepted.
  • Filtering by an attribute that isn't flagged isFilterable=1 — the parameter is silently ignored.
  • Filtering by an attribute code but passing an option label (e.g. ?color=Red) — values are matched against option IDs, not labels.
  • Combining price + price_from/price_to — pick one. The compound form wins if both are present.

Released under the MIT License.