Import Formats
The exact spreadsheet layout for every bulk import Kassly accepts, column by column.
17 min read · Updated 25 Oct 2026
On this page
- Read this before you build a spreadsheet
- Products
- Products with variants
- Same name, different category
- Ingredients
- How rows are matched
- Opening quantities
- Plan limits
- Bulk Stock-In
- Recipes
- What gets rejected
- Create versus update
- Customers
- How customer rows are matched
- Suppliers
- Imports Kassly does not have
- When an import fails
Kassly accepts six bulk imports, all of them Excel spreadsheets. The products, customers and suppliers imports also take a CSV, and the products import takes a Loyverse items export uploaded as-is (see Importing products). This page is the column-by-column reference for each.
| Import | Where | What it does |
|---|---|---|
| Products | Products page → Import | Adds and updates sellable products and their variants, with opening stock and a preferred supplier |
| Ingredients | Ingredients page → Import | Adds and updates raw materials, with opening stock |
| Bulk Stock-In | Inventory → Bulk Stock-In → Import from Excel | Adds quantity to products you already have |
| Recipes | Compositions page → Import | Builds recipes and their ingredient lines |
| Customers | Customers page → Import | Adds and updates customers, with their credit limit, payment terms and billing details |
| Suppliers | Suppliers page → Import | Adds and updates suppliers, with their credit days |
Read this before you build a spreadsheet
Three rules apply to every import, and ignoring any of them will cost you an afternoon.
Always start from the template Kassly gives you. Every import has a Download template button that produces an .xlsx pre-filled with your own data. Fill that in and upload it back.
Kassly reads columns by position, not by heading. The heading row is there for you to read; the importer skips it and takes column A as column A. So:
- Do not insert, delete, or reorder columns. A sheet with the right headings in the wrong order imports the wrong data into the wrong fields, without complaining.
- Renaming a heading is harmless, with one exception: the products sheet's Variant column is found by its heading, so keep that one as it is.
- Adding columns to the right of the last one is harmless.
Everything is all-or-nothing. One bad row rejects the whole file with a list of what to fix, and nothing is saved. You never end up with half a catalogue and no idea which half. (One exception, on the products sheet: a Supplier name that matches no supplier is reported after the import instead of rejecting the file.)
File rules, the same for every import:
| Format | .xlsx or .xls. Products, Customers and Suppliers also accept .csv |
| Maximum size | 5 MB |
| Data starts on | Row 2 |
| Who can import | Owner or Manager only |
Products
Adds and updates the things you sell.
- Template:
products-template.xlsx, pre-filled with your existing sellable products. The Export button on the Products page downloads the same file. - Sheet name:
Products. Helper tabsLists(your categories and suppliers) andHow to usecome with it. - Matching: by SKU, then by name within the row's category when the SKU is blank. A blank cell on an existing product leaves that field as it is.
- Variants: rows that share a Name and Category and fill in Variant are one product with variants. See Products with variants.
| 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. |
| R | Reorder Qty | No | How much Inventory → Reorder suggests ordering at the branch you pick. Blank leaves it as it is. |
| S | Variant | No | A size or flavour, e.g. 16oz, Iced, Strawberry. Up to 255 characters. Found by its heading, not its letter. |
Supplier (P) is matched against your Suppliers page by name and never creates a supplier. An unknown or ambiguous name imports the rest of the row and leaves the supplier as it was, with a note after the import. A sheet from before columns P and Q existed still imports.
Variant (S) is the one column Kassly finds by its heading: any column headed
Variant (capitals don't matter) is read, wherever it sits. A sheet with no
such column imports as before, every row a single product, so a sheet saved
before the column existed still works.
Products with variants
Give each variant its own row, with the same Name and Category and the size or flavour in Variant:
| A · Name | B · SKU | D · Category | E · Cost Price | F · Selling Price | H · Track Stock | J · Opening Qty | S · Variant |
|---|---|---|---|---|---|---|---|
| Milk Tea | MT-REG | Drinks | 30 | 85 | Yes | 24 | Regular |
| Milk Tea | MT-LRG | Drinks | 38 | 105 | Yes | 24 | Large |
| Fruit Soda | Drinks | 15 | 45 | Green Apple | |||
| Fruit Soda | Drinks | 15 | 45 | Strawberry |
That is two products: Milk Tea with two variants, and Fruit Soda with two. The other columns are left blank.
| Column | Read from |
|---|---|
| SKU, Barcode, Cost Price, Selling Price, Opening Qty, Reorder Point, Reorder Qty | Each row, for that variant |
| VAT, Track Stock, Stock Unit, Show in POS, Active, Description, Sold By, Supplier, Supplier SKU | The product. Fill them on any row; rows that fill one in must agree |
- Two to 50 variants per product. A new item with only one Variant row is rejected; clear its Variant to sell it as a single item.
- Selling Price is required on a new variant.
- SKU is the variant's own. Blank generates the product's SKU plus
-1,-2and so on. A variant row may not use a product's SKU, and a row without a Variant may not use a variant's SKU. - Matching: an existing variant is found by its SKU, then by its name within the product. Variants missing from the sheet are left alone.
- Plan limit: a product with variants counts as one item, whatever the number of rows.
Same name, different category
A row without a SKU is identified by its Name within its Category, so the same name can appear once in each category. Rows that will be rejected:
- The same name twice in one category, with no SKU and no Variant.
- A blank Category on a row whose name the sheet lists under more than one category.
- A name your catalog holds more than once, on a row with neither Category nor SKU.
Ingredients
Adds and updates the raw materials you cook or build with — flour, cooking oil, shampoo, brake fluid.
- Template:
ingredients-template.xlsx, pre-filled with your existing ingredients plus 50 blank rows - Sheet name read:
Ingredients, falling back to whichever sheet is active - Row limit: 2,000 rows. Rows past that are silently ignored — split a larger catalogue into several files.
- Add-on: none. Available on the Free plan.
| Col | Heading | Required | Format and notes |
|---|---|---|---|
| A | Name |
Yes | What you call the raw material, e.g. Pasta Sauce |
| B | SKU |
No | Leave blank and Kassly generates one prefixed ING. Keep the existing SKU to update rather than duplicate. |
| C | Stock Unit |
No | One of pc, g, kg, ml, L. Case-sensitive — L is valid, l is not. Blank means pc. The template gives you a dropdown. |
| D | Cost per Unit |
Yes | A number, 0 or more. What one stock unit costs — cost per gram, not the price of the sack. Rice at ₱45/kg tracked in grams is 0.045. |
| E | Opening Qty |
No | A number, 0 or more. Stock to add at the chosen branch. |
| F | Reorder Point |
No | A number, 0 or more. Only saved if you pick a branch. |
| G | Notes |
No | Free text, recorded against the opening-stock movement |
| H | Reorder Qty |
No | A number, 0 or more. How much Inventory → Reorder suggests ordering at the branch you pick. Only saved if you pick a branch; a blank cell leaves it as it is. |
How rows are matched
- If SKU is filled in and matches one of your existing items, that item is updated — only its name, stock unit and cost.
- If SKU is blank, Kassly matches on Name, exactly, ignoring case.
- No match either way, and a new ingredient is created: stock-tracked, hidden from the POS, priced at zero.
Rows that will be rejected:
- The same SKU twice in one file.
- A SKU that already belongs to something that is not an ingredient.
- Two rows with the same name and no SKU.
Opening quantities
If any row has an Opening Qty above zero, you must pick a branch in the import dialog. Stock has to land somewhere.
Blank out Opening Qty before you re-upload. The template leaves it blank on existing rows for exactly this reason. Opening Qty adds stock; uploading the same file twice adds it twice.
Plan limits
New ingredients count against your plan's product limit — 50 on the Free plan. If the file would take you over, Kassly refuses the whole upload and tells you how many places are left. Any active add-on lifts the limit entirely.
Bulk Stock-In
Adds quantity to products you already have, with optional cost, batch and expiry. Use it for a big delivery, or to load your opening stock at go-live.
- Template:
bulk-stock-in-template.xlsx— you must choose a branch to download it - Sheet read: whichever sheet is active
- Row limit: none
- Add-on: none. Available on the Free plan.
This import only works with a template you downloaded yourself. Columns A and B hold Kassly's internal product IDs, and they are how a row is matched. They are hidden in the template. A sheet you built by hand, or one another store downloaded, will fail on every row with Product not found.
| Col | Heading | Read? | Required | Notes |
|---|---|---|---|---|
| A | product_id |
Yes | Yes | Kassly's product ID. Hidden. Never edit or clear it. |
| B | variant_id |
Yes | No | Kassly's variant ID. Hidden. |
| C | Product Name |
No | — | For you to read. Editing it does nothing. |
| D | SKU |
No | — | For you to read |
| E | Variant |
No | — | For you to read; — when there is no variant |
| F | Current Qty |
No | — | The branch's quantity when you downloaded the template |
| G | Quantity to Add |
Yes | Yes | At least 0.01. Blank or 0 skips the row entirely — that is how you ignore products you are not receiving. |
| H | Cost Price |
Yes | No | Cost per unit for this delivery |
| I | Batch Number |
Yes | No | Needs batch tracking to be useful |
| J | Expiry Date (YYYY-MM-DD) |
Yes | For some items | Exactly that format, e.g. 2027-03-15. Required for an item set to Require expiry date on stock-in: a row without it rejects the file |
| K | Notes |
Yes | No | Free text |
The workflow is: download the template for the branch, delete nothing, type quantities into column G only on the lines you actually received, and upload.
Quantity to Add adds. It does not set. A product at 40 with
10in column G ends up at 50, not 10. Upload the same file twice and you have added twice. To correct a wrong quantity, use a stock adjustment instead — see Stock adjustments.
There is no Unit column. Everything is in the product's own stock unit.
Recipes
Builds recipes — which ingredients, how much of each, and how much waste. One row per ingredient line, so a recipe with six ingredients is six rows that repeat the same menu item and composition name.
- Template:
compositions-template.xlsx, pre-filled with your existing recipes in the same layout - Sheet name read:
Compositions, falling back to whichever sheet is active - Row limit: 5,000 rows. Rows past that are silently ignored.
- Add-on: needs the Recipe Costing add-on (₱350 per branch each month), or any bundle that includes it.
| Col | Heading | Required | Notes |
|---|---|---|---|
| A | Menu Item SKU |
One of A or B | Tried first, matched ignoring case |
| B | Menu Item |
One of A or B | Exact name, ignoring case. Also the fallback if the SKU in A matches nothing. |
| C | Variant |
No | Must be the name of an existing variant of that item |
| D | Composition Name |
Yes | What this recipe is called, e.g. Regular, Large |
| E | Yield |
No | How many servings one batch makes. Greater than 0; blank means 1. Put it on every row of the recipe. |
| F | Ingredient SKU |
One of F or G | Tried first |
| G | Ingredient |
One of F or G | Exact name, ignoring case |
| H | Quantity |
Yes | How much of the ingredient, greater than 0, in the unit in column I |
| I | Unit |
No | Blank falls back to the ingredient's own stock unit |
| J | Waste % |
No | 0 to 99.99. Blank means 0. |
| K | Producible (commissary) |
No | yes, y, true or 1 for yes. Anything else, blank included, is no. The template writes yes / no. |
What gets rejected
- A menu item or ingredient Kassly cannot find. Ingredients must already exist — import them first.
- An ingredient that does not have stock tracking switched on. It would sit in the recipe and never actually deduct, so Kassly refuses it rather than let you believe it works.
- A variant name that item does not have.
- The same ingredient listed twice in one recipe.
Create versus update
A recipe is matched on menu item + variant + composition name, ignoring case.
- New combination → a new recipe.
- Existing combination → the recipe's yield and commissary flag are updated, and all its ingredient lines are replaced by the ones in your sheet.
- Not in your sheet at all → left completely alone. A partial upload is never a mass delete.
That means an existing recipe must be listed in full. Uploading a file with one line of a six-ingredient recipe leaves you with a one-ingredient recipe.
Note that Kassly is forgiving in one place: if the SKU in column A or F matches nothing, it quietly falls back to the name in the neighbouring column. So a typo'd SKU with a correct name still imports.
Customers
Adds and updates your customer list. Moving from another system, or from a notebook of suki and their utang limits, is the usual reason.
- Template:
customers-template.xlsx, pre-filled with your existing customers (up to 5,000) plus 50 blank rows - Sheet name read:
Customers, falling back to whichever sheet is active. A.csvin the same column order works too. - Row limit: 5,000 rows. A longer file is refused with a note to split it; nothing is cut off silently.
- Add-on: needs Customer Memory & Promos, like the Customers page. Importing needs permission to edit customers (Owner and Manager by default); a Cashier can add customers at the counter but cannot import.
| Col | Heading | Required | Notes |
|---|---|---|---|
| A | Name |
Yes | As it should appear on receipts |
| B | Phone |
No | Digits, spaces, dashes, brackets and +. 0917 123 4567 and +63 917 123 4567 count as the same number. The template formats this column as text so Excel keeps the leading zero; if Excel drops it anyway, Kassly puts it back on a 10-digit 9… number. |
| C | Email |
No | Must be a valid address |
| D | Type |
No | Regular, Wholesale, Senior Citizen or PWD. Blank on a new customer means Regular. The template gives you a dropdown. |
| E | Business Name |
No | For a customer you bill as a business |
| F | TIN |
No | Stored as typed |
| G | Billing Address |
No | Up to 1,000 characters |
| H | Credit Limit |
No | A number, 0 or more. The most the customer may owe on credit. 0 means no limit. |
| I | Payment Terms (days) |
No | Whole days from 0 to 365, e.g. 30 |
| J | Senior Citizen ID |
No | The OSCA ID number |
| K | PWD ID |
No | The PWD ID number |
| L | Notes |
No | Up to 2,000 characters |
Business Name, TIN, Billing Address, Credit Limit and Payment Terms are not on the customer form, so this sheet is how you set them in bulk. A sales invoice uses the business details for its Bill To block when you leave that blank, and sales order documents print the TIN and billing address.
How customer rows are matched
- A row whose phone belongs to an existing customer updates that customer.
- Otherwise a row whose email belongs to one updates that customer.
- Otherwise a row whose name (ignoring case) matches exactly one existing customer updates them, but only if that customer's own phone and email can't contradict the row. A new Maria Santos with her own number never overwrites the Maria Santos already on file; she is added as a second customer.
- No match, and a new customer is created.
A blank cell never erases anything. On an existing customer it leaves that detail as it is, so a sheet with only names and phones is safe to upload.
Rows that will be rejected:
- The same phone, or the same email, on two rows.
- Two rows that both point at the same existing customer.
- A phone that belongs to one customer and an email that belongs to another.
- A name shared by two or more existing customers, with no phone or email to tell which one is meant.
- Two new rows with the same name and neither a phone nor an email.
Suppliers
Adds and updates the businesses you buy from: the same fields as the Add Supplier form.
- Template:
suppliers-template.xlsx, pre-filled with your existing suppliers plus 50 blank rows - Sheet name read:
Suppliers, falling back to whichever sheet is active. A.csvin the same column order works too. - Row limit: 2,000 rows. A longer file is refused with a note to split it.
- Add-on: needs Inventory Pro, like the Suppliers page.
| Col | Heading | Required | Notes |
|---|---|---|---|
| A | Name |
Yes | The business name. This is how a row is matched. |
| B | Contact Person |
No | The person you deal with |
| C | Phone |
No | Up to 50 characters |
| D | Email |
No | Must be a valid address. Purchase orders are emailed here. |
| E | Address |
No | Up to 1,000 characters |
| F | TIN |
No | Stored as typed |
| G | Credit Days |
No | Whole days from 0 to 365. New purchase orders for this supplier start on credit with these days. Blank on a new supplier means you pay on delivery. |
A row updates the supplier with the same name, ignoring case, or adds a new one. That means renaming a supplier in the sheet adds a second supplier: rename on the Suppliers page instead. As with customers, a blank cell leaves that detail as it is.
Rows that will be rejected:
- The same name on two rows.
- A name that two of your existing suppliers already share. Rename one first.
Imports Kassly does not have
Be straight about this, because older documentation claimed otherwise:
- There is no staff or employee import.
- There is no stock count import.
- CSV only works for Products, Customers and Suppliers. For the others, open the CSV in Excel or Google Sheets, paste the values into the Kassly template, and save as .xlsx.
If you are working from a "CSV Import Format" appendix with columns like
name,sku,barcode,price,cost_price,stock— that came from a previous version of this manual and describes an importer that does not exist. Nothing reads those columns. The formats above are the complete list.
When an import fails
The error list names the row number and the problem, one line per bad row. Fix them in your spreadsheet and upload the same file again — nothing was saved, so there is nothing to undo.
The exception is Bulk Stock-In, which reports the failure but shows less detail per row. If it will not go through, the cause is almost always an edited or missing column A.