---
title: "List products"
method: GET
path: "/v1/products"
tags: ["Products"]
---

# List products

`GET /v1/products`

Returns a paginated list of your products, most recent first. Archived products are excluded unless you pass `include_archived=true`. See [Pagination](/guides/pagination) for how to page through results. Requires the `products:read` scope.

## Query parameters

- `limit` integer
- `cursor` string
- `include_archived` boolean

## Response `200`

Success

- ProductListResponse
  - `pagination` PaginationResponse
    - `next_cursor` string, nullable
    - `prev_cursor` string, nullable
    - `has_more` boolean
    - `limit` integer
    - `offset` integer
    - `returned` integer
    - `total` integer
  - `items` ProductResponse[] — The products on this page. Each item is a product object.
    - `id` string — Unique identifier for the product, prefixed with `prod_`.
    - `organization_id` string — The organization that owns the product.
    - `name` string — Display name of the product.
    - `description` string, nullable — Optional description of the product. `null` when not set.
    - `price` PriceResponse
      - `currency` string
      - `price_type` 'fixed' | 'free' | 'custom' — How the product is priced. `fixed`: a set amount, given in `amount`. `free`: no charge. `custom`: the customer pays what they want, bounded by `minimum_amount` and `maximum_amount` with an optional `preset_amount` suggestion.
      - `amount` string — Price in the primary currency as a decimal string.
      - `preset_amount` string, nullable — Suggested amount prefilled at checkout for a custom price, as a decimal string. Only used when `price_type` is `custom`.
      - `minimum_amount` string, nullable — Minimum the customer must pay. Present only when `price_type` is `custom`.
      - `maximum_amount` string, nullable — Maximum the customer may pay. Present only when `price_type` is `custom`.
      - `currency_options` CurrencyOptionResponse[]
        - `currency` string
        - `amount` string
        - `minimum_amount` string, nullable
        - `maximum_amount` string, nullable
    - `status` 'active' | 'archived' — Status of the product. `active`: Live and available for use in checkouts and subscriptions. `archived`: Retired. Kept for reference but not available for new purchases.
    - `metadata` object, nullable — Your own key-value data attached to the product, returned unchanged.
    - `media` MediaItemResponse[] — Media items (images) attached to the product. Empty when none are set.
      - `id` string
      - `url` string, nullable
      - `file_name` string
      - `mime_type` string
      - `file_size_bytes` integer
      - `created_at` string, date-time
    - `actor_id` string — Identifier of the user or key that created the product.
    - `created_at` string, date-time — ISO 8601 timestamp when the product was created.
    - `updated_at` string, date-time — ISO 8601 timestamp when the product was last updated.
    - `archived_at` string, date-time, nullable — When set, the product is archived and cannot be used in new checkouts. `null` while the product is active.
    - `billing_cycle` SubscriptionCadence
      - `interval` 'day' | 'week' | 'month' | 'year' — Unit of time for each billing cycle. `day`: billed daily. `week`: billed weekly. `month`: billed monthly. `year`: billed yearly.
      - `frequency` integer — Number of intervals per cycle. For example, `interval` `month` with `frequency` `3` bills every three months.
    - `trial_period` TrialPeriod — The length of the free trial before the first charge, expressed as a count of time units. For example, `{ "interval": "day", "frequency": 14 }` is a 14-day trial.
      - `interval` 'day' | 'week' | 'month' | 'year', required — The unit of time the trial is measured in: `day`, `week`, `month`, or `year`.
      - `frequency` integer, required — How many `interval` units the trial lasts. For example, `interval` `day` with `frequency` `14` is a 14-day trial.
    - `prices` object[] — All prices configured on the product, one per currency. Each has `currency`, `amount`, optional `minimum_amount` and `maximum_amount`, and `is_default`.
    - `total_payments` integer — Running count of completed payments for this product. Starts at `0` and increments as customers pay.
    - `total_amount` string — Running total collected for this product, as a decimal string in the product currency. Starts at `"0.00"`.

## Other responses

- `401` — Unauthorized - Invalid, missing, or expired API key. Verify your API key is correctly formatted and included in the Authorization header as `Bearer sk_sandbox_...` or `Bearer sk_live_...`. Check that your key hasn't been revoked.
- `403` — Forbidden - API key does not have permission for the requested resource. Verify you're using the correct organization's API key and that you're not trying to access another organization's data.

---

[API](https://skmtc.dev/bachs/apis/bachs-api.md) · [All operations](https://skmtc.dev/bachs/apis/bachs-api/llms.txt) · [OpenAPI document](https://skmtc-service-production.skmtc.workers.dev/v1/apis/bachs/bachs-api/revisions/f29efa8a22df/schema)
