> ## Documentation Index
> Fetch the complete documentation index at: https://spreecommerce.org/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Update a product

> Updates a product. Only provided fields are updated.

**Required scope:** `write_products` (for API-key authentication).



## OpenAPI

````yaml /api-reference/admin.yaml patch /api/v3/admin/products/{id}
openapi: 3.0.3
info:
  title: Admin API
  contact:
    name: Spree Commerce
    url: https://spreecommerce.org
    email: hello@spreecommerce.org
  description: >
    Spree Admin API v3 - Administrative API for managing products, orders, and
    store settings.


    ## Authentication


    The Admin API requires a secret API key passed in the `x-spree-api-key`
    header.

    Secret API keys can be generated in the Spree admin dashboard.


    ## Response Format


    All responses are JSON. List endpoints return paginated responses with
    `data` and `meta` keys.

    Single resource endpoints return a flat JSON object.


    ## Resource IDs


    Every resource is identified by an opaque string ID (e.g. `prod_86Rf07xd4z`,

    `variant_k5nR8xLq`, `or_UkLWZg9DAJ`). Use these IDs everywhere — URL paths,

    request bodies, and Ransack filters all accept them directly.


    ## Error Handling


    Errors return a consistent format:

    ```json

    {
      "error": {
        "code": "validation_error",
        "message": "Validation failed",
        "details": { "name": ["can't be blank"] }
      }
    }

    ```
  version: v3
servers:
  - url: http://{defaultHost}
    variables:
      defaultHost:
        default: localhost:3000
security: []
tags:
  - name: Authentication
    description: Admin user authentication
  - name: Product Catalog
    description: Products, variants, and option types
  - name: Orders
    description: >-
      Order management — orders, items, payments, fulfillments, refunds, gift
      cards, store credits
  - name: Customers
    description: Customer management — profiles, addresses, store credits, credit cards
  - name: Configuration
    description: Store configuration — payment methods, tag autocomplete
