Create a signup
API v2 is in public beta: endpoints and fields can change before general availability. See the changelog
/back_in_stock/signupsCosts 2 rate-limit points · Rate limits
Add a customer to a variant's back-in-stock waitlist, as the dashboard's Add signup page does.
Give email, phone or both: each one becomes its own signup (email channel, sms channel), and a channel that is turned off is skipped with a message in errors. shopify_product_id is read from the variant when omitted. 409 when a pending signup already exists for that contact and variant.
Also searched ascreate signupadd to waitlistadd customer to the notify me listregister a restock alertsign someone up for back in stockadd signup
Headers
Idempotency-KeystringA fresh unique key for every write (a new UUID, say); reuse it only to retry that write. Keys are remembered for 1 hour: the same key and the same request within that hour returns the first result, with
Idempotent-Replayed: true, without running again; the same key with a different method, path or body is refused (422idempotency_key_reused); a retry while the first is still running gets 409idempotency_key_in_progress. Keys are per store. Server errors and rate limits are not kept, so their retry runs.
Request body
shopify_variant_idstringRequiredExample:gid://shopify/ProductVariant/47284734423096quantityintegerExample:2accepts_marketingbooleanshopify_product_idanyemailstringExample:john@example.comphoneanynamestringExample:John Doeshopify_market_idany
Returns
signupsarray of objectsShow 20 child attributesHide child attributes
idstringExample:5f0c2a9e-3b1d-4c8e-9a51-2d7e6b1f0a42channelstringExample:emailcontactstringExample:john@example.comquantityintegerExample:2shopify_product_idstringExample:gid://shopify/Product/8784906035384shopify_variant_idstringExample:gid://shopify/ProductVariant/47284734423096product_titlestringExample:Trail Shoevariant_titlestringExample:Blue / MediumskustringExample:TS-BLU-Mshopify_market_idanycustomer_idstringExample:8b6f1e2a-0c4d-4f7a-b1e3-9d2c5a7f6e10customer_namestringExample:John Doeaccepts_marketingbooleanExample:falsecustomer_unsubscribed_atanycustomer_bounce_countintegerExample:0optin_confirmedanyunsubscribed_atanynotifications_countintegerExample:0notified_atanycreated_atstringExample:2026-06-25T13:45:30Z
errorsobject
Errors
Missing or invalid X-Auth-Token.
An earlier request with the same Idempotency-Key is still running. Wait, then resend the same request with the same key.
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 -X POST "https://app.stoqapp.com/api/v2/external/back_in_stock/signups" \
-H "X-Auth-Token: $STOQ_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"shopify_variant_id": "gid://shopify/ProductVariant/47284734423096",
"email": "john@example.com",
"quantity": 2,
"name": "John Doe"
}'const res = await fetch("https://app.stoqapp.com/api/v2/external/back_in_stock/signups", {
method: "POST",
headers: {
"X-Auth-Token": process.env.STOQ_API_KEY,
"Content-Type": "application/json",
},
body: JSON.stringify({
"shopify_variant_id": "gid://shopify/ProductVariant/47284734423096",
"email": "john@example.com",
"quantity": 2,
"name": "John Doe"
}),
});
const data = await res.json();import os
import requests
res = requests.post(
"https://app.stoqapp.com/api/v2/external/back_in_stock/signups",
headers={"X-Auth-Token": os.environ["STOQ_API_KEY"]},
json={
"shopify_variant_id": "gid://shopify/ProductVariant/47284734423096",
"email": "john@example.com",
"quantity": 2,
"name": "John Doe"
},
)
data = res.json()require "net/http"
require "json"
uri = URI("https://app.stoqapp.com/api/v2/external/back_in_stock/signups")
req = Net::HTTP::Post.new(uri, "X-Auth-Token" => ENV["STOQ_API_KEY"], "Content-Type" => "application/json")
req.body = {
shopify_variant_id: "gid://shopify/ProductVariant/47284734423096",
email: "john@example.com",
quantity: 2,
name: "John Doe"
}.to_json
res = Net::HTTP.start(uri.host, uri.port, use_ssl: true) { |http| http.request(req) }
data = JSON.parse(res.body){
"signups": [
{
"id": "5f0c2a9e-3b1d-4c8e-9a51-2d7e6b1f0a42",
"channel": "email",
"contact": "john@example.com",
"quantity": 2,
"shopify_product_id": "gid://shopify/Product/8784906035384",
"shopify_variant_id": "gid://shopify/ProductVariant/47284734423096",
"product_title": "Trail Shoe",
"variant_title": "Blue / Medium",
"sku": "TS-BLU-M",
"shopify_market_id": null,
"customer_id": "8b6f1e2a-0c4d-4f7a-b1e3-9d2c5a7f6e10",
"customer_name": "John Doe",
"accepts_marketing": false,
"customer_unsubscribed_at": null,
"customer_bounce_count": 0,
"optin_confirmed": null,
"unsubscribed_at": null,
"notifications_count": 0,
"notified_at": null,
"created_at": "2026-06-25T13:45:30Z"
}
],
"errors": {}
}{
"job_id": "job_a1b2c3",
"status_url": "/api/v2/external/jobs/job_a1b2c3"
}{
"errors": [
"Invalid API key"
],
"code": "auth_invalid",
"details": [
{
"code": "auth_invalid",
"message": "Invalid API key",
"path": null,
"value": null,
"expected": null
}
]
}{
"errors": [
"A request with this Idempotency-Key is still running"
],
"code": "idempotency_key_in_progress",
"details": [
{
"code": "idempotency_key_in_progress",
"message": "A request with this Idempotency-Key is still running",
"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
}
]
}