Products

The Product Import Endpoint

https://{BASE_URL}/imports/products

All import integration endpoints use the same authentication parameters, please see Authentication page for more details.

Advanced Product Import Parameters

When importing Products you can additionally specify which Markets and Channels you wish to import for. The default market is dk (Denmark) and the default channel is pos - signifying the POS channel for all Shops in the Danish market.

These defaults can be overridden by the query parameters markets and channels respectively. The value for both parameters are comma separated lists of markets and channels.

E.g.:

https://{BASE_URL}/imports/products?markets=dk,se,no&channels=pos,online&...

For further clarification of the Market and Channel concepts, please read the Vocabulary.

Importing Products

Send a POST request to the endpoint with the parameters specified above.

The body of the POST request must be a JSON object with the following layout:

{
    "products": [
        [product A],
        [product B],
        ...
    ]
}

The definition of the Product model can be found in the Models document. The minimal data required for a regular product is an id, a retail_price and a name:

{
    "products": [
        {
            "id": "0001",
            "name": "Coffee",
            "retail_price": 25
        },
        {
            "id": "0002",
            "name": "Tea",
            "retail_price": 20
        }
    ]
}

NOTE

When products are imported into the Ka-ching system, the id will be used as a unique key.

One limitation in the database we are using (the Firebase real-time database) is that not all characters are valid to use in keys.

This means that the following list of characters may not be used in the "id" field of a product: ., /, #, $, *, [ and ]

Other basic properties of products include:

  • description
  • image_url
  • barcode

The description will be shown when displaying product details.

The image_url is a URL for an image that will be shown in the Product Grid, basket and Product Details.

The barcode could be either an EAN number, a SKU, an ISBN number or any other means of identifying a product. The only thing that matters for the POS is that this is the bar code that you would scan in the shop in order to add the product to the basket.

Advanced product models

Importing products with prices for different markets

All price information on a product will be interpreted to be in the currency of the market in which they are imported.

If you are importing for multiple markets, then you naturally need to be able to specify prices for each of these markets. This can be done by supplying the pricing information as objects keyed by the market. Here is an example of importing a few products in the markets: Denmark, Norway and Sweden:

{
    "products": [
        {
            "id": "0001",
            "name": "Coffee",
            "retail_price": {
                "dk": 25,
                "no": 35,
                "se": 30
            }
        },
        {
            "id": "000"",
            "name": "Tea",
            "retail_price": {
                "dk": 20,
                "no": 32,
                "se": 28
            }
        },
        ...
    ]
}

Localizing product names and other details

Throughout the Ka-ching system, data can be localized into multiple languages. This could for instance be used to display a chinese version of product names on a secondary, customer facing display.

The way this is modelled is that all string data can either be a simple, non-localized string -or- an object containing localizations for various language codes.

Localizing the product name could for instance be done as follows:

{
    "products": [
        {
            "id": "0001",
            "name": {
                "da": "Kaffe",
                "en": "Coffee",
                "nb": "Kaffe"
            },
            "retail_price": 25
        }
    ]
}

Variable priced products

The Ka-ching system allows for variable priced products. These are products that do not have an explicit retail price, but rather need the product price to be entered when the product is added to the basket on the POS.

Variable priced products can be created simply by not specifying a retail price.

{
    "products": [
        {
            "id": "0001",
            "name": "Variable priced coffee"
        }
    ]
}

Taxes

The market that your shop operates in defines a set of one or more default taxes. This means that in countries like Denmark, you never need to specify other taxes directly on the product.

But in special situations you have the option to override the set of taxes for individual products. This can be done as follows:

{
    "products": [
        {
            "id": "0001",
            "name": "Coffee",
            "retail_price": 25,
            "taxes": [
                {
                    "id": "coffee_tax",
                    "name": "Coffee tax",
                    "rate": 0.1,
                    "type": "vat"
                }
            ]
        }
    ]
}

Taxes can be either vat or sales_tax. This determines how the base price is calculated from the retail price. See the Vocabulary for more on this.

Notice that the taxes are specified as an array. This is because in some countries, multiple taxes can be in effect at the same time. For instance you could imagine taxation to be split into two rates defining 'city tax' and 'state tax'. Again the Vocabulary has more details on this concept.

Creating simple, fixed sale discounts

Our Discount Campaign engine can be used to model powerful discount concepts in a very expressive manner, but sometimes this complexity is unneeded.

So if a product is currently on sale, this sale_price can be added directly to the product.

