Import and export

Bring records into Carbon from a CSV, and download any table's current view as a CSV.

Carbon supports CSV export for every shared data table and CSV import for selected entities. Export runs in the browser against the current table result set. Import uses a guided mapping workflow and a privileged background function that inserts or updates records in a transaction.

Exporting a table to CSV

Use Download CSV in a data table's header. Every table built on Carbon's shared data grid includes this action.

The download reflects what you are currently looking at, not a full server dump:

  • Only the rows on the current page / result set are written. Filter or search first to widen or narrow what lands in the file, then export.
  • Only the columns visible in your current saved view are included, in the order you've arranged them. Hidden columns are left out; the synthetic select, expand, and actions columns never export.
  • The CSV headers are the same human labels shown in the grid.

For id-bearing columns like item, supplier, employee, and customer, the export substitutes the readable name for the raw id so the file is legible. A few columns are marked export-only: they stay hidden in the grid but are always written to the CSV.

NOTE

The file is always named data.csv

Export builds the file entirely in your browser and downloads it as data.csv with no server round-trip. Rename it after downloading if you're exporting several tables.

Every Carbon data table exports its current view. Filter and arrange columns first, since the export mirrors exactly what's on screen.

What you can import

Bulk import is available only for supported entities. Import each entity from the Bulk Import menu on its list screen:

FieldType
From the customers list. Optionally rides address, payment term, and contact-style fields on the same row.
From the suppliers list. Also carries address, payment term, shipping method, and incoterm fields.
From each item type's list. A single row can optionally create a supplier-part link, set purchasing lead time, and seed unit cost alongside the item.
From the work centers list, including labor, machine, and overhead rates and a location.
From the processes list.
From Inventory → Quantities. Adds opening stock for items that already exist, one import per . See Opening stock.

The Bulk Import menu on the parts and tools lists also offers three method imports that load bills of materials and operations: BOM, Operations, and Parts with Methods, which creates parts and their full BOM and routing together. These are row-typed CSVs: each row is tagged PART, BOM, BOP, STEP, TOOL, or PARAM and names its parent part.

A method import adds to the make method that is already there. With Make Method Version blank it writes into the highest version that is not archived; a version you name must be a number above 0 with at most 2 decimals. New BOM lines go after the existing ones. An Op No is the operation's order, so it must be a number: one that matches an existing operation's order adds its steps, tools, and parameters to that operation, and 10, 10.0 and 010 all name the same operation. Rows already on the method (the same material, operation, step name, tool, or parameter key) are skipped and listed, so a file can run again safely. The import changes only a Draft version and follows the same change notice and release locks as the BOM and BOP editors. A part it refuses is listed with the reason, and none of its rows are written. When release control is set to warn, the import writes into a released revision as the editors do, and the results list that part under a warning.

Blank cells take the values the editors fill in: a BOM line with no Unit of Measure takes the material's own unit, and an operation with no Operation Type or Operation Description takes its process's type and name. The import also refuses what the editors refuse: a BOM line that is the part itself or a tool or service, a tool that is not a tool item, a negative quantity, time or cost, and a step whose maximum is below its minimum. An Inspection operation needs an Inspection Plan, which a CSV cannot carry, so add Inspection operations in the app.

HEADS UP

Fixed assets aren't importable here

The models list a fixedAsset import shape, but the import function's own table list omits it, so a fixed-asset CSV is rejected. Create fixed assets in the app. BOM lines have no table import of their own (methodMaterial); add them with the BOM method import above or in the app.

The import flow

Import uses a four-step wizard followed by a background write.

Upload. Click Bulk Import, pick the entity, and drop your CSV. Carbon parses it in the browser to read the header row, and uploads the file to your company's private storage. You can download a template for the entity first: it's a one-row CSV whose header is every field label and whose single data row is a hint marking each column REQUIRED or optional and listing valid enum values. Overwrite that hint row with your data and re-upload.

Map columns. Match each of your CSV columns to a Carbon field. Required fields must be mapped; anything you leave as N/A is skipped. For enum fields (like or ), you also map your raw values to Carbon's, and the wizard fuzzy-matches obvious ones for you (a CSV "B" proposes "Buy"). Some lookups can be created inline: a type or status that doesn't exist yet can be added without leaving the wizard.

Validate. The mapped data is checked against the entity's schema. Missing a required field or an unparseable value surfaces before anything is written.

