> ## 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.

# Get a product

> Returns a single product by slug or prefix ID



## OpenAPI

````yaml /api-reference/store.yaml get /api/v3/store/products/{id}
openapi: 3.0.3
info:
  title: Store API
  contact:
    name: Spree Commerce
    url: https://spreecommerce.org
    email: hello@spreecommerce.org
  description: >
    Spree Store API v3 - Customer-facing storefront API for building headless
    commerce experiences.


    ## Authentication


    The Store API uses two authentication methods:


    ### API Key (Required)

    All requests must include a publishable API key in the `x-spree-api-key`
    header.


    ### JWT Bearer Token (For authenticated customers)

    After login, include the JWT token in the `Authorization: Bearer <token>`
    header.


    ### Order Token (For guest checkout)

    When creating an order, a `token` is returned. Include this in the
    `x-spree-token` header

    for guest access to that specific order.


    ## Response Format


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


    ## Error Handling


    Errors return a consistent format:

    ```json

    {
      "error": {
        "code": "record_not_found",
        "message": "Product not found"
      }
    }

    ```
  version: v3
servers:
  - url: http://{defaultHost}
    variables:
      defaultHost:
        default: localhost:3000
security: []
tags:
  - name: Authentication
    description: Customer authentication (login, logout, token refresh)
  - name: Product Catalog
    description: Products and categories
  - name: Carts
    description: Shopping cart management
  - name: Orders
    description: Order lookup
  - name: Customers
    description: Customer account, addresses, saved payment methods, and order history
  - name: Markets
    description: Markets, countries, currencies, and locales
  - name: Wishlists
    description: Customer wishlists
  - name: Policies
    description: Store policies (return policy, privacy policy, terms of service)
  - name: Digitals
    description: Digital product downloads
paths:
  /api/v3/store/products/{id}:
    get:
      tags:
        - Product Catalog
      summary: Get a product
      description: Returns a single product by slug or prefix ID
      parameters:
        - name: x-spree-api-key
          in: header
          required: true
          description: Publishable API key
          schema:
            type: string
        - name: id
          in: path
          required: true
          description: Product slug (e.g., spree-tote) or prefix ID (e.g., product_abc123)
          schema:
            type: string
        - name: expand
          in: query
          required: false
          description: Comma-separated associations to expand
          schema:
            type: string
        - name: fields
          in: query
          required: false
          description: >-
            Comma-separated list of fields to include (e.g., name,slug,price).
            id is always included.
          schema:
            type: string
      responses:
        '200':
          description: product without prior_price expanded does not include field
          content:
            application/json:
              example:
                id: prod_UkLWZg9DAJ
                name: Product 1453907
                slug: product-1453907
                meta_title: null
                meta_description: null
                meta_keywords: null
                variant_count: 1
                available_on: '2025-05-13T22:27:22.136Z'
                purchasable: true
                in_stock: false
                backorderable: true
                available: true
                description: A comfortable cotton t-shirt.
                description_html: <p>A <strong>comfortable</strong> cotton t-shirt.</p>
                default_variant_id: variant_gbHJdmfrXB
                thumbnail_url: null
                tags: []
                price:
                  id: price_gbHJdmfrXB
                  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
                original_price: null
                prior_price:
                  id: _AXs1igzRC6
                  amount: '9.99'
                  amount_in_cents: 999
                  currency: USD
                  display_amount: $9.99
                  recorded_at: '2026-04-28T22:27:22Z'
              schema:
                $ref: '#/components/schemas/Product'
        '404':
          description: draft product not visible
          content:
            application/json:
              example:
                error:
                  code: record_not_found
                  message: Product not found
              schema:
                $ref: '#/components/schemas/ErrorResponse'
      security:
        - api_key: []
      x-codeSamples:
        - lang: javascript
          label: Spree SDK
          source: |-
            import { createClient } from '@spree/sdk'

            const client = createClient({
              baseUrl: 'https://your-store.com',
              publishableKey: '<api-key>',
            })

            const product = await client.products.get('spree-tote', {
              expand: ['variants', 'media'],
            })
components:
  schemas:
    Product:
      type: object
      properties:
        id:
          type: string
        name:
          type: string
        slug:
          type: string
        meta_title:
          type: string
          nullable: true
        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
      required:
        - id
        - name
        - slug
        - meta_title
        - 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
      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
      required:
        - id
        - amount
        - amount_in_cents
        - compare_at_amount
        - compare_at_amount_in_cents
        - currency
        - display_amount
        - display_compare_at_amount
        - price_list_id
      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
      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
      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
      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
      x-typelizer: true
    OptionType:
      type: object
      properties:
        id:
          type: string
        name:
          type: string
        label:
          type: string
        position:
          type: number
        kind:
          type: string
      required:
        - id
        - name
        - label
        - position
        - kind
      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'
      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
      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
      required:
        - id
        - label
        - type
        - field_type
        - key
        - value
      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
      required:
        - id
        - amount
        - amount_in_cents
        - currency
        - display_amount
        - recorded_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
      required:
        - id
        - option_type_id
        - name
        - label
        - position
        - color_code
        - option_type_name
        - option_type_label
        - image_url
      x-typelizer: true
  securitySchemes:
    api_key:
      type: apiKey
      name: x-spree-api-key
      in: header
      description: Publishable API key for store access

````