SegOps AIDocs

CSV Import Wizard

Import a product catalog from a CSV file: SegOps reads your columns, uses Claude to suggest a schema and column mapping, and runs the import as a background job you can track to completion.


Before you start#

The file must be a UTF-8 encoded .csv (a UTF-8 BOM is handled automatically). The wizard handles up to 100k rows. Two fields are reserved and always live on the product itself rather than in your schema:

  • sku — the product's unique identifier (one product per sku per workspace)
  • name — the product's display name

Every other column is mapped to a field in your tenant ProductSchema.


Step 1 — Upload#

Open /pim/import and drag a CSV onto the drop zone, or click to browse. On upload SegOps:

  • parses the header row and the first 5 rows as a preview sample
  • counts the total rows
  • asks Claude Haiku to infer a schema and a column-to-field mapping for any columns it has not seen before
  • reuses the workspace's learned mapping (confirmed mappings from prior imports) for known columns — learned memory wins over AI

This creates an ImportJob in the mapping state and returns job_id, headers, sample_rows, suggested_schema, and suggested_mapping.

http
POST /api/pim/import/csv/
Content-Type: multipart/form-data

file=<catalog.csv>

The draft is saved to your browser and the URL becomes /pim/import?job=<id>, so a refresh — or resuming later from Import history — restores your progress.


Step 2 — Map columns#

The wizard shows three panels:

PanelWhat it does
PreviewThe first sample rows, exactly as parsed
Column mappingEach CSV column → a schema field, sku, name, or — skip —
Schema fieldsThe fields that will be saved as your product schema

AI suggestions are pre-filled — review and adjust. For each schema field you can change the Type (Text, Number, Boolean, List, URL, Price, Multi-price, Datetime) and toggle Required, or remove the field entirely. Removing a field also clears any column mapped to it. Columns mapped to sku/name are stripped from the schema automatically since they are not stored in data.


Step 3 — Confirm and import#

Click Import N rows. This calls:

http
POST /api/pim/import/<job_id>/confirm/
Content-Type: application/json

{ "mapping": { "Product Title": "name", "Sale Price": "price" },
  "schema": [ { "name": "price", "type": "price", "required": false } ],
  "default_currency": "USD", "default_locale": "en_US" }

This persists (or updates) your ProductSchema, merges every confirmed non-null mapping into the workspace's learned memory, sets the job back to pending, and enqueues the background run_csv_import task. You are returned to /pim immediately — the import runs asynchronously.


Tracking the job#

Import jobs move through five states:

StateMeaning
pendingConfirmed; queued for the worker
mappingAwaiting your column mapping (resume from Import history)
importingRows being upserted
doneFinished; imported_count rows in the catalog
failedAborted; see error_message

The Import history page (/pim/imports) lists the 20 most recent jobs with a live progress bar and polls every 3 seconds while any job is pending or importing. You can also poll a single job:

http
GET /api/pim/import/<job_id>/

A job stuck in mapping shows a Resume mapping button that reopens the wizard at Step 2.


Re-imports and upserts#

Imports are idempotent on (workspace, sku). Each row is upserted with update_or_create: a new sku is inserted, an existing one is overwritten with the new name and mapped data. The original row is kept in raw_data. To refresh a catalog, re-import a CSV with the same SKUs — there is no separate "update" mode. After a successful import the stored CSV content is cleared, products are synced to ClickHouse, and AI-search embeddings are regenerated.

For programmatic upserts, POST /api/pim/products/bulk/ accepts {"products": [{sku, name, ...fields}]} and auto-merges any new field keys into the schema. See the API reference.