Skip to content

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.

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
BRK-20A-1P,20A single-pole breaker,8.75,each,Graybar
WIRE-12-2-250,12/2 NM-B wire 250ft roll,89.00,box,Graybar
BOX-1G-PVC,1-gang PVC device box,1.10,each,

That third row has an empty supplier_name, which is fine — the column is 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_code is blank → "Missing sku_code"
  • description is blank → "Missing description"
  • unit_of_measure is blank → "Missing unit_of_measure"
  • unit_price isn't a number, or is negative → "Invalid unit_price: …"

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.

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.

  • Setting your labor rates — the other half of your bid pricing inputs
  • Building a bid (coming soon) — how SKUs flow into line-item pricing