CSV import

The fastest way to fill a fresh organization is a CSV import — the self-setup path most new customers take. One upload can carry products, serialized items, quantity stock, and meter readings together. You run it from Admin → Import; it needs the products.create and items.create permissions.

One file, a "kind" column

Every row starts with a kind column that says what it is — product, item, stock, or reading (the plural forms work too). A single file may mix all four. The importer runs in two passes, so an item or stock row may reference a product defined anywhere in the same file — earlier or later — by its name (plus model) or by a short ref you assign. Products are matched by name + model and are idempotent: one that already exists is skipped with a warning, not duplicated.

The four row kinds

kindWhat it createsKey columns
productA catalog definition (manufacturer, model, tracking mode).name, manufacturer, model, category, tracking_mode, department
itemA serialized asset that hangs off a serialized product.product / product_ref, serial_number, condition, location
stockAn opening quantity for a quantity-tracked product, as a purchase movement.product / product_ref, location, quantity, min_quantity, unit
readingA meter reading against an existing item (by asset tag).asset_tag, meter, value, read_at

The exact header row for each kind:

products
kind,name,manufacturer,model,category,tracking_mode,description,url,ref,department
items
kind,product,product_model,product_ref,serial_number,condition,location,purchase_date,purchase_price,currency,supplier,notes
stock
kind,product,product_model,product_ref,location,quantity,min_quantity,unit
readings
kind,asset_tag,meter,value,read_at,note

Download a template

From Admin → Import, use the Download template buttons to get a ready CSV with the header row already in place — one each for products, items, and stock. Fill it in a spreadsheet, export as CSV (UTF-8), and upload. The same screen also offers a starter template library of common theatre gear, so a small org can skip the spreadsheet entirely.

Locations and categories by name

Put locations and categories in as name paths with / between levels — e.g. Main stage / Rack B. A path that already exists is matched (case- insensitively); an unknown path is an error unless you tick create missing, which spawns the nodes parents-first. Creating locations needs locations.manage; creating categories needs admin.taxonomy.manage.

How validation works

  • Two steps. You upload, get a per-row report (each row marked ok, warning, or error), then confirm. Apply re-runs the same validation server-side — nothing changes until you commit.
  • Errors block the file. Nothing lands while any row is in error, unless you choose to skip error rows and import only the clean ones.
  • Warnings still import — a skipped duplicate product, or a path that will be created, is a warning, not a stop.
  • Up to 2000 rows per file (imports run synchronously within the Worker's limits). Split a bigger dataset across files.

Field rules

ColumnRule
tracking_modeserialized (default) or quantity.
departmentOptional. The owning department's name or key; empty means Shared. An unknown department errors the row.
conditionnew, good (default), fair, or poor.
purchase_dateISO date, e.g. 2026-03-14.
purchase_priceA decimal amount (up to 2 places); currency is a 3-letter code, defaulting to the org currency.
quantityA whole number ≥ 1 (stock rows).
product vs item vs stockitem rows need a serialized product; stock rows need a quantity product — a mismatch errors.
valueA non-negative meter value; read_at is an ISO date or datetime.
Stock rows land as purchase movements on the ledger — the same append-only path every other stock change uses — so your opening balances are auditable from day one. See Getting started for the setup order (locations and categories first), and Items & products for what the catalog layer holds.