When a product with a sale_price is added to the basket, a new price discount is automatically applied to the item.

{
    "products": [
        {
            "id": "0001",
            "name": "Coffee on sale",
            "retail_price": 25,
            "sale_price": 15
        }
    ]
}

Unlocking Contribution Ratio functionality in the POS

In the Ka-ching Back Office, you can configure a desired Contribution Ratio for your sales. In order for this to work, you need to supply a cost price for all products.

When a desired Contribution Ratio is configured, the Action Button in the bottom right of the POS will show a status indicating wether the Contribution Ratio is met (green) or not (orange) or if money are actually lost by performing the sale (red). This could be the case if too much of a discount is being applied to the sale.

Note that retail prices in Ka-ching always represent the price that you would print on a price-tag (meaning including VAT, but excluding american style sales tax), but cost prices are always represented without any taxes.

{
    "products": [
        {
            "id": "0001",
            "name": "T-shirt",
            "retail_price": 150,
            "cost_price": 40
        }
    ]
}

Purchase types

The concept of purchase types exists to let pricing and tax details of a product vary with an aspect of the sales situation. Most often this would be used to model varying prices and taxes for 'eat in' and 'dine out' sales. For instance taxation in many states in the US varies exactly based on this choice.

Currently the setup for the available purchase types needs to be performed by Ka-ching, but when the desired purchase types are added, you may specify price or tax variations for each purchase type in the manner shown below. Note that you can default to the base pricing and taxing, so if you are modelling 'eat in' vs. 'dine out', you only need to use once explicit purchase type.

For the example below, imagine that we have defined the purchase type 'dine_out', and that the absence of 'dine_out' means 'eating in'.

{
    "products": [
        {
            "id": "0001",
            "name": "Pie",
            "retail_price": 25,
            "retail_price_map": {
                "dine_out": 20
            }
        }
    ]
}

Similarly you can vary taxes by having both a 'taxes' and a 'taxes_map':

{
    "products": [
        {
            "id": "0001",
            "name": "Pie",
            "retail_price": 25,
            "taxes": [
                {
                    "id": "coffee_tax",
                    "name": "Coffee tax",
                    "rate": 0.1,
                    "type": "vat"
                }
            ],
            "taxes_map": {
                "dine_out": [
                    {
                        "id": "coffee_tax",
                        "name": "Coffee tax",
                        "rate": 0.07,
                        "type": "vat"
                    }
                ]
            }
        }
    ]
}

Product Groups

Product Groups can be defined in the Ka-ching Back Office and are used to group sold goods on the X- and Z-reports. A Product Group is defined as an identifier and a display name. By adding the product group identifier to a product on import, this will make the grouping appear on the reports.

A Product can belong to 1 or 0 Product Groups

{
    "products": [
        {
            "id": "0001",
            "name": "Pie",
            "retail_price": 25,
            "product_group": "deserts"
        }
    ]
}

More functionality may be added around the Product Group concept in the future.

Tags

Tags can be defined in the Ka-ching Back Office and are informal identifiers that can be added to a Product. A Tag is defined as an identifier and a display name.

In the Ka-ching POS, the tags can be used to create the tab bar and a folder hierarchy.

Tags can also be used in conjunction with Discount Campaigns as a means of triggering discounts in case a certain number of products bearing the same tag are in the shopping basket.

Any number og tags can be added to one Product.

{
    "products": [
        {
            "id": "0001",
            "name": "Pie",
            "retail_price": 25,
            "tags": {
                "deserts": true,
                "food": true,
                "popular": true
            }
        }
    ]
}

More functionality may be added around the Tag concept in the future.

Attributes

Attributes can be defined in the Ka-ching Back Office. They are similar to tags, but allow you to define stronger semantics between values.

Consider the tags merlot, cabernet, denmark and france. While all of these may be used for filtering purposes, there is nothing that binds merlot and cabernet to each other - and the same for denmark and france. One product could easily contain all four tags.

Instead you may wish to define a more formal relationship where you let the system know that merlot and cabernet are both types of grapes - and denmark and france are both countries.

From Ka-ching release 11 you may now specify an Attribute called Grape that can list all of the available grapes - and similarly for Country. For each of these two attributes, a product can only have a single value.

With these added semantics, each attribute can now be represented in Ka-ching POS as a search facet.

Any number og attributes can be added to one Product.

