Appearance
Products
On this page:Mandatory fields · Optional fields · Company-specific fields · Product variants · Localizing product data · Product versioning · Stock quantities · Examples
A product represents a single sellable item. Each product is defined by a set of mandatory, optional and company-specific custom fields.
Mandatory fields
A product record must contain in minimum two fields, the identifier, which you use to refer the product and a price.
| Field | Type | Description |
|---|---|---|
| external_id | string | An identifier which uniquely identifies the product. |
| price | money | Base price of the product in cents. A price of 10.50 € should be passed as 1050. |
Optional fields
Optional fields are not required, but recommended, since they add more richness for Custobar users, thus allowing them to make better marketing decisions.
| Field | Type | Description |
|---|---|---|
| type | string | Product type, e.g. CD or T-Shirt. |
| category | string or list of string | Visible name of the category, e.g. Bedding, Jazz or Men's Knitwear. |
| category_id | string or list of string | Your technical name or id for the category. |
| vendor | string | Publisher or manufacturer of a product, e.g. L'Oréal. |
| ean | string | International Article Number of the product. An identifier which uniquely identifies the product. In case product imports from another source do not contain a product_id, Custobar will try to look for sku or ean field to connect the product update with. |
| sku | string | An identifier which uniquely identifies the product. In case product imports from another source do not contain a product_id, Custobar will try to look for sku or ean field to connect the product update with. |
| shop_id | string | Name or identifier for the shop in which the product is available. This field can then be used to only show a specific shops products in the email editor. |
| brand | string | Name of the brand, e.g. Escada Home, Gucci or Miles Davis. |
| title | string | Name of the product, e.g. Egyptian Cotton Linen Fitted Sheet. |
| image | string | Persistent address to a product image. The image may be cached or served through a proxy during marketing campaigns. |
| date | datetime | The date, when the product has been modified most recently, e.g. 2016-06-08 or 2016-06-10T14:10:00Z. If the timezone is not given, the timezone will be defaulted to the timezone configured in the Custobar's settings. |
| url | string | Address of a product page. This field is used to provide link to a web page in campaign mails. |
| sale_price | money | Advertised sale price of the item in cents, if the product is in sale, e.g. for a sale price of 9.45 €, pass 945. |
| lowest_price | money | Lowest price of the item in the past 30 days the item in cents. This field is related to EU's Omnibus directive. |
| price_before_campaign | money | Price of the item in cents before a long-term campaign that lasts more than 30 days but less than 60 days, and where the price progressively decreases. This field is related to EU's Omnibus directive. |
| highest_price | money | Highest price of the item in the past 30 days the item in cents. This field is related to EU's Omnibus directive. |
| description | string | Description is embedded into marketing templates as text. |
| language | language_code | Language of given product information. See section "Localizing product data". |
| visible | boolean | Determines whether a product is "active". Products that are end-of-life, should be marked as not visible. If omitted, defaults to true. |
| exclude_from_recommendations | boolean | A master flag determining whether the product may appear in product recommendations. If omitted, defaults to true. |
| recommendation_set_ids | list of string | A list of external_ids that that belong to same recommendation set. When generating recommendations, only the highest-ranking recommendation from the set is used. Up to 20 external_ids can be provided for the set. |
| in_stock | boolean | Indicates whether the product is currently stocked in general. |
| stock | list of object | Shop specific stock status. A list of objects containing keys shop_id and quantity, e.g. [{"shop_id": "east-london", "quantity": 5}]. The key shop_id is the external_id of the imported shop. |
| tags | [set][] of string | Tags assigned for this product. |
| main_product_ids | list of string | A list of external_ids of products that are considered to be the main products. I.e. if you have shirts with different sizes, define the main_product_ids for the product variants that refer the main product. |
| versions | object | Structured versioning for language translations and shop-specific field overrides in a single import. See section "Product versioning". |
In addition to recommended optional fields, you may describe the product further by defining its unit of sale and item weight.
| Field | Type | Description |
|---|---|---|
| unit | string | Plural shorthand for units sold, e.g. l, oz or pcs. |
| weight | string | Weight of one sold unit. For product bundles or multi-packs, the weight is the combined weight of items sold in one bundle. |
Company-specific fields
You may add additional fields, that are company specific by prefixing them with a company short name and a double underscore __, e.g. COMPANY__color.
Company specific fields are searchable in the Custobar user interface.
Product variants
Suppose you sell clothes and have different sizes for each product. To create a relation between the main product and the size variants, define main_product_ids in the individual shirt products that represent the products in given size.
Localizing product data
Product data can be localized into different languages in two ways.
Approach 1 — Repeated imports with the language field
Supply information for the same product multiple times (same external_id), translating the relevant fields and changing the language code to the appropriate language. Only the translated fields need to be included in each language-specific record.
json
{
"products": [
{
"external_id": "w-1234",
"language": "en",
"title": "Long Johns",
"description": "Nice and warm",
"price": 1099
},
{
"external_id": "w-1234",
"language": "fi",
"title": "Pitkät kalsarit",
"description": "Mukavat ja lämpöisät"
},
{
"external_id": "w-1234",
"language": "se",
"title": "Långa baracker",
"description": "Bekväma och varma"
}
]
}Approach 2 — Inline translations using versions.language
Alternatively, send all language translations in a single product record using the versions field. Under versions.language, provide a map of language codes to the fields that differ for that locale. Base-level fields act as the default and are used for any language not listed.
json
{
"products": [
{
"external_id": "w-1234",
"title": "Long Johns",
"description": "Nice and warm",
"brand": "HIKI",
"price": 1099,
"versions": {
"language": {
"fi": {
"title": "Pitkät kalsarit",
"description": "Mukavat ja lämpöisät"
},
"se": {
"title": "Långa baracker"
}
}
}
}
]
}Product versioning
Beyond language localization, the versions field also supports versioning product data by shop. This lets you maintain a single product record while overriding specific fields — such as price, currency, URL, or image — per shop. Base-level fields act as defaults and are used for any shop not listed in the versions map.
| Versioning key | Description |
|---|---|
versions.language | Override fields per language code (e.g. "fi", "se"). Typically used for translated title and description. |
versions.shop_id | Override fields per shop identifier (e.g. "webstore", "helsinki"). Typically used for shop-specific price, currency, url, and image. |
Both versions.language and versions.shop_id can be combined in the same product record.
Shop versioning example
json
{
"products": [
{
"external_id": "w-1234",
"title": "Long Johns",
"description": "Nice and warm",
"brand": "HIKI",
"category": ["clothing", "underwear"],
"versions": {
"shop_id": {
"webstore": {
"price": 1099,
"currency": "EUR",
"url": "https://testi.fi/1234",
"image": "https://testi.fi/1234.jpg"
},
"helsinki": {
"price": 1299,
"currency": "EUR",
"url": "https://testi.fi/123456",
"image": "https://testi.fi/123456.jpg"
},
"stockholm": {
"price": 10990,
"currency": "SEK",
"url": "https://testi.se/12345678",
"image": "https://testi.se/12345678.jpg"
}
}
}
}
]
}Combined language and shop versioning
Language and shop versioning can be combined in a single product record, allowing both localized content and shop-specific pricing or links in one import.
json
{
"products": [
{
"external_id": "w-1234",
"title": "Long Johns",
"description": "Nice and warm",
"brand": "HIKI",
"category": ["clothing", "underwear"],
"versions": {
"language": {
"fi": {
"title": "Pitkät kalsarit",
"description": "Mukavat ja lämpöisät"
},
"se": {
"title": "Långa baracker"
}
},
"shop_id": {
"webstore": {
"price": 1099,
"currency": "EUR",
"url": "https://testi.fi/1234",
"image": "https://testi.fi/1234.jpg"
},
"helsinki": {
"price": 1299,
"currency": "EUR",
"url": "https://testi.fi/123456",
"image": "https://testi.fi/123456.jpg"
},
"stockholm": {
"price": 10990,
"currency": "SEK",
"url": "https://testi.se/12345678",
"image": "https://testi.se/12345678.jpg"
}
}
}
}
]
}Stock quantities
Available stock per location can be specifed as a list of shop_id/quantity pairs under the stock property. For example, specifying the available stock for a product at three shops:
json
{
"products": [
{
"external_id": "11912",
"stock": [
{ "shop_id": "hki", "quantity": 14 },
{ "shop_id": "tku", "quantity": 0 },
{ "shop_id": "hml", "quantity": 8 }
]
}
]
}When updating stock data, the incoming data is merged by the shop_id, so the entries that are not explicitly given in new data are not erased. For example, after updating the stock state above with the following import:
json
{
"products": [
{
"external_id": "11912",
"stock": [
{ "shop_id": "hki", "quantity": 9 },
{ "shop_id": "lpr", "quantity": 1 }
]
}
]
}the quantities are: hki:9, tku:0, hml:8, lpr:1.
When importing data using CSV, stock quantities can be updated using the property path notation, e.g.
csv
external_id;stock.0.shop_id;stock.0.quantity
11912;hki;14
11912;tku;0
11912;hml;8Examples
To upload new or changed product information, you may pass them to Custobar using a HTTP POST command, e.g.
bash
curl -X POST -u USER -H "Content-Type: application/json" \
--data-binary @products.json https://COMPANY.custobar.com/api/products/upload/Basic product import
The product objects must be provided as a list, wrapped into a JSON object, with a key products, as shown in the example below.
json
{
"products": [
{
"external_id": "1619490226",
"category": "Children's Books",
"category_id": "1619",
"title": "Alice in Wonderland",
"date": "2013-02-13T13:10:40Z",
"url": "https://www.example.com/product/1619490226",
"brand": "Lewis Carroll",
"type": "Paperback",
"price": 1200,
"stock": [
{"shop_id": "BAKER-STREET", "quantity": 40},
{"shop_id": "CANNON-STREET", "quantity": 17}
],
"COMPANY__author": "Lewis Carroll",
"COMPANY__publisher": "Empire Books"
},
{
"external_id": "1770461221",
"category": ["Children's Books", "Nordic Classics"],
"category_id": ["1619", "1311"],
"title": "Moomin and the Comet",
"date": "2011-12-10T08:10:42Z",
"url": "https://www.example.com/product/1770461221",
"brand": "Tove Jansson",
"type": "Paperback",
"price": 2080,
"recommendation_set_ids": ["1619490226"],
"COMPANY__author": "Tove Jansson",
"COMPANY__publisher": "Drawn and Quarterly"
}
]
}Product with variants where main product also has a price defined
To import a product which has variants, use the main_product_ids array to define the relationship as shown below. In the example below, the first product is a master product that also includes a price. This price can be a "starting at" sort of price if the variants pricing varies a lot. After the main product there are three subsequent variant products.
json
{
"products": [
{
"external_id": "5789422",
"title": "Vintage t-shirt",
"type": "T-shirt",
"price": 1995
},
{
"external_id": "5789422LG",
"title": "Vintage t-shirt - Large",
"main_product_ids": ["5789422"],
"price": 1995
},
{
"external_id": "5789422MD",
"title": "Vintage t-shirt - Medium",
"main_product_ids": ["5789422"],
"price": 1995
},
{
"external_id": "5789422SM",
"title": "Vintage t-shirt - Small",
"main_product_ids": ["5789422"],
"price": 1995
}
]
}