Importing CSV files
How to prepare Products, Customers and Pricing Rules files for PriceRules: the columns each import accepts, how values are checked, what happens when something is wrong, and how to fix it.
Products
SKUs, names, base prices and categories.
Customers
Customer codes, names and countries.
Pricing Rules
Fixed prices and discounts per customer and product.
Quick start
Checklist before you upload
Most rejected imports fail one of these checks.
- Import in order: Products, then Customers, then Pricing rules.
- Save the file as
.csv(UTF-8), no larger than 50 MB, with the header row on the first line. - Name your headers like the fields on this page (
sku,name,base_price, …) so they're matched automatically. - Fill every required field on every row.
- Keep SKUs and customer codes unique within a file, and spelled the same way in every file.
- In pricing rules, use one customer code and one SKU per row, and plain whole numbers for
minimum_quantityandpriority. - Every row must pass. If a single row is invalid, nothing from the file is imported.
Dependencies
Import order
Pricing rules point to products and customers, so those must exist first.
Products
No prerequisites. Required before any pricing-rule import.
Customers
No prerequisites. Required before importing a pricing-rules file, because every rule row names a customer code.
Pricing Rules
Can only start when your workspace has at least one product and one customer, and each row's SKU and code must exist.
Enforced, not just recommended
Onboarding vs. dashboard
Both use the same upload, mapping, validation and saving steps, and the same rules on this page. The differences:
- During onboarding, progress and results are shown on the setup screen itself. In the dashboard, starting an import opens that import's own page, and every import is listed under Imports in the dashboard.
- Onboarding presents the Customers step as optional and also lets you create a pricing rule by hand instead of importing a file. Hand-made rules don't need customers — but a pricing-rules file still does.
- Onboarding also offers sample data, which is imported through the same pipeline.
Workflow
How imports work
What happens between choosing a file and seeing it completed.
- 01
Choose a file
Open the import for Products, Customers or Pricing rules (during onboarding, or from the Import button on each page in the dashboard). The browser only accepts
.csvfiles up to 50 MB, reads the header row, detects the delimiter and previews the first rows. - 02
Map your columns
PriceRules suggests which column fills each field, based on the header names. Check every suggestion and change any that are wrong. Required fields (marked
*) must be mapped before you can start; optional fields can be set to Unmapped. Columns you don't map are ignored. - 03
Start the import
Your file is uploaded and the server checks that the import can start: pricing-rule files need products and customers to exist, only one import of each type can run at a time, and your plan's monthly import allowance must not be used up. If a check fails, nothing is queued and the reason is shown next to the Start button.
- 04
Queued
Imports in the same workspace are processed one at a time; an import started while another is running waits its turn.
- 05
Plan capacity check
Before any row is saved, PriceRules checks that the records in the file fit your plan (see Limits). If they don't, the whole file is rejected.
- 06
Validation
Every row is checked against the rules on this page — including duplicates and, for pricing rules, references to existing customers, products and rules. If any row has a problem, the whole file is rejected and nothing is saved.
- 07
Saving
Rows are saved in batches of 1,000. Products and customers are created or updated; pricing rules are always created as new rules. The progress bar follows the batches.
- 08
Pricing engine update
For products and pricing rules, the pricing engine is refreshed so the API returns the new prices. Customer imports skip this step. An import is only marked Completed after this step succeeds.
How it ends
Reading the error log
- Download Error Log (.csv) contains every invalid row — not just the sample shown on screen — with an extra
pricing_errorcolumn listing that row's problems (for exampleSKU: Missing). - Row numbers count data rows: row 1 is the first line after the header (line 2 in a spreadsheet). Blank lines are skipped but still counted, so the numbers match your file.
- The products error log is separated with semicolons (
;); the customers and pricing-rules logs use the same delimiter as your file. - The on-screen results group problems under Errors and Duplicates. Both block the import.
CSV
Preparing your CSV
Rules that apply to all three imports.
File format
- A
.csvfile of at most 50 MB. Excel workbooks (.xlsx) aren't accepted — export them as CSV. - The first line is the header row; every following line is one record.
- The delimiter is detected automatically from your file: comma (
,), semicolon (;), tab or pipe (|). Use one delimiter throughout the file. - Wrap a value in double quotes when it contains the delimiter, for example
"Hex Bolt M8 x 40, box of 100". Write a quote inside a quoted value as two quotes (""). - Save as UTF-8. A byte-order mark (BOM), as added by Excel's CSV UTF-8 option, is fine.
- Blank lines — empty, or containing only delimiters and spaces — are skipped, including extra empty lines at the end.
- Spaces around values are removed before they're checked and saved.
Headers and column mapping
Your headers don't have to match the field names exactly: after you choose a file, you map each PriceRules field to one of your columns. PriceRules pre-fills the mapping from your header names, so using the field names on this page as headers gives the best results. Header matching is not case-sensitive for the suggestions, and you can always change a suggestion by hand.
The column must be mapped and every row needs a valid value.
You can leave the field unmapped. If you map it, its values are still validated.
- Each field can be mapped to one column. Extra columns you don't map are ignored and never saved.
- Some optional fields are validated more strictly once mapped: a mapped category or country column must have a value on every row.
- Products and customers have no other fields than the ones listed below — currencies, emails, external IDs and metadata can't be imported.
One invalid row rejects the whole file
Products
Products
Your catalog and the base prices that pricing rules start from.
skuRequired- Surrounding spaces are removed.
- Must be unique within the file. The check ignores upper/lower case:
ABC-1andabc-1count as duplicates. - Identifies the product. If a product with exactly this SKU already exists in your workspace, it is updated instead of created.
- Can't differ only in upper/lower case from an existing product:
abc-1when your workspace hasABC-1rejects the file. Use the existing spelling to update it.
nameRequired- Surrounding spaces are removed. A blank name rejects the file.
base_priceRequired- Accepted formats:
1750,1750.00,1750,00,1,750.00,1.750,00. Don't include currency symbols. - A single dot is always a decimal point:
1.750is read as 1.75, not 1750. 0is allowed. Negative or non-numeric values reject the file.- Stored with up to 4 decimal places (more are rounded). At most 8 digits before the decimal point — larger prices reject the file.
categoryOptional- If you map this column, every row must have a category — a blank cell rejects the file.
- To import products without categories, leave the column unmapped.
- Re-importing with this column unmapped keeps the existing categories of the products in the file.
Examples
sku,name,base_price
FAS-1001,Hex Bolt M8 x 40 (box of 100),18.50
TOL-2001,Cordless Drill 18V,149.00
SAF-4001,Safety Gloves Cut Level C (pair),6.80sku,name,base_price,category
FAS-1001,"Hex Bolt M8 x 40, box of 100",18.50,Fasteners
TOL-2001,Cordless Drill 18V,149.00,Power Tools
SAF-4001,Safety Gloves Cut Level C (pair),6.80,Safety
LUB-6002,Industrial Degreaser 5L,36.00,MaintenanceThe first name in the complete example contains a comma, so it's wrapped in double quotes.
Error log messages
SKU: MissingThe SKU cell is empty.SKU: DuplicateThe SKU already appeared on an earlier row of this file (case-insensitive).NAME: MissingThe name cell is empty.PRICE: MissingThe base_price cell is empty.PRICE: InvalidThe base_price is negative or isn't a number.PRICE: Too largeThe base_price has more than 8 digits before the decimal point.SKU: Differs only in case from existing "…"An active product has the same SKU in different upper/lower case. Use the existing spelling.CATEGORY: InvalidThe category column is mapped but this row's category is empty.Customers
Customers
The accounts that customer-specific pricing rules point to.
codeRequired- Surrounding spaces are removed.
- Must be unique within the file. The check ignores upper/lower case:
ACMEandacmecount as duplicates. - Identifies the customer. If a customer with exactly this code already exists in your workspace, it is updated instead of created.
- Can't differ only in upper/lower case from an existing customer:
acmewhen your workspace hasACMErejects the file. Use the existing spelling to update it. - This is the value pricing rules use in their code column.
nameRequired- Surrounding spaces are removed. A blank name rejects the file.
countryOptional- Any non-empty text is accepted — values are not checked against a list of countries, so pick one convention (for example ISO codes such as DE, FR) and use it consistently.
- If you map this column, every row must have a country — a blank cell rejects the file. Leave it unmapped to import customers without one.
- Re-importing with this column unmapped keeps the existing countries of the customers in the file.
Examples
code,name
ACME-BUILD,Acme Construction GmbH
NORDIC-FAB,Nordic Fabrication AScode,name,country
ACME-BUILD,Acme Construction GmbH,DE
NORDIC-FAB,Nordic Fabrication AS,NO
ATLAS-MRO,Atlas Maintenance Services,NLError log messages
ID: MissingThe code cell is empty.ID: DuplicateThe code already appeared on an earlier row of this file (case-insensitive).ID: Differs only in case from existing "…"An active customer has the same code in different upper/lower case. Use the existing spelling.NAME: MissingThe name cell is empty.COUNTRY: InvalidThe country column is mapped but this row's country is empty.Pricing Rules
Pricing rules
Fixed prices and percentage discounts for a specific customer and product.
Every imported rule targets one customer and one product
code and an existing product sku. Rules that apply to all customers or all products can't be imported — create them by hand on the Customer Pricing page.nameOptional- Only a label — it isn't used for matching prices or detecting duplicates.
codeRequired- Must match a customer that already exists in your workspace, ignoring upper/lower case. The rule is saved with the customer's stored spelling (see how references are saved).
- One code per cell. A comma-separated list rejects the file (
CODE: One customer code per row) — add one row per customer instead. - Can't be left blank: a rules file can't create rules that apply to all customers. Create those by hand in the app instead.
skuRequired- Must match a product that already exists in your workspace, ignoring upper/lower case. The rule is saved with the product's stored SKU.
- One SKU per cell. Blank cells and comma-separated lists (
SKU: One SKU per row) reject the file.
typeRequiredfixed or discountfixed:valueis the final unit price.discount:valueis a percentage taken off the product's base price (10means 10% off).- Any capitalization is accepted (
Fixed,DISCOUNT); the rule is saved in lowercase.
valueRequired- Same formats as
base_price:12.5,12,5,1,750.00,1.750,00. A single dot or comma is always a decimal separator. - Stored with up to 4 decimal places (more are rounded). At most 8 digits before the decimal point — larger values reject the file.
- There is no range check: negative values and discounts above 100 are not rejected, so check them before importing.
minimum_quantityOptional- The rule only applies when the requested quantity is at least this number.
- Only plain digits are accepted. Negative values, decimals (
2.5), separators (1,000) and text reject the file. - For duplicate detection, a blank cell and
0are the same value (1is a different one).
priorityOptional1- Only plain digits with an optional minus sign are accepted. Decimals (
1.5), separators and text reject the file. - When several rules qualify, a higher number wins (see how rules are chosen).
- For duplicate detection, a blank cell and
1are the same value.
statusOptionaltrue, yes, 1, active. Inactive: false, no, 0, inactivetrue (active)- Any capitalization is accepted.
- Any other value rejects the file (
STATUS: Invalid). - Inactive rules are saved but never applied to prices.
Duplicate rules
A rule is identified by four values together: code, sku, minimum_quantity and priority. Code and SKU are compared ignoring upper/lower case and surrounding spaces; a blank minimum quantity counts as 0; a blank priority counts as 1. name, type, value and statusare not part of the identity, so an inactive rule still counts. Deleted rules don't.
- Two rows in the file with the same identity: the later row is reported as
PRICING_RULE: Duplicate in import. - A row matching a rule already in your workspace:
PRICING_RULE: Already exists. - To have several rules for the same customer and product, give them different minimum quantities (volume tiers) or priorities.
Rules created by hand with several customers or products
ACME and BETA, an imported rule for BETA with the same product, minimum quantity and priority is not reported as a duplicate. Check those rules before importing overlapping ones.How imported rules are chosen
In the default pricing mode, when a price is resolved for a customer, product and quantity, only active rules whose minimum quantity is reached are considered. Among them, the rules with the highest minimum quantity are kept, then the most specific rule wins, then the highest priority, then the lowest resulting price. Imported rules always name both a customer and a product, which is the most specific kind.
How references are saved
- Customer codes and SKUs are matched ignoring upper/lower case and spaces around the value in your file:
acme-buildfinds the customerACME-BUILD. - The rule is saved with the stored spelling —
ACME-BUILD— so it matches the customer and product exactly when prices are resolved. - A product or customer whose stored SKU or code has spaces around it (for example
"SKU-9 ") can't be referenced by an import: the row is reported as not found. Correct the stored value on the Products or Customers page first.
Examples
The minimal example uses the minimal products and customers examples above; the complete example uses the complete ones. They don't overlap, so you can import both.
name,code,sku,type,value
Acme fixed price - drill,ACME-BUILD,TOL-2001,fixed,129
,NORDIC-FAB,FAS-1001,discount,8name is optional: the second rule leaves it empty, and you can also leave the column out. Without minimum_quantity, priority and status columns, both rules apply from quantity 1, have priority 1 and are active.
name,code,sku,type,value,minimum_quantity,priority,status
Acme contract - fasteners,ACME-BUILD,FAS-1001,discount,12,,1,true
Acme volume - bolts 50+,ACME-BUILD,FAS-1001,discount,18,50,1,true
Nordic gloves bulk,NORDIC-FAB,SAF-4001,discount,25,100,1,true
Atlas degreaser contract,ATLAS-MRO,LUB-6002,fixed,31.50,,2,true
Atlas drill (paused),ATLAS-MRO,TOL-2001,fixed,139,,1,false- Rows 1–2: Acme gets 12% off FAS-1001, and 18% off from 50 units. Same code, SKU and priority, but different minimum quantities — so they aren't duplicates.
- Row 3: a volume discount of 25% from 100 units.
- Row 4: a fixed unit price of 31.50 with priority 2.
- Row 5:
statusisfalse, so the rule is saved but inactive. - Empty cells (two commas in a row) mean “no value”: the default for that column applies.
Error log messages
CODE: MissingThe code cell is empty.CODE: Customer not foundNo customer with this code exists in your workspace.CODE: One customer code per rowThe cell lists several codes separated by commas.CODE: Matches more than one customerMore than one customer has this code (ignoring upper/lower case). Make the codes unique first.SKU: MissingThe sku cell is empty.SKU: Product not foundNo product with this SKU exists in your workspace.SKU: One SKU per rowThe cell lists several SKUs separated by commas.SKU: Matches more than one productMore than one product has this SKU (ignoring upper/lower case). Make the SKUs unique first.TYPE: MissingThe type cell is empty.TYPE: InvalidThe type is something other than fixed or discount.VALUE: MissingThe value cell is empty.VALUE: InvalidThe value isn't a number.VALUE: Too largeThe value has more than 8 digits before the decimal point.MINIMUM_QUANTITY: InvalidThe minimum quantity isn't a whole number of 0 or more.PRIORITY: InvalidThe priority isn't a whole number.STATUS: InvalidThe status isn't one of the accepted values.PRICING_RULE: Duplicate in importAn earlier row of this file has the same code, SKU, minimum quantity and priority.PRICING_RULE: Already existsYour workspace already has a rule with the same code, SKU, minimum quantity and priority.PRICING_RULE: Deleted since the previous attempt — upload the file againA rule this import saved before it failed has been deleted since. See Troubleshooting.Updates
Re-importing data
What happens when a file contains records that already exist.
sku. Existing products are updated: name, base price and category are replaced by the file's values (if the category column is unmapped, existing categories are kept). New SKUs are created. Products not in the file are left alone — imports never delete. New prices are live once the import shows Completed.code. Existing customers are updated: name and country are replaced (if the country column is unmapped, existing countries are kept). New codes are created; customers not in the file are left alone.Already exists, which rejects the whole file — so uploading the same rules file again fails. (Retrying a failed import with Try again is different: see Troubleshooting.) Change existing rules on the Customer Pricing page.- Write each SKU and customer code exactly the same way, including upper/lower case, every time you import it. A SKU or code that differs only in case from an active one rejects the file.
- If a SKU or code exactly matches a product or customer you deleted, the deleted record is updated but stays deleted — it doesn't reappear in your lists.
- Re-importing products and customers counts toward your monthly import allowance like any other import, but updates don't use up plan capacity.
Limits
Limits
File, plan and concurrency limits that apply to imports.
- File size: up to 50 MB per file. There is no separate row limit — your plan's capacity is the limit.
- One import of each type can run at a time per workspace, and imports in a workspace are processed one after another.
- Plan capacity: products and customers count only records the file would create (updates are free); every row of a pricing-rules file is a new rule. If the total would exceed your plan, the whole file is rejected before anything is saved.
- Monthly import allowance: each completed import counts as one. Rejected and failed imports don't count, but imports still running are reserved.
| Plan | Products | Customers | Pricing rules | Imports per period |
|---|---|---|---|---|
| Free | 100 | 10 | 200 | 6 |
| Starter | 5,000 | 2,000 | 10,000 | 20 |
| Growth | 25,000 | 10,000 | 50,000 | 100 |
Help
Troubleshooting
Common problems, why they happen, and how to fix them.
Import can't start: nothing was queued. Whole file rejected: nothing was saved. Import failed: processing stopped on an unexpected error. Saved, not yet live: rows are saved, the pricing engine isn't updated yet. Not rejected: the import succeeds, but the data may not behave as you expect.
A required field can't be mapped, or the wrong column is suggested
Import can't start- Cause
- Your header names don't resemble the field names, so the suggestion is missing or wrong. Start stays disabled until every required field is mapped.
- Fix
- Pick the right column for each field in the mapping table. Naming your headers exactly like the field names on this page (
sku,base_price, …) gives the most reliable suggestions.
Every row is rejected as missing the same value
Whole file rejected- Cause
- A column is mapped to the wrong field, or the mapped column is empty in your file.
- Fix
- Use Fix mapping to check which column fills each field.
Empty required fields
Whole file rejected- Cause
- A required cell is blank (
SKU: Missing,NAME: Missing, …). - Fix
- Fill in the cell, or remove the row. Download the error log to see every affected row.
Empty optional category or country
Whole file rejected- Cause
- The optional column is mapped, so every row needs a value.
- Fix
- Fill in the missing values, or set the field to Unmapped if you don't want to import it.
Invalid numbers
Whole file rejected- Cause
- A price, value, minimum quantity or priority isn't a number, or a price or minimum quantity is negative.
- Fix
- Remove currency symbols and text. Use plain whole numbers for minimum quantity and priority, and keep prices and values under 100,000,000.
Duplicate SKUs or customer codes
Whole file rejected- Cause
- The same SKU (products) or code (customers) appears on more than one row. Case is ignored when comparing.
- Fix
- Keep one row per SKU or code. To update an existing record, import it again in a later file — that updates it.
Duplicate pricing rules
Whole file rejected- Cause
- Two rows — or a row and an existing rule — share the same customer code, SKU, minimum quantity and priority (
PRICING_RULE: Duplicate in import/Already exists). - Fix
- Remove the repeated rows. Rules can't be updated by import: change an existing rule on the Customer Pricing page, or give the new rule a different minimum quantity or priority. See Re-importing data.
Customer code or SKU not found
Whole file rejected- Cause
- The pricing rule references a customer or product that doesn't exist in your workspace (yet).
- Fix
- Import or create the missing customers and products first, wait for those imports to complete, then import the rules again.
Pricing rules import is locked or refused
Import can't start- Cause
- Your workspace has no products (
PRODUCTS_REQUIRED) or no customers (CUSTOMERS_REQUIRED). - Fix
- Import products, then customers, before pricing rules. See Import order.
Invalid rule type or status
Whole file rejected- Cause
- The type is something other than
fixedordiscount(for examplepercentorflat), or the status isn't one of the accepted values. - Fix
- Use
fixedordiscount, andtrue/false(or another accepted status value).
A rule was imported but never applies
Not rejected — check your data- Cause
- The rule is inactive, or your price requests spell the SKU or customer code differently from the stored product or customer. Imported rules use the stored spelling, and prices are matched on the exact spelling.
- Fix
- Check the rule's status on the Customer Pricing page, and send the SKU and customer code exactly as stored on the product and customer.
File too large or not a CSV
Import can't start- Cause
- The file is over 50 MB, or isn't a
.csvfile (for example an.xlsxworkbook). - Fix
- Export as CSV from your spreadsheet. Split very large files into several smaller files.
File doesn't fit your plan
Whole file rejected- Cause
- Importing the file would take you over your plan's limit for products, customers or pricing rules.
- Fix
- Import fewer new records, delete records you no longer need, or upgrade your plan. See Limits.
Monthly import limit reached, or another import is running
Import can't start- Cause
- Your plan's CSV imports for this period are used up (
IMPORT_LIMIT_REACHED), or an import of the same type is still running (IMPORT_IN_PROGRESS). - Fix
- Wait for the running import to finish, or for your next usage period. Upgrading raises the monthly allowance.
The import failed with an unexpected error
Import failed- Cause
- Something went wrong while processing (not a problem in your data). PriceRules retries automatically, up to 3 attempts in total, before showing the import as failed.
- Fix
- Try again starts a new import of the same file and mapping. Rows are saved in batches of 1,000 and batches saved before the error stay saved — but retrying the same file with the same mapping doesn't save them twice or reject them as
Already exists; it saves the remaining rows. Uploading the file again, or changing the mapping, starts from scratch: rules saved by the failed attempt are then reported asAlready exists. If you deleted any of those saved rules before retrying, the retry is rejected (Deleted since the previous attempt) — deleted rules are never restored automatically. Upload the file again as a new import, without the rows the failed attempt saved.
“Your data was saved, but the pricing engine couldn't be updated”
Saved, not yet live- Cause
- Every row was saved, but refreshing the pricing engine failed on every attempt. The API may still return old prices.
- Fix
- Click Try again. It only repeats the pricing-engine update — your rows aren't written twice. Don't upload the file again.
The import stays in progress, then stops
Import failed- Cause
- If the background job behind an import disappears, the import is closed as failed with “The import stopped unexpectedly. Please try again.”
- Fix
- Use Try again. If it keeps happening, contact support.