Paloma Catalog API

Updated: 12.05.2021 09:47

The Paloma Catalog API provides access to category and product data.

https://[organization].paloma.one/api/catalog/v2

Products

Products are the main entities of the catalog. A Product object contains basic information about the product, its attributes, price, availability, images and variants.

A product itself cannot be purchased, only one of its variants. Therefore, each product comes with at least one variant. Each variant comes with a SKU (variants[n].sku) which identifies the variant and can be used for example to add an item to a shopping cart.

Example

GET /api/{channel}/{locale}/products/{itemNumber}

The most important properties of a Product are:

Property Type Description
itemNumber string Product item number (unique within a channel )
name string The product name
slug string SEO friendly name to be used for product URLs (together with the product item number)
price CatalogPrice Base price of the product
variants array[ProductVariant] List of all variants of this product
master.attributes map[ProductAttribute] A map of product attributes
master.images array[ProductImage] List of all product images
categories array[ProductCategory List of all categories assigned to this product

See Catalog API Reference for detailed information.

Options

Each product may have a set of options (like colors and sizes) which specify the available product variants.

Example

{
    "color": {
        "option": "color",
        "label": "Farbe",
        "values": [
            {
                "value": "green",
                "label": "Grün",
                "image": {},
                "skus": [
                    "100-GREEN-S",
                    "100-GREEN-M"
                ]
            },
            {
                "value": "blue",
                "label": "Blau",
                "image": {},
                "skus": [
                    "100-BLUE-S",
                    "100-BLUE-M"
                ]
            }
        ]
    },
    "size": {
        "option": "size",
        "label": "Grösse",
        "values": [
            {
                "value": "s",
                "label": "S",
                "image": {},
                "skus": [
                    "100-GREEN-S",
                    "100-BLUE-S"
                ]
            },
            {
                "value": "m",
                "label": "M",
                "image": {},
                "skus": [
                    "100-GREEN-M",
                    "100-BLUE-M"
                ]
            }
        ]
    }
}

Those options are well suited to render an overview of all available variants of a product, for example:

product_options.png

Variants

A product can have multiple variants. A ProductVariant can have its own attributes, price and images.

If applicable, each variant has a list of options which define the variant (e.g. "size" or "color").

Example

"options": {
  "color": {
    "option": "color",
    "label": "Farbe",
    "value": "000"
  },
  "size": {
    "option": "size",
    "label": "Grösse",
    "value": "35"
  }
}

The most important properties of a ProductVariant are:

Property Type Description
sku string Unique identifier for the variant (within a channel)
name string Variant name
price CatalogPrice The purchase price of this variant
options map[ProductOption] Map of options which define the variant (e.g. "size" or "color")
attributes map[ProductAttribute] Map of attributes specifically for this variant
images array[ProductImage] List of images for this variant
Note: If your products have many variants and attributes, the product JSON can become quite large, especially if you retrieve a list of products (e.g. using search). If you run into performance issues because of large products, you can omit all the variants by using omit-variants=true (or "omitVariants": true in request bodies). See "Get a product" for example.

Attributes

Attributes consist of a type, label and one or multiple values. The type can be used as an identifier in case some logic needs to be applied for certain attributes. Attributes can also be used to filter product search results.

Values
An attribute's value contains localized content to be displayed in the front-end. Some attributes additionally come with valueCode, which is a language-independent identifier for an attribute.

Multi-valued attributes have those values listed in values and valueCodes respectively.

"origin": {
    "type": "origin",
    "label": "Herkunft",
    "value": "Belgien, Deutschland, Frankreich, Luxemburg, Niederlande",
    "valueCode": "origin_be, origin_de, origin_fr, origin_lu, origin_nl",
    "values": [
        "Belgien",
        "Deutschland",
        "Frankreich",
        "Luxemburg",
        "Niederlande"
    ],
    "valueCodes": [
        "origin_be",
        "origin_de",
        "origin_fr",
        "origin_lu",
        "origin_nl"
    ]
}

See the ProductAttribute model for more information.

Price

The purchase price for a variant can be found in the price object. This price object contains the following:

Property Type Description
currency string Formatted currency, usually the currency code
unitPrice string The price of one unit. Check taxIncluded to know whether this is the net or the gross price
unit string Name of the unit this price is valid for (default: 'piece')
tax string The formatted tax rate
taxIncluded boolean Whether the unitPrice includes taxes
originalUnitPrice string The price before possible discounts
unitMsrp string The manufacturer's suggested retail price

The base price for the product can be found in the master.price object. Be aware that each variant of a product can have its own price. The product base price should only be used to display on product views (e.g. category product listings) where no individual variants are visible

Ordering Units

A product variant may be available in different OrderingUnits. This is most commonly the case in B2B shops where an article may be purchased in different packagings like "logistic unit" or "consumer unit". Each ordering unit contains the purchase price for one item of the specific unit.

{
  /* ... */
  "orderingUnits": [
    {
      "unit": "TU",
      "unitCode": "trade_unit",
      "unitDecimals": 0,
      "portioning": "none",
      "price": { /* ... */ }
    },
    {
      "unit": "kg",
      "unitCode": "kilogram",
      "unitDecimals": 3,
      "portioning": "optional",
      "price": { /* ... */ }
    },
  ]
}

Additional Units

There may be other units, which can not be purchased as such but still contain useful information for a user. Therefore, all known product units (including ordering units) are listed in the ProductVariant's units property. Those units may also contain weight and bundle information.

[
    {
        "unit": "kg",
        "unitCode": "kilogram",
        "price": { /* ... */ }
    },
    {
        "unit": "Consumer Unit",
        "unitCode": "CU",,
        "price": { /* ... */ }
        "grossWeightKg": "0.95",
        "netWeightKg": "0.8",
        "bundleUnit": {
            "unit": "kg",
            "unitCode": "kilogram",
            "quantity": "0.8"
        }
    }
]

Images

Each product image comes in different (pre-configured) sizes. You can either chose the appropriate size for the view you want do display or use all sizes for image source maps.

"images": [
    {
        "name": "1716.839_Rosenkohl_15_25mm_uc.jpg",
        "title": "Hauptbild",
        "caption": null,
        "set": "image_main_jpg_rgb",
        "sources": [
            {
                "size": "full",
                "url": "https://..."
            },
            {
                "size": "large",
                "url": "https://..."
            },
            {
                "size": "medium",
                "url": "https://..."
            },
            {
                "size": "small",
                "url": "https://..."
            }
        ]
    }
]

Categories

Shop categories are organized in a hierarchical fashion. Each category has a parent category (except for the top-level categories) and a list of sub-categories.

A category is uniquely identified by its code.

Each category also has a slug, which should be included when rendering category links. Note: slugs are not unique or constant, so you should always use the category code as identifier in category links.

Example

{
    "code": "11",
    "channel": "b2c",
    "catalog": "b2c",
    "locale": "de_CH",
    "parent": "8",
    "position": 1,
    "level": 2,
    "subCategories": [
        {
            ...
        }
    ],
    "name": "Schuhe",
    "slug": "damen/damenschuhe",
    "h1Title": "Damenschuhe",
    "pageTitle": "Damenschuhe online kaufen jetzt im ACME Onlineshop",
    "metaDescription": "Damenschuhe online kaufen! Jetzt bei ACME, Ihrem Onlineshop für hochwertige Lederwaren.",
    "aliases": "Damenschuhe, Damenschuh, Damnschuhe, Danenschuhe, Frauenschuhe",
    "ancestors": [
        {
            "code": "8",
            "name": "Damen",
            "slug": "damen",
            "level": 1
        }
    ]
}

See the Category model for more information.

Search

Product search is used for all views with product listings. This can be a search results page or a category details page. In the latter case, search is simply restricted to the current category using the category parameter.

See Catalog API Reference.

For search suggestions ("as you type") a separate method is available.

There are three ways to search for products, all of which can be used in conjunction.

1. Filter by category code: Only products listed in the given category are found.

POST /api/catalog/v2/{channel}/{locale}/search
{
  "category": "123" # from category.code
}

2. Search query: The query parameter is intended for search field scenarios. Any input the user puts into a search field can be used here.

POST /api/catalog/v2/{channel}/{locale}/search
{
  "query": "banana"
}

3. Filters: Search results are filtered by the given property and values.

POST /api/catalog/v2/{channel}/{locale}/search
{
  "filters": [
    {
      "property": "variants.options.size.value", # filter by 'size' option
      "values": [ "L", "XL" ]
    }
  ]
}
Note: If your products have many variants and attributes, the search response body JSON can become quite large, especially if you use large page sizes. If you run into performance issues because of large products, you can omit all the variants by using "omitVariants": true.

Search Filters

A common use case in shop front-ends is faceted search through the application of search filters.

The data for displaying those filters can be obtained when using the "Search products" operation with the filterAggregates flag turned on.

POST /{channel}/{locale}/search
{
  "category": "123",
  "filterAggregates": true
}

The return value will contain aggregated filter values alongside the normal search results:

{
  "content": [ ... ],
  "aggregates": [
    {
      "property": "variants.options.color.value",
      "label": "Color",
      "values": [
        {
          "value": "black",
          "count": 90
        },
        {
          "value": "blue",
          "count": 64
        },
        ...
      ]
    }
  ],
  ...
}

Screenshot 2019-12-06 at 13.45.13.png

After the user has selected the preferred filter values, the search can be executed again. Note the use of the property field from the search response (aggregates[n].property).

POST /{channel}/{locale}/search
{
  "category": "123",
  "filterAggregates": true,
  "filters": [
    {
      "property": "variants.options.color.value",
      "values": [ "bordeaux", "brown" ]
    }
  ]
}

The return value will contain the filtered search results as well as the updated filter values for the current search.

Screenshot 2019-12-06 at 13.45.44.png

Sorting

Product search results can be sorted using the sort and order parameters.

The sort parameter takes the following values:

  • position: products have a fixed position within a category. Sorting by position therefore only makes sense if the category parameter is also set in the search request.
  • relevance: only available when a search query was used in the request. Results are sorted so that best matching results come first.
  • attribute.[ATTRIBUTE_TYPE]: results are sorted by attribute value (e.g. attribute.color). See the ListAttributes operation for available attribute types.
  • name: results are sorted by product name.
  • price: results are sorted by the default price of the master variant (each variant can have multiple prices, so the usefulness of sorting by price is limited).

Response Manipulation

All catalog endpoints support special x-paloma-jq headers and _jq query parameters for manipulating the response before it's sent to the client. This is based on the popular jq JSON Processor. Headers/parameters may be repeated, in which case all of them will be applied.

Its main use-case is to remove unnecessary content from the response, reducing the time it takes to transfer the requested payload. When using API endpoints that provide a lot of data, like product searches, cutting down on transfer size may greatly improve the user experience.

Based on the product search response, here are a few example headers that may be used. While the examples use the header for readability reasons, all operations are also possible with the _jq query parameter, in which case the expressions need to be properly escaped/encoded!

Examples

  • Only retain the "itemNumber", "name", "slug", "description", and "master" properties from objects in $.content:
    x-paloma-jq: .content |= map({ itemNumber, name, slug, description, master })
    
  • If you're only interested in the filterAggregates you might want to remove the complete content:
    x-paloma-jq: del(.content)
    
  • Retaining "sku", "price", "attributes", "images", "availability" on $.content.master:
    x-paloma-jq: .content |= map(.master |= { sku, price, attributes, images, availability })
    
  • If a master or variant contains multiple images, you might only be interested in one with a certain size. This example will only retain the image with size "medium":
    x-paloma-jq: .content |= map(.master.images |= map( .sources |= map(select(.size == "medium")) ))
    
  • Remove all master attributes with an empty value:
    x-paloma-jq: .content |= map(.master.attributes |= with_entries(select( .value.value != "" )) )
    
  • Only retain certain attributes based on their prefix, or exact match:
    x-paloma-jq: .content |= map(.master.attributes |= with_entries(select( .key | startswith("allergenes_") or startswith("extras_") or (. == "durability") )) )
    

Next: Carts & Checkout