paths:
  /api/v3/admin/products/{id}:
    patch:
      tags:
        - Product Catalog
      summary: Update a product
      description: |-
        Updates a product. Only provided fields are updated.

        **Required scope:** `write_products` (for API-key authentication).
      parameters:
        - name: x-spree-api-key
          in: header
          required: true
          schema:
            type: string
        - name: Authorization
          in: header
          required: true
          description: Bearer token for admin authentication
          schema:
            type: string
        - name: id
          in: path
          required: true
          description: Product ID
          schema:
            type: string
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                name:
                  type: string
                  example: Premium T-Shirt
                price:
                  type: number
                  example: 29.99
                description:
                  type: string
                slug:
                  type: string
                status:
                  type: string
                  enum:
                    - draft
                    - active
                    - archived
                sku:
                  type: string
                tax_category_id:
                  type: string
                  description: Tax category ID
                category_ids:
                  type: array
                  items:
                    type: string
                  description: Array of category IDs
                tags:
                  type: array
                  items:
                    type: string
                  example:
                    - eco
                    - sale
                variants:
                  type: array
                  description: >-
                    Array of variant payloads. Variants can declare multiple
                    option pairs via `options:` and per-currency prices via
                    `prices:`. Stock counts go in `stock_items:` (per stock
                    location).
                  items:
                    type: object
                    properties:
                      sku:
                        type: string
                      options:
                        type: array
                        description: >-
                          One pair per option type the variant participates in
                          (e.g. size + color). Option types and values are
                          auto-created if missing.
                        items:
                          type: object
                          required:
                            - name
                            - value
                          properties:
                            name:
                              type: string
                              example: size
                            value:
                              type: string
                              example: Small
                      prices:
                        type: array
                        description: Per-currency prices. Upserted by currency.
                        items:
                          type: object
                          required:
                            - currency
                            - amount
                          properties:
                            currency:
                              type: string
                              example: USD
                            amount:
                              type: number
                              example: 29.99
                            compare_at_amount:
                              type: number
                              example: 39.99
                      stock_items:
                        type: array
                        description: >-
                          Per-stock-location inventory. Upserted by
                          stock_location_id.
                        items:
                          type: object
                          required:
                            - stock_location_id
                            - count_on_hand
                          properties:
                            stock_location_id:
                              type: string
                              description: Stock location ID (e.g. sloc_xxx)
                            count_on_hand:
                              type: integer
                              example: 50
                            backorderable:
                              type: boolean
      responses:
        '200':
          description: product updated
          content:
            application/json:
              example:
                id: prod_UkLWZg9DAJ
                name: Updated Name
                slug: product-459820
                meta_description: null
                meta_keywords: null
                variant_count: 0
                available_on: '2025-05-09T10:05:04.881Z'
                purchasable: true
                in_stock: false
                backorderable: true
                available: true
                description: >-
                  Accusamus saepe quas repellat harum modi maxime. Incidunt
                  impedit quos ex consequatur quia qui deserunt neque. Veritatis
                  commodi velit doloribus accusamus repellendus. Non sed
                  veritatis fugit laudantium quis quisquam ducimus in. Ea fugit
                  repudiandae inventore neque deserunt officiis cupiditate sed.
                  Nostrum voluptas quis maiores eius in cupiditate. Praesentium
                  omnis fuga ratione exercitationem quas quam hic. Cupiditate
                  sapiente hic sequi labore delectus. Aliquam nesciunt dolorum
                  sunt itaque pariatur. Harum exercitationem facilis ea tenetur
                  eveniet. Laudantium perspiciatis asperiores id adipisci. Vel
                  doloremque placeat qui doloribus pariatur assumenda corporis
                  tempora. Ea quibusdam enim dolores nam.
                description_html: >-
                  Accusamus saepe quas repellat harum modi maxime. Incidunt
                  impedit quos ex consequatur quia qui deserunt neque. Veritatis
                  commodi velit doloribus accusamus repellendus. Non sed
                  veritatis fugit laudantium quis quisquam ducimus in. Ea fugit
                  repudiandae inventore neque deserunt officiis cupiditate sed.

                  Nostrum voluptas quis maiores eius in cupiditate. Praesentium
                  omnis fuga ratione exercitationem quas quam hic. Cupiditate
                  sapiente hic sequi labore delectus. Aliquam nesciunt dolorum
                  sunt itaque pariatur. Harum exercitationem facilis ea tenetur
                  eveniet.

                  Laudantium perspiciatis asperiores id adipisci. Vel doloremque
                  placeat qui doloribus pariatur assumenda corporis tempora. Ea
                  quibusdam enim dolores nam.
                default_variant_id: variant_UkLWZg9DAJ
                thumbnail_url: null
                tags: []
                price:
                  id: price_UkLWZg9DAJ
                  amount: '19.99'
                  amount_in_cents: 1999
                  compare_at_amount: null
                  compare_at_amount_in_cents: null
                  currency: USD
                  display_amount: $19.99
                  display_compare_at_amount: null
                  price_list_id: null
                  variant_id: variant_UkLWZg9DAJ
                  created_at: '2026-05-09T10:05:04.930Z'
                  updated_at: '2026-05-09T10:05:04.930Z'
                original_price: null
                status: active
                make_active_at: '2025-05-09T10:05:04.881Z'
                discontinue_on: null
                metadata: {}
                deleted_at: null
                created_at: '2026-05-09T10:05:04.906Z'
                updated_at: '2026-05-09T10:05:05.226Z'
                cost_price: '17.0'
                cost_currency: USD
              schema:
                $ref: '#/components/schemas/Product'
        '422':
          description: validation error
          content:
            application/json:
              example:
                error:
                  code: validation_error
                  message: Name can't be blank
                  details:
                    name:
                      - can't be blank
              schema:
                $ref: '#/components/schemas/ErrorResponse'
      security:
        - api_key: []
          bearer_auth: []
      x-codeSamples:
        - lang: javascript
          label: Spree Admin SDK
          source: |-
            import { createAdminClient } from '@spree/admin-sdk'

            const client = createAdminClient({
              baseUrl: 'https://your-store.com',
              secretKey: 'sk_xxx',
            })

            const product = await client.products.update('prod_86Rf07xd4z', {
              name: 'Updated Name',
              status: 'active',
              tags: ['eco', 'sale'],
            })
