Skip to content

Sorting

How to sort and filter list endpoints. The mechanics are the same across every Shop list, so endpoint pages don't repeat them.

Sorting

REST

Two accepted forms — compound token or split params:

GET /api/shop/products?sort=name-asc
GET /api/shop/products?sort=name&order=desc
Sort fieldToken examples
namename-asc, name-desc
priceprice-asc, price-desc
created_atcreated_at-asc, created_at-desc
updated_atupdated_at-asc, updated_at-desc
idid-asc, id-desc

String sorts are case-insensitive.

Example — cheapest first:

bash
curl -X GET "https://your-domain.com/api/shop/products?sort=price-asc&per_page=2" \
  -H "X-STOREFRONT-KEY: pk_storefront_xxxxxxxxxxxxx"
json
[
  { "id": 7, "sku": "BASICTEE", "name": "Basic Tee", "price": "12.00" },
  { "id": 3, "sku": "CANVASCAP", "name": "Canvas Cap", "price": "15.00" }
]

GraphQL

graphql
query {
  products(sortKey: PRICE, reverse: false, first: 2) {
    edges {
      node {
        id
        name
      }
    }
  }
}
json
{
  "data": {
    "products": {
      "edges": [
        { "node": { "id": "/api/shop/products/7", "name": "Basic Tee" } },
        { "node": { "id": "/api/shop/products/3", "name": "Canvas Cap" } }
      ]
    }
  }
}

sortKey is the field in upper-case (NAME, PRICE, CREATED_AT, UPDATED_AT, ID); reverse: true = descending. So REST ?sort=price-desc ≡ GraphQL sortKey: PRICE, reverse: true.

Filtering (products)

REST — query-string params

GET /api/shop/products?type=configurable&category_id=2&price=10,200&new=1
FilterParam
Search termquery
Typetype (simple / configurable / …)
Categorycategory_id
Price rangeprice=<from>,<to> — or price_from + price_to
New / Featurednew=1 / featured=1
Attribute (e.g. colour, size)color=<optionId>, size=<optionId> — any filterable attribute code

Multiple filters combine with AND. Any query-string key that isn't a reserved one (query, sort, order, page, per_page, locale, channel, filter) is treated as an attribute filter.

GraphQL — a JSON filter string

The same filters go into a single JSON-encoded filter argument:

graphql
products(filter: "{\"type\":\"configurable\",\"category_id\":2,\"price\":\"10,200\",\"new\":1}") {
  edges {
    node {
      id
      name
    }
  }
}

This is the one shape that does not carry over literally between transports — REST spreads filters across query params, GraphQL packs them into the filter string.

Category children — a common trip-up

REST fetches a category's children with ?parent_id=<id>. GraphQL has no parentId argument on categories — children come from treeCategories(parentId: <id>). Sending the REST shape into the GraphQL categories field returns everything, not the children.

Released under the MIT License.