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

# List products

> Returns a paginated list of products for the current store.

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



## OpenAPI

````yaml /api-reference/admin.yaml get /api/v3/admin/products
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 login, logout, token refresh, and current user profile
  - name: Allowed Origins
    description: CORS allowlist for storefront and admin client origins
  - name: API Keys
    description: Secret and publishable API keys
  - name: Categories
    description: >-
      Hierarchical product categories — tree management, repositioning, and
      product assignments
  - name: Channels
    description: >-
      Sales channels, product publication across channels, and per-channel order
      routing rules
  - name: Custom Fields
    description: >-
      Custom field definitions for products, variants, customers, and other
      resources
  - name: Customer Groups
    description: >-
      Customer groups for segmenting customers (e.g. wholesale, VIP) used by
      pricing and promotions
  - name: Customers
    description: Customer profiles, addresses, credit cards, and store credits
  - name: Exports
    description: Async CSV exports of admin resources
  - name: Fulfillments
    description: Order fulfillments — shipments, fulfill, cancel, resume, split
  - name: Gift Cards
    description: Gift cards and gift card batches
  - name: Imports
    description: >-
      Async CSV imports of admin resources, with per-row status and failed-row
      retry
  - name: Markets
    description: >-
      Markets — geographic groupings of countries used for pricing, tax, and
      fulfillment rules
  - name: Option Types
    description: >-
      Option types and option values used to build product variants (e.g. Size,
      Color)
  - name: Orders
    description: Orders, order items, applied gift cards, and applied store credits
  - name: Payment Methods
    description: Configured payment providers and their available types
  - name: Payments
    description: Order payments — list, capture, void
  - name: Pricing
    description: >-
      Prices and price lists for currency-, market-, and customer-group-specific
      pricing
  - name: Products
    description: >-
      Products, taxons/categories, product custom field values, and bulk product
      operations
  - name: Promotions
    description: Promotions, promotion rules, promotion actions, and coupon codes
  - name: Refunds
    description: Order refunds
  - name: Settings
    description: Store-level settings — store profile, tags, store credit categories
  - name: Staff
    description: Admin users, roles, and invitations to the store
  - name: Stock Locations
    description: Warehouses and physical fulfillment locations
  - name: Variants
    description: >-
      Product variants — the individual SKUs (size/color combinations) sold
      under a product
  - name: Webhooks
    description: Webhook endpoints and webhook delivery history
