Assortment Files

The assortment file is the collection of items, packages and item prices that gets posted to the create assortment file endpoint.

File Structure

This endpoint expects a JSON file with the following structure:

[
    {
        "third_party_id": string, --> required
        "shared_id": string,
        "supplier_outlet_id": string,
        "brand": string,
        "name": string, --> required
        "description": string,
        "package_type": string,
      	"price": decimal, --> required
        "price_type_code": integer, --> required (0: per package; 1: per unit)
        "price_unit": string, --> required if price_type_code=1
        "orderable": boolean, --> defaults to true
        "gtin": string,
        "package_description": { --> required if "package_description_str" is missing
            "quantity": decimal, --> required
            "gtin":string,
            "package": {
                "quantity": decimal, 
                "unit_name": string, --> required at lower level
                "gtin":string
            }
        },
        "package_description_str": string, --> required if "package_description" is missing
        "lead_time": string, --> optional, duration in the format: [DD] [HH:[MM:]]ss[.uuuuuu]
        "weighted": boolean --> optional, defaults to false
    },
    {...}
]

The package_description attribute has a recursive nature. Its package can be a nested structure that contains other packages. This is also a viable representation:

{
    "package_description": {
        "quantity": decimal, --> required
        "gtin":string,
        "package": { --> required for nested packages
            "quantity": decimal,
            "gtin":string,
            "package": {
                "quantity": decimal, 
                "gtin":string,
                "package: {
                    ....
                    "unit_name": string --> required at the lowest level
                }
            }
        }
    }
}
  • third_party_id: The package's unique identifier (REQUIRED);
  • shared_id: An ID that identifies the article that the package belongs to (or an identifier shared between packages);
  • supplier_outlet_id: The ID of the supplier distribution center associated with the assortment;
  • brand: The article's brand;
  • name: The name of the article (REQUIRED);
  • description: Any extra information about the package;
  • package_type: The type of package (if it's a box, case or ...)
  • price: The price of the article;
  • price_type_code: If the package is billed by its unit (1) or by the whole package (0);
  • price_unit: Unit which the package is priced. REQUIRED if price_type_code=1. The units supported are defined here.
  • orderable: True, if the package can be ordered (default). False, otherwise;
  • gtin: The article's GTIN/EAN/UPC code;
    • Use this field only if you're sending the package structure with the package_description_str field (see below). Otherwise, send it directly within the package_description.
    • We don't validate the value of this field when POSTing, but it will be validated when syncing the uploaded file. This means invalid GTINs will be accepted but not shown to our customer in our platform. Invalid GTINs will generate error events, which can be viewed in the log events endpoint.
  • package_description: Our preferred way to represent how the package is structured. REQUIRED if package_description_str is not set.
  • package_description_str: An alternative for package_description to describe the package structure. REQUIRED if package_description is not set.
  • lead_time: How long it takes to deliver the article. E.g: 24 hours should be represented as "24:00:00".
  • weighted: Whether the article is ordered in a defined unit (liters, kg, oz, lb) or not. In other words, the article can be ordered in decimal amounts, e.g. 2.4 kg. If true, the package description should be defined as 1 time one of the units mentioned (1 l, 1 kg, 1 oz, 1 lb).

The Package Description

The package_description field is critical when sending integrated assortment items. Its completeness will be validated, as we rely on this information to ensure accurate pricing and measurements. For instance, we will not allow items to be sent with no indication of weight, volume, or quantity.

The package description can be specified in the following ways:

  • (Preferred representation) As a nested JSON (using the package_description attribute). The advantage of this field (over the package_description_str) is the possibility of defining the GTIN for multiple package levels:
{
    "package_description": {
        "quantity": 2,
        "gtin": "26989625952452",
        "package": {
            "quantity": 3,
            "gtin": "306995253187",
            "package": {
                "quantity": 100.0, 
                "unit_name": "g"
            }
        }
    }
}
  • As a string (using the package_description_str attribute):
{"package_description_str": "2 x 3 x 100 g"}

Please, note that if you plan to use this field, you must be consistent with the "package multipliers" format. That is to say that if you use the format above, we expect all files in all assortments to follow the same format, and not something like "2/3/100g". Although both are supported, the files must keep consistent with the chosen format.

It's very important for us to have the package description as much detailed as possible. Let's take for example the article "Tomato sauce", which is a box containing 4 bottles of 250 ml each. Here are the possible ways of representing it with the package_description field:

  • {"quantity": 4, "unit_name": "piece"}: This meets the minimum requirements but doesn't provide any information about the package structure nor the article unit. This can limit our customer to use other features in our software such as:
    • inventory: it's not possible to count individual bottles of tomato sauce.
    • food cost: if a recipe is created on our platform using 100 ml of tomato sauce, it's not possible for our software to calculate it's food cost since the unit is defined in piece.
  • {"quantity": 4, "package": {"quantity": 1, "unit_name": "piece"}}: There's a small improvement when compared to the last one because the package structure is more clear. However the food cost feature will still not work properly for this article.
  • {"quantity": 4, "package": {"quantity": 250, "unit_name": "g"}}: This is better than the previous options because now the food cost should work. However the article is defined in a mass unit (grams) while it should be clearly a volume unit (ml). This is not a problem for us because there's a conversion ratio configurable per article by the customer, which defaults to 1 kg = 1 liter. But it'd for sure be better to have a more appropriated unit for it.
  • {"quantity": 4, "package": {"quantity": 250, "unit_name": "ml"}}: That's the best representation we can have for this article.

📘

The piece unit is fine for non-food articles, e.g. cleaning products, or articles where this unit is fitting, for example a box of eggs with 12 units.

Pricing

The package pricing is defined by the fields price, price_type_code and price_unit. Please take the following into consideration when defining the package price:

  1. The price is for the package as a whole, e.g. $5 for a Coca-Cola pack (6 x 33cl). Then we have price=5 and price_type_code=0. The field price_unit must not be set.
  2. The price is for the unit, e.g. $10 for the kilogram of steak. Then we'd have price=10, price_type_code=1 and price_unit=kg.

Package Availability

The availability affects whether the customer can place orders or not for the package. It can be represented in 2 ways:

  1. Explictly: This can be done by setting the field orderable. This is pretty much straightforward: packages with orderable=true are available and packages with orderable=false are not available.
  2. Implicitly: Packages not listed in the latest assortment file from a given customer will not be available for ordering. We always expect to receive the full customer assortment file, so if an article is not available in the latest file received, then we consider it to not be available anymore.

Supported Units

  • For mass: μg, mg, g, kg, tonne, oz, lb, metric ton, short ton, long ton
  • For volume: cm³ (use as cubic_centimeter), dm³ (use as cubic_decimeter), ft³ (use as cubic_foot), in³ (use as cubic_inch), m³ (use as cubic_meter), mm³ (use as cubic_milliliter), cup (UK), cup (US), fl oz (UK), fl oz (US), gal (UK), gal (US), l, pt (UK), pt (US), qt (UK), qt (UK), tbsp (UK), tbsp (UK), tsp (UK), tsp (UK), DZ, #10
  • Pieces: piece

🚧

Units that cannot be interpreted (not included in this list) will be interpreted as piece.

FAQ

  1. How can I determine whether a unit is available or not for individual order? For example, a package that contains a box of wine bottles (750 ml), with 6 bottles in total, how can I define if the bottle unit (750 ml) can be ordered or not?
    We'll explore the package_description field in more detail, assuming that the individual bottle can either be ordered separately or not.

    Bottles ARE individually orderable

    It is possible to order a single bottle.
    Since you have two orderable packages, we need two distinct items in the assortment file. Each item will have the same shared_id but unique third_party_ids:

    [
        {
             "third_party_id": "CS123456",
             "shared_id": "123456",
             "package_description": {
                 "quantity": 6,
                 "package": {
                     "quantity": 750.0, 
                     "unit_name": "ml"
                 },
                 "gtin": "2698962595245"
             },
         },
         {
            "third_party_id": "EA123456",
            "shared_id": "123456",
            "package_description": {
                "quantity": 750.0,
                "unit_name": "ml",
                "gtin": "6820540261525"
            },
       },
    ]
    

    This will generate two orderable packages: one that represents the whole box, and one that represents the bottles. Using the same shared_id is very important for us to know both packages are different representations of the same article.

    Bottles ARE NOT individually orderable

    It is not possible to order a single bottle separately.
    Without nested packages, you should provide only one item:

    [
       {
            "third_party_id": "123456",
            "package_description": {
                "quantity": 6.0,
                "package": {
                    "quantity": 750.0, 
                    "unit_name": "ml"
                },
                "gtin": "2698962595245"
            },
           ...
       }
    ]
    

    There's no need to provide a value for the shared_id attribute, either. This will generate a package for the whole box.

  2. How can I specify that a product is not delivered with an exact weight but is instead weighed at the time of delivery? For instance, if a customer orders 1 kilogram of tomatoes, the delivered quantity might be 1.1 kg, or 0.9 kg. etc.
    You should make sure the following is covered:

    • The package description is defined as the average package weight and is constant, i.e. it's the same value for every assortment file containing this article. The example above could be represented as {"quantity": 1, "unit_name": "kg"}.
    • The price is defined accordingly. This kind of package is often priced per unit, so the delivered package is priced for the weighted amount at delivery time. The example above would have price_type_code=1 and price_unit="kg".
  3. How long is an article or a catalog/assortment valid? How do I handle seasonal products, i.e. articles available for a defined time period?
    As mentioned in the Package Availability section, we always expect to receive the full customer assortment file and we consider the current article/assortment status as the one we get in the latest assortment file received for a given customer. That means an article will be available for a given customer as long as it's listed in the latest customer assortment file we received with the status orderable=true (or with the field orderable omitted).

  4. Is it possible to set different lead times based on the day of the week? For instance, having a lead time of 3 days for orders placed on Mondays and 2 days for orders placed on Tuesdays.

    Unfortunately this feature is not available in our API. However the customer can set this up on our platform per location and define which days it is possible to schedule a delivery for the order and up to when the order should be placed. In the example below, the customer place orders to be delivered only on Mondays and Wednesdays and orders to be delivered on Monday should be placed 2 days before (Saturday up to 6 PM)

    However, please notice we don't support in any way setting the lead times per article based on the day of the week. The lead times described above are applied for all articles in the customer assortment.

  5. How often is the assortment file processed?

    The assortment file is processed once per day for every customer due to limitations on our side. Normally this frequency is enough because the article data often doesn't change much within this time period. However this also means that all the assortment files must be sent before the agreed time, else their processing will be delayed for 1 day. For example, if the agreed time is 4 AM, any file sent after this time will be processed only on the next day at 4 AM.

    Please also notice if multiple files for the same customer are sent in the same day, only the latest file will be processed. For instance, if 3 files are sent for the customer number 123456, then only the last file will be processed, while the other 2 will be ignored.

    At last, assortment files don't need to be sent daily as long as there are no changes when compared to the previous file. However, the customer full assortment must be always sent even if the change is about a single article.