Paloma Catalog API
Updated: 22.05.2024 06:40
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 an 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:
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 specific to this variant |
images |
array[ProductImage] |
List of images for this variant |
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 value.
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 OrderingUnit
s. 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.
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" ]
}
]
}
"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
},
...
]
}
],
...
}
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.
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 thecategory
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