components:
  schemas:
    Product:
      type: object
      properties:
        id:
          type: string
        name:
          type: string
        slug:
          type: string
        meta_description:
          type: string
          nullable: true
        meta_keywords:
          type: string
          nullable: true
        variant_count:
          type: number
        available_on:
          type: string
          nullable: true
        purchasable:
          type: boolean
        in_stock:
          type: boolean
        backorderable:
          type: boolean
        available:
          type: boolean
        description:
          type: string
          nullable: true
        description_html:
          type: string
          nullable: true
        default_variant_id:
          type: string
        thumbnail_url:
          type: string
          nullable: true
        tags:
          type: array
          items:
            type: string
        price:
          $ref: '#/components/schemas/Price'
        original_price:
          allOf:
            - $ref: '#/components/schemas/Price'
          nullable: true
        primary_media:
          $ref: '#/components/schemas/Media'
        media:
          type: array
          items:
            $ref: '#/components/schemas/Media'
        variants:
          type: array
          items:
            $ref: '#/components/schemas/Variant'
        default_variant:
          $ref: '#/components/schemas/Variant'
        option_types:
          type: array
          items:
            $ref: '#/components/schemas/OptionType'
        categories:
          type: array
          items:
            $ref: '#/components/schemas/Category'
        custom_fields:
          type: array
          items:
            $ref: '#/components/schemas/CustomField'
        prior_price:
          allOf:
            - $ref: '#/components/schemas/PriceHistory'
          nullable: true
        status:
          type: string
        make_active_at:
          type: string
          nullable: true
        discontinue_on:
          type: string
          nullable: true
        metadata:
          type: object
        deleted_at:
          type: string
          nullable: true
        created_at:
          type: string
        updated_at:
          type: string
        cost_price:
          type: string
          nullable: true
        cost_currency:
          type: string
          nullable: true
      required:
        - id
        - name
        - slug
        - meta_description
        - meta_keywords
        - variant_count
        - available_on
        - purchasable
        - in_stock
        - backorderable
        - available
        - description
        - description_html
        - default_variant_id
        - thumbnail_url
        - tags
        - price
        - original_price
        - status
        - make_active_at
        - discontinue_on
        - metadata
        - deleted_at
        - created_at
        - updated_at
        - cost_price
        - cost_currency
      x-typelizer: true
    ErrorResponse:
      type: object
      properties:
        error:
          type: object
          properties:
            code:
              type: string
              example: record_not_found
            message:
              type: string
              example: Record not found
            details:
              type: object
              description: Field-specific validation errors
              nullable: true
              example:
                name:
                  - is too short
                  - is required
                email:
                  - is invalid
          required:
            - code
            - message
      required:
        - error
      example:
        error:
          code: validation_error
          message: Validation failed
          details:
            name:
              - is too short
            email:
              - is invalid
    Price:
      type: object
      properties:
        id:
          type: string
        amount:
          type: string
          nullable: true
        amount_in_cents:
          type: number
          nullable: true
        compare_at_amount:
          type: string
          nullable: true
        compare_at_amount_in_cents:
          type: number
          nullable: true
        currency:
          type: string
          nullable: true
        display_amount:
          type: string
          nullable: true
        display_compare_at_amount:
          type: string
          nullable: true
        price_list_id:
          type: string
          nullable: true
        variant_id:
          type: string
          nullable: true
        created_at:
          type: string
        updated_at:
          type: string
        variant:
          $ref: '#/components/schemas/Variant'
      required:
        - id
        - amount
        - amount_in_cents
        - compare_at_amount
        - compare_at_amount_in_cents
        - currency
        - display_amount
        - display_compare_at_amount
        - price_list_id
        - variant_id
        - created_at
        - updated_at
      x-typelizer: true
    Media:
      type: object
      properties:
        id:
          type: string
        product_id:
          type: string
          nullable: true
        variant_ids:
          type: array
          items:
            type: string
        position:
          type: number
        alt:
          type: string
          nullable: true
        media_type:
          type: string
        focal_point_x:
          type: number
          nullable: true
        focal_point_y:
          type: number
          nullable: true
        external_video_url:
          type: string
          nullable: true
        original_url:
          type: string
          nullable: true
        mini_url:
          type: string
          nullable: true
        small_url:
          type: string
          nullable: true
        medium_url:
          type: string
          nullable: true
        large_url:
          type: string
          nullable: true
        xlarge_url:
          type: string
          nullable: true
        og_image_url:
          type: string
          nullable: true
        created_at:
          type: string
        updated_at:
          type: string
        viewable_id:
          type: string
        metadata:
          type: object
        viewable_type:
          type: string
      required:
        - id
        - product_id
        - variant_ids
        - position
        - alt
        - media_type
        - focal_point_x
        - focal_point_y
        - external_video_url
        - original_url
        - mini_url
        - small_url
        - medium_url
        - large_url
        - xlarge_url
        - og_image_url
        - created_at
        - updated_at
        - viewable_id
        - metadata
        - viewable_type
      x-typelizer: true
    Variant:
      type: object
      properties:
        id:
          type: string
        product_id:
          type: string
        sku:
          type: string
          nullable: true
        options_text:
          type: string
        track_inventory:
          type: boolean
        media_count:
          type: number
        thumbnail_url:
          type: string
          nullable: true
        purchasable:
          type: boolean
        in_stock:
          type: boolean
        backorderable:
          type: boolean
        weight:
          type: number
          nullable: true
        height:
          type: number
          nullable: true
        width:
          type: number
          nullable: true
        depth:
          type: number
          nullable: true
        price:
          $ref: '#/components/schemas/Price'
        original_price:
          allOf:
            - $ref: '#/components/schemas/Price'
          nullable: true
        primary_media:
          $ref: '#/components/schemas/Media'
        media:
          type: array
          items:
            $ref: '#/components/schemas/Media'
        option_values:
          type: array
          items:
            $ref: '#/components/schemas/OptionValue'
        custom_fields:
          type: array
          items:
            $ref: '#/components/schemas/CustomField'
        prior_price:
          allOf:
            - $ref: '#/components/schemas/PriceHistory'
          nullable: true
        metadata:
          type: object
        position:
          type: number
        total_on_hand:
          type: number
          nullable: true
        tax_category_id:
          type: string
          nullable: true
        cost_price:
          type: string
          nullable: true
        cost_currency:
          type: string
          nullable: true
        deleted_at:
          type: string
          nullable: true
        created_at:
          type: string
        updated_at:
          type: string
        product_name:
          type: string
        display_price:
          type: string
          nullable: true
        prices:
          type: array
          items:
            $ref: '#/components/schemas/Price'
      required:
        - id
        - product_id
        - sku
        - options_text
        - track_inventory
        - media_count
        - thumbnail_url
        - purchasable
        - in_stock
        - backorderable
        - weight
        - height
        - width
        - depth
        - price
        - original_price
        - option_values
        - metadata
        - position
        - total_on_hand
        - tax_category_id
        - cost_price
        - cost_currency
        - deleted_at
        - created_at
        - updated_at
        - product_name
        - display_price
      x-typelizer: true
    OptionType:
      type: object
      properties:
        id:
          type: string
        name:
          type: string
        label:
          type: string
        position:
          type: number
        kind:
          type: string
        metadata:
          type: object
        created_at:
          type: string
        updated_at:
          type: string
        option_values:
          type: array
          items:
            $ref: '#/components/schemas/OptionValue'
      required:
        - id
        - name
        - label
        - position
        - kind
        - metadata
        - created_at
        - updated_at
        - option_values
      x-typelizer: true
    Category:
      type: object
      properties:
        id:
          type: string
        name:
          type: string
        permalink:
          type: string
        position:
          type: number
        depth:
          type: number
        meta_title:
          type: string
          nullable: true
        meta_description:
          type: string
          nullable: true
        meta_keywords:
          type: string
          nullable: true
        children_count:
          type: number
        parent_id:
          type: string
          nullable: true
        description:
          type: string
        description_html:
          type: string
        image_url:
          type: string
          nullable: true
        square_image_url:
          type: string
          nullable: true
        is_root:
          type: boolean
        is_child:
          type: boolean
        is_leaf:
          type: boolean
        parent:
          $ref: '#/components/schemas/Category'
        children:
          type: array
          items:
            $ref: '#/components/schemas/Category'
        ancestors:
          type: array
          items:
            $ref: '#/components/schemas/Category'
        custom_fields:
          type: array
          items:
            $ref: '#/components/schemas/CustomField'
        metadata:
          type: object
        pretty_name:
          type: string
        lft:
          type: number
        rgt:
          type: number
        created_at:
          type: string
        updated_at:
          type: string
      required:
        - id
        - name
        - permalink
        - position
        - depth
        - meta_title
        - meta_description
        - meta_keywords
        - children_count
        - parent_id
        - description
        - description_html
        - image_url
        - square_image_url
        - is_root
        - is_child
        - is_leaf
        - metadata
        - pretty_name
        - lft
        - rgt
        - created_at
        - updated_at
      x-typelizer: true
    CustomField:
      type: object
      properties:
        id:
          type: string
        label:
          type: string
        type:
          type: string
          deprecated: true
        field_type:
          type: string
          enum:
            - short_text
            - long_text
            - rich_text
            - number
            - boolean
            - json
        key:
          type: string
        value:
          type: object
        created_at:
          type: string
        updated_at:
          type: string
        storefront_visible:
          type: boolean
        custom_field_definition_id:
          type: string
      required:
        - id
        - label
        - type
        - field_type
        - key
        - value
        - created_at
        - updated_at
        - storefront_visible
        - custom_field_definition_id
      x-typelizer: true
    PriceHistory:
      type: object
      properties:
        id:
          type: string
        amount:
          type: string
        amount_in_cents:
          type: number
        currency:
          type: string
        display_amount:
          type: string
        recorded_at:
          type: string
        variant_id:
          type: string
        price_id:
          type: string
        compare_at_amount:
          type: string
          nullable: true
        created_at:
          type: string
      required:
        - id
        - amount
        - amount_in_cents
        - currency
        - display_amount
        - recorded_at
        - variant_id
        - price_id
        - compare_at_amount
        - created_at
      x-typelizer: true
    OptionValue:
      type: object
      properties:
        id:
          type: string
        option_type_id:
          type: string
        name:
          type: string
        label:
          type: string
        position:
          type: number
        color_code:
          type: string
          nullable: true
        option_type_name:
          type: string
        option_type_label:
          type: string
        image_url:
          type: string
          nullable: true
        metadata:
          type: object
        created_at:
          type: string
        updated_at:
          type: string
        option_type:
          $ref: '#/components/schemas/OptionType'
      required:
        - id
        - option_type_id
        - name
        - label
        - position
        - color_code
        - option_type_name
        - option_type_label
        - image_url
        - metadata
        - created_at
        - updated_at
      x-typelizer: true
  securitySchemes:
    api_key:
      type: apiKey
      name: x-spree-api-key
      in: header
      description: Secret API key for admin access
    bearer_auth:
      type: http
      scheme: bearer
      bearerFormat: JWT
      description: JWT token for admin user authentication

````