List products
API v2 is in public beta: endpoints and fields can change before general availability. See the changelog
/back_in_stock/productsCosts 1 rate-limit point · Rate limits
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) 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. "gid://shopify/ProductVariant/123".
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.
Also searched aswhich products have custom notify me settingsper product back in stock configproduct button visibilityproducts tab settings
Query parameters
count_bystringOne ofcustomerssignupssortstringOne oftitle_asctitle_desccreated_desccreated_ascgroup_bystringOne ofvariantproductrestock_messagestringOne ofhasnoneshopify_product_idstringshopify_variant_idstringoverrides_onlystringhas_waitliststringlimitintegersearchstringafterstringproduct_statusstringbutton_visibilitystringrestock_message_querystring
Errors
Missing or invalid X-Auth-Token.
The request failed validation.
Rate limited: cost-weighted per token (read 1, write 2; 360 points / 60s). Check Retry-After.
Every error has the same shape: see Errors.
curl "https://app.stoqapp.com/api/v2/external/back_in_stock/products" \
-H "X-Auth-Token: $STOQ_API_KEY"const res = await fetch("https://app.stoqapp.com/api/v2/external/back_in_stock/products", {
headers: {
"X-Auth-Token": process.env.STOQ_API_KEY,
},
});
const data = await res.json();import os
import requests
res = requests.get(
"https://app.stoqapp.com/api/v2/external/back_in_stock/products",
headers={"X-Auth-Token": os.environ["STOQ_API_KEY"]},
)
data = res.json()require "net/http"
require "json"
uri = URI("https://app.stoqapp.com/api/v2/external/back_in_stock/products")
req = Net::HTTP::Get.new(uri, "X-Auth-Token" => ENV["STOQ_API_KEY"])
res = Net::HTTP.start(uri.host, uri.port, use_ssl: true) { |http| http.request(req) }
data = JSON.parse(res.body)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"const res = await fetch("https://app.stoqapp.com/api/v2/external/back_in_stock/products?count_by=customers&sort=title_asc&group_by=variant", {
headers: {
"X-Auth-Token": process.env.STOQ_API_KEY,
},
});
const data = await res.json();import os
import requests
res = requests.get(
"https://app.stoqapp.com/api/v2/external/back_in_stock/products?count_by=customers&sort=title_asc&group_by=variant",
headers={"X-Auth-Token": os.environ["STOQ_API_KEY"]},
)
data = res.json()require "net/http"
require "json"
uri = URI("https://app.stoqapp.com/api/v2/external/back_in_stock/products?count_by=customers&sort=title_asc&group_by=variant")
req = Net::HTTP::Get.new(uri, "X-Auth-Token" => ENV["STOQ_API_KEY"])
res = Net::HTTP.start(uri.host, uri.port, use_ssl: true) { |http| http.request(req) }
data = JSON.parse(res.body){
"errors": [
"Invalid API key"
],
"code": "auth_invalid",
"details": [
{
"code": "auth_invalid",
"message": "Invalid API key",
"path": null,
"value": null,
"expected": null
}
]
}{
"errors": [
"name is required"
],
"code": "validation_failed",
"details": [
{
"code": "validation_failed",
"message": "name is required",
"path": null,
"value": null,
"expected": null
}
]
}{
"errors": [
"Rate limit exceeded"
],
"code": "rate_limited",
"details": [
{
"code": "rate_limited",
"message": "Rate limit exceeded",
"path": null,
"value": null,
"expected": null
}
]
}