Skip to main content

Import Product Bins

POST 

/api/v2/product-warehouse-locations/import

Assign products to their preferred (home) bins in a warehouse in bulk from a CSV.

Required scope: warehouses:write

Grant this scope to your token under Settings → Developer → Personal Access Tokens.

Each row is sku, bin[, default]. The bin is matched by its location code in the given warehouse and must be an active bin that accepts put-away stock. Bundle and matrix products are skipped (they hold no stock of their own).

Default bin per product: the first row marked default=yes. Without one, a product that already has a default keeps it (a blank cell never replaces it); a product with no default gets its first row not marked default=no, or its first row when every row says no. Existing preferred bins are kept; a listed bin that is already preferred is promoted to default when its row is the product's default.

With move_stock=1, each product whose default bin is listed in the file has its current Unassigned on-hand moved into that bin, recorded as a put-away location transfer. Re-running the same file is safe: applied rows come back as unchanged, and stock still in Unassigned is moved.

Rows with a missing or unknown SKU, an unknown, deprecated or non-put-away bin, or a duplicate SKU+bin are skipped and listed with a reason and their line number in the file. At most 500 skipped rows / move failures are listed; skipped_count and move_failures_count give the totals. Files are limited to 20,000 rows (422 above that).

dry_run=1 answers immediately with to_create, to_set_default, unchanged, skipped, skipped_count, products_to_move, units_to_move. A real import of more than 200 rows is queued and returns {queued: true, tracked_job_log_id, total_rows}; smaller files return created, defaults_set, unchanged, skipped, skipped_count, moved_products, moved_units, move_failures, move_failures_count.

Booleans in form-data: send 1 or 0.

Authentication: Requires Bearer token. Scope: warehouses (read/write).

Requires permission: warehouses.manage_locations. move_stock=1 without dry_run also requires inventory.transfer (403 otherwise).

Request​

Responses​

OK