# Update a product (PATCH)

```http
PATCH https://secure.yoprint.com/v1/api/store/{team_slug}/product/{hash_id}
```

- API version: v1
- Operation ID: `v1_public_products_update_patch`
- Section: Products and catalog › [Products](https://developer.yoprint.com/reference/products.md)
- Web page: https://developer.yoprint.com/reference/products/v1-products-update-patch/
- Authentication: `Authorization: Bearer YOUR_API_KEY`

Updates a product. A custom variant product's `size_data` and `color_data` follow its variants and are not taken here; rename a size or color through `variant/rename_options`. A variant's own price, weight and vendor are changed with Update a variant.

Use `PUT`: it checks the fields, and needs `type` (send the product's type; a product's type never changes). `PATCH` takes the same body but checks nothing.

## Permission

Needs the Manage Products permission at the level that can update products.

## Business rules

- Send `vendor_id` on every update: leaving it out, or sending an empty string, clears the product's vendor.
- Send prices as a whole number of thousandths: `12500` is 12.50.
- Existing sales order lines keep the price they were sold at.
- Other fields sent as `null` are dropped, as if left out (for `vendor_id` that means the vendor is cleared, as above). Send an empty string to blank a text field.

## Path parameters

- `team_slug` (string, required): Your team slug, shown as Team ID next to your API key in Profile. Example `your-team`.
- `hash_id` (string, required): The product's id (`id` from List products). A hash id from an earlier answer; unique keys and document numbers (such as `PO0042`) don't work here. Example `EDhVUaC6jbLbed`.

## Request body

Content type `application/json`, required.

Fields:

- `type` (string, required): Required on `PUT`: `simple` or `variant`. It is not compared with the product and never changes it. One of: `"simple"`, `"variant"`.
- `barcode` (string, optional): The product's barcode. Saved as sent.
- `brand` (string, optional): The product's brand.
- `default_price` (integer, optional): Send a whole number of thousandths: `12500` is 12.50.
- `description` (string, optional): A description of the product.
- `dimension_x` (number, optional)
- `dimension_y` (number, optional)
- `dimension_z` (number, optional)
- `price_data` (map of objects, optional): Prices for pricing groups, keyed by pricing group id: `{"<pricing group id>": {"price": 11000}}`. A line priced with that group uses this price instead of `default_price`. Send a whole number of thousandths: `11000` is 11.00.
  - Each item:
    - `price` (integer, required): Send a whole number of thousandths: `11000` is 11.00.
- `supplier_id` (string, optional): The supplier's code for the product.
- `taxable` (boolean, optional): Whether sales tax applies to it.
- `title` (string, optional): Required on create. The product name shown on orders.
- `vendor_id` (string, optional): The vendor you buy it from.
- `weight` (number, optional): The product's weight. Simple products only.

### Example request

```bash
curl -X PATCH 'https://secure.yoprint.com/v1/api/store/your-team/product/EDhVUaC6jbLbed' \
  -H 'Authorization: Bearer YOUR_API_KEY' \
  -H 'Accept: application/json' \
  -H 'X-Yoprint-Decimal-Format: exact-v1' \
  -H 'Content-Type: application/json' \
  -d '{
    "default_price": 13500,
    "title": "Enamel mug, 11 oz",
    "type": "simple",
    "vendor_id": "MFwvMEIK7ud89l"
  }'
```

## Response

`200` Successful response.

Fields:

- `data` (object, required)
  - One of, picked by `type`:
    - **Simple product** (`simple`)
      - `type` (string, required): Always `"simple"`.
      - `default_price` (integer | number | string | null, required): The selling price. Null when not set. Thousandths, an older encoding: `12500` is 12.50. Usually a whole number; an amount finer than a thousandth comes back as a number with a fraction (`1234.5` is 1.2345), or as a string (`"1234.5"`) when you send `X-Yoprint-Decimal-Format: exact-v1`. See [Money and quantities](/concepts/money-and-quantities/).
      - `id` (string, required)
      - `phased_out` (boolean, required)
      - `title` (string | null, required)
      - `trashed` (boolean, required)
      - `barcode` (string | null, optional)
      - `brand` (string | null, optional)
      - `color_data` (array of any, optional)
      - `deleted_at` (string (date-time) | null, optional)
      - `deleted_by` (object | null, optional): Who did it, as `{id, name}`; null when on sale or nobody was recorded.
        - `id` (string, optional)
        - `name` (string, optional)
      - `deleted_variant_count` (null, optional)
      - `description` (string | null, optional)
      - `enable` (boolean, optional)
      - `phased_out_at` (string (date-time) | null, optional)
      - `phased_out_by` (object | null, optional): Who did it, as `{id, name}`; null when on sale or nobody was recorded.
        - `id` (string, optional)
        - `name` (string, optional)
      - `phased_out_variant_count` (null, optional)
      - `price_data` (object | array, optional): Prices for pricing groups, as saved: keyed by the pricing group's internal number (not its hash id), each `{"price": <thousandths>}`. An empty list `[]` when there are none.
      - `size_data` (array of any, optional)
      - `supplier_id` (string | null, optional)
      - `taxable` (boolean, optional)
      - `track_inventory` (boolean, optional)
      - `variant_count` (null, optional)
      - `vendor_id` (string | null, optional)
      - `weight` (number | string | null, optional)
    - **Variant product** (`variant`)
      - `type` (string, required): Always `"variant"`.
      - `color_data` (array of objects, required)
        - Each item:
          - `id` (string, required)
          - `label` (string | null, required)
          - `hex` (string | null, optional)
      - `id` (string, required)
      - `size_data` (array of objects, required)
        - Each item:
          - `id` (string, required)
          - `label` (string | null, required)
      - `title` (string | null, required)
      - `trashed` (boolean, required)
      - `variant_type` (string, required): One of: `"size"`, `"color"`, `"size_color"`.
      - `brand` (string | null, optional)
      - `default_price` (integer | number | string | null, optional): Not used for variant products: each variant has its own. Null when not set. Thousandths, an older encoding: `12500` is 12.50. Usually a whole number; an amount finer than a thousandth comes back as a number with a fraction (`1234.5` is 1.2345), or as a string (`"1234.5"`) when you send `X-Yoprint-Decimal-Format: exact-v1`. See [Money and quantities](/concepts/money-and-quantities/).
      - `description` (string | null, optional)
      - `enable` (boolean, optional)
      - `supplier_id` (string | null, optional)
      - `taxable` (boolean, optional)
      - `vendor_id` (string | null, optional)
- `status` (integer, required)
- `success` (boolean, required)

Example response:

```json
{
  "data": {
    "barcode": null,
    "brand": "Northwind",
    "color_data": [],
    "default_price": 13500,
    "deleted_at": null,
    "deleted_by": null,
    "deleted_variant_count": null,
    "description": null,
    "enable": true,
    "id": "HuUud6gosvykdV",
    "phased_out": false,
    "phased_out_at": null,
    "phased_out_by": null,
    "phased_out_variant_count": null,
    "price_data": [],
    "size_data": [],
    "supplier_id": "MUG-11",
    "taxable": true,
    "title": "Enamel mug, 11 oz",
    "track_inventory": true,
    "trashed": false,
    "type": "simple",
    "variant_count": null,
    "vendor_id": "MFwvMEIK7ud89l",
    "weight": null
  },
  "status": 200,
  "success": true
}
```

## Errors

- `401` The API key is missing or wrong (`unauthenticated`).
- `403` You are not allowed to do this. `api_access_not_in_plan`: your team's plan doesn't include API access (Pro and above, with an active subscription or trial), so every request answers this until the team upgrades. When your role lacks the permission the operation needs, the body is only `{"message": "Insufficient Permission"}`. Other refusals use the error envelope, with `unauthorized` or `user_is_not_authorized`.
  - When: Your role cannot update products. This 403 has a short body, `{"message": "Insufficient Permission"}`, with no `success` or `error`. Fix: Ask a team owner to set Manage Products to "Users CAN view, update and create products".
- `404` Not found. `page_not_found`: the team slug is unknown, you are not a member of the team, or an id in the path is not one of this team's. `code: null`, with a message that starts "No query results for": there is no record with that id.
  - When: No live product with this id. `error.code` is null and `error.message` names the record type. Fix: Restore a deleted product first.
- `500` A business rule refused the request (see the operation's errors), or something failed inside YoPrint. Refusals use the error envelope with a code such as `action_not_allowed`; an unexpected failure answers `{"message": "Server Error"}`. Repeating a refusal gets the same answer; after an unexpected failure, read the record back before you retry a change.
  - When: `default_price` is not a whole number of thousandths. Fix: Send a whole number: `13500` for 13.50.

## Related

- [Rename sizes and colors of a product](https://developer.yoprint.com/reference/product-variants/v1-product-variant-rename-options.md): `POST /v1/api/store/{team_slug}/product/{hash_id}/variant/rename_options`
- [Update a variant](https://developer.yoprint.com/reference/product-variants/v1-product-variant-update.md): `PUT /v1/api/store/{team_slug}/product/{hash_id}/variant/{id}`