Import. Submitting posts your mappings to Carbon, which invokes a privileged import function. It re-downloads the file from storage, applies your column and enum mappings, decides insert-versus-update per row, and writes the results inside a database transaction.

NOTE

Enum values fall back to a default

When a CSV value has no mapping to a Carbon enum, the row imports with that field's configured default rather than failing. An unmapped "Replenishment System" cell, for example, lands as "Buy and Make". Map your values deliberately if the default isn't what you want.

Insert, update, or skip

For standard entity imports, re-importing the same identifiers updates existing records instead of duplicating them. The importer classifies each row before writing:

Off-track
Update
An existing record matches. Carbon matches first by the CSV's Unique ID (via a stored CSV-to-record mapping), then falls back to matching by Name, and updates that record in place.

Matching by Unique ID uses a shared external-mapping table keyed to the csv source, so the second import of a file with the same ids takes the update path instead of creating duplicates. If a record was created in the app and you later import a CSV using the same Name, the name fallback catches it and updates rather than duplicates.

NOTE

Custom fields aren't populated on import

Import writes the entity's standard fields plus its documented side-tables (address, payment, supplier-part, cost). It does not map into per-company custom fields. Set those in the app after importing, or via the record's own form.

Opening stock

The Inventory → Quantities table carries three imports that load on-hand stock, typically once during go-live. Each row is posted as a Positive Adjmt. through the same posting core as a manual inventory adjustment: an item ledger entry at the item's current cost, dated today, and a line pair on one inventory adjustment journal for the whole file. A row whose item has zero cost posts no journal lines. Inventory adjustment business rules are not evaluated on import. These imports only ever add stock; they never reduce or set a quantity.

Pick the import that matches the item's tracking type. A row whose item is tracked differently is reported as an error naming the right import, and Non-Inventory items can't be stocked at all.

FieldType
For items tracked as Inventory. Columns: Part Number, Revision, Location, Storage Unit, Quantity, Comment.
For items tracked as Batch. Columns: Part Number, Revision, Location, Storage Unit, Batch Number, Quantity, Expiration Date, Comment. Each row creates a new batch.
For items tracked as Serial. Columns: Part Number, Revision, Location, Storage Unit, Serial Number, Expiration Date, Comment. There's no Quantity column: every row is one unit.

Rules shared by all three:

  • Part Number + Revision must match an existing item; a blank Revision means 0. An unknown item is an error.
  • Location is mapped to one of your locations in the wizard. Storage Unit is optional and matched by name within that location, ignoring case. A named storage unit that doesn't exist there is an error; the import never creates one.
  • Quantity must be a positive number.
  • Expiration Date is optional and must be written YYYY-MM-DD. Left blank, an item with a fixed-duration shelf life gets its expiry calculated the same way a manual adjustment does.
  • There's no Unique ID column, so these imports don't record CSV id mappings.
HEADS UP

Re-importing an Inventory Quantities file adds the stock again

Inventory-tracked rows have no natural key, so every valid row posts, every time. Importing the same file twice doubles the quantities. Batch and serial rows are protected: a batch or serial number that already exists on that item (in any status) is skipped, and a number repeated in the file is skipped after its first row. The same serial number on two different items is allowed.

Errors and partial failures

Import handles validation failures per row. Invalid rows are reported while valid rows continue. Results include:

  • inserted and updated — counts of records written.
  • errors — rows you should fix and re-import (missing required data), each with its row number, a reason, and the original cell values.
  • skipped — rows intentionally not written (in-file duplicates, already-existing), same shape.

A BOM, Operations, or Parts with Methods import counts parts as inserted and updated, and also reports how many BOM lines, operations, steps, tools, and parameters it added. The results read, for example, "4 parts updated. Added: 6 BOM lines. 0 rows need fixing, 2 rows skipped."

Because the results carry each failed row's original cells, the wizard's results view shows you exactly which rows to fix without re-parsing your file. A hard failure (the file can't be downloaded, or an unexpected database error) is the only case that fails the whole import and returns an error message instead of a per-row report.

HEADS UP

Import bypasses row-level security by design

The import function writes with a privileged database connection that bypasses RLS, so your permission to import is checked once, up front, when you submit: sales for customers, purchasing for suppliers, parts for items and methods, production for work centers and processes, inventory for storage units and opening stock. If you lack that module's update permission, the import is refused before any write. Opening stock imports also need inventory create permission, the same as a manual inventory adjustment.