---
search:
  tags:
    - Products
    - PUT
seo:
  description: >-
    Updates the product. If a product with the given ID/slug does not exist and
    dont_create… Reference for the PUT /products/{id} endpoint in the Bolder API
    v2.
sidebar:
  label: Update a product
  badge: PUT
title: Update a product
type: openapi-operation
---
Updates the product. If a product with the given ID/slug does not exist and
`dont_create` is not set, a new product will be created (upsert).

`PUT /products/{id}`

**cURL**

```bash
curl -s -X PUT \
  -H "Authorization: Bearer $BOLDER_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"status":"hidden","sale_price":2499}' \
  "https://api.onbolder.com/v2/products/101"
```

**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
{
  "name": "Wireless Headphones Pro",
  "regular_price": 12999,
  "sale_price": 9999,
  "status": "visible",
  "description": "Updated premium wireless headphones.",
  "tags": [
    "electronics",
    "audio",
    "wireless"
  ]
}
```

**Responses**

- `200` — Product updated
- `201` — Product created (upsert)
- `403` — Access denied

Response example, 200:

```json
{
  "id": 101,
  "name": "Wireless Headphones Pro",
  "slug": "wireless-headphones-pro",
  "status": "visible",
  "price": 9999,
  "regular_price": 12999,
  "currency_code": "USD",
  "_links": {
    "self": {
      "href": "https://api.onbolder.com/v2/products/101"
    }
  }
}
```

Response example, 201:

```json
{
  "_links": {
    "property1": {
      "href": "string",
      "templated": true,
      "method": "get",
      "title": "string",
      "type": "string"
    },
    "property2": {
      "href": "string",
      "templated": true,
      "method": "get",
      "title": "string",
      "type": "string"
    }
  },
  "id": 0,
  "name": "string",
  "slug": "string",
  "class_name": "string",
  "status": "visible",
  "description": "string",
  "short_description": "string",
  "is_bundle": true,
  "is_deliverable": true,
  "has_options": true,
  "tags": [
    "string"
  ],
  "currency_code": "USD",
  "bundle_price_mode": "price",
  "bundle_discount": 0,
  "regular_price": 0,
  "price": 0,
  "sale_price": 0,
  "sale_price_starts_at": "2019-08-24T14:15:22Z",
  "sale_price_ends_at": "2019-08-24T14:15:22Z",
  "has_multiple_prices": true,
  "discount_percentage": 0,
  "safety_stock": 0,
  "available": true,
  "stock": 0,
  "online_stock": 0,
  "all_stock": 0,
  "vendor": "string",
  "variant_options": [
    {
      "name": "string",
      "value": "string"
    }
  ],
  "global_tags": [
    "string"
  ],
  "stocks": {
    "property1": 0,
    "property2": 0
  },
  "stocks_per_location": {
    "property1": 0,
    "property2": 0
  },
  "cart_max_quantity": 0,
  "cart_quantity_multiple": 0,
  "list_prices": [
    {
      "price_list_id": 0,
      "price": 0
    }
  ],
  "created_on": "2019-08-24T14:15:22Z",
  "updated_on": "2019-08-24T14:15:22Z"
}
```
