Your data

Catalog

Every product the assistant can sell: name, brand, price of the sales unit, net size, weight or pack, stock.

What it does in the conversation

It is the price list the assistant reads at every request. It searches by name, brand, department and barcode; reads the size and the price of the sales unit; decides whether a product is sold by the piece, by weight or only as a whole pack; and checks whether it is available. Every cart line and every order you receive carries the code (sku) of a row of this file.

The price is always the price of what the customer puts in the cart: the pack, the case of six, or the kilo for a product sold by weight without an average piece weight. With «sold by weight» and the average piece weight, «a kilo of apples» becomes the right number of apples; with «pieces per pack» and «whole pack only», «ten bottles» become two cases of six.

«Reliable stock = no» is for fresh counter products (meat, fish, fruit) whose stock you do not count: they stay on sale even at zero stock.

Example

Customer: Can you add ten bottles of still water and a kilo of apples?

Assistant: Done! 🛒 • Acqua naturale 6x1,5l [Fonte Esempio] 2x6x1.5l – €6.60 • Mele Golden 4x250g (1kg) – €2.40 Water is sold in cases of six: for ten bottles I added two cases (twelve bottles). Anything else?

The water has «pieces per pack» 6 and «whole pack only» yes; the apples are sold by weight with an average piece weight of 0.25 kg. Illustrative example, with the products of the template and an invented store.

If it is missing

  • Without the code or the name, the row is rejected and the product does not exist for the assistant.
  • Without the price, the product has no amount: it stays «to be confirmed» and the customer does not see what it costs.
  • Without the brand, the cart line does not say it, and the customer does not recognise their usual product.
  • Without the net size (quantity and unit), the size comes from the name; if the name says nothing, the line says «pack» and the customer does not know how much they are buying.
  • Without «sold by weight», a product sold by weight is sold as one piece: «a kilo of apples» becomes one apple.
  • Without the average piece weight, the assistant does not know how many pieces make a kilo.
  • Without «pieces per pack» and «whole pack only», «ten bottles» does not become cases.
  • Without «reliable stock = no» on fresh counter products, meat, fish and fruit at zero stock look unavailable.
  • Without the department, cart lines are not grouped; without the sub-department, there are no shelf links.
  • Without the product page and the image, the reply has no link and no photo.
  • A product you no longer sell stays on sale until you switch it off («sold online» = no) or send the file as the whole catalog.

The fields

Required: without it the product is not sold the way the customer expects. Recommended: without it there is a declared fallback, but the experience is poorer. Optional: an improvement.

  • skurequired
    Column in the file
    SKU
    Type
    text
    Example
    000201111 · 000301555 · 000405020
    Rule
    required, unique in the file, max 128 characters, stable over time
  • titlerequired
    Column in the file
    Product name
    Type
    text
    Example
    Pasta Spaghetti n.5 500g · Acqua naturale 6x1,5l · Mele Golden
    Rule
    required, as the customer reads it, max 512 characters
  • brandrequired
    Column in the file
    Brand
    Type
    text
    Example
    Barilla · Fonte Esempio
    Rule
    required (empty = warning, not a rejection)
  • categoryrecommended
    Column in the file
    Department
    Type
    text
    Example
    Pasta e riso · Bevande · Frutta e verdura
    Rule
    the department: groups the cart lines
  • subcategoryrecommended
    Column in the file
    Subdepartment
    Type
    text
    Example
    Pasta secca · Acqua · Frutta
    Rule
    the shelf within the department
  • descriptionoptional
    Column in the file
    Long description
    Type
    text
    Example
    Mele di montagna, calibro 75-80
    Rule
    max 4,000 characters; does not replace the name
  • gtinoptional
    Column in the file
    GTIN (EAN)
    Type
    text
    Example
    2000000000015 · 2000000000022
    Rule
    8, 12, 13 or 14 digits with the GS1 check digit
  • pricerequired
    Column in the file
    Selling price
    Type
    number (¤)
    Example
    1.29 · 3.30 · 2.40
    Rule
    VAT included, of the sales unit (the pack, the case; the kg if sold by weight without an average weight)
  • min_order_qtyrequired
    Column in the file
    Net size (quantity)
    Type
    number
    Example
    500 · 9 · 1
    Rule
    > 0: net content of the pack sold; by weight, the minimum quantity
  • min_order_unitrequired
    Column in the file
    Net size (unit)
    Type
    symbol
    Example
    g · l · kg
    Rule
    one of: kg g l ml cl pz
  • sold_by_weightrequired
    Column in the file
    Sold by weight
    Type
    yes/no
    Example
    no · sì
    Rule
    yes/no: the cart quantity is in units of average weight
  • avg_piece_weight_kgrecommended
    Column in the file
    Average piece weight (kg)
    Type
    number (kg)
    Example
    0.25
    Rule
    > 0, only for products sold by weight: «1 kg» becomes a number of pieces
  • items_per_packrequired
    Column in the file
    Items per pack
    Type
    integer
    Example
    1 · 6
    Rule
    integer ≥ 1 (1 if it is not a multipack)
  • pack_onlyrecommended
    Column in the file
    Pack only
    Type
    yes/no
    Example
    no · sì
    Rule
    yes/no: only the pack is sold (water, beer): «10 bottles» become cases
  • stock_managedrecommended
    Column in the file
    Stock is tracked
    Type
    yes/no
    Example
    sì · no
    Rule
    yes/no: «no» for fresh counter goods, sellable even at stock 0
  • unit_priceoptional
    Column in the file
    Price per kg or litre
    Type
    number (¤/kg ¤/l)
    Example
    2.58 · 0.37
    Rule
    > 0, as on the label; never instead of the selling price
  • gross_weight_kgoptional
    Column in the file
    Gross weight (kg)
    Type
    number (kg)
    Example
    0.52 · 9.3
    Rule
    > 0, packaging included: weighs the cart for the courier and heavy items
  • tare_kgoptional
    Column in the file
    Tare (kg)
    Type
    number (kg)
    Example
    0.02
    Rule
    ≥ 0
  • vat_rateoptional
    Column in the file
    VAT rate (%)
    Type
    number (%)
    Example
    4 · 10
    Rule
    0-100
  • linkrecommended
    Column in the file
    Product page
    Type
    web address
    Example
    https://www.esempio.it/p/000201111
    Rule
    https:// on the store website
  • image_linkrecommended
    Column in the file
    Image
    Type
    web address
    Example
    https://www.esempio.it/img/000201111.jpg
    Rule
    https://
  • diet_tagsoptional
    Column in the file
    Dietary tags
    Type
    list
    Example
    organic|local
    Rule
    separated by |: organic vegan lactose_free gluten_free whole_grain local
  • is_onlinerequired
    Column in the file
    Sold online
    Type
    yes/no
    Example
    sì
    Rule
    yes/no (empty = yes)
  • stock_qtyrequired
    Column in the file
    Stock
    Type
    number
    Example
    120 · 40 · 0
    Rule
    ≥ 0, in sales units