{
    "products": [
        {
            "id": "0001",
            "name": "2016, Grand Sud",
            "retail_price": 305,
            "attributes": {
                "grape": "merlot",
                "country": "france"
            }
        }
    ]
}

More functionality may be added around the Attribute concept in the future.

For instance, attributes can only be 'option sets' today. In the future they might also embrace numerical values and other data types.

Product Variants

In the Ka-ching system, a product can either be a stand-alone, sellable entity, but it can also be used to model the concept of Product Variants. If, for instance, a product can be sold in a big and a small variant, then this can be modelled as a product that has two variants. This basically means that the product itself is not a sellable entity (you cannot sell this product without knowing whether you are selling the big or the small variant), but each variant becomes a sellable entity instead.

The variant can have it's own name, barcode, image_url and can also specify price variations. If it does not specify a retail_price, the retail_price of the product will be used.

In the POS, tapping a product with variants will display the variant selector. Variants are displayed in a list unless dimensions are also specified (read more about dimensions below).

If all variants of a product have the same price, this price will be displayed in the Product Grid. If the prices of the variants vary, then the prices will only be shown when the product is tapped.

{
    "products": [
        {
            "id": "0001",
            "name": "Pie",
            "retail_price": 25,
            "variants": [
                {
                    "id": "small",
                    "name": "Small"
                },
                {
                    "id": "big",
                    "name": "Big",
                    "retail_price": 50
                }
            ]
        }
    ]
}

Dimensions and dimension values

Imagine the situation where you sell a shirt in sizes: S, M and L and colors: red, yellow and blue. This basically gives rise to 9 variants, so one way of modelling this would just be to include 9 variants with the names "S, red", "S, yellow", etc., etc.

This would of course give a list of 9 variants to choose from in the UI, but conceptually, the cashier just needs to make one choice of the size and one choice for the color. These two choices will then uniquely identify one of the 9 variants.

In the Ka-ching system we model this by a concept called dimensions. A product can contain any number of dimensions - and each of these dimensions can define a number of available dimension values. In the example above we could define the dimension: size with the values S, M and L and the dimension: color with the values red, yellow and blue.

By defining these, and adding a dimension value for each dimension to each of the variants, the POS can now display a much nicer UI - namely a list of dimensions, each having a number of possible values to select from.

In order to make the experience for the cashier even nicer, the dimension values can define both a color and also an image.

Example of a product with variants and dimensions:

{
    "products": [
        {
            "id": "0001",
            "name": "T-shirt",
            "retail_price": 150,
            "dimensions": [
                {
                    "id": "size",
                    "name": "Size",
                    "values": [
                        {
                            "id": "s",
                            "name": "S"
                        },
                        {
                            "id": "l",
                            "name": "L"
                        }
                    ]
                },
                {
                    "id": "color",
                    "name": "Color",
                    "values": [
                        {
                            "id": "red",
                            "name": "Red",
                            "color": "#FF0000",
                            "image_url": "https://url.for/red_cloth.image"
                        },
                        {
                            "id": "blue",
                            "name": "Blue",
                            "color": "#0000FF",
                            "image_url": "https://url.for/blue_cloth.image"
                        }
                    ]
                }
            ]
            "variants": [
                {
                    "id": "a",
                    "dimension_values": {
                        "color": "red",
                        "size": "s"
                    }
                },
                {
                    "id": "b",
                    "dimension_values": {
                        "color": "red",
                        "size": "l"
                    }
                },
                {
                    "id": "c",
                    "retail_price": 200,
                    "dimension_values": {
                        "color": "blue",
                        "size": "s"
                    }
                },
                {
                    "id": "d",
                    "retail_price": 200,
                    "dimension_values": {
                        "color": "blue",
                        "size": "l"
                    }
                }
            ]
        }
    ]
}

Notice how the blue t-shirts in this example are more expensive than the red ones.

Importing products to specific shops

If the imported products should not be shared between all shops, you can specify a list of shop identifiers as follows:

{
    "products": [
        {
            "id": "0001",
            "name": "Pie",
            "retail_price": 25
        }
    ],
    "shops": {
        "shop_a": true,
        "shop_b": true,
        "shop_c": true
    }
}

Deleting Products

Send an HTTP DELETE request to the endpoint with a body containing a JSON object containing product ids to delete.

{
  "ids": ["0001", "0002"]
}

In order to delete shop specific products you may additionally specify an array of shop ids in the DELETE request:

{
  "ids": ["0001", "0002"],
  "shops": ["xxx", "yyy"]
}