---
title: "List digital products"
description: "List the digital products (Shopify products or variants with files attached in Filemonk), by product title, paginated (page, per_page up to 200). search matches title, variant title or SKU the way the Products page searc"
url: https://docs.filemonk.io/v2/api-reference/digital-products/list-digital-products/
api: "API v2 reference"
method: GET
path: "/digital_products"
---

# List digital products

`GET https://app.filemonk.io/api/v2/external/digital_products`

List the digital products (Shopify products or variants with files attached in Filemonk), by product title, paginated (page, per_page up to 200). search matches title, variant title or SKU the way the Products page search does; scope is product or variant; shopify_product_id / shopify_variant_id narrow to one Shopify product or variant; preorder and attach_to_every_order take true or false.

## Query parameters

- `scope` (string) One of: `product`, `variant`.
- `preorder` (string) One of: `true`, `false`.
- `attach_to_every_order` (string) One of: `true`, `false`.
- `page` (integer): 1-based page number.
- `per_page` (integer): Rows per page, max 200.
- `search` (string)
- `shopify_product_id` (string)
- `shopify_variant_id` (string)

## Returns

- `data` (array of objects, required)
  - `id` (string, nullable, required): e.g. `7ea3c05d-6f29-42b6-b24f-43260caeaa32`
  - `scope` (string, nullable, required): e.g. `product`
  - `shopify_product_id` (string, nullable, required): e.g. `gid://shopify/Product/9642107044135`
  - `shopify_variant_id` (any, required)
  - `title` (string, nullable, required): e.g. `Watercolour Course`
  - `variant_title` (any, required)
  - `sku` (any, required)
  - `files_count` (integer, nullable, required): e.g. `2`
  - `preorder` (object, required)
    - `enabled` (boolean, nullable, required): e.g. `false`
  - `delivery` (object, required)
    - `attach_to_every_order` (boolean, nullable, required): e.g. `false`
  - `exists_on_shopify` (any, required)
  - `updated_at` (string, nullable, required): e.g. `2025-05-31T13:37:52Z`
- `meta` (object, required): Paging of a list (`page`, `per_page` query params).
  - `total_count` (integer, required): Rows across all pages.
  - `page` (integer, required): 1-based page number.
  - `per_page` (integer, required): Rows per page, max 200.
  - `total_pages` (integer, required): e.g. `1`

Rate limit: this call costs 1 point ([rate limits](https://docs.filemonk.io/v2/errors-and-rate-limits/)).

## Examples

### List digital products

```sh
curl "https://app.filemonk.io/api/v2/external/digital_products" \
  -H "X-Auth-Token: $FILEMONK_API_KEY"
```

### List digital products filtered by scope, preorder and attach_to_every_order

```sh
curl "https://app.filemonk.io/api/v2/external/digital_products?scope=product&preorder=true&attach_to_every_order=true" \
  -H "X-Auth-Token: $FILEMONK_API_KEY"
```

## 200

Success: one page of rows.

```json
{
  "data": [
    {
      "id": "7ea3c05d-6f29-42b6-b24f-43260caeaa32",
      "scope": "product",
      "shopify_product_id": "gid://shopify/Product/9642107044135",
      "shopify_variant_id": null,
      "title": "Watercolour Course",
      "variant_title": null,
      "sku": null,
      "files_count": 2,
      "preorder": {
        "enabled": false
      },
      "delivery": {
        "attach_to_every_order": false
      },
      "exists_on_shopify": null,
      "updated_at": "2025-05-31T13:37:52Z"
    }
  ],
  "meta": {
    "total_count": 6,
    "page": 1,
    "per_page": 50,
    "total_pages": 1
  }
}
```

## 401

Missing or invalid API key.

```json
{
  "errors": [
    "Invalid API key"
  ]
}
```

## 422

The request failed validation, or sent a key the action does not take (`code: &quot;unknown_parameters&quot;` with `unknown` and `accepted`). Nothing was saved.

```json
{
  "errors": [
    "access.download_limit_count must be an integer of at least 0"
  ],
  "field_errors": {
    "access.download_limit_count": [
      "must be an integer of at least 0"
    ]
  }
}
```

## 429

Rate limited. Cost-weighted per API key, shared with API v1: a read costs 1 point, a write 2, 40 points per fixed 60-second window. Every response carries `X-RateLimit-Limit`, `X-RateLimit-Remaining` and `X-RateLimit-Reset` (Unix time the window ends); a 429 adds `Retry-After` (seconds), `retry_after`, `retryable: true` and a `next_step` in the body. A 429 did nothing: wait `retry_after` seconds, then send the same request again. The budget is per key, so every tool or script using the key shares it; prefer one list call with `per_page` over many single reads.

```json
{
  "errors": [
    "You have exceeded the rate limit of 40 points per 60 seconds. Read requests cost 1 point(s) and write requests cost 2 point(s). Please retry after 12 second(s)."
  ],
  "code": "rate_limited",
  "retry_after": 12,
  "error": "Rate limit exceeded",
  "message": "You have exceeded the rate limit of 40 points per 60 seconds. Read requests cost 1 point(s) and write requests cost 2 point(s). Please retry after 12 second(s)."
}
```

