---
title: "List products"
description: "Read per-product back-in-stock configuration: notify-me button visibility (always_show / when_out_of_stock / never_show), restock message and assigned widget template (widget_template_id, from GET /back_in_stock/widget_t"
url: https://docs.stoqapp.com/v2-reference/back-in-stock-products/list-products/
api: "API v2 reference"
method: GET
path: "/back_in_stock/products"
---

# List products

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

Read per-product back-in-stock configuration: notify-me button visibility (always_show / when_out_of_stock / never_show), restock message and assigned widget template (widget_template_id, from [`GET /back_in_stock/widget_templates`](https://docs.stoqapp.com/v2-reference/back-in-stock-widget-templates/list-widget-templates/)) for each variant, plus whether the shop-level per-product customization toggle is on. Each row also has the variant's pending and total signups (count_by as on the dashboard) and its lifetime back-in-stock units sold and revenue. Without search, rows are the variants STOQ has activity for (signups, per-product settings, offers), sorted by pending signups, most first. search (product name, variant title, SKU, product URL or id) also looks the term up in the Shopify catalog: matching variants STOQ has no row for come after the STOQ rows, with default settings and zero counts. Every row has has_stoq_activity; a search response has catalog_searched (false when the catalog was skipped or could not be reached). Filter with shopify_product_id, shopify_variant_id, overrides_only=true or has_waitlist=true; the last two only match STOQ rows, so they skip the catalog. Shopify ids are gids both ways, e.g. &quot;gid://shopify/ProductVariant/123&quot;.

**Note:** Any of sort, group_by, after, product_status, button_visibility, restock_message or restock_message_query lists the dashboard's Products tab instead: the whole Shopify catalog, sorted by sort (title_asc, the default, title_desc, created_desc, created_asc), limit rows per page (default 20, max 100), search matching title or SKU. product_status is a comma list of active, draft, archived, unlisted. button_visibility (comma list of the three values) and restock_message (has or none) with restock_message_query (text the message contains) only match variants STOQ has a row for, as on the tab; with them product_status_filter_skipped is true when product statuses could not be checked and the status filter was left out. group_by=product returns products, each with its variants. Pass the response's end_cursor as after for the next page while has_next_page is true. shopify_product_id, shopify_variant_id, overrides_only and has_waitlist cannot be combined with these.

## Query parameters

- `count_by` (string) One of: `customers`, `signups`.
- `sort` (string) One of: `title_asc`, `title_desc`, `created_desc`, `created_asc`.
- `group_by` (string) One of: `variant`, `product`.
- `restock_message` (string) One of: `has`, `none`.
- `shopify_product_id` (string)
- `shopify_variant_id` (string)
- `overrides_only` (string)
- `has_waitlist` (string)
- `limit` (integer)
- `search` (string)
- `after` (string)
- `product_status` (string)
- `button_visibility` (string)
- `restock_message_query` (string)

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

## Examples

### List products

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

### List products filtered by count_by, sort and group_by

```sh
curl "https://app.stoqapp.com/api/v2/external/back_in_stock/products?count_by=customers&sort=title_asc&group_by=variant" \
  -H "X-Auth-Token: $STOQ_API_KEY"
```

## 200

Success: the requested resource.

## 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
    }
  ]
}
```

