V1 and V2

V1 and V2 filtering and search

Search endpoints in V1 and V2 take their filters in a JSON request body, not in the query string. This page documents that body: how to write filter conditions, which operators exist, how to choose the attributes that come back, and how to filter products by their relationships.

Key points on this page:

  • Every search is a POST to a /search path, such as POST /api/v1/products/search.
  • The request body can carry filters, attributes, and pagination.
  • A search returns only ID and SKU unless you list the attributes you want in attributes.
  • Filter and attribute names use the label of the field, and custom attributes need the attributes. prefix.
  • Invalid fields, operators, or values return 422.

Search request body

A search body has three parts, and all of them are optional:

FieldTypeDescription
filtersarray of arraysThe conditions a record must meet. Omit to match everything.
attributesarray of stringsThe fields to return in each record.
paginationobjectThe page, page size, and sort order. See Pagination.

Product search also accepts relationship_filters, covered in Filter on relationships.

Write a filter

A filter is built from three layers. Each layer adds one level of logic:

LayerShapeLogic
Simple filterAn object with field, operator, and valueOne condition
Compound filterAn array of simple filtersEvery condition must be met (AND)
FilterAn array of compound filtersAny compound filter can be met (OR)

A simple filter has these fields:

FieldTypeRequiredDescription
fieldstringYesThe label of the field to test.
operatorstringYesThe test to run.
valuestring, array, or objectDepends on the operatorThe value to compare against. Unary operators take none.

The filters field is the outer array of compound filters. This example finds products modified in November 2018 (AND), or whose name attribute contains "unicorn" (OR):

{
  "filters": [
    [
      { "field": "modified", "operator": "gt", "value": "2018-11-01" },
      { "field": "modified", "operator": "lt", "value": "2018-11-30" }
    ],
    [
      { "field": "attributes.name", "operator": "like", "value": "unicorn" }
    ]
  ]
}

The inner arrays are the AND groups, and the outer array joins them with OR. To express AND only, send a single inner array. To express OR only, send one inner array per condition.

Operators

The operators below are common to all search endpoints. Not every operator is allowed on every field, and some fields add operators of their own. Call the matching /filters endpoint to see what each field accepts.

OperatorArityDescription
existsUnaryTrue when the field has a value.
!existsUnaryTrue when the field has no value.
eqBinaryTrue when the field equals the value. Text comparison ignores case.
!eqBinaryTrue when the field doesn't equal the value. Text comparison ignores case.
likeBinaryTrue when the field contains the supplied string.
inBinaryTrue when the field matches any value in the list. Multiselect and Dropdown attributes are case sensitive.
!inBinaryTrue when the field matches none of the values in the list. Multiselect and Dropdown attributes are case sensitive.
gtBinaryTrue when the field is greater than the value.
gteBinaryTrue when the field is greater than or equal to the value.
ltBinaryTrue when the field is less than the value.
lteBinaryTrue when the field is less than or equal to the value.
text_searchBinarySearches for the text across several fields. Pass the list of fields as field.

A unary operator takes no value. A binary operator needs one, and in and !in need a list.

Find available filters

Each searchable resource has a matching endpoint that lists its fields, the operators each field allows, and the exact key to use in requests.

ResourceEndpoint
ProductsGET /api/v1/filters/product
AssetsGET /api/v1/filters/asset
RelationshipsGET /api/v1/filters/relationships

Use the key value from these responses as the field in a filter or as an entry in attributes. The same endpoint gives you each custom attribute's name and label.

Choose which attributes come back

A search returns only the record's ID and SKU unless you ask for more. List the fields you want in attributes:

{
  "attributes": ["sku", "label", "attributes.in_stock", "attributes.volume_liters"]
}

Follow these rules when you name attributes:

  • Custom attributes need the attributes. prefix, followed by the attribute's label. An attribute named In Stock with the label in_stock is attributes.in_stock.
  • Relationship columns need the relationships. prefix, followed by the relationship's label, such as relationships.gift_basket.
  • System fields, such as modified or categories, use their plain name.
  • You can sort by a field that isn't in attributes, but it isn't returned.
  • Asking for a field that doesn't exist returns 422.

A search also returns a 422 if more than 50 attributes are requested. System attributes and custom attributes both count toward the limit, and ID and SKU don't.

Filter on relationships

Product search can filter products by their relationships, using a separate relationship_filters field. It follows the same shape as filters: an array of arrays, with AND inside each inner array and OR between them. You can select only one relationship in the filters.

A relationship filter has these fields:

FieldTypeRequiredDescription
relationship_idstringYesThe ID of the relationship.
operatorstringYesexists or !exists. No other operator is supported.
product_idsarray of objectsNoConstraints on specific related products. Only valid with exists.

Each entry in product_ids has these fields:

FieldTypeRequiredDescription
idstringYesThe ID of the related product.
qty_operatorstringYesThe test to run on the relationship's quantity.
valuearray of integersDepends on the operatorThe quantity to compare against. bte takes two values.

This example finds products that have the Recommended products relationship with product 5d89c67796c8f4a322df4bb8, where the quantity is greater than 2:

{
  "filters": [],
  "attributes": ["relationships.recommended_products"],
  "relationship_filters": [
    [
      {
        "relationship_id": "5d89c6c696c8f4a322df4bbc",
        "operator": "exists",
        "product_ids": [
          {
            "id": "5d89c67796c8f4a322df4bb8",
            "qty_operator": "gt",
            "value": [2]
          }
        ]
      }
    ]
  ],
  "pagination": { "order": null, "page": 1, "page_size": 25 }
}

The value field is an array even when you compare against one number. To find quantities between 1 and 2, use "qty_operator": "bte" with "value": [1, 2].

When a request includes a relationships. column in attributes, each product in the response carries a relationships array:

FieldTypeDescription
relationship_idstringThe ID of the relationship.
labelstringThe label of the relationship.
related_productsarrayThe related products, each with a product_id and a quantity.

On this page