Importing Products

What Kassly can and cannot bulk-load from a spreadsheet, the exact columns of each import sheet, and what happens when a row is wrong.

11 min read · Updated 27 Sep 2026

On this page

Kassly has four spreadsheet importers. Between them they cover sellable products, raw materials, recipes and stock quantities — and they are worth knowing about before you type a hundred rows by hand.

What the three sheets do

Sheet Where to start What it creates or changes Add-on needed
Products Catalog → Products → Import Creates and updates sellable products: prices, category, VAT, stock tracking, reorder points, opening stock and preferred supplier None
Ingredients Inventory → Ingredients → Import Creates and updates raw-material products, their costs, units, reorder points and opening stock None
Compositions Inventory → Compositions → Import Creates and updates recipes and their ingredient lines Recipe Costing (₱350 per branch each month)
Bulk Stock-In Inventory → Stock Levels → Bulk Stock-In → Import from Excel Adds quantities to products that already exist. Creates nothing None

Two sheets create catalog rows: the products sheet for things you sell, and the ingredients sheet for raw materials. They are kept apart on purpose — a product row never rewrites a raw material of the same name.

Only an Owner or a Manager can import.

How a sheet import works

All four follow the same three steps, and it is worth doing them in order:

  1. Download the template. It comes back already filled in with what you have, so you are editing your own data rather than guessing at a format.
  2. Fill it in. Edit an existing row to update that item; type new rows underneath to add.
  3. Upload it back. Kassly checks every row before it writes anything.

File format

Accepted .xlsx and .xls
Not accepted CSV, Google Sheets links, PDF, ODS
Maximum size 5 MB

CSV is not accepted anywhere. If you keep your list in a CSV, open it in Excel, Numbers or Google Sheets and save or export it as .xlsx first.

Each template also arrives with a second tab called How to use, which repeats the column rules next to the sheet itself. Do not rename the first tab — the importer looks for it by name and falls back to whichever sheet is open, which is not always the one you meant.

The products sheet

Start from Catalog → Products → Import. The Export button beside it downloads the same sheet without opening the dialog, which is the quickest way to get your product list into a spreadsheet.

Seventeen columns, in this order.

Col Heading Required Notes
A Name Yes What the item is called on the menu or shelf.
B SKU No Blank generates one. Keep it to update the product on a re-upload.
C Barcode No Scanned at the counter.
D Category On a new product A category that doesn't exist yet is created, so watch the spelling.
E Cost Price No Blank on a new product means 0.
F Selling Price On a new product What the customer pays.
G VAT No Vatable, VAT Exempt or Zero Rated. Defaults to Vatable.
H Track Stock No Yes or No.
I Stock Unit No One of the stock units, e.g. pc, kg, L. Only matters when Track Stock is Yes.
J Opening Qty No Stock to add at the branch you pick. Needs Track Stock set to Yes.
K Reorder Point No Warn when stock falls to this level. Only saved if you pick a branch.
L Show in POS No Yes or No.
M Active No Yes or No.
N Description No Shown on the online store and receipts.
O Sold By No Per piece (default) or By weight/volume/length.
P Supplier No The preferred supplier. Must match a name on your Suppliers page; capitals don't matter.
Q Supplier SKU No The supplier's own code for the item. Up to 100 characters.

