CSV import is the fastest way to move a batch of products into Closo. Drop a spreadsheet, map the columns once, and your products land in the crosslister — drafts, active listings, and even items that are already live on Poshmark, eBay, Mercari, Depop, Vinted, or Etsy. This guide walks you through preparing the file, the wizard steps, how existing marketplace listings register, how duplicate handling works, and what to do when a row is rejected.
Who can use CSV import
CSV import is a Phase-1 feature available to a paid/operator-managed cohort. If your account is not in the cohort, opening the CSV wizard returns an access-denied error (HTTP 403, code cohort_locked) and you will not be able to upload. If you see that, you are not doing anything wrong — your account simply does not have CSV import enabled yet. See the companion article on requesting access, or contact support to ask about eligibility and the upgrade path.
What this is
CSV import takes a spreadsheet of products and turns each row into a Closo product, all in one background job. You can use it to migrate inventory from Shopify, Vendoo, List Perfectly, or any tool that exports a CSV; to bulk-load drafts before a photoshoot; or to round-trip an existing Closo export back into your catalog. For a single product, Add product is faster — CSV import is built for batches, and the wizard handles batching, retry, and error reporting on your behalf.
Prepare your CSV
Closo accepts UTF-8 encoded .csv and .tsv files. Delimiter is detected automatically from the file extension: .csv is parsed with commas, .tsv with tabs.
Closo recognises common column-name variants — Item Name, product_title, and title all map to the same field. You can use whatever header names your existing tool exports; the wizard's mapping step lets you correct anything Closo guesses wrong.
| Column | Type | Notes |
| `title` | string | Required. Max 140 characters; longer titles are trimmed with a warn. |
| `price` | decimal | Required. Strip currency symbols. Use `19.99`, not `$19.99`. |
| `description` | string | Free text. No length cap, but keep it under 8000 chars per marketplace. |
| `brand` | string | Designer or manufacturer. |
| `sku` | string | Your internal reference. Used as the primary match key for duplicates. |
| `condition` | enum | One of: `New`, `Like New`, `Good`, `Fair`, `Poor`. |
| `size` | string | Marketplace-specific format (e.g. `M`, `8`, `One Size`). |
| `primary_color` | string | Plain English (`Red`, `Navy`, `Off White`). |
| `category` | string | A category path (`Women > Tops > T-Shirts`) or a single category name. |
| `images` | string | Comma-separated list of `https://…` URLs. |
| `status` | enum | `draft` (default), `active`, or `sold`. |
| `qty` | integer | Stock-on-hand. Defaults to `1`. |Exporting from Excel. Open the file, choose File → Save As → CSV UTF-8 (Comma delimited). Older Excel versions sometimes save in cp1252 instead — if you see weird characters in the preview, save again with the UTF-8 option explicitly.
Exporting from Google Sheets. File → Download → Comma-separated values (.csv). Google Sheets always writes UTF-8 and quotes any field that contains commas. Nothing extra to do.
Required columns
Only two columns are strictly required: title and price. Every other column is optional. If you give Closo nothing else, your products land in the crosslister as bare-bones drafts with the default condition (Good) and quantity (1), and you can edit them to fill in the gaps later.
That said, sellers who provide more columns get better results. The best-practice optional columns are:
description — sets the listing body. Without it, your draft shows an empty description in every marketplace's editor. brand — drives category recommendations and search ranking. sku — your internal reference. Closo uses this as the primary match key when you re-import the same file (see Duplicate handling below). condition — defaults to Good. Set this explicitly so each marketplace's condition picker is pre-filled correctly. size, primary_color, category — these power the per-marketplace required-field forms. Provide them once and Closo translates them to the right marketplace-specific format. images — a comma-separated list of public image URLs. Closo downloads each image, normalises it, and attaches it to the product. Local file paths like C:\photos\shirt.jpg are skipped. status — draft (default), active, or sold. Set to sold for already-sold inventory you want in your history. Marketplace URL columns — see the next section.
The wizard steps
The CSV import wizard is at /seller-v4/import/csv. Once you start, you can leave the page at any point; progress is saved and a notice appears in your inbox when the import finishes.
1. Upload. Drag your file onto the drop zone or click Choose file. Closo validates the file extension and size in the browser before sending it to the server, so you'll see invalid-extension or file-too-large errors immediately.
2. Map columns. Closo auto-detects each column by header name. A coloured chip next to every column tells you the confidence — high confidence (exact match against the alias dictionary), medium (substring match), or low (best-guess). Review the suggested mapping; if anything looks wrong, pick the right Closo field from the dropdown. Unmapped columns are ignored on import.
3. Preview rows. Closo shows the first 10 rows of your file with the mapping applied. This is your sanity check — read each row exactly as the importer will, and any inline validation errors (bad price, missing title, unrecognised condition) show up here before you commit.
4. Settings. Pick the duplicate-handling policy (see below), the default status for new rows (draft or active), and whether to send-to-marketplaces immediately on import or keep drafts. The default settings are safe — Smart merge, drafts only.
5. Confirm. A summary screen: total rows, columns mapped, columns ignored, picked policy, picked status. Click Start import to queue the background job.
6. Importing. A progress page shows live counts: rows processed, rows imported, rows skipped, rows with errors. A 100-row import finishes quickly, though image fetching can add time. You can close this page; the bell notification will let you know when it's done.
7. Done. A summary of what was created plus a downloadable error report (CSV) if any rows were rejected. From here you can jump straight into the crosslister to review and publish.
Marketplace URLs (existing listings)
If a product is already live on a marketplace, paste its listing URL into the matching column. Closo records the URL as a pre-existing listing — no API requests fire, no extension wakes up, no re-dispatching happens. The marketplace chip just appears on your product so you know coverage is in place.
| Column | Sample URL |
| `poshmark_url` | `https://poshmark.com/listing/levis-501-vintage-jeans-67abc123` |
| `ebay_url` | `https://www.ebay.com/itm/123456789` |
| `mercari_url` | `https://www.mercari.com/us/item/m12345678901/` |
| `depop_url` | `https://www.depop.com/products/user/product-slug/` |
| `vinted_url` | `https://www.vinted.com/items/4567890-title` |
| `etsy_url` | `https://www.etsy.com/listing/1234567890/` |
| `shopify_url` | `https://your-shop.myshopify.com/products/slug` |URLs that don't match the expected domain for that column are silently skipped — only valid marketplace URLs become listings. If you import a product with three marketplace URLs and one of them is wrong, the other two still register; the bad one is reported in the error CSV at the end so you can fix and re-upload that row.
Duplicate handling
When a row matches an existing Closo product, the importer needs to decide what to do. Matching is by sku first; if there's no SKU on either side, by title + brand. The duplicate-handling policy is chosen in the Settings step; the default is Smart merge, which is right for most cases.
| Policy | What it does | Pick this when |
| Smart merge | Updates only the empty fields on the existing product. Anything you've edited is preserved. | Default. You're filling in gaps from a richer source spreadsheet. |
| Skip existing | Leaves matching products untouched. Only genuinely-new rows create products. | Re-running the same import safely; bulk-loading without overwriting. |
| Overwrite | Replaces every field with the CSV's values. | The CSV is your source of truth and you want to push corrections. |
| Always new | Creates a brand-new product even when a match exists. | You have legitimate duplicate inventory (two of the same shirt). |Troubleshooting
If a row can't be processed, the importer logs an error and keeps going with the rest of the file. After the import you'll find an error report on the Done screen; download it as CSV, fix the flagged rows, and re-upload.
Common errors and their fixes:
cohort_locked — Your account is not in the CSV import cohort (HTTP 403). CSV import is a paid/operator-managed Phase-1 feature; contact support about eligibility, or use Add product in the meantime. invalid_extension — File is not .csv or .tsv. Excel .xlsx is not supported directly; open in Excel/Numbers/Sheets and Save As → CSV UTF-8. row_cap_exceeded — File has more than 100 rows ('CSV has N rows; Phase-1 cap is 100'). Split the catalog into batches of 100 rows or fewer and run several imports in sequence. parse_failed — A line couldn't be parsed. Almost always broken quoting — a description with commas in it that isn't wrapped in double quotes. Re-export from Excel/Sheets, which quote automatically. rate_limited — You've hit the daily limit of 10 imports per seller. The cap resets at midnight UTC. Ping support if you legitimately need more. missing_title / missing_price — Required field empty on that row. Fill it in or set price to 0.01 if you want to set the real value later. invalid_price — Couldn't parse as a number. Strip currency symbols and thousands separators (1,299.00 → 1299.00). unknown_condition — condition is set to something Closo doesn't recognise. Use one of: New, Like New, Good, Fair, Poor. invalid_image_url — Image URL doesn't start with http:// or https://. Closo can't fetch local file paths. invalid_marketplace_url — Marketplace URL doesn't match the expected domain for its column. Double-check you haven't pasted an eBay URL into the poshmark_url column. Mapping mismatch — A column was auto-detected as the wrong Closo field (e.g. MSRP was detected as price). Go back to the Map columns step and pick the right field from the dropdown, or set it to (ignore) if Closo shouldn't read that column at all.
If you hit an error this guide doesn't cover, the error CSV on the Done screen includes the raw error code for every rejected row. Send that code to support and we can usually tell you what happened in a single reply.