# Products & SKUs > Create products from catalog products and your designs, give variants your own SKUs, map them to your store and export them to Shopify or WooCommerce. Source: https://swaglists.com/docs/products A **product** is what you sell: a [catalog product](https://swaglists.com/docs/catalog.md) + your [designs](https://swaglists.com/docs/designs.md) + a set of **variants**, each with a **SKU**. When your store sells a variant, you send us its SKU in an order — that is the whole mapping. ```text product "Company A Logo Tee" (prod_…) ├── catalog_product_id cp_… (Classic Unisex Tee) ├── designs front: [file_… at {x, y, width, height}] └── variants pvar_… SKU CA-TEE-BLK-M → catalog variant Black / M price 1299 pvar_… SKU CA-TEE-BLK-L → catalog variant Black / L price 1299 ``` Products, variants and SKUs are shared between test and live mode. ## Create a product ```bash title="cURL" curl -X POST https://swaglists.com/api/v1/products \ -H "Authorization: Bearer $API_KEY" \ -H "Content-Type: application/json" \ -H "Idempotency-Key: $(uuidgen)" \ -d '{ "catalog_product_id": "cp_01k8w1a2s3d4f5g6h7j8k9m0n1", "title": "Company A Logo Tee", "description": "Our classic logo on a soft tee.", "designs": [ { "placement": "front", "layers": [{ "file_id": "file_01k8x3y1q3w5e7r9t1y3u5i7o9" }] } ], "variants": [ { "catalog_variant_id": "cv_01k8w1a2s7d9f1g3h5j7k9m1n3", "sku": "CA-TEE-BLK-M", "retail_price": 2900 }, { "catalog_variant_id": "cv_01k8w1a2s9f1g3h5j7k9m1n3p5", "sku": "CA-TEE-BLK-L", "retail_price": 2900 } ], "external_id": "shopify-product-9921" }' ``` ```js title="Node.js" const res = await fetch("https://swaglists.com/api/v1/products", { method: "POST", headers: { Authorization: `Bearer ${process.env.API_KEY}`, "Content-Type": "application/json", "Idempotency-Key": `product-${myProduct.id}`, }, body: JSON.stringify({ catalog_product_id: "cp_01k8w1a2s3d4f5g6h7j8k9m0n1", title: "Company A Logo Tee", designs: [{ placement: "front", layers: [{ file_id: "file_01k8x3y1q3w5e7r9t1y3u5i7o9" }] }], variants: "all", // every available catalog variant, SKUs generated retail_price: 2900, }), }); const product = await res.json(); for (const v of product.variants) console.log(v.sku, v.title, v.price); ``` ```python title="Python" product = requests.post( "https://swaglists.com/api/v1/products", headers={"Authorization": f"Bearer {os.environ['API_KEY']}", "Idempotency-Key": f"product-{my_product_id}"}, json={ "catalog_product_id": "cp_01k8w1a2s3d4f5g6h7j8k9m0n1", "title": "Company A Logo Tee", "designs": [{"placement": "front", "layers": [{"file_id": "file_01k8x3y1q3w5e7r9t1y3u5i7o9"}]}], "variants": "all", "retail_price": 2900, }, ).json() for v in product["variants"]: print(v["sku"], v["title"], v["price"]) ``` | Field | Notes | | --- | --- | | `catalog_product_id` | From `GET /catalog/products`. | | `designs` | At least one; every `required` placement must be covered. See [Designs](https://swaglists.com/docs/designs.md). | | `variants` | `"all"` (every available catalog variant) or a list of `{ catalog_variant_id, sku?, retail_price?, external_id? }`. Default `"all"`. | | `retail_price` | Your selling price in cents — informational (used in exports), never charged. | | `external_id`, `tags`, `metadata` | Your references. `external_id` is unique among your products. | | `status` | `active` (default) or `draft`. Drafts can still be ordered. | The response is the [product](https://swaglists.com/docs/objects.md#product) with its variants and a `warnings` array (resolution or placement issues that did not block creation). Mockups are rendered in the background; `product.updated` fires when they are ready (`mockups[]`). Each variant's `price` is your **wholesale price** for one unit of this product with all its designs — what an order line will cost before shipping and tax. ## Availability Each variant's `available` says whether it can be ordered **right now**: the variant is enabled, the product isn't archived, and the item is in stock. Variants can become temporarily unavailable (out of stock, discontinued); orders that include them are rejected with `400 item_unavailable` until they are back. Whenever `available` changes we send `product.updated` (with the previous values in `previous_attributes.variants`) and notify you in the dashboard (plus an email when variants become unavailable) — mark those variants sold out in your store, and back in stock when the next `product.updated` says so. ## Mockup images `mockups[].url` links **don't expire**, so you can use them directly as product images in your store or headless storefront. Each URL belongs to one rendering: when you change the designs or the enabled colors, the mockups are re-rendered, the new URLs arrive with `product.updated`, and the previous URLs stop working (`404`). Update your listing from that event (or re-fetch the product) instead of keeping old URLs — or download the images into your store, as the Shopify and WooCommerce imports do. ## SKUs SKUs connect your store to us. Rules: - 1–64 printable ASCII characters (no leading/trailing spaces), **unique in your account** across all products. - Omit `sku` and we generate a readable one from the product title and the variant options (e.g. `QUICKSTART-BLACK-M`; a `-2`, `-3`, … suffix is added on collisions). - Disabled variants and archived products keep their SKUs reserved. Already have SKUs in your store? Use them — set `sku` when creating the product, or change it later: ```bash title="Change a variant's SKU" curl -X PATCH https://swaglists.com/api/v1/products/prod_01k8x3z7r1t3y5u7i9o1p3a5s7/variants/pvar_01k8x3z7r4f6g8h0j2k4l6z8x0 \ -H "Authorization: Bearer $API_KEY" \ -H "Content-Type: application/json" \ -d '{ "sku": "STORE-TEE-BLACK-M", "external_id": "shopify-variant-4410" }' ``` Look a variant up by SKU with `GET /products/by_sku/{sku}` (URL-encode special characters). ### Mapping your store's products | Your store has… | Do this | | --- | --- | | No products yet | Create products here (API or designer), then [export them](#exports) to your store. The CSV carries our SKUs. | | Products with SKUs | Create matching products here with `variants: [{ catalog_variant_id, sku: "" }]`. | | Products without SKUs | Add our generated SKUs to your store's variants (Shopify and WooCommerce have a SKU field per variant). | Order line items whose SKU is not one of your products return `400 resource_missing` with `param` = `items[i].sku`; skip non-print items (gift cards, digital goods) before sending the order. ## Update, add variants, archive | Request | What it does | | --- | --- | | `PATCH /products/{id}` | Change `title`, `description`, `tags`, `metadata`, `external_id`, `retail_price`, `status`, or replace all `designs` (mockups are re-rendered). | | `POST /products/{id}/variants` | Add catalog variants (or re-enable disabled ones): `{ "variants": "all" }` or a list. | | `PATCH /products/{id}/variants/{variant_id}` | Change a variant's `sku`, `retail_price`, `external_id` or `enabled`. | | `DELETE /products/{id}` | Archive: it can no longer be ordered; SKUs stay reserved; existing orders are unaffected. Restore with `PATCH` `{ "status": "active" }`. | Archived products cannot be edited (`409 product_archived` — product fields, designs and variants) until restored: send `PATCH /products/{id}` with a `status` (other changes may be included in that same request). Orders keep a snapshot of the designs and prices at order time, so later product changes never affect orders already placed. ## Exports Export products as a CSV ready to import into your store: in the dashboard open **Products → Export** and choose: | Format | Import it in | Notes | | --- | --- | --- | | Shopify CSV | Shopify admin → Products → Import | One row per variant; `SKU` = our SKU; `Fulfillment service` = manual; mockups as images; prices = your retail prices. | | WooCommerce CSV | WooCommerce → Products → Import | Variable products with one variation per variant; `SKU` = our SKU; weights in your chosen unit. | | CSV | Spreadsheets, other platforms | One row per variant with ids, SKU, options, retail price and image URL. | Select products in the list to export only those. See [Product catalog export & import](https://swaglists.com/docs/catalog-export.md) for the column mapping and how to keep your store in sync.