---
title: "Retrieve products"
description: "Preorder units, orders, line revenue and last order date per variant (or product), as the dashboard's products table."
url: https://docs.stoqapp.com/v2-reference/preorders-reports/retrieve-products/
api: "API v2 reference"
method: GET
path: "/preorders/reports/products"
---

# Retrieve products

`GET https://app.stoqapp.com/api/v2/external/preorders/reports/products`

Preorder units, orders, line revenue and last order date per variant (or product), as the dashboard's products table.

**Note:** Counts preorder line items only (ordinary items in a mixed cart are excluded). revenue is line revenue. group_by=product rolls variants up to their product. range=all_time is the dashboard's All time. image_url is the variant's stored image, else the product's (null if none is stored).

## Query parameters

- `range` (string)
- `group_by` (string) One of: `variant`, `product`.
- `from` (string)
- `to` (string)
- `sort_by` (string)
- `direction` (string)
- `page` (string)
- `per_page` (string)

## Returns

- `window` (object)
  - `from` (string): e.g. `2026-05-26T00:00:00Z`
  - `to` (string): e.g. `2026-06-25T23:59:59Z`
- `group_by` (string): e.g. `variant`
- `sort_by` (string): e.g. `revenue`
- `direction` (string): e.g. `desc`
- `currency` (string): e.g. `USD`
- `rows` (array of objects)
  - `shopify_product_id` (string): e.g. `gid://shopify/Product/8784906035384`
  - `product_title` (string): e.g. `Classic Sneaker`
  - `shopify_variant_id` (string): e.g. `gid://shopify/ProductVariant/47284734423096`
  - `variant_title` (string): e.g. `Blue / Medium`
  - `sku` (string): e.g. `CS-BLU-M`
  - `units` (integer): e.g. `64`
  - `orders` (integer): e.g. `58`
  - `revenue` (string): e.g. `7040.00`
  - `last_order_date` (string): e.g. `2026-06-25T10:02:00Z`
- `meta` (object)
  - `total_count` (integer): e.g. `42`
  - `page` (integer): e.g. `1`
  - `per_page` (integer): e.g. `25`
  - `total_pages` (integer): e.g. `2`

Rate limit: this call costs 1 point ([rate limits](https://docs.stoqapp.com/docs/rate-limits/)).

## Examples

### Retrieve products

```sh
curl "https://app.stoqapp.com/api/v2/external/preorders/reports/products" \
  -H "X-Auth-Token: $STOQ_API_KEY"
```

### Retrieve products filtered by group_by

```sh
curl "https://app.stoqapp.com/api/v2/external/preorders/reports/products?group_by=variant" \
  -H "X-Auth-Token: $STOQ_API_KEY"
```

## 200

Success: example response shown.

```json
{
  "window": {
    "from": "2026-05-26T00:00:00Z",
    "to": "2026-06-25T23:59:59Z"
  },
  "group_by": "variant",
  "sort_by": "revenue",
  "direction": "desc",
  "currency": "USD",
  "rows": [
    {
      "shopify_product_id": "gid://shopify/Product/8784906035384",
      "product_title": "Classic Sneaker",
      "shopify_variant_id": "gid://shopify/ProductVariant/47284734423096",
      "variant_title": "Blue / Medium",
      "sku": "CS-BLU-M",
      "units": 64,
      "orders": 58,
      "revenue": "7040.00",
      "last_order_date": "2026-06-25T10:02:00Z"
    },
    {
      "shopify_product_id": "gid://shopify/Product/8784906035384",
      "product_title": "Classic Sneaker",
      "shopify_variant_id": "gid://shopify/ProductVariant/47284734455864",
      "variant_title": "Red / Large",
      "sku": "CS-RED-L",
      "units": 31,
      "orders": 30,
      "revenue": "3410.00",
      "last_order_date": "2026-06-24T18:40:00Z"
    }
  ],
  "meta": {
    "total_count": 42,
    "page": 1,
    "per_page": 25,
    "total_pages": 2
  }
}
```

## 401

Missing or invalid `X-Auth-Token`.

```json
{
  "errors": [
    "Invalid API key"
  ],
  "code": "auth_invalid",
  "details": [
    {
      "code": "auth_invalid",
      "message": "Invalid API key",
      "path": null,
      "value": null,
      "expected": null
    }
  ]
}
```

## 422

The request failed validation.

```json
{
  "errors": [
    "name is required"
  ],
  "code": "validation_failed",
  "details": [
    {
      "code": "validation_failed",
      "message": "name is required",
      "path": null,
      "value": null,
      "expected": null
    }
  ]
}
```

## 429

Rate limited: cost-weighted per token (read 1, write 2; 360 points / 60s). Check `Retry-After`.

```json
{
  "errors": [
    "Rate limit exceeded"
  ],
  "code": "rate_limited",
  "details": [
    {
      "code": "rate_limited",
      "message": "Rate limit exceeded",
      "path": null,
      "value": null,
      "expected": null
    }
  ]
}
```