How rows are matched and written:

  • A row updates the product with the same SKU (capitals don't matter), anywhere in your catalog. A row with a blank SKU matches a sellable product of the same name instead, and never a raw material.
  • A blank cell on an existing product leaves that field alone. Only what you type overwrites what is there, so deleting a column by accident changes nothing.
  • Pick a branch in the dialog if you fill in Opening Qty or Reorder Point — both are per branch.
  • Suppliers are matched, never created. A supplier carries contact details and a TIN the sheet can't supply, so add new suppliers on the Suppliers page first. A name that matches no supplier — or more than one — does not stop the upload: the rest of the row imports, the product's supplier is left as it was, and the dialog lists the skipped cells after the import. See Suppliers.

A sheet downloaded before the Supplier columns existed still imports; its empty P and Q columns simply leave suppliers alone.

The ingredients sheet

Seven columns, in this order.

Column Header Required What to put in it
A Name Yes What you call the raw material.
B SKU No Leave blank and one is generated. Keep the existing value to update rather than duplicate.
C Stock Unit Yes One of pc, g, kg, ml, L. Blank is read as pc. The column has a dropdown.
D Cost per Unit Yes The cost of one Stock Unit — not the price of a whole sack. Sub-centavo values are kept to four decimals.
E Opening Qty No Stock to add at the selected branch.
F Reorder Point No Warn when stock falls to this level.
G Notes No Recorded against the opening stock movement.

The template lists your existing ingredients first and leaves about fifty blank rows underneath to type into. It reads up to about 2,000 rows.

Two things to be careful about:

  • Opening Qty adds, it does not set. The template deliberately leaves it blank on existing rows. Fill it in on a re-upload and you will add that quantity a second time.
  • Opening Qty and Reorder Point need a branch. Both are per branch, so pick one in the dialog. Upload a sheet with quantities and no branch selected and Kassly stops you: "Pick a branch before importing opening quantities — stock has to land somewhere."

How rows are matched

For each row, Kassly looks for an existing ingredient:

  1. by SKU, ignoring capitalisation, then
  2. by exact name, ignoring capitalisation and surrounding spaces.

A match updates the name, unit and cost. No match creates a new ingredient.

Matching only looks at items already flagged as ingredients. A row named after an ordinary product you have not flagged will create a second, ingredient-flagged copy instead of updating it. Flag the item as an ingredient first — the Products page can do it in bulk — then import.

The compositions sheet

This one is in long format: one row per ingredient line. Rows that share the same Menu Item, Variant and Composition Name make up one recipe.

Column Header Required What to put in it
A Menu Item SKU One of A or B The item you sell. Matched first.
B Menu Item One of A or B Used when the SKU is blank.
C Variant No Leave blank if the recipe applies to every size or option.
D Composition Name Yes e.g. Chicken Adobo Standard. Repeat it on every row of the recipe.
E Yield No Servings the listed quantities make. Blank is read as 1. Repeat it on every row.
F Ingredient SKU One of F or G Must already exist.
G Ingredient One of F or G Used when the SKU is blank.
H Quantity Yes How much of the ingredient the whole yield uses.
I Unit No Defaults to the ingredient's stock unit. Any packaging conversion you have set up also works.
J Waste % No 0 to 99.99.
K Producible (commissary) No yes only for batches produced at a commissary. These are not deducted at the point of sale.

You need either the SKU or the name for the menu item, and either the SKU or the name for the ingredient. The SKU wins when both are filled in.

Ingredients must exist before you import recipes. The sheet cannot create them. Run the ingredients import first, or add them on the Ingredients page.

Two rules protect what you already have:

  • A recipe you leave out of the sheet is untouched. A partial sheet is never a mass delete.
  • A recipe that is in the sheet has its ingredient lines replaced by whatever the sheet says. Half a recipe in the sheet means half a recipe afterwards.

It reads up to about 5,000 rows, which is a lot of recipes.

The bulk stock-in sheet

This one changes quantities only — it never creates or edits a product. It also requires you to pick a branch.

Column Header Notes
A product_id Filled in for you. Do not edit or clear it.
B variant_id Filled in for you. Leave alone.
C Product Name For your reference.
D SKU For your reference.
E Variant For your reference.
F Current Qty What is on hand now. For your reference.
G Quantity to Add The one column you fill in. Must be at least 0.01.
H Cost Price Optional. The cost of this batch.
I Batch Number Optional.
J Expiry Date (YYYY-MM-DD) Optional.
K Notes Optional.

Leave a row's Quantity to Add blank and that row is skipped. Batch numbers and expiry dates are only meaningful with the Inventory Pro add-on — see Batch and expiry — and receiving against a purchase order is a different, better-documented path: see Receiving stock.

What happens to a bad row

All four importers are all-or-nothing. If one row is wrong, nothing at all is saved — you never end up with half a catalog and no idea which half.

Instead the dialog shows a list, in place, under the heading "Nothing was saved — fix these rows and upload again", with one line per problem naming the row number. For example:

Row 14: Cost per Unit must be a number of 0 or more.
Row 22: "Kalamansi" is repeated on row 9. Give each row a unique name or SKU.
Row 31: no ingredient found for "Patis". Add it on the Ingredients page (or import it) first.

The checks that will stop an import:

Sheet Rows are rejected for
Products Missing name; no category or selling price on a new product; a non-numeric or negative cost, price, opening quantity or reorder point; an unrecognised VAT setting, stock unit or Sold By value; a Yes/No column that is neither; an opening quantity on an item that doesn't track stock; the same SKU twice; the same name twice when the SKU is blank; a Supplier SKU over 100 characters.
Ingredients Missing name; an unrecognised stock unit; a non-numeric or negative cost, opening quantity or reorder point; the same SKU twice; the same name twice when the SKU is blank; a SKU that already belongs to a product that is not an ingredient.
Compositions A menu item or ingredient that cannot be found; a missing composition name; an ingredient that does not track stock, since it would never deduct; a quantity of zero or less; a yield of zero or less; waste outside 0–99.99; a variant name the item does not have; the same ingredient twice in one recipe.
Bulk Stock-In A quantity below 0.01.

Fix the sheet and upload it again. Nothing was written, so there is nothing to undo.

Entirely blank rows are ignored, not treated as errors — the templates ship with spare rows on purpose.

One thing is reported without rejecting the file: on the products sheet, a Supplier name that matches no supplier. That row still imports, and the dialog stays open after the import with a note naming the row, so you can add the supplier and set it on the product page.

Re-uploading a sheet

Re-uploading is the normal way to make bulk changes, and both catalog importers are built for it: download, edit, upload, repeat. The one thing that does not survive a careless re-upload is the ingredients sheet's Opening Qty, because it adds rather than sets. Clear that column before you upload again.

The Free plan and imports

New rows count against the Free plan's 50-item limit, and the check happens before anything is written:

"This file would add 40 new items but only 12 remain on your plan. Subscribe to any add-on to unlock unlimited SKUs."

Rows that update an existing item do not count. See Plans and add-ons.

Getting data out

Exports are separate from imports and more widely available:

  • Compositions — the Export CSV button on the Compositions page gives you the whole filtered list with cost per serving and cost percentage.
  • Products — the Export button on the Products page downloads the products sheet, pre-filled with your catalog.
  • Templates as exports — because every template arrives pre-filled with your current data, downloading one is also the quickest way to get your ingredient list or your recipes into a spreadsheet.

A full reference of every file format Kassly reads and writes is collected in Import formats.