paths:
  /api/v3/admin/products:
    get:
      tags:
        - Products
      summary: List products
      description: |-
        Returns a paginated list of products for the current store.

        **Required scope:** `read_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: page
          in: query
          required: false
          description: Page number
          schema:
            type: integer
        - name: limit
          in: query
          required: false
          description: Number of records per page
          schema:
            type: integer
        - name: sort
          in: query
          required: false
          description: Sort field (e.g., name, -name, price, -price, best_selling)
          schema:
            type: string
        - name: expand
          in: query
          required: false
          description: >-
            Comma-separated associations to expand (e.g., variants, media,
            option_types, categories). Use dot notation for nested expand (max 4
            levels).
          schema:
            type: string
        - name: fields
          in: query
          required: false
          description: >-
            Comma-separated list of fields to include (e.g.,
            name,slug,price,status). id is always included.
          schema:
            type: string
        - name: q[name_cont]
          in: query
          required: false
          description: Filter by name (contains)
          schema:
            type: string
        - name: q[status_eq]
          in: query
          required: false
          description: Filter by status
          schema:
            type: string
      responses:
        '200':
          description: products found
          content:
            application/json:
              example:
                data:
                  - id: prod_UkLWZg9DAJ
                    name: Product 623463
                    slug: product-623463
                    meta_title: null
                    meta_description: null
                    meta_keywords: null
                    variant_count: 0
                    available_on: null
                    preorder_ships_at: null
                    purchasable: true
                    preorder: false
                    in_stock: false
                    backorderable: true
                    available: true
                    description: >-
                      Quidem culpa ea deserunt architecto. Eaque rem hic nulla
                      totam quibusdam fugit dolorum. Dignissimos perspiciatis
                      earum deserunt mollitia recusandae voluptas distinctio
                      placeat. Fugiat animi quibusdam iste facilis sed nostrum
                      ipsam. Nihil nesciunt vel debitis natus in. Rem
                      praesentium architecto cupiditate deleniti deserunt.
                      Cumque vero vel provident hic ipsam saepe porro suscipit.
                    description_html: >-
                      Quidem culpa ea deserunt architecto. Eaque rem hic nulla
                      totam quibusdam fugit dolorum. Dignissimos perspiciatis
                      earum deserunt mollitia recusandae voluptas distinctio
                      placeat. Fugiat animi quibusdam iste facilis sed nostrum
                      ipsam.

                      Nihil nesciunt vel debitis natus in. Rem praesentium
                      architecto cupiditate deleniti deserunt. Cumque vero vel
                      provident hic ipsam saepe porro suscipit.
                    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-07-26T14:25:36.301Z'
                      updated_at: '2026-07-26T14:25:36.301Z'
                    original_price: null
                    status: active
                    metadata: {}
                    deleted_at: null
                    created_at: '2026-07-26T14:25:36.291Z'
                    updated_at: '2026-07-26T14:25:36.308Z'
                    tax_category_id: taxcat_UkLWZg9DAJ
                meta:
                  page: 1
                  limit: 25
                  count: 1
                  pages: 1
                  from: 1
                  to: 1
                  in: 1
                  previous: null
                  next: null
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      $ref: '#/components/schemas/Product'
                  meta:
                    $ref: '#/components/schemas/PaginationMeta'
                required:
                  - data
                  - meta
        '401':
          description: unauthorized
          content:
            application/json:
              example:
                error:
                  code: authentication_required
                  message: Authentication required
              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 { data: products } = await client.products.list({
              name_cont: 'shirt',
              status_eq: 'active',
              sort: '-created_at',
              limit: 25,
            })
        - lang: bash
          label: Spree CLI
          source: >-
            spree api get /products -d
            '{"name_cont":"shirt","status_eq":"active","sort":"-created_at","limit":25}'
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
        preorder_ships_at:
          type: string
          nullable: true
        purchasable:
          type: boolean
        preorder:
          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:
          allOf:
            - $ref: '#/components/schemas/Price'
          nullable: true
        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'
        option_values:
          type: array
          items:
            $ref: '#/components/schemas/OptionValue'
        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
        translations:
          type: object
        status:
          type: string
        metadata:
          type: object
        deleted_at:
          type: string
          nullable: true
        created_at:
          type: string
        updated_at:
          type: string
        tax_category_id:
          type: string
          nullable: true
        product_publications:
          type: array
          items:
            $ref: '#/components/schemas/ProductPublication'
        channels:
          type: array
          items:
            $ref: '#/components/schemas/Channel'
      required:
        - id
        - name
        - slug
        - meta_title
        - meta_description
        - meta_keywords
        - variant_count
        - available_on
        - preorder_ships_at
        - purchasable
        - preorder
        - in_stock
        - backorderable
        - available
        - description
        - description_html
        - default_variant_id
        - thumbnail_url
        - tags
        - price
        - original_price
        - status
        - metadata
        - deleted_at
        - created_at
        - updated_at
        - tax_category_id
      x-typelizer: true
    PaginationMeta:
      type: object
      properties:
        page:
          type: integer
          example: 1
        limit:
          type: integer
          example: 25
        count:
          type: integer
          example: 100
          description: Total number of records
        pages:
          type: integer
          example: 4
          description: Total number of pages
        from:
          type: integer
          example: 1
          description: Index of first record on this page
        to:
          type: integer
          example: 25
          description: Index of last record on this page
        in:
          type: integer
          example: 25
          description: Number of records on this page
        previous:
          type: integer
          nullable: true
          example: null
          description: Previous page number
        next:
          type: integer
          nullable: true
          example: 2
          description: Next page number
      required:
        - page
        - limit
        - count
        - pages
        - from
        - to
        - in
    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
        download_url:
          type: string
          nullable: true
        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
        - download_url
        - 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
        preorder_ships_at:
          type: string
          nullable: true
        thumbnail_url:
          type: string
          nullable: true
        purchasable:
          type: boolean
        in_stock:
          type: boolean
        backorderable:
          type: boolean
        preorder:
          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
        cost_price:
          type: string
          nullable: true
        cost_currency:
          type: string
          nullable: true
        barcode:
          type: string
          nullable: true
        weight_unit:
          type: string
          nullable: true
        dimensions_unit:
          type: string
          nullable: true
        backorder_limit:
          type: number
          nullable: true
        deleted_at:
          type: string
          nullable: true
        created_at:
          type: string
        updated_at:
          type: string
        preorderable:
          type: boolean
        tax_category_id:
          type: string
          nullable: true
        available_stock:
          type: number
          nullable: true
        reserved_quantity:
          type: number
        total_on_hand:
          type: number
          nullable: true
        product_name:
          type: string
        prices:
          type: array
          items:
            $ref: '#/components/schemas/Price'
        stock_items:
          type: array
          items:
            $ref: '#/components/schemas/StockItem'
      required:
        - id
        - product_id
        - sku
        - options_text
        - track_inventory
        - media_count
        - preorder_ships_at
        - thumbnail_url
        - purchasable
        - in_stock
        - backorderable
        - preorder
        - weight
        - height
        - width
        - depth
        - price
        - original_price
        - option_values
        - metadata
        - position
        - cost_price
        - cost_currency
        - barcode
        - weight_unit
        - dimensions_unit
        - backorder_limit
        - deleted_at
        - created_at
        - updated_at
        - preorderable
        - tax_category_id
        - available_stock
        - reserved_quantity
        - total_on_hand
        - product_name
      x-typelizer: true
    OptionType:
      type: object
      properties:
        id:
          type: string
        name:
          type: string
        label:
          type: string
        position:
          type: number
        kind:
          type: string
        translations:
          type: object
        metadata:
          type: object
        filterable:
          type: boolean
        created_at:
          type: string
        updated_at:
          type: string
        option_values:
          type: array
          items:
            $ref: '#/components/schemas/OptionValue'
      required:
        - id
        - name
        - label
        - position
        - kind
        - metadata
        - filterable
        - created_at
        - updated_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
    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'
        translations:
          type: object
        metadata:
          type: object
        pretty_name:
          type: string
        lft:
          type: number
        rgt:
          type: number
        products_count:
          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
        - products_count
        - 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
    ProductPublication:
      type: object
      properties:
        id:
          type: string
        published_at:
          type: string
          nullable: true
        unpublished_at:
          type: string
          nullable: true
        product_id:
          type: string
        channel_id:
          type: string
        created_at:
          type: string
        updated_at:
          type: string
      required:
        - id
        - published_at
        - unpublished_at
        - product_id
        - channel_id
        - created_at
        - updated_at
      x-typelizer: true
    Channel:
      type: object
      properties:
        id:
          type: string
        name:
          type: string
        code:
          type: string
        active:
          type: boolean
        default:
          type: boolean
        storefront_access:
          type: string
        guest_checkout:
          type: boolean
        preferred_order_routing_strategy:
          type: string
          nullable: true
        preferred_storefront_access:
          type: string
          nullable: true
        preferred_guest_checkout:
          type: boolean
          nullable: true
        created_at:
          type: string
        updated_at:
          type: string
      required:
        - id
        - name
        - code
        - active
        - default
        - storefront_access
        - guest_checkout
        - preferred_order_routing_strategy
        - preferred_storefront_access
        - preferred_guest_checkout
        - created_at
        - updated_at
      x-typelizer: true
    StockItem:
      type: object
      properties:
        id:
          type: string
        count_on_hand:
          type: number
        backorderable:
          type: boolean
        stock_location_id:
          type: string
          nullable: true
        variant_id:
          type: string
          nullable: true
        metadata:
          type: object
        created_at:
          type: string
        updated_at:
          type: string
        allocated_count:
          type: number
        available_count:
          type: number
        stock_location:
          $ref: '#/components/schemas/StockLocation'
        variant:
          $ref: '#/components/schemas/Variant'
      required:
        - id
        - count_on_hand
        - backorderable
        - stock_location_id
        - variant_id
        - metadata
        - created_at
        - updated_at
        - allocated_count
        - available_count
      x-typelizer: true
    StockLocation:
      type: object
      properties:
        id:
          type: string
        state_abbr:
          type: string
          nullable: true
        name:
          type: string
        address1:
          type: string
          nullable: true
        city:
          type: string
          nullable: true
        zipcode:
          type: string
          nullable: true
        country_iso:
          type: string
          nullable: true
        country_name:
          type: string
          nullable: true
        state_text:
          type: string
          nullable: true
        admin_name:
          type: string
          nullable: true
        address2:
          type: string
          nullable: true
        state_name:
          type: string
          nullable: true
        phone:
          type: string
          nullable: true
        company:
          type: string
          nullable: true
        active:
          type: boolean
        default:
          type: boolean
        backorderable_default:
          type: boolean
        propagate_all_variants:
          type: boolean
        kind:
          type: string
        pickup_enabled:
          type: boolean
        pickup_stock_policy:
          type: string
        pickup_ready_in_minutes:
          type: number
          nullable: true
        pickup_instructions:
          type: string
          nullable: true
        created_at:
          type: string
        updated_at:
          type: string
      required:
        - id
        - state_abbr
        - name
        - address1
        - city
        - zipcode
        - country_iso
        - country_name
        - state_text
        - admin_name
        - address2
        - state_name
        - phone
        - company
        - active
        - default
        - backorderable_default
        - propagate_all_variants
        - kind
        - pickup_enabled
        - pickup_stock_policy
        - pickup_ready_in_minutes
        - pickup_instructions
        - 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

````