Download the template

The first row is the header; the second row (starting with #) describes each column; the three example rows also start with # and are not imported. Column names are recognised in all six languages and by their field name.

Frequent errors and their message

  • SKU_MANCANTE

    «The product code is missing.»

    What to do: Every row needs the code your till or management system uses, always the same over time.

  • TITLE_MANCANTE

    «The product name is missing.»

    What to do: Write the name as the customer reads it on the shelf.

  • PREZZO_NON_VALIDO

    «The price must be a number, zero or more.»

    What to do: Only the number, without the currency symbol: 1.29 or 1,29.

  • NUMERO_AMBIGUO

    «This number reads two ways: write it without the thousands separator, or with two decimals.»

    What to do: Use the same decimal separator in the whole file and no thousands separator.

  • BOOLEANO_NON_VALIDO

    «Yes or no is needed here.»

    What to do: Write yes/no (or sì/no, 1/0) in «sold by weight», «whole pack only», «reliable stock», «sold online».

  • UNITA_NON_AMMESSA

    «The net size unit must be one of: kg, g, l, ml, cl, pz.»(explanation of this guide: Core returns the code)

    What to do: Units go with their symbol: GroceryAI reads no words in any language to understand a unit.

  • GTIN_NON_VALIDO

    «The barcode is not valid: check the digits.»

    What to do: 8, 12, 13 or 14 digits with the GS1 check digit; leave it empty if you do not have it.

  • OFFERTA_SUPERIORE_AL_PREZZO

    «The offer price is higher than the price: check the two columns.»

    What to do: The selling price is the full price; the offer price is the lower one.

How to send it

  • From the portalIn part

    Today: Products → upload a CSV file; the page's own template has code, name, price, barcode, brand, department, stock and sold online, and the preview shows rows to fix with their number and reason before anything is written. Coming: this guide's 24-column template, the Excel workbook, the # rows skipped, and «this file is the whole catalog».

  • From the APIAvailable

    PUT /v1/products (permission catalog:write), up to 500 products per batch: each product updates only the fields it carries; a field sent as null is removed. DELETE /v1/products/{sku} withdraws a product (switched off, never deleted). Snapshots (POST /v1/products/snapshots) withdraw what the whole catalog no longer carries.

  • Scheduled feedAvailable

    PUT /v1/catalog/feed with the address of your file: we read it every 24 hours (or every_hours). Our CSV or Excel template, or the Google Merchant / Meta Commerce product feed (XML or TSV) as it is.

Availability as measured on the live service on 30 October 2026.

Update two products (only the fields you send change)

curl

curl -X PUT "https://oxjqgjbiltoviwldailg.supabase.co/functions/v1/core-api/v1/products" \
  -H "Authorization: Bearer $GAI_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: listino-2026-11-02" \
  -d '{"products":[{"sku":"000201111","title":"Pasta Spaghetti n.5 500g","brand":"Barilla","price":1.29,"min_order_qty":500,"min_order_unit":"g","items_per_pack":1,"stock_qty":120},{"sku":"000301555","title":"Acqua naturale 6x1,5l","price":3.30,"items_per_pack":6,"pack_only":true}]}'

Node.js (18+)

const risposta = await fetch("https://oxjqgjbiltoviwldailg.supabase.co/functions/v1/core-api/v1/products", {
  method: "PUT",
  headers: {
    Authorization: `Bearer ${process.env.GAI_KEY}`,
    "Content-Type": "application/json",
    "Idempotency-Key": crypto.randomUUID(),
  },
  body: JSON.stringify({
    products: [
      { sku: "000201111", title: "Pasta Spaghetti n.5 500g", brand: "Barilla", price: 1.29,
        min_order_qty: 500, min_order_unit: "g", items_per_pack: 1, stock_qty: 120 },
      { sku: "000301555", title: "Acqua naturale 6x1,5l", price: 3.3, items_per_pack: 6, pack_only: true },
    ],
  }),
});
console.log(risposta.status, await risposta.json());

API documentation