Skip to main content

Bulk Create SKU.io Products From Store Products

POST 

/api/storefront/instances/:id/products/create-sku-products

Create SKU.io catalog products from unmapped store products, then map them. A store product whose SKU already exists in the SKU.io catalogue is linked to it rather than duplicated.

Not yet available to API tokens

This endpoint currently requires session authentication; Personal Access Token scope support is in progress.

This is the deliberate counterpart of auto-matching: it ADDS rows to your catalogue, so it never runs implicitly during an import.

Selecting what to act on — the shared selection contract used by this endpoint, POST /bulk-map, POST /create-sku-products, PUT /archive, PUT /unarchive, POST /archiveable, PUT /delete and PUT /deleteable:

  • {"ids": [16, 17]} — an explicit list of store-product ids.
  • {"apply_to_all": true} — every product on the instance that the product list would show with no filters, i.e. every NON-ARCHIVED product.
  • {"apply_to_all": true, "filters": { ... }} — every product matching those filters, however many pages that spans. This is "select everything matching what I am looking at".

filters carries the SAME keys the product list accepts, but written as bare column names with no filter[...] wrapper — e.g. {"mapping_status": "unmapped", "status": "active", "search": "door", "search_columns": "sku,unified_title", "price.greater_than": 100, "filter_groups": "<base64 tree>"}. A nested {"filter": {...}} object, literal filter[col] keys, and a JSON string of the whole object are all accepted too. Display and paging keys (page, per_page, sort, included, total, table_specifications, query) are ignored — the selection is never limited to one page. search is deliberately NOT ignored.

Two rules worth knowing:

  • If filters does not mention archived, archived products are excluded, exactly as the list hides them by default. A sweep can therefore never reach a product the list was not showing.
  • A filters payload that cannot be parsed, or a filter_groups tree that cannot be parsed, is rejected with 422 rather than being treated as "no filters" — which would have acted on every row.

Body fields: ids (array of integers, optional), apply_to_all (boolean, optional), filters (object or JSON string, optional — only consulted when apply_to_all is true). Resolving to an empty selection returns 200 with No products to create and changes nothing.

Field mappings are not accepted here; the connection's stored mappings (or the defaults) are used. To override them for a single product, use POST /{product}/create-sku-product.

The response is the refreshed catalogue counts, so you can see how many products are still unmapped.

Permission: integrations.update.

Authentication: Bearer token (session or PAT).

Request​

Responses​

OK

Response Headers
    Content-Type