---
search:
  tags:
    - Products
    - POST
seo:
  description: >-
    Creates a product in the specified shop. shop_id must be a shop belonging to
    the… Reference for the POST /products endpoint in the Bolder API v2.
sidebar:
  label: Create a product
  badge: POST
title: Create a product
type: openapi-operation
---
Creates a product in the specified shop. `shop_id` must be a shop belonging to the authenticated account.

`POST /products`

**cURL**

```bash
curl -s -X POST \
  -H "Authorization: Bearer $BOLDER_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"shop_id":1,"name":"Organic Cotton Tee","status":"visible","sale_price":2999,"regular_price":3999}' \
  "https://api.onbolder.com/v2/products"
```

**Request body** (`application/json`, required)

- `shop_id` (integer, required) — ID of the shop (required on create)
- `name` (string, required) — Product name.
- `slug` (string) — URL slug. Auto-generated from name if omitted.
- `status` (string)
- `class` (string) — Product class. Defaults to \`Product\`.
- `description` (string)
- `short_description` (string)
- `deliverable` (boolean) — Whether the product requires physical delivery. Defaults to \`true\`. Set to \`false\` for digital goods, event tickets, subscriptions, etc. Returned as \`is\_deliverable\` in responses.
- `tracks_stock` (boolean) — Whether stock is tracked for this product's variants.
- `has_prices_per_variant` (boolean) — Required when variants have different prices. Must be \`true\` if any variant sets its own \`regular\_price\`; the API returns 422 otherwise.
- `has_weights_per_variant` (boolean) — Whether variants carry individual weights.
- `regular_price` (integer) — Regular price in cents, applied to all variants (for non-bundle products). Use per-variant \`regular\_price\` inside \`variants\` when \`has\_prices\_per\_variant\` is true.
- `sale_price` (integer) — Sale price in cents, applied to all variants.
- `sale_price_starts_at` (string<date-time>) — ISO 8601 datetime when the sale price activates.
- `sale_price_ends_at` (string<date-time>) — ISO 8601 datetime when the sale price expires.
- `product_type_name` (string) — Product type name. Created automatically if it doesn't exist.
- `vendor_name` (string) — Vendor name. Created automatically if it doesn't exist.
- `tags` (string[]) — Tag names. Replaces all existing tags unless \`\_policies.keep\_attributes\` is set.
- `cart_quantity_multiple` (integer) — Enforces cart quantities to be multiples of this value.
- `variant_options` (object) — Names for up to 3 variant option axes (e.g. "Color", "Size").
- `variants` (VariantInput[]) — Variant definitions. By default, variants not present in the array are removed; set \`\_policies.keep\_variants: true\` to preserve them.
- `collections` (object[]) — Collections to assign the product to. Pass \`id\` to reference an existing collection, or \`title\` to create/find by name. Replaces all existing collections unless \`\_policies.keep\_collections: true\`.
- `custom_attributes` (object[]) — Custom meta-field attributes.
- `volume_discount_id` (integer) — Assigns an existing volume discount to this product.
- `relations` (object[]) — Related products (e.g. "goes well with"). Replaces all existing relations unless \`\_policies.keep\_relations: true\`.
- `custom_variant_options` (object) — Custom variant option metadata (id/name/type) for up to 3 option axes, keyed by \`option1\`/\`option2\`/\`option3\`.
- `bundle_options` (object[]) — Configurable bundle option groups (customer picks items from each group). Only applies to \`class: ProductBundle\`.
- `bundle_items` (object[]) — Fixed bundle items (always included, no customer choice). Only applies to \`class: ProductBundle\`.
- `_policies` (object) — Control update behaviour. All flags default to \`false\` (destructive replace). Set to \`true\` to preserve existing data when the corresponding field is not included in the request.

Request body example:

```json
{
  "shop_id": 1,
  "name": "Organic Cotton Tee",
  "slug": "organic-cotton-tee",
  "status": "visible",
  "sale_price": 2999,
  "regular_price": 3999
}
```

**Responses**

- `201` — Product created
- `403` — Not authorized to create products in this shop
- `422` — Validation error or missing shop\_id

Response example, 201:

```json
{
  "id": 103,
  "name": "Organic Cotton Tee",
  "slug": "organic-cotton-tee",
  "status": "visible",
  "price": 2999,
  "regular_price": 3999,
  "currency_code": "USD",
  "created_on": "2024-06-20T14:22:00Z",
  "_links": {
    "self": {
      "href": "https://api.onbolder.com/v2/products/103"
    },
    "products:update": {
      "href": "https://api.onbolder.com/v2/products/103",
      "method": "put"
    },
    "products:delete": {
      "href": "https://api.onbolder.com/v2/products/103",
      "method": "delete"
    }
  }
}
```
