Importing your SKU catalog from a CSV
Your SKU catalog is your materials price list — one row per part you buy (a breaker, a length of wire, a device box), each with a code, a description, a unit price, and a unit of measure. Flow's bid builder pulls from this list so line-item pricing starts from real numbers instead of guesses. Rather than type every part in by hand, you can upload a CSV and create the whole list at once.
Find it under Settings → Catalog → Import. Only a tenant owner can run an import.
Upload a .csv file with the columns below and click Import SKUs. Flow
reads each row, creates any new SKU, and updates any SKU whose code it already
has. When it finishes, it tells you how many rows it created, how many it
updated, and lists any rows it had to skip.
The exact columns
Your file needs a header row, then one data row per SKU. Column order does not
matter — Flow matches on the header name, not position. Header names are
matched case-insensitively and trimmed, so SKU_Code and sku_code both
work. Any extra columns are ignored.
| Column | Required? | What it is |
|---|---|---|
sku_code |
Required | Your code for the part. This is the identity of the row — see Import updates existing rows. |
description |
Required | Plain-English name of the part. |
unit_price |
Required | Price as a plain number (for example 12.50). Must be zero or greater. |
unit_of_measure |
Required | The unit you buy in — each, ft, box, and so on. Free text; Flow doesn't check it against a list. |
supplier_name |
Optional | Who you buy it from. See How suppliers are handled. |
default_waste_percent |
Optional | How much of this part you typically buy but don't install, as a percent — 10 means 10%. See The waste column. |
If your header is missing any of the four required columns, Flow rejects the whole file before importing anything and tells you which columns it expects.
Example CSV
sku_code,description,unit_price,unit_of_measure,supplier_name,default_waste_percent
BRK-20A-1P,20A single-pole breaker,8.75,each,Graybar,0
WIRE-12-2-250,12/2 NM-B wire 250ft roll,89.00,box,Graybar,15
BOX-1G-PVC,1-gang PVC device box,1.10,each,,
That third row has an empty supplier_name and an empty
default_waste_percent, which is fine — both columns are optional, and you can
leave any single cell blank.
What Flow checks, row by row
Flow validates each data row on its own. A row that fails is skipped and reported — the rest of the file still imports. A row is skipped when:
sku_codeis blank → "Missing sku_code"descriptionis blank → "Missing description"unit_of_measureis blank → "Missing unit_of_measure"unit_priceisn't a number, or is negative → "Invalid unit_price: …"default_waste_percentisn't a number, or is negative → "Invalid default_waste_percent: …"default_waste_percentis over 100 → "…this column is a percent, so 10 means 10%"
After the import runs you'll see a green summary like "Import complete: 12 created, 3 updated, 2 errors," and, if there were errors, an orange list naming each skipped row and why. The row number is the line number in your file — the header is row 1, so your first SKU is row 2.
Values may be wrapped in double quotes if they contain commas (for example a
description like "lug, 2-hole"), and a doubled quote "" inside a quoted
value is read as one literal quote.
Import updates existing rows in place
The import is an upsert, keyed on sku_code:
- If a SKU with that code doesn't exist yet, Flow creates it.
- If a SKU with that code already exists, Flow updates it in place — overwriting the description, unit price, unit of measure, and supplier from your file, and stamping a fresh "last refreshed" time.
So you can re-upload an updated price list any time and Flow will refresh the
prices you already have rather than making duplicates. The sku_code is what
ties an upload back to an existing row, so keep your codes stable.
One thing to watch: an update overwrites the supplier from your file every
time. If an existing SKU is linked to a supplier and you re-import that row with
supplier_name blank (or without the column at all), Flow clears the
supplier link on that SKU. Include the supplier name on every row you want to
keep linked.
The waste column
default_waste_percent is how much of a part you buy but don't install — the
offcuts, the bends, the wire nut that ends up in the insulation. Conduit is
usually about 10%, Romex about 15%, wire nuts about 20%, and a device box is 0%
because you buy seven and install seven.
Put it on the part once, and every takeoff line you add for that part starts from it. You can still change the waste on any individual line — a run that's unusually clean or unusually chopped up is a per-job fact — but you no longer have to remember the number every time. Left blank, a line used to price at 0% waste, which quietly under-buys.
Two details worth knowing:
- It's a percent, not a multiplier. If your spreadsheet writes
1.10for 10% conduit waste, write10here. Flow refuses anything over 100, because that's almost always a multiplier typed by mistake. - Blank means "not stated", not "zero". If you re-upload a price list
without the column, or with that cell empty, Flow leaves the waste you already
had alone. To actually set a part to no waste, write
0.
How suppliers are handled
supplier_name is optional. When you do provide one, Flow looks for a supplier
by that exact name:
- If it finds one, it links the SKU to that existing supplier.
- If it doesn't, it creates a new supplier with that name for you (marked as sourced from CSV upload).
Matching is by exact name, so Graybar and Graybar Electric become two
different suppliers. Keep the spelling consistent across your file.
What's not in v1 yet
Being straight with you about the current limits:
- This importer only does SKUs (and the suppliers they name). Your catalog also includes task codes and other reference data, but this screen doesn't import those — only the materials price list. Suppliers get created only as a side effect of a SKU row that names them.
- No export and no template download. Flow can't hand you a starter CSV or export your current catalog. You build the file yourself; the column list above is the spec.
- The import isn't all-or-nothing. Rows are saved as they're processed, so a file with some good rows and some bad ones leaves the good rows imported and reports the bad ones. There's no undo — to back out a bad import, re-upload corrected rows.
- Deletion isn't supported. Leaving a SKU out of a later upload doesn't remove it; the importer only creates and updates. Remove obsolete parts elsewhere.
- The parser is simple. It reads a plain comma-separated file with quoted fields. It doesn't handle other delimiters, and — unlike the data rows — the header line isn't quote-aware, so keep your header names plain.
Who can do this
Catalog import is owner-only. If the import screen isn't available to you, sign in as the tenant owner.
Related
- Labor roles and payroll burden — the other half of your bid pricing inputs
- Building a bid — how catalog parts flow into the materials takeoff