Home

STOQ API v2 (Beta)

v2.0.0-beta

Contact: support@stoqapp.com

Base URL
https://app.stoqapp.com/api/v2/externalProduction

STOQ's action-driven, AI-native external API. Every action is self-describing (description, aliases, notes, JSON request schema) and also reachable via the /help manifest, skill.md, llms.txt, and the MCP server. Public beta — actions and schemas may change before GA. All endpoints require the X-Auth-Token API key.

Authentication

ApiKeyAuthapiKey

Send your shop’s STOQ API key in the X-Auth-Token header on every request. Find it in the STOQ app under Settings → Integrations → API Key. The key resolves the shop context; the same scheme is used by the MCP server and the v1 API.

API Key: X-Auth-Token in header

Back In Stock · Notifications

List

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

List back-in-stock notifications (the send log) in this shop, paginated.

Note: status=blocked surfaces sends stopped by plan limits (with blocked_reason).

Parameters

channelanyemailsmspushquery
statusanysentblockedquery
variant_idanyquery
product_idanyquery
fromanyquery
toanyquery
pageanyquery
per_pageanyquery

Response

200OKobject

Success — the requested resource.

401UnauthorizedError

Missing or invalid X-Auth-Token.

422Unprocessable EntityError

The request failed validation.

429Too Many RequestsError

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

Authorization

ApiKeyAuthapiKey in header

Send your shop’s STOQ API key in the X-Auth-Token header on every request. Find it in the STOQ app under Settings → Integrations → API Key. The key resolves the shop context; the same scheme is used by the MCP server and the v1 API.

List
curl -X GET 'https://app.stoqapp.com/api/v2/external/back_in_stock/notifications'
const response = await fetch('https://app.stoqapp.com/api/v2/external/back_in_stock/notifications', {
  method: 'GET',
});

const data = await response.json();
import requests

response = requests.get('https://app.stoqapp.com/api/v2/external/back_in_stock/notifications')
data = response.json()
{}
{
  "errors": [
    "Unauthorized"
  ]
}
{
  "errors": [
    "name is required"
  ]
}
{
  "errors": [
    "Rate limit exceeded"
  ]
}

Read

GET
https://app.stoqapp.com/api/v2/external/back_in_stock/notifications/{id}

Read one back-in-stock notification (a single send-log entry).

Parameters

idstringrequiredpath

Response

200OKobject

Success — the requested resource.

401UnauthorizedError

Missing or invalid X-Auth-Token.

404Not FoundError

The resource does not exist for this shop, or the action path is not registered.

422Unprocessable EntityError

The request failed validation.

429Too Many RequestsError

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

Authorization

ApiKeyAuthapiKey in header

Send your shop’s STOQ API key in the X-Auth-Token header on every request. Find it in the STOQ app under Settings → Integrations → API Key. The key resolves the shop context; the same scheme is used by the MCP server and the v1 API.

Read
curl -X GET 'https://app.stoqapp.com/api/v2/external/back_in_stock/notifications/{id}'
const response = await fetch('https://app.stoqapp.com/api/v2/external/back_in_stock/notifications/{id}', {
  method: 'GET',
});

const data = await response.json();
import requests

response = requests.get('https://app.stoqapp.com/api/v2/external/back_in_stock/notifications/{id}')
data = response.json()
{}
{
  "errors": [
    "Unauthorized"
  ]
}
{
  "errors": [
    "Offer not found"
  ]
}
{
  "errors": [
    "name is required"
  ]
}
{
  "errors": [
    "Rate limit exceeded"
  ]
}

Back In Stock · Reports

List

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

List every available back-in-stock report (name, description, aliases, url).

Response

200OKobject

Success — the requested resource.

401UnauthorizedError

Missing or invalid X-Auth-Token.

422Unprocessable EntityError

The request failed validation.

429Too Many RequestsError

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

Authorization

ApiKeyAuthapiKey in header

Send your shop’s STOQ API key in the X-Auth-Token header on every request. Find it in the STOQ app under Settings → Integrations → API Key. The key resolves the shop context; the same scheme is used by the MCP server and the v1 API.

List
curl -X GET 'https://app.stoqapp.com/api/v2/external/back_in_stock/reports'
const response = await fetch('https://app.stoqapp.com/api/v2/external/back_in_stock/reports', {
  method: 'GET',
});

const data = await response.json();
import requests

response = requests.get('https://app.stoqapp.com/api/v2/external/back_in_stock/reports')
data = response.json()
{}
{
  "errors": [
    "Unauthorized"
  ]
}
{
  "errors": [
    "name is required"
  ]
}
{
  "errors": [
    "Rate limit exceeded"
  ]
}

Conversions

GET
https://app.stoqapp.com/api/v2/external/back_in_stock/reports/conversions

Time-series of orders attributed to back-in-stock alerts and the revenue recovered.

Parameters

fromanyquery
toanyquery
variant_idanyquery
product_idanyquery
channelanyquery
granularityanyquery

Response

200OKobject

Success — the requested resource.

401UnauthorizedError

Missing or invalid X-Auth-Token.

422Unprocessable EntityError

The request failed validation.

429Too Many RequestsError

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

Authorization

ApiKeyAuthapiKey in header

Send your shop’s STOQ API key in the X-Auth-Token header on every request. Find it in the STOQ app under Settings → Integrations → API Key. The key resolves the shop context; the same scheme is used by the MCP server and the v1 API.

Conversions
curl -X GET 'https://app.stoqapp.com/api/v2/external/back_in_stock/reports/conversions'
const response = await fetch('https://app.stoqapp.com/api/v2/external/back_in_stock/reports/conversions', {
  method: 'GET',
});

const data = await response.json();
import requests

response = requests.get('https://app.stoqapp.com/api/v2/external/back_in_stock/reports/conversions')
data = response.json()
{}
{
  "errors": [
    "Unauthorized"
  ]
}
{
  "errors": [
    "name is required"
  ]
}
{
  "errors": [
    "Rate limit exceeded"
  ]
}

Conversions Export

POST
https://app.stoqapp.com/api/v2/external/back_in_stock/reports/conversions/export

Async CSV export of the back-in-stock conversions time series.

Body

application/json
fromany
toany
variant_idany
product_idany
channelany
granularityany
sort_byany
directionany
pageany
per_pageany

Response

200OKobject

Success — the updated resource.

202AcceptedJobAccepted

Accepted — async/bulk work was queued. Poll the returned job.

401UnauthorizedError

Missing or invalid X-Auth-Token.

422Unprocessable EntityError

The request failed validation.

429Too Many RequestsError

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

Authorization

ApiKeyAuthapiKey in header

Send your shop’s STOQ API key in the X-Auth-Token header on every request. Find it in the STOQ app under Settings → Integrations → API Key. The key resolves the shop context; the same scheme is used by the MCP server and the v1 API.

Conversions Export
curl -X POST 'https://app.stoqapp.com/api/v2/external/back_in_stock/reports/conversions/export' \
  -H 'Content-Type: application/json' \
  -d '{
    "from": "string",
    "to": "string",
    "variant_id": "45000000001",
    "product_id": "78000000001",
    "channel": "string",
    "granularity": "string",
    "sort_by": "string",
    "direction": "string",
    "page": "string",
    "per_page": "string"
  }'
const response = await fetch('https://app.stoqapp.com/api/v2/external/back_in_stock/reports/conversions/export', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
      "from": "string",
      "to": "string",
      "variant_id": "45000000001",
      "product_id": "78000000001",
      "channel": "string",
      "granularity": "string",
      "sort_by": "string",
      "direction": "string",
      "page": "string",
      "per_page": "string"
    }),
});

const data = await response.json();
import requests

payload = {
  "from": "string",
  "to": "string",
  "variant_id": "45000000001",
  "product_id": "78000000001",
  "channel": "string",
  "granularity": "string",
  "sort_by": "string",
  "direction": "string",
  "page": "string",
  "per_page": "string"
}

response = requests.post('https://app.stoqapp.com/api/v2/external/back_in_stock/reports/conversions/export', json=payload)
data = response.json()
Request Body
{
  "from": "string",
  "to": "string",
  "variant_id": "45000000001",
  "product_id": "78000000001",
  "channel": "string",
  "granularity": "string",
  "sort_by": "string",
  "direction": "string",
  "page": "string",
  "per_page": "string"
}
{}
{
  "job_id": "job_a1b2c3",
  "status_url": "/api/v2/external/jobs/job_a1b2c3"
}
{
  "errors": [
    "Unauthorized"
  ]
}
{
  "errors": [
    "name is required"
  ]
}
{
  "errors": [
    "Rate limit exceeded"
  ]
}

Exports

GET
https://app.stoqapp.com/api/v2/external/back_in_stock/reports/exports/{job_id}

Check the status of an async report export and get the download URL when ready.

Parameters

job_idstringrequiredpath

Response

200OKobject

Success — the requested resource.

401UnauthorizedError

Missing or invalid X-Auth-Token.

404Not FoundError

The resource does not exist for this shop, or the action path is not registered.

422Unprocessable EntityError

The request failed validation.

429Too Many RequestsError

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

Authorization

ApiKeyAuthapiKey in header

Send your shop’s STOQ API key in the X-Auth-Token header on every request. Find it in the STOQ app under Settings → Integrations → API Key. The key resolves the shop context; the same scheme is used by the MCP server and the v1 API.

Exports
curl -X GET 'https://app.stoqapp.com/api/v2/external/back_in_stock/reports/exports/{job_id}'
const response = await fetch('https://app.stoqapp.com/api/v2/external/back_in_stock/reports/exports/{job_id}', {
  method: 'GET',
});

const data = await response.json();
import requests

response = requests.get('https://app.stoqapp.com/api/v2/external/back_in_stock/reports/exports/{job_id}')
data = response.json()
{}
{
  "errors": [
    "Unauthorized"
  ]
}
{
  "errors": [
    "Offer not found"
  ]
}
{
  "errors": [
    "name is required"
  ]
}
{
  "errors": [
    "Rate limit exceeded"
  ]
}

Notifications

GET
https://app.stoqapp.com/api/v2/external/back_in_stock/reports/notifications

Time-series of back-in-stock notifications sent, split by channel (email/sms/push).

Parameters

fromanyquery
toanyquery
variant_idanyquery
product_idanyquery
channelanyquery
granularityanyquery

Response

200OKobject

Success — the requested resource.

401UnauthorizedError

Missing or invalid X-Auth-Token.

422Unprocessable EntityError

The request failed validation.

429Too Many RequestsError

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

Authorization

ApiKeyAuthapiKey in header

Send your shop’s STOQ API key in the X-Auth-Token header on every request. Find it in the STOQ app under Settings → Integrations → API Key. The key resolves the shop context; the same scheme is used by the MCP server and the v1 API.

Notifications
curl -X GET 'https://app.stoqapp.com/api/v2/external/back_in_stock/reports/notifications'
const response = await fetch('https://app.stoqapp.com/api/v2/external/back_in_stock/reports/notifications', {
  method: 'GET',
});

const data = await response.json();
import requests

response = requests.get('https://app.stoqapp.com/api/v2/external/back_in_stock/reports/notifications')
data = response.json()
{}
{
  "errors": [
    "Unauthorized"
  ]
}
{
  "errors": [
    "name is required"
  ]
}
{
  "errors": [
    "Rate limit exceeded"
  ]
}

Notifications Export

POST
https://app.stoqapp.com/api/v2/external/back_in_stock/reports/notifications/export

Async CSV export of the back-in-stock notifications time series.

Body

application/json
fromany
toany
variant_idany
product_idany
channelany
granularityany
sort_byany
directionany
pageany
per_pageany

Response

200OKobject

Success — the updated resource.

202AcceptedJobAccepted

Accepted — async/bulk work was queued. Poll the returned job.

401UnauthorizedError

Missing or invalid X-Auth-Token.

422Unprocessable EntityError

The request failed validation.

429Too Many RequestsError

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

Authorization

ApiKeyAuthapiKey in header

Send your shop’s STOQ API key in the X-Auth-Token header on every request. Find it in the STOQ app under Settings → Integrations → API Key. The key resolves the shop context; the same scheme is used by the MCP server and the v1 API.

Notifications Export
curl -X POST 'https://app.stoqapp.com/api/v2/external/back_in_stock/reports/notifications/export' \
  -H 'Content-Type: application/json' \
  -d '{
    "from": "string",
    "to": "string",
    "variant_id": "45000000001",
    "product_id": "78000000001",
    "channel": "string",
    "granularity": "string",
    "sort_by": "string",
    "direction": "string",
    "page": "string",
    "per_page": "string"
  }'
const response = await fetch('https://app.stoqapp.com/api/v2/external/back_in_stock/reports/notifications/export', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
      "from": "string",
      "to": "string",
      "variant_id": "45000000001",
      "product_id": "78000000001",
      "channel": "string",
      "granularity": "string",
      "sort_by": "string",
      "direction": "string",
      "page": "string",
      "per_page": "string"
    }),
});

const data = await response.json();
import requests

payload = {
  "from": "string",
  "to": "string",
  "variant_id": "45000000001",
  "product_id": "78000000001",
  "channel": "string",
  "granularity": "string",
  "sort_by": "string",
  "direction": "string",
  "page": "string",
  "per_page": "string"
}

response = requests.post('https://app.stoqapp.com/api/v2/external/back_in_stock/reports/notifications/export', json=payload)
data = response.json()
Request Body
{
  "from": "string",
  "to": "string",
  "variant_id": "45000000001",
  "product_id": "78000000001",
  "channel": "string",
  "granularity": "string",
  "sort_by": "string",
  "direction": "string",
  "page": "string",
  "per_page": "string"
}
{}
{
  "job_id": "job_a1b2c3",
  "status_url": "/api/v2/external/jobs/job_a1b2c3"
}
{
  "errors": [
    "Unauthorized"
  ]
}
{
  "errors": [
    "name is required"
  ]
}
{
  "errors": [
    "Rate limit exceeded"
  ]
}

Products In Demand

GET
https://app.stoqapp.com/api/v2/external/back_in_stock/reports/products_in_demand

Ranked variants by back-in-stock demand (pending/total signups, last requested).

Parameters

fromanyquery
toanyquery
variant_idanyquery
product_idanyquery
channelanyquery
sort_byanyquery
directionanyquery
pageanyquery
per_pageanyquery

Response

200OKobject

Success — example response shown.

401UnauthorizedError

Missing or invalid X-Auth-Token.

422Unprocessable EntityError

The request failed validation.

429Too Many RequestsError

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

Authorization

ApiKeyAuthapiKey in header

Send your shop’s STOQ API key in the X-Auth-Token header on every request. Find it in the STOQ app under Settings → Integrations → API Key. The key resolves the shop context; the same scheme is used by the MCP server and the v1 API.

Products In Demand
curl -X GET 'https://app.stoqapp.com/api/v2/external/back_in_stock/reports/products_in_demand'
const response = await fetch('https://app.stoqapp.com/api/v2/external/back_in_stock/reports/products_in_demand', {
  method: 'GET',
});

const data = await response.json();
import requests

response = requests.get('https://app.stoqapp.com/api/v2/external/back_in_stock/reports/products_in_demand')
data = response.json()
{
  "window": {
    "from": "2026-05-26T00:00:00Z",
    "to": "2026-06-25T23:59:59Z"
  },
  "sort_by": "pending",
  "direction": "desc",
  "rows": [
    {
      "shopify_variant_id": 47284734423096,
      "shopify_product_id": 8784906035384,
      "variant_title": "Blue / Medium",
      "product_title": "Classic Sneaker",
      "pending": 47,
      "total": 89,
      "last_requested_at": "2026-06-25T11:30:00Z"
    },
    {
      "shopify_variant_id": 47284734455864,
      "shopify_product_id": 8784906035384,
      "variant_title": "Red / Large",
      "product_title": "Classic Sneaker",
      "pending": 23,
      "total": 56,
      "last_requested_at": "2026-06-25T09:15:00Z"
    }
  ],
  "meta": {
    "total_count": 287,
    "page": 1,
    "per_page": 50,
    "total_pages": 6
  }
}
{
  "errors": [
    "Unauthorized"
  ]
}
{
  "errors": [
    "name is required"
  ]
}
{
  "errors": [
    "Rate limit exceeded"
  ]
}

Products In Demand Export

POST
https://app.stoqapp.com/api/v2/external/back_in_stock/reports/products_in_demand/export

Async CSV export of the back-in-stock products-in-demand report.

Body

application/json
fromany
toany
variant_idany
product_idany
channelany
granularityany
sort_byany
directionany
pageany
per_pageany

Response

200OKobject

Success — the updated resource.

202AcceptedJobAccepted

Accepted — async/bulk work was queued. Poll the returned job.

401UnauthorizedError

Missing or invalid X-Auth-Token.

422Unprocessable EntityError

The request failed validation.

429Too Many RequestsError

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

Authorization

ApiKeyAuthapiKey in header

Send your shop’s STOQ API key in the X-Auth-Token header on every request. Find it in the STOQ app under Settings → Integrations → API Key. The key resolves the shop context; the same scheme is used by the MCP server and the v1 API.

Products In Demand Export
curl -X POST 'https://app.stoqapp.com/api/v2/external/back_in_stock/reports/products_in_demand/export' \
  -H 'Content-Type: application/json' \
  -d '{
    "from": "string",
    "to": "string",
    "variant_id": "45000000001",
    "product_id": "78000000001",
    "channel": "string",
    "granularity": "string",
    "sort_by": "string",
    "direction": "string",
    "page": "string",
    "per_page": "string"
  }'
const response = await fetch('https://app.stoqapp.com/api/v2/external/back_in_stock/reports/products_in_demand/export', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
      "from": "string",
      "to": "string",
      "variant_id": "45000000001",
      "product_id": "78000000001",
      "channel": "string",
      "granularity": "string",
      "sort_by": "string",
      "direction": "string",
      "page": "string",
      "per_page": "string"
    }),
});

const data = await response.json();
import requests

payload = {
  "from": "string",
  "to": "string",
  "variant_id": "45000000001",
  "product_id": "78000000001",
  "channel": "string",
  "granularity": "string",
  "sort_by": "string",
  "direction": "string",
  "page": "string",
  "per_page": "string"
}

response = requests.post('https://app.stoqapp.com/api/v2/external/back_in_stock/reports/products_in_demand/export', json=payload)
data = response.json()
Request Body
{
  "from": "string",
  "to": "string",
  "variant_id": "45000000001",
  "product_id": "78000000001",
  "channel": "string",
  "granularity": "string",
  "sort_by": "string",
  "direction": "string",
  "page": "string",
  "per_page": "string"
}
{}
{
  "job_id": "job_a1b2c3",
  "status_url": "/api/v2/external/jobs/job_a1b2c3"
}
{
  "errors": [
    "Unauthorized"
  ]
}
{
  "errors": [
    "name is required"
  ]
}
{
  "errors": [
    "Rate limit exceeded"
  ]
}

Signups

GET
https://app.stoqapp.com/api/v2/external/back_in_stock/reports/signups

Time-series of back-in-stock signups created (day/week/month).

Parameters

fromanyquery
toanyquery
variant_idanyquery
product_idanyquery
channelanyquery
granularityanyquery

Response

200OKobject

Success — the requested resource.

401UnauthorizedError

Missing or invalid X-Auth-Token.

422Unprocessable EntityError

The request failed validation.

429Too Many RequestsError

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

Authorization

ApiKeyAuthapiKey in header

Send your shop’s STOQ API key in the X-Auth-Token header on every request. Find it in the STOQ app under Settings → Integrations → API Key. The key resolves the shop context; the same scheme is used by the MCP server and the v1 API.

Signups
curl -X GET 'https://app.stoqapp.com/api/v2/external/back_in_stock/reports/signups'
const response = await fetch('https://app.stoqapp.com/api/v2/external/back_in_stock/reports/signups', {
  method: 'GET',
});

const data = await response.json();
import requests

response = requests.get('https://app.stoqapp.com/api/v2/external/back_in_stock/reports/signups')
data = response.json()
{}
{
  "errors": [
    "Unauthorized"
  ]
}
{
  "errors": [
    "name is required"
  ]
}
{
  "errors": [
    "Rate limit exceeded"
  ]
}

Signups Export

POST
https://app.stoqapp.com/api/v2/external/back_in_stock/reports/signups/export

Async CSV export of the back-in-stock signups time series.

Body

application/json
fromany
toany
variant_idany
product_idany
channelany
granularityany
sort_byany
directionany
pageany
per_pageany

Response

200OKobject

Success — the updated resource.

202AcceptedJobAccepted

Accepted — async/bulk work was queued. Poll the returned job.

401UnauthorizedError

Missing or invalid X-Auth-Token.

422Unprocessable EntityError

The request failed validation.

429Too Many RequestsError

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

Authorization

ApiKeyAuthapiKey in header

Send your shop’s STOQ API key in the X-Auth-Token header on every request. Find it in the STOQ app under Settings → Integrations → API Key. The key resolves the shop context; the same scheme is used by the MCP server and the v1 API.

Signups Export
curl -X POST 'https://app.stoqapp.com/api/v2/external/back_in_stock/reports/signups/export' \
  -H 'Content-Type: application/json' \
  -d '{
    "from": "string",
    "to": "string",
    "variant_id": "45000000001",
    "product_id": "78000000001",
    "channel": "string",
    "granularity": "string",
    "sort_by": "string",
    "direction": "string",
    "page": "string",
    "per_page": "string"
  }'
const response = await fetch('https://app.stoqapp.com/api/v2/external/back_in_stock/reports/signups/export', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
      "from": "string",
      "to": "string",
      "variant_id": "45000000001",
      "product_id": "78000000001",
      "channel": "string",
      "granularity": "string",
      "sort_by": "string",
      "direction": "string",
      "page": "string",
      "per_page": "string"
    }),
});

const data = await response.json();
import requests

payload = {
  "from": "string",
  "to": "string",
  "variant_id": "45000000001",
  "product_id": "78000000001",
  "channel": "string",
  "granularity": "string",
  "sort_by": "string",
  "direction": "string",
  "page": "string",
  "per_page": "string"
}

response = requests.post('https://app.stoqapp.com/api/v2/external/back_in_stock/reports/signups/export', json=payload)
data = response.json()
Request Body
{
  "from": "string",
  "to": "string",
  "variant_id": "45000000001",
  "product_id": "78000000001",
  "channel": "string",
  "granularity": "string",
  "sort_by": "string",
  "direction": "string",
  "page": "string",
  "per_page": "string"
}
{}
{
  "job_id": "job_a1b2c3",
  "status_url": "/api/v2/external/jobs/job_a1b2c3"
}
{
  "errors": [
    "Unauthorized"
  ]
}
{
  "errors": [
    "name is required"
  ]
}
{
  "errors": [
    "Rate limit exceeded"
  ]
}

Summary

GET
https://app.stoqapp.com/api/v2/external/back_in_stock/reports/summary

High-level overview of back-in-stock activity over a date window.

Parameters

fromanyquery
toanyquery
variant_idanyquery
product_idanyquery
channelanyquery

Response

200OKobject

Success — the requested resource.

401UnauthorizedError

Missing or invalid X-Auth-Token.

422Unprocessable EntityError

The request failed validation.

429Too Many RequestsError

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

Authorization

ApiKeyAuthapiKey in header

Send your shop’s STOQ API key in the X-Auth-Token header on every request. Find it in the STOQ app under Settings → Integrations → API Key. The key resolves the shop context; the same scheme is used by the MCP server and the v1 API.

Summary
curl -X GET 'https://app.stoqapp.com/api/v2/external/back_in_stock/reports/summary'
const response = await fetch('https://app.stoqapp.com/api/v2/external/back_in_stock/reports/summary', {
  method: 'GET',
});

const data = await response.json();
import requests

response = requests.get('https://app.stoqapp.com/api/v2/external/back_in_stock/reports/summary')
data = response.json()
{}
{
  "errors": [
    "Unauthorized"
  ]
}
{
  "errors": [
    "name is required"
  ]
}
{
  "errors": [
    "Rate limit exceeded"
  ]
}

Summary Export

POST
https://app.stoqapp.com/api/v2/external/back_in_stock/reports/summary/export

Async CSV export of the back-in-stock summary report.

Body

application/json
fromany
toany
variant_idany
product_idany
channelany
granularityany
sort_byany
directionany
pageany
per_pageany

Response

200OKobject

Success — the updated resource.

202AcceptedJobAccepted

Accepted — async/bulk work was queued. Poll the returned job.

401UnauthorizedError

Missing or invalid X-Auth-Token.

422Unprocessable EntityError

The request failed validation.

429Too Many RequestsError

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

Authorization

ApiKeyAuthapiKey in header

Send your shop’s STOQ API key in the X-Auth-Token header on every request. Find it in the STOQ app under Settings → Integrations → API Key. The key resolves the shop context; the same scheme is used by the MCP server and the v1 API.

Summary Export
curl -X POST 'https://app.stoqapp.com/api/v2/external/back_in_stock/reports/summary/export' \
  -H 'Content-Type: application/json' \
  -d '{
    "from": "string",
    "to": "string",
    "variant_id": "45000000001",
    "product_id": "78000000001",
    "channel": "string",
    "granularity": "string",
    "sort_by": "string",
    "direction": "string",
    "page": "string",
    "per_page": "string"
  }'
const response = await fetch('https://app.stoqapp.com/api/v2/external/back_in_stock/reports/summary/export', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
      "from": "string",
      "to": "string",
      "variant_id": "45000000001",
      "product_id": "78000000001",
      "channel": "string",
      "granularity": "string",
      "sort_by": "string",
      "direction": "string",
      "page": "string",
      "per_page": "string"
    }),
});

const data = await response.json();
import requests

payload = {
  "from": "string",
  "to": "string",
  "variant_id": "45000000001",
  "product_id": "78000000001",
  "channel": "string",
  "granularity": "string",
  "sort_by": "string",
  "direction": "string",
  "page": "string",
  "per_page": "string"
}

response = requests.post('https://app.stoqapp.com/api/v2/external/back_in_stock/reports/summary/export', json=payload)
data = response.json()
Request Body
{
  "from": "string",
  "to": "string",
  "variant_id": "45000000001",
  "product_id": "78000000001",
  "channel": "string",
  "granularity": "string",
  "sort_by": "string",
  "direction": "string",
  "page": "string",
  "per_page": "string"
}
{}
{
  "job_id": "job_a1b2c3",
  "status_url": "/api/v2/external/jobs/job_a1b2c3"
}
{
  "errors": [
    "Unauthorized"
  ]
}
{
  "errors": [
    "name is required"
  ]
}
{
  "errors": [
    "Rate limit exceeded"
  ]
}

Back In Stock · Settings

Read

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

Read all back-in-stock settings for the shop.

Response

200OKobject

Success — the requested resource.

401UnauthorizedError

Missing or invalid X-Auth-Token.

422Unprocessable EntityError

The request failed validation.

429Too Many RequestsError

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

Authorization

ApiKeyAuthapiKey in header

Send your shop’s STOQ API key in the X-Auth-Token header on every request. Find it in the STOQ app under Settings → Integrations → API Key. The key resolves the shop context; the same scheme is used by the MCP server and the v1 API.

Read
curl -X GET 'https://app.stoqapp.com/api/v2/external/back_in_stock/settings'
const response = await fetch('https://app.stoqapp.com/api/v2/external/back_in_stock/settings', {
  method: 'GET',
});

const data = await response.json();
import requests

response = requests.get('https://app.stoqapp.com/api/v2/external/back_in_stock/settings')
data = response.json()
{}
{
  "errors": [
    "Unauthorized"
  ]
}
{
  "errors": [
    "name is required"
  ]
}
{
  "errors": [
    "Rate limit exceeded"
  ]
}

Update

PATCH
https://app.stoqapp.com/api/v2/external/back_in_stock/settings

Update back-in-stock settings for the shop.

Note: Accepts any combination of capability blobs: channels, delivery, compliance, tagging, alerts — deep partial, delegated to the capability PATCHes, errors accumulated. Boolean toggles are set via this PATCH (or the capability PATCH): channels.email.enabled, channels.sms.enabled, channels.push.enabled, delivery.batching.enabled, delivery.locations.filter_enabled, delivery.any_variant.enabled, compliance.optin_required, tagging.order_tags.enabled, alerts.signups_threshold.notify, alerts.scheduled_reports.daily, alerts.scheduled_reports.weekly, alerts.scheduled_reports.monthly — e.g. { channels: { sms: { enabled: true } } }.

Body

application/json
channelsany
deliveryany
complianceany
taggingany
alertsany

Response

200OKobject

Success — the updated resource.

202AcceptedJobAccepted

Accepted — async/bulk work was queued. Poll the returned job.

401UnauthorizedError

Missing or invalid X-Auth-Token.

422Unprocessable EntityError

The request failed validation.

429Too Many RequestsError

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

Authorization

ApiKeyAuthapiKey in header

Send your shop’s STOQ API key in the X-Auth-Token header on every request. Find it in the STOQ app under Settings → Integrations → API Key. The key resolves the shop context; the same scheme is used by the MCP server and the v1 API.

Update
curl -X PATCH 'https://app.stoqapp.com/api/v2/external/back_in_stock/settings' \
  -H 'Content-Type: application/json' \
  -d '{
    "channels": "string",
    "delivery": "string",
    "compliance": "string",
    "tagging": "string",
    "alerts": "string"
  }'
const response = await fetch('https://app.stoqapp.com/api/v2/external/back_in_stock/settings', {
  method: 'PATCH',
  headers: {
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
      "channels": "string",
      "delivery": "string",
      "compliance": "string",
      "tagging": "string",
      "alerts": "string"
    }),
});

const data = await response.json();
import requests

payload = {
  "channels": "string",
  "delivery": "string",
  "compliance": "string",
  "tagging": "string",
  "alerts": "string"
}

response = requests.patch('https://app.stoqapp.com/api/v2/external/back_in_stock/settings', json=payload)
data = response.json()
Request Body
{
  "channels": "string",
  "delivery": "string",
  "compliance": "string",
  "tagging": "string",
  "alerts": "string"
}
{}
{
  "job_id": "job_a1b2c3",
  "status_url": "/api/v2/external/jobs/job_a1b2c3"
}
{
  "errors": [
    "Unauthorized"
  ]
}
{
  "errors": [
    "name is required"
  ]
}
{
  "errors": [
    "Rate limit exceeded"
  ]
}

Alerts

GET
https://app.stoqapp.com/api/v2/external/back_in_stock/settings/alerts

Read back-in-stock merchant alert and scheduled report settings.

Response

200OKobject

Success — the requested resource.

401UnauthorizedError

Missing or invalid X-Auth-Token.

422Unprocessable EntityError

The request failed validation.

429Too Many RequestsError

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

Authorization

ApiKeyAuthapiKey in header

Send your shop’s STOQ API key in the X-Auth-Token header on every request. Find it in the STOQ app under Settings → Integrations → API Key. The key resolves the shop context; the same scheme is used by the MCP server and the v1 API.

Alerts
curl -X GET 'https://app.stoqapp.com/api/v2/external/back_in_stock/settings/alerts'
const response = await fetch('https://app.stoqapp.com/api/v2/external/back_in_stock/settings/alerts', {
  method: 'GET',
});

const data = await response.json();
import requests

response = requests.get('https://app.stoqapp.com/api/v2/external/back_in_stock/settings/alerts')
data = response.json()
{}
{
  "errors": [
    "Unauthorized"
  ]
}
{
  "errors": [
    "name is required"
  ]
}
{
  "errors": [
    "Rate limit exceeded"
  ]
}

Alerts

PATCH
https://app.stoqapp.com/api/v2/external/back_in_stock/settings/alerts

Update back-in-stock merchant alert and scheduled report settings.

Note: Toggles set via this PATCH: signups_threshold.notify, scheduled_reports.daily, scheduled_reports.weekly, scheduled_reports.monthly — e.g. { scheduled_reports: { weekly: true } }. signups_threshold.count is the per-variant signup count that triggers the merchant alert email.

Body

application/json
signups_thresholdany
scheduled_reportsany

Response

200OKobject

Success — the updated resource.

202AcceptedJobAccepted

Accepted — async/bulk work was queued. Poll the returned job.

401UnauthorizedError

Missing or invalid X-Auth-Token.

422Unprocessable EntityError

The request failed validation.

429Too Many RequestsError

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

Authorization

ApiKeyAuthapiKey in header

Send your shop’s STOQ API key in the X-Auth-Token header on every request. Find it in the STOQ app under Settings → Integrations → API Key. The key resolves the shop context; the same scheme is used by the MCP server and the v1 API.

Alerts
curl -X PATCH 'https://app.stoqapp.com/api/v2/external/back_in_stock/settings/alerts' \
  -H 'Content-Type: application/json' \
  -d '{
    "signups_threshold": "string",
    "scheduled_reports": "string"
  }'
const response = await fetch('https://app.stoqapp.com/api/v2/external/back_in_stock/settings/alerts', {
  method: 'PATCH',
  headers: {
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
      "signups_threshold": "string",
      "scheduled_reports": "string"
    }),
});

const data = await response.json();
import requests

payload = {
  "signups_threshold": "string",
  "scheduled_reports": "string"
}

response = requests.patch('https://app.stoqapp.com/api/v2/external/back_in_stock/settings/alerts', json=payload)
data = response.json()
Request Body
{
  "signups_threshold": "string",
  "scheduled_reports": "string"
}
{}
{
  "job_id": "job_a1b2c3",
  "status_url": "/api/v2/external/jobs/job_a1b2c3"
}
{
  "errors": [
    "Unauthorized"
  ]
}
{
  "errors": [
    "name is required"
  ]
}
{
  "errors": [
    "Rate limit exceeded"
  ]
}

Channels

GET
https://app.stoqapp.com/api/v2/external/back_in_stock/settings/channels

Read back-in-stock notification channel settings.

Response

200OKobject

Success — the requested resource.

401UnauthorizedError

Missing or invalid X-Auth-Token.

422Unprocessable EntityError

The request failed validation.

429Too Many RequestsError

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

Authorization

ApiKeyAuthapiKey in header

Send your shop’s STOQ API key in the X-Auth-Token header on every request. Find it in the STOQ app under Settings → Integrations → API Key. The key resolves the shop context; the same scheme is used by the MCP server and the v1 API.

Channels
curl -X GET 'https://app.stoqapp.com/api/v2/external/back_in_stock/settings/channels'
const response = await fetch('https://app.stoqapp.com/api/v2/external/back_in_stock/settings/channels', {
  method: 'GET',
});

const data = await response.json();
import requests

response = requests.get('https://app.stoqapp.com/api/v2/external/back_in_stock/settings/channels')
data = response.json()
{}
{
  "errors": [
    "Unauthorized"
  ]
}
{
  "errors": [
    "name is required"
  ]
}
{
  "errors": [
    "Rate limit exceeded"
  ]
}

Channels

PATCH
https://app.stoqapp.com/api/v2/external/back_in_stock/settings/channels

Update back-in-stock notification channel toggles.

Note: Channel toggles are set via this PATCH: email.enabled, sms.enabled, push.enabled — e.g. { sms: { enabled: true } }. Enabling SMS for the first time triggers a restricted-content verification check; sends may be held until the shop is verified.

Body

application/json
emailany
smsany
pushany

Response

200OKobject

Success — example response shown.

202AcceptedJobAccepted

Accepted — async/bulk work was queued. Poll the returned job.

401UnauthorizedError

Missing or invalid X-Auth-Token.

422Unprocessable EntityError

The request failed validation.

429Too Many RequestsError

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

Authorization

ApiKeyAuthapiKey in header

Send your shop’s STOQ API key in the X-Auth-Token header on every request. Find it in the STOQ app under Settings → Integrations → API Key. The key resolves the shop context; the same scheme is used by the MCP server and the v1 API.

Channels
curl -X PATCH 'https://app.stoqapp.com/api/v2/external/back_in_stock/settings/channels' \
  -H 'Content-Type: application/json' \
  -d '{
    "channels": {
      "email": {
        "enabled": true
      },
      "sms": {
        "enabled": true
      },
      "push": {
        "enabled": false
      }
    }
  }'
const response = await fetch('https://app.stoqapp.com/api/v2/external/back_in_stock/settings/channels', {
  method: 'PATCH',
  headers: {
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
      "channels": {
        "email": {
          "enabled": true
        },
        "sms": {
          "enabled": true
        },
        "push": {
          "enabled": false
        }
      }
    }),
});

const data = await response.json();
import requests

payload = {
  "channels": {
    "email": {
      "enabled": True
    },
    "sms": {
      "enabled": True
    },
    "push": {
      "enabled": False
    }
  }
}

response = requests.patch('https://app.stoqapp.com/api/v2/external/back_in_stock/settings/channels', json=payload)
data = response.json()
Request Body
{
  "channels": {
    "email": {
      "enabled": true
    },
    "sms": {
      "enabled": true
    },
    "push": {
      "enabled": false
    }
  }
}
{
  "channels": {
    "email": {
      "enabled": true
    },
    "sms": {
      "enabled": true
    },
    "push": {
      "enabled": false
    }
  },
  "delivery": {
    "batching": {
      "enabled": false
    },
    "stock_threshold": 1,
    "locations": {
      "filter_enabled": false,
      "location_ids": []
    }
  },
  "compliance": {
    "optin_required": false,
    "optin_method": "single"
  },
  "tagging": {
    "order_tags": {
      "enabled": false,
      "tags": []
    }
  },
  "alerts": {
    "scheduled_reports": {
      "weekly": true,
      "email": "merchant@example.com"
    }
  }
}
{
  "job_id": "job_a1b2c3",
  "status_url": "/api/v2/external/jobs/job_a1b2c3"
}
{
  "errors": [
    "Unauthorized"
  ]
}
{
  "errors": [
    "name is required"
  ]
}
{
  "errors": [
    "Rate limit exceeded"
  ]
}

Compliance

GET
https://app.stoqapp.com/api/v2/external/back_in_stock/settings/compliance

Read back-in-stock compliance settings (double opt-in).

Response

200OKobject

Success — the requested resource.

401UnauthorizedError

Missing or invalid X-Auth-Token.

422Unprocessable EntityError

The request failed validation.

429Too Many RequestsError

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

Authorization

ApiKeyAuthapiKey in header

Send your shop’s STOQ API key in the X-Auth-Token header on every request. Find it in the STOQ app under Settings → Integrations → API Key. The key resolves the shop context; the same scheme is used by the MCP server and the v1 API.

Compliance
curl -X GET 'https://app.stoqapp.com/api/v2/external/back_in_stock/settings/compliance'
const response = await fetch('https://app.stoqapp.com/api/v2/external/back_in_stock/settings/compliance', {
  method: 'GET',
});

const data = await response.json();
import requests

response = requests.get('https://app.stoqapp.com/api/v2/external/back_in_stock/settings/compliance')
data = response.json()
{}
{
  "errors": [
    "Unauthorized"
  ]
}
{
  "errors": [
    "name is required"
  ]
}
{
  "errors": [
    "Rate limit exceeded"
  ]
}

Compliance

PATCH
https://app.stoqapp.com/api/v2/external/back_in_stock/settings/compliance

Update back-in-stock compliance settings (double opt-in).

Note: The double-opt-in toggle is set via this PATCH: optin_required — e.g. { optin_required: true }. When enabled, signups must confirm via email before they are eligible for notifications (GDPR double opt-in).

Body

application/json
optin_requiredany

Response

200OKobject

Success — the updated resource.

202AcceptedJobAccepted

Accepted — async/bulk work was queued. Poll the returned job.

401UnauthorizedError

Missing or invalid X-Auth-Token.

422Unprocessable EntityError

The request failed validation.

429Too Many RequestsError

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

Authorization

ApiKeyAuthapiKey in header

Send your shop’s STOQ API key in the X-Auth-Token header on every request. Find it in the STOQ app under Settings → Integrations → API Key. The key resolves the shop context; the same scheme is used by the MCP server and the v1 API.

Compliance
curl -X PATCH 'https://app.stoqapp.com/api/v2/external/back_in_stock/settings/compliance' \
  -H 'Content-Type: application/json' \
  -d '{
    "optin_required": "string"
  }'
const response = await fetch('https://app.stoqapp.com/api/v2/external/back_in_stock/settings/compliance', {
  method: 'PATCH',
  headers: {
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
      "optin_required": "string"
    }),
});

const data = await response.json();
import requests

payload = {
  "optin_required": "string"
}

response = requests.patch('https://app.stoqapp.com/api/v2/external/back_in_stock/settings/compliance', json=payload)
data = response.json()
Request Body
{
  "optin_required": "string"
}
{}
{
  "job_id": "job_a1b2c3",
  "status_url": "/api/v2/external/jobs/job_a1b2c3"
}
{
  "errors": [
    "Unauthorized"
  ]
}
{
  "errors": [
    "name is required"
  ]
}
{
  "errors": [
    "Rate limit exceeded"
  ]
}

Delivery

GET
https://app.stoqapp.com/api/v2/external/back_in_stock/settings/delivery

Read back-in-stock delivery settings (batching, stock threshold, locations, any-variant).

Response

200OKobject

Success — the requested resource.

401UnauthorizedError

Missing or invalid X-Auth-Token.

422Unprocessable EntityError

The request failed validation.

429Too Many RequestsError

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

Authorization

ApiKeyAuthapiKey in header

Send your shop’s STOQ API key in the X-Auth-Token header on every request. Find it in the STOQ app under Settings → Integrations → API Key. The key resolves the shop context; the same scheme is used by the MCP server and the v1 API.

Delivery
curl -X GET 'https://app.stoqapp.com/api/v2/external/back_in_stock/settings/delivery'
const response = await fetch('https://app.stoqapp.com/api/v2/external/back_in_stock/settings/delivery', {
  method: 'GET',
});

const data = await response.json();
import requests

response = requests.get('https://app.stoqapp.com/api/v2/external/back_in_stock/settings/delivery')
data = response.json()
{}
{
  "errors": [
    "Unauthorized"
  ]
}
{
  "errors": [
    "name is required"
  ]
}
{
  "errors": [
    "Rate limit exceeded"
  ]
}

Delivery

PATCH
https://app.stoqapp.com/api/v2/external/back_in_stock/settings/delivery

Update back-in-stock delivery settings (batching, stock threshold, locations, any-variant).

Note: Deep partial. Toggles set via this PATCH: batching.enabled, locations.filter_enabled, any_variant.enabled — e.g. { batching: { enabled: true } }. batching.mode is an enum: 'multiplier' (batch size = restocked quantity x batching.multiplier) or 'fixed' (batch size = batching.batch_size); batching.wait_hours is the wait between batches. stock_threshold is the minimum restocked quantity before notifications send (>= 1). locations.location_ids and any_variant.product_ids are arrays of Shopify numeric ids and are replaced wholesale when present.

Body

application/json
batchingany
stock_thresholdany
locationsany
any_variantany

Response

200OKobject

Success — the updated resource.

202AcceptedJobAccepted

Accepted — async/bulk work was queued. Poll the returned job.

401UnauthorizedError

Missing or invalid X-Auth-Token.

422Unprocessable EntityError

The request failed validation.

429Too Many RequestsError

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

Authorization

ApiKeyAuthapiKey in header

Send your shop’s STOQ API key in the X-Auth-Token header on every request. Find it in the STOQ app under Settings → Integrations → API Key. The key resolves the shop context; the same scheme is used by the MCP server and the v1 API.

Delivery
curl -X PATCH 'https://app.stoqapp.com/api/v2/external/back_in_stock/settings/delivery' \
  -H 'Content-Type: application/json' \
  -d '{
    "batching": "string",
    "stock_threshold": "string",
    "locations": "string",
    "any_variant": "string"
  }'
const response = await fetch('https://app.stoqapp.com/api/v2/external/back_in_stock/settings/delivery', {
  method: 'PATCH',
  headers: {
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
      "batching": "string",
      "stock_threshold": "string",
      "locations": "string",
      "any_variant": "string"
    }),
});

const data = await response.json();
import requests

payload = {
  "batching": "string",
  "stock_threshold": "string",
  "locations": "string",
  "any_variant": "string"
}

response = requests.patch('https://app.stoqapp.com/api/v2/external/back_in_stock/settings/delivery', json=payload)
data = response.json()
Request Body
{
  "batching": "string",
  "stock_threshold": "string",
  "locations": "string",
  "any_variant": "string"
}
{}
{
  "job_id": "job_a1b2c3",
  "status_url": "/api/v2/external/jobs/job_a1b2c3"
}
{
  "errors": [
    "Unauthorized"
  ]
}
{
  "errors": [
    "name is required"
  ]
}
{
  "errors": [
    "Rate limit exceeded"
  ]
}

Tagging

GET
https://app.stoqapp.com/api/v2/external/back_in_stock/settings/tagging

Read back-in-stock order tagging settings.

Response

200OKobject

Success — the requested resource.

401UnauthorizedError

Missing or invalid X-Auth-Token.

422Unprocessable EntityError

The request failed validation.

429Too Many RequestsError

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

Authorization

ApiKeyAuthapiKey in header

Send your shop’s STOQ API key in the X-Auth-Token header on every request. Find it in the STOQ app under Settings → Integrations → API Key. The key resolves the shop context; the same scheme is used by the MCP server and the v1 API.

Tagging
curl -X GET 'https://app.stoqapp.com/api/v2/external/back_in_stock/settings/tagging'
const response = await fetch('https://app.stoqapp.com/api/v2/external/back_in_stock/settings/tagging', {
  method: 'GET',
});

const data = await response.json();
import requests

response = requests.get('https://app.stoqapp.com/api/v2/external/back_in_stock/settings/tagging')
data = response.json()
{}
{
  "errors": [
    "Unauthorized"
  ]
}
{
  "errors": [
    "name is required"
  ]
}
{
  "errors": [
    "Rate limit exceeded"
  ]
}

Tagging

PATCH
https://app.stoqapp.com/api/v2/external/back_in_stock/settings/tagging

Update back-in-stock order tagging settings.

Note: The toggle is set via this PATCH: order_tags.enabled — e.g. { order_tags: { enabled: true } }. order_tags.tag is the single tag applied to Shopify orders attributed to a back-in-stock notification (default 'STOQ-back-in-stock').

Body

application/json
order_tagsany

Response

200OKobject

Success — the updated resource.

202AcceptedJobAccepted

Accepted — async/bulk work was queued. Poll the returned job.

401UnauthorizedError

Missing or invalid X-Auth-Token.

422Unprocessable EntityError

The request failed validation.

429Too Many RequestsError

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

Authorization

ApiKeyAuthapiKey in header

Send your shop’s STOQ API key in the X-Auth-Token header on every request. Find it in the STOQ app under Settings → Integrations → API Key. The key resolves the shop context; the same scheme is used by the MCP server and the v1 API.

Tagging
curl -X PATCH 'https://app.stoqapp.com/api/v2/external/back_in_stock/settings/tagging' \
  -H 'Content-Type: application/json' \
  -d '{
    "order_tags": "string"
  }'
const response = await fetch('https://app.stoqapp.com/api/v2/external/back_in_stock/settings/tagging', {
  method: 'PATCH',
  headers: {
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
      "order_tags": "string"
    }),
});

const data = await response.json();
import requests

payload = {
  "order_tags": "string"
}

response = requests.patch('https://app.stoqapp.com/api/v2/external/back_in_stock/settings/tagging', json=payload)
data = response.json()
Request Body
{
  "order_tags": "string"
}
{}
{
  "job_id": "job_a1b2c3",
  "status_url": "/api/v2/external/jobs/job_a1b2c3"
}
{
  "errors": [
    "Unauthorized"
  ]
}
{
  "errors": [
    "name is required"
  ]
}
{
  "errors": [
    "Rate limit exceeded"
  ]
}

Back In Stock · Signups

List

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

List back-in-stock signups (the waitlist) in this shop, paginated.

Note: status compiles notified_at / unsubscribed_at / blocked_at into one lifecycle value; email and phone filters match partial values on the signup or its customer.

Parameters

channelanyemailsmspushquery
statusanypendingnotifiedunsubscribedquery
variant_idanyquery
product_idanyquery
emailanyquery
phoneanyquery
fromanyquery
toanyquery
pageanyquery
per_pageanyquery

Response

200OKobject

Success — example response shown.

401UnauthorizedError

Missing or invalid X-Auth-Token.

422Unprocessable EntityError

The request failed validation.

429Too Many RequestsError

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

Authorization

ApiKeyAuthapiKey in header

Send your shop’s STOQ API key in the X-Auth-Token header on every request. Find it in the STOQ app under Settings → Integrations → API Key. The key resolves the shop context; the same scheme is used by the MCP server and the v1 API.

List
curl -X GET 'https://app.stoqapp.com/api/v2/external/back_in_stock/signups'
const response = await fetch('https://app.stoqapp.com/api/v2/external/back_in_stock/signups', {
  method: 'GET',
});

const data = await response.json();
import requests

response = requests.get('https://app.stoqapp.com/api/v2/external/back_in_stock/signups')
data = response.json()
{
  "signups": [
    {
      "id": 5847392,
      "status": "pending",
      "channel": "email",
      "contact": "john@example.com",
      "quantity": 2,
      "variant": {
        "shopify_variant_id": 47284734423096,
        "shopify_product_id": 8784906035384,
        "title": "Blue / Medium"
      },
      "customer": {
        "id": 9284756,
        "email": "john@example.com",
        "name": "John Doe"
      },
      "notifications_sent": 0,
      "last_notified_at": null,
      "created_at": "2026-06-25T13:45:30Z"
    },
    {
      "id": 5847393,
      "status": "notified",
      "channel": "sms",
      "contact": "+14155552671",
      "quantity": 1,
      "variant": {
        "shopify_variant_id": 47284734455864,
        "shopify_product_id": 8784906035384,
        "title": "Red / Large"
      },
      "customer": {
        "id": 9284757,
        "email": "jane@example.com",
        "name": "Jane Smith"
      },
      "notifications_sent": 1,
      "last_notified_at": "2026-06-24T10:30:00Z",
      "created_at": "2026-06-20T15:20:15Z"
    }
  ],
  "meta": {
    "total_count": 147,
    "page": 1,
    "per_page": 50,
    "total_pages": 3
  }
}
{
  "errors": [
    "Unauthorized"
  ]
}
{
  "errors": [
    "name is required"
  ]
}
{
  "errors": [
    "Rate limit exceeded"
  ]
}

Create

POST
https://app.stoqapp.com/api/v2/external/back_in_stock/signups

Create a back-in-stock signup (add a customer to the waitlist for a variant).

Note: email is required for the email channel, phone for sms. shopify_product_id is resolved from the variant when omitted. Returns 409 when a pending signup already exists for the same contact + variant + channel.

Body

application/json
channelanyemailsmsrequired
shopify_variant_idanyrequired
quantityinteger
shopify_product_idany
emailany
phoneany
nameany

Response

200OKobject

Success — example response shown.

202AcceptedJobAccepted

Accepted — async/bulk work was queued. Poll the returned job.

401UnauthorizedError

Missing or invalid X-Auth-Token.

422Unprocessable EntityError

The request failed validation.

429Too Many RequestsError

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

Authorization

ApiKeyAuthapiKey in header

Send your shop’s STOQ API key in the X-Auth-Token header on every request. Find it in the STOQ app under Settings → Integrations → API Key. The key resolves the shop context; the same scheme is used by the MCP server and the v1 API.

Create
curl -X POST 'https://app.stoqapp.com/api/v2/external/back_in_stock/signups' \
  -H 'Content-Type: application/json' \
  -d '{
    "channel": "email",
    "shopify_variant_id": 47284734423096,
    "shopify_product_id": 8784906035384,
    "email": "john@example.com",
    "quantity": 2,
    "name": "John Doe"
  }'
const response = await fetch('https://app.stoqapp.com/api/v2/external/back_in_stock/signups', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
      "channel": "email",
      "shopify_variant_id": 47284734423096,
      "shopify_product_id": 8784906035384,
      "email": "john@example.com",
      "quantity": 2,
      "name": "John Doe"
    }),
});

const data = await response.json();
import requests

payload = {
  "channel": "email",
  "shopify_variant_id": 47284734423096,
  "shopify_product_id": 8784906035384,
  "email": "john@example.com",
  "quantity": 2,
  "name": "John Doe"
}

response = requests.post('https://app.stoqapp.com/api/v2/external/back_in_stock/signups', json=payload)
data = response.json()
Request Body
{
  "channel": "email",
  "shopify_variant_id": 47284734423096,
  "shopify_product_id": 8784906035384,
  "email": "john@example.com",
  "quantity": 2,
  "name": "John Doe"
}
{
  "id": 5847392,
  "status": "pending",
  "channel": "email",
  "contact": "john@example.com",
  "quantity": 2,
  "variant": {
    "shopify_variant_id": 47284734423096,
    "shopify_product_id": 8784906035384,
    "title": "Blue / Medium"
  },
  "customer": {
    "id": 9284756,
    "email": "john@example.com",
    "name": "John Doe"
  },
  "optin": {
    "required": false,
    "confirmed": null
  },
  "notifications_sent": 0,
  "last_notified_at": null,
  "created_at": "2026-06-25T13:45:30Z"
}
{
  "job_id": "job_a1b2c3",
  "status_url": "/api/v2/external/jobs/job_a1b2c3"
}
{
  "errors": [
    "Unauthorized"
  ]
}
{
  "errors": [
    "name is required"
  ]
}
{
  "errors": [
    "Rate limit exceeded"
  ]
}

Read

GET
https://app.stoqapp.com/api/v2/external/back_in_stock/signups/{id}

Read one back-in-stock signup's full representation.

Parameters

idstringrequiredpath

Response

200OKobject

Success — the requested resource.

401UnauthorizedError

Missing or invalid X-Auth-Token.

404Not FoundError

The resource does not exist for this shop, or the action path is not registered.

422Unprocessable EntityError

The request failed validation.

429Too Many RequestsError

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

Authorization

ApiKeyAuthapiKey in header

Send your shop’s STOQ API key in the X-Auth-Token header on every request. Find it in the STOQ app under Settings → Integrations → API Key. The key resolves the shop context; the same scheme is used by the MCP server and the v1 API.

Read
curl -X GET 'https://app.stoqapp.com/api/v2/external/back_in_stock/signups/{id}'
const response = await fetch('https://app.stoqapp.com/api/v2/external/back_in_stock/signups/{id}', {
  method: 'GET',
});

const data = await response.json();
import requests

response = requests.get('https://app.stoqapp.com/api/v2/external/back_in_stock/signups/{id}')
data = response.json()
{}
{
  "errors": [
    "Unauthorized"
  ]
}
{
  "errors": [
    "Offer not found"
  ]
}
{
  "errors": [
    "name is required"
  ]
}
{
  "errors": [
    "Rate limit exceeded"
  ]
}

Delete

DELETE
https://app.stoqapp.com/api/v2/external/back_in_stock/signups/{id}

Delete a pending back-in-stock signup (remove the customer from the waitlist).

Note: Pending signups only; deleting an already-notified signup returns 409.

Parameters

idstringrequiredpath

Response

200OKobject

Success — the updated resource.

202AcceptedJobAccepted

Accepted — async/bulk work was queued. Poll the returned job.

401UnauthorizedError

Missing or invalid X-Auth-Token.

404Not FoundError

The resource does not exist for this shop, or the action path is not registered.

422Unprocessable EntityError

The request failed validation.

429Too Many RequestsError

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

Authorization

ApiKeyAuthapiKey in header

Send your shop’s STOQ API key in the X-Auth-Token header on every request. Find it in the STOQ app under Settings → Integrations → API Key. The key resolves the shop context; the same scheme is used by the MCP server and the v1 API.

Delete
curl -X DELETE 'https://app.stoqapp.com/api/v2/external/back_in_stock/signups/{id}'
const response = await fetch('https://app.stoqapp.com/api/v2/external/back_in_stock/signups/{id}', {
  method: 'DELETE',
});

const data = await response.json();
import requests

response = requests.delete('https://app.stoqapp.com/api/v2/external/back_in_stock/signups/{id}')
data = response.json()
{}
{
  "job_id": "job_a1b2c3",
  "status_url": "/api/v2/external/jobs/job_a1b2c3"
}
{
  "errors": [
    "Unauthorized"
  ]
}
{
  "errors": [
    "Offer not found"
  ]
}
{
  "errors": [
    "name is required"
  ]
}
{
  "errors": [
    "Rate limit exceeded"
  ]
}

Notify

POST
https://app.stoqapp.com/api/v2/external/back_in_stock/signups/{id}/notify

Send the back-in-stock notification for one signup now, regardless of stock state.

Note: 409 when the signup was already notified and allow_resend is not set.

Body

application/json
allow_resendany

Parameters

idstringrequiredpath

Response

200OKobject

Success — example response shown.

202AcceptedJobAccepted

Accepted — async/bulk work was queued. Poll the returned job.

401UnauthorizedError

Missing or invalid X-Auth-Token.

404Not FoundError

The resource does not exist for this shop, or the action path is not registered.

422Unprocessable EntityError

The request failed validation.

429Too Many RequestsError

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

Authorization

ApiKeyAuthapiKey in header

Send your shop’s STOQ API key in the X-Auth-Token header on every request. Find it in the STOQ app under Settings → Integrations → API Key. The key resolves the shop context; the same scheme is used by the MCP server and the v1 API.

Notify
curl -X POST 'https://app.stoqapp.com/api/v2/external/back_in_stock/signups/{id}/notify' \
  -H 'Content-Type: application/json' \
  -d '{
    "allow_resend": false
  }'
const response = await fetch('https://app.stoqapp.com/api/v2/external/back_in_stock/signups/{id}/notify', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
      "allow_resend": false
    }),
});

const data = await response.json();
import requests

payload = {
  "allow_resend": False
}

response = requests.post('https://app.stoqapp.com/api/v2/external/back_in_stock/signups/{id}/notify', json=payload)
data = response.json()
Request Body
{
  "allow_resend": false
}
{
  "signup_id": 5847392,
  "queued": true
}
{
  "job_id": "job_a1b2c3",
  "status_url": "/api/v2/external/jobs/job_a1b2c3"
}
{
  "errors": [
    "Unauthorized"
  ]
}
{
  "errors": [
    "Offer not found"
  ]
}
{
  "errors": [
    "name is required"
  ]
}
{
  "errors": [
    "Rate limit exceeded"
  ]
}

Bulk Delete

POST
https://app.stoqapp.com/api/v2/external/back_in_stock/signups/bulk_delete

Delete up to 1000 pending back-in-stock signups in one request.

Note: Pending-only: 422 listing the offending ids when any signup was already notified.

Body

application/json
signup_idsArray<string>required

Response

200OKobject

Success — the updated resource.

202AcceptedJobAccepted

Accepted — async/bulk work was queued. Poll the returned job.

401UnauthorizedError

Missing or invalid X-Auth-Token.

422Unprocessable EntityError

The request failed validation.

429Too Many RequestsError

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

Authorization

ApiKeyAuthapiKey in header

Send your shop’s STOQ API key in the X-Auth-Token header on every request. Find it in the STOQ app under Settings → Integrations → API Key. The key resolves the shop context; the same scheme is used by the MCP server and the v1 API.

Bulk Delete
curl -X POST 'https://app.stoqapp.com/api/v2/external/back_in_stock/signups/bulk_delete' \
  -H 'Content-Type: application/json' \
  -d '{
    "signup_ids": [
      "sgn_a1b2c3"
    ]
  }'
const response = await fetch('https://app.stoqapp.com/api/v2/external/back_in_stock/signups/bulk_delete', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
      "signup_ids": [
        "sgn_a1b2c3"
      ]
    }),
});

const data = await response.json();
import requests

payload = {
  "signup_ids": [
    "sgn_a1b2c3"
  ]
}

response = requests.post('https://app.stoqapp.com/api/v2/external/back_in_stock/signups/bulk_delete', json=payload)
data = response.json()
Request Body
{
  "signup_ids": [
    "sgn_a1b2c3"
  ]
}
{}
{
  "job_id": "job_a1b2c3",
  "status_url": "/api/v2/external/jobs/job_a1b2c3"
}
{
  "errors": [
    "Unauthorized"
  ]
}
{
  "errors": [
    "name is required"
  ]
}
{
  "errors": [
    "Rate limit exceeded"
  ]
}

Bulk Notify

POST
https://app.stoqapp.com/api/v2/external/back_in_stock/signups/bulk_notify

Send back-in-stock notifications for up to 1000 signups in one request.

Note: Responds 200 when all succeed, 207 with { success, failed } on partial failure. Already-notified signups fail unless allow_resend is set.

Body

application/json
signup_idsArray<string>required
allow_resendany

Response

200OKobject

Success — example response shown.

202AcceptedJobAccepted

Accepted — async/bulk work was queued. Poll the returned job.

401UnauthorizedError

Missing or invalid X-Auth-Token.

422Unprocessable EntityError

The request failed validation.

429Too Many RequestsError

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

Authorization

ApiKeyAuthapiKey in header

Send your shop’s STOQ API key in the X-Auth-Token header on every request. Find it in the STOQ app under Settings → Integrations → API Key. The key resolves the shop context; the same scheme is used by the MCP server and the v1 API.

Bulk Notify
curl -X POST 'https://app.stoqapp.com/api/v2/external/back_in_stock/signups/bulk_notify' \
  -H 'Content-Type: application/json' \
  -d '{
    "signup_ids": [
      "5847392",
      "5847393",
      "5847394"
    ],
    "allow_resend": false
  }'
const response = await fetch('https://app.stoqapp.com/api/v2/external/back_in_stock/signups/bulk_notify', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
      "signup_ids": [
        "5847392",
        "5847393",
        "5847394"
      ],
      "allow_resend": false
    }),
});

const data = await response.json();
import requests

payload = {
  "signup_ids": [
    "5847392",
    "5847393",
    "5847394"
  ],
  "allow_resend": False
}

response = requests.post('https://app.stoqapp.com/api/v2/external/back_in_stock/signups/bulk_notify', json=payload)
data = response.json()
Request Body
{
  "signup_ids": [
    "5847392",
    "5847393",
    "5847394"
  ],
  "allow_resend": false
}
{
  "success": [
    5847392,
    5847393
  ],
  "failed": [
    {
      "signup_id": "5847394",
      "error": "Already notified — pass allow_resend to send again"
    }
  ]
}
{
  "job_id": "job_a1b2c3",
  "status_url": "/api/v2/external/jobs/job_a1b2c3"
}
{
  "errors": [
    "Unauthorized"
  ]
}
{
  "errors": [
    "name is required"
  ]
}
{
  "errors": [
    "Rate limit exceeded"
  ]
}

Transfer

POST
https://app.stoqapp.com/api/v2/external/back_in_stock/signups/transfer

Move back-in-stock signups from one variant to another (variant merges or replacements).

Note: scope picks which signups move: pending (default), notified, or all. Signups that would duplicate a pending signup on the target variant are dropped. from_shopify_product_id is resolved from the source variant when omitted.

Body

application/json
from_shopify_variant_idanyrequired
to_shopify_variant_idanyrequired
to_shopify_product_idanyrequired
scopeanypendingnotifiedall
from_shopify_product_idany

Response

200OKobject

Success — the updated resource.

202AcceptedJobAccepted

Accepted — async/bulk work was queued. Poll the returned job.

401UnauthorizedError

Missing or invalid X-Auth-Token.

422Unprocessable EntityError

The request failed validation.

429Too Many RequestsError

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

Authorization

ApiKeyAuthapiKey in header

Send your shop’s STOQ API key in the X-Auth-Token header on every request. Find it in the STOQ app under Settings → Integrations → API Key. The key resolves the shop context; the same scheme is used by the MCP server and the v1 API.

Transfer
curl -X POST 'https://app.stoqapp.com/api/v2/external/back_in_stock/signups/transfer' \
  -H 'Content-Type: application/json' \
  -d '{
    "from_shopify_variant_id": "45000000001",
    "to_shopify_variant_id": "45000000001",
    "to_shopify_product_id": "78000000001",
    "scope": "pending",
    "from_shopify_product_id": "78000000001"
  }'
const response = await fetch('https://app.stoqapp.com/api/v2/external/back_in_stock/signups/transfer', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
      "from_shopify_variant_id": "45000000001",
      "to_shopify_variant_id": "45000000001",
      "to_shopify_product_id": "78000000001",
      "scope": "pending",
      "from_shopify_product_id": "78000000001"
    }),
});

const data = await response.json();
import requests

payload = {
  "from_shopify_variant_id": "45000000001",
  "to_shopify_variant_id": "45000000001",
  "to_shopify_product_id": "78000000001",
  "scope": "pending",
  "from_shopify_product_id": "78000000001"
}

response = requests.post('https://app.stoqapp.com/api/v2/external/back_in_stock/signups/transfer', json=payload)
data = response.json()
Request Body
{
  "from_shopify_variant_id": "45000000001",
  "to_shopify_variant_id": "45000000001",
  "to_shopify_product_id": "78000000001",
  "scope": "pending",
  "from_shopify_product_id": "78000000001"
}
{}
{
  "job_id": "job_a1b2c3",
  "status_url": "/api/v2/external/jobs/job_a1b2c3"
}
{
  "errors": [
    "Unauthorized"
  ]
}
{
  "errors": [
    "name is required"
  ]
}
{
  "errors": [
    "Rate limit exceeded"
  ]
}

Preorders · Offers

List

GET
https://app.stoqapp.com/api/v2/external/preorders/offers

List preorder offers in this shop, paginated.

Parameters

pageanyquery
per_pageanyquery

Response

200OKobject

Success — example response shown.

401UnauthorizedError

Missing or invalid X-Auth-Token.

422Unprocessable EntityError

The request failed validation.

429Too Many RequestsError

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

Authorization

ApiKeyAuthapiKey in header

Send your shop’s STOQ API key in the X-Auth-Token header on every request. Find it in the STOQ app under Settings → Integrations → API Key. The key resolves the shop context; the same scheme is used by the MCP server and the v1 API.

List
curl -X GET 'https://app.stoqapp.com/api/v2/external/preorders/offers'
const response = await fetch('https://app.stoqapp.com/api/v2/external/preorders/offers', {
  method: 'GET',
});

const data = await response.json();
import requests

response = requests.get('https://app.stoqapp.com/api/v2/external/preorders/offers')
data = response.json()
{
  "offers": [
    {
      "id": "gid://shopify/SellingPlan/1",
      "name": "Summer Sneaker Drop",
      "internal_name": "summer-2026",
      "status": "draft",
      "created_at": "2026-06-25T10:30:45Z",
      "updated_at": "2026-06-25T10:30:45Z"
    },
    {
      "id": "gid://shopify/SellingPlan/2",
      "name": "Winter Collection",
      "internal_name": "winter-2026",
      "status": "active",
      "created_at": "2026-06-20T14:15:30Z",
      "updated_at": "2026-06-22T09:45:12Z"
    }
  ],
  "meta": {
    "total_count": 2,
    "page": 1,
    "per_page": 50,
    "total_pages": 1
  }
}
{
  "errors": [
    "Unauthorized"
  ]
}
{
  "errors": [
    "name is required"
  ]
}
{
  "errors": [
    "Rate limit exceeded"
  ]
}

Create

POST
https://app.stoqapp.com/api/v2/external/preorders/offers

Create a new preorder offer.

Body

application/json
nameany
internal_nameany

Response

200OKobject

Success — example response shown.

202AcceptedJobAccepted

Accepted — async/bulk work was queued. Poll the returned job.

401UnauthorizedError

Missing or invalid X-Auth-Token.

422Unprocessable EntityError

The request failed validation.

429Too Many RequestsError

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

Authorization

ApiKeyAuthapiKey in header

Send your shop’s STOQ API key in the X-Auth-Token header on every request. Find it in the STOQ app under Settings → Integrations → API Key. The key resolves the shop context; the same scheme is used by the MCP server and the v1 API.

Create
curl -X POST 'https://app.stoqapp.com/api/v2/external/preorders/offers' \
  -H 'Content-Type: application/json' \
  -d '{
    "name": "Summer Sneaker Drop",
    "internal_name": "summer-2026"
  }'
const response = await fetch('https://app.stoqapp.com/api/v2/external/preorders/offers', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
      "name": "Summer Sneaker Drop",
      "internal_name": "summer-2026"
    }),
});

const data = await response.json();
import requests

payload = {
  "name": "Summer Sneaker Drop",
  "internal_name": "summer-2026"
}

response = requests.post('https://app.stoqapp.com/api/v2/external/preorders/offers', json=payload)
data = response.json()
Request Body
{
  "name": "Summer Sneaker Drop",
  "internal_name": "summer-2026"
}
{
  "id": "gid://shopify/SellingPlan/1",
  "name": "Summer Sneaker Drop",
  "internal_name": "summer-2026",
  "status": "draft",
  "created_at": "2026-06-25T10:30:45Z",
  "updated_at": "2026-06-25T10:30:45Z",
  "variants": {
    "count": 0,
    "url": "/api/v2/external/preorders/offers/1/products/variants"
  }
}
{
  "job_id": "job_a1b2c3",
  "status_url": "/api/v2/external/jobs/job_a1b2c3"
}
{
  "errors": [
    "Unauthorized"
  ]
}
{
  "errors": [
    "name is required"
  ]
}
{
  "errors": [
    "Rate limit exceeded"
  ]
}

Read

GET
https://app.stoqapp.com/api/v2/external/preorders/offers/{id}

Read a preorder offer's full representation.

Parameters

idstringrequiredpath

Response

200OKobject

Success — example response shown.

401UnauthorizedError

Missing or invalid X-Auth-Token.

404Not FoundError

The resource does not exist for this shop, or the action path is not registered.

422Unprocessable EntityError

The request failed validation.

429Too Many RequestsError

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

Authorization

ApiKeyAuthapiKey in header

Send your shop’s STOQ API key in the X-Auth-Token header on every request. Find it in the STOQ app under Settings → Integrations → API Key. The key resolves the shop context; the same scheme is used by the MCP server and the v1 API.

Read
curl -X GET 'https://app.stoqapp.com/api/v2/external/preorders/offers/{id}'
const response = await fetch('https://app.stoqapp.com/api/v2/external/preorders/offers/{id}', {
  method: 'GET',
});

const data = await response.json();
import requests

response = requests.get('https://app.stoqapp.com/api/v2/external/preorders/offers/{id}')
data = response.json()
{
  "id": "gid://shopify/SellingPlan/1",
  "name": "Summer Sneaker Drop",
  "internal_name": "summer-2026",
  "status": "active",
  "created_at": "2026-06-25T10:30:45Z",
  "updated_at": "2026-06-25T11:45:30Z",
  "variants": {
    "count": 3,
    "url": "/api/v2/external/preorders/offers/1/products/variants"
  },
  "products": {
    "source": "custom",
    "custom": {
      "variant_ids_sample": [
        47284734423096,
        47284734455864,
        47284734488632
      ]
    }
  },
  "widget": {
    "button": {
      "text": "Preorder Now",
      "colors": {
        "enabled": true,
        "text_color": "#FFFFFF",
        "background_color": "#1a1a1a"
      }
    },
    "disclaimer": {
      "enabled": true,
      "text": "Expected to ship by August 2026",
      "text_color": "#666666",
      "background_color": "#F5F5F5",
      "border_radius": "4px"
    },
    "badge": {
      "enabled": true,
      "text": "Pre-Order",
      "text_color": "#FFFFFF",
      "background_color": "#FF6B35"
    }
  },
  "shipping": {
    "delivery": {
      "applies_to_all_products": true,
      "type": "on_date",
      "days": null,
      "date": "2026-08-15T00:00:00Z"
    },
    "display": {
      "show_shipping_timeline": true,
      "shipping_text": "Ships in August 2026",
      "shipping_line_item_property_enabled": true
    }
  },
  "payments": {
    "mode": "full",
    "discount": {
      "type": null,
      "value": null
    },
    "options": [
      {
        "type": "full",
        "deposit_percent": null
      }
    ]
  },
  "limits": {
    "per_order": {
      "min": 1,
      "max": 5
    },
    "per_customer": {
      "max": 2
    },
    "total": {
      "max": 500,
      "current_count": null
    },
    "display": {
      "show_remaining": true,
      "quantity_limit_text": "Only 500 available"
    }
  },
  "checkout": {
    "terms": {
      "enabled": true,
      "text": "I understand this is a pre-order and will ship in August",
      "disable_button_until_acknowledged": true
    },
    "mixed_cart": {
      "allowed": false,
      "error_message": "Pre-orders cannot be mixed with regular items"
    },
    "order_tags": {
      "tags": [
        "preorder",
        "summer-2026"
      ]
    }
  },
  "inventory": {
    "provider": "stoq",
    "reservation": {
      "timing": "on_sale"
    },
    "continue_selling": {
      "enabled": true,
      "auto_apply_to_new_variants": true
    }
  },
  "markets": {
    "enabled": false,
    "applies_to_all_markets": false,
    "market_ids": []
  },
  "countdown": {
    "enabled": true,
    "mode": "to_schedule_end",
    "format": "d:h:m:s",
    "text": "Offer ends in"
  },
  "integrations": {
    "pos": {
      "enabled": true,
      "skip_inventory_check": false
    },
    "b2b": {
      "enabled": false
    }
  },
  "translations": {
    "default_locale": "en",
    "locales": [
      "en",
      "fr"
    ],
    "fields": [
      "widget.button.text"
    ],
    "translations": {
      "fr": {
        "widget.button.text": "Pré-commander"
      }
    }
  },
  "advanced": {
    "use_shopify_selling_plan": false,
    "custom_css": ".preorder-badge { font-weight: bold; }"
  }
}
{
  "errors": [
    "Unauthorized"
  ]
}
{
  "errors": [
    "Offer not found"
  ]
}
{
  "errors": [
    "name is required"
  ]
}
{
  "errors": [
    "Rate limit exceeded"
  ]
}

Update

PATCH
https://app.stoqapp.com/api/v2/external/preorders/offers/{id}

Update top-level fields of a preorder offer.

Body

application/json
nameany
internal_nameany

Parameters

idstringrequiredpath

Response

200OKobject

Success — the updated resource.

202AcceptedJobAccepted

Accepted — async/bulk work was queued. Poll the returned job.

401UnauthorizedError

Missing or invalid X-Auth-Token.

404Not FoundError

The resource does not exist for this shop, or the action path is not registered.

422Unprocessable EntityError

The request failed validation.

429Too Many RequestsError

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

Authorization

ApiKeyAuthapiKey in header

Send your shop’s STOQ API key in the X-Auth-Token header on every request. Find it in the STOQ app under Settings → Integrations → API Key. The key resolves the shop context; the same scheme is used by the MCP server and the v1 API.

Update
curl -X PATCH 'https://app.stoqapp.com/api/v2/external/preorders/offers/{id}' \
  -H 'Content-Type: application/json' \
  -d '{
    "name": "Summer Sneaker Drop",
    "internal_name": "summer-2026"
  }'
const response = await fetch('https://app.stoqapp.com/api/v2/external/preorders/offers/{id}', {
  method: 'PATCH',
  headers: {
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
      "name": "Summer Sneaker Drop",
      "internal_name": "summer-2026"
    }),
});

const data = await response.json();
import requests

payload = {
  "name": "Summer Sneaker Drop",
  "internal_name": "summer-2026"
}

response = requests.patch('https://app.stoqapp.com/api/v2/external/preorders/offers/{id}', json=payload)
data = response.json()
Request Body
{
  "name": "Summer Sneaker Drop",
  "internal_name": "summer-2026"
}
{}
{
  "job_id": "job_a1b2c3",
  "status_url": "/api/v2/external/jobs/job_a1b2c3"
}
{
  "errors": [
    "Unauthorized"
  ]
}
{
  "errors": [
    "Offer not found"
  ]
}
{
  "errors": [
    "name is required"
  ]
}
{
  "errors": [
    "Rate limit exceeded"
  ]
}

Advanced

GET
https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/advanced

Read power-user settings for a preorder offer (line item properties, button text overrides, Shopify selling plan attachment).

Parameters

idstringrequiredpath

Response

200OKobject

Success — the requested resource.

401UnauthorizedError

Missing or invalid X-Auth-Token.

404Not FoundError

The resource does not exist for this shop, or the action path is not registered.

422Unprocessable EntityError

The request failed validation.

429Too Many RequestsError

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

Authorization

ApiKeyAuthapiKey in header

Send your shop’s STOQ API key in the X-Auth-Token header on every request. Find it in the STOQ app under Settings → Integrations → API Key. The key resolves the shop context; the same scheme is used by the MCP server and the v1 API.

Advanced
curl -X GET 'https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/advanced'
const response = await fetch('https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/advanced', {
  method: 'GET',
});

const data = await response.json();
import requests

response = requests.get('https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/advanced')
data = response.json()
{}
{
  "errors": [
    "Unauthorized"
  ]
}
{
  "errors": [
    "Offer not found"
  ]
}
{
  "errors": [
    "name is required"
  ]
}
{
  "errors": [
    "Rate limit exceeded"
  ]
}

Advanced

PATCH
https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/advanced

Update advanced (power-user) settings on a preorder offer.

Note: Deep partial. Toggles and clears are done via this PATCH: the line-item-property toggles are line_item_properties.include_shipping_text, .include_payment_breakdown, and .include_acknowledgement (true/false each). button_text_overrides is deep-partial per state — send null to clear an override for one state, e.g. { "button_text_overrides": { "out_of_stock": null } } removes that override (the read shape still emits all three states, with null for unset). custom_css is cleared by sending an empty string or null.

Body

application/json
line_item_propertiesany
button_text_overridesany
use_shopify_selling_planany
custom_cssany

Parameters

idstringrequiredpath

Response

200OKobject

Success — the updated resource.

202AcceptedJobAccepted

Accepted — async/bulk work was queued. Poll the returned job.

401UnauthorizedError

Missing or invalid X-Auth-Token.

404Not FoundError

The resource does not exist for this shop, or the action path is not registered.

422Unprocessable EntityError

The request failed validation.

429Too Many RequestsError

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

Authorization

ApiKeyAuthapiKey in header

Send your shop’s STOQ API key in the X-Auth-Token header on every request. Find it in the STOQ app under Settings → Integrations → API Key. The key resolves the shop context; the same scheme is used by the MCP server and the v1 API.

Advanced
curl -X PATCH 'https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/advanced' \
  -H 'Content-Type: application/json' \
  -d '{
    "line_item_properties": "string",
    "button_text_overrides": "Preorder now",
    "use_shopify_selling_plan": "string",
    "custom_css": "string"
  }'
const response = await fetch('https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/advanced', {
  method: 'PATCH',
  headers: {
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
      "line_item_properties": "string",
      "button_text_overrides": "Preorder now",
      "use_shopify_selling_plan": "string",
      "custom_css": "string"
    }),
});

const data = await response.json();
import requests

payload = {
  "line_item_properties": "string",
  "button_text_overrides": "Preorder now",
  "use_shopify_selling_plan": "string",
  "custom_css": "string"
}

response = requests.patch('https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/advanced', json=payload)
data = response.json()
Request Body
{
  "line_item_properties": "string",
  "button_text_overrides": "Preorder now",
  "use_shopify_selling_plan": "string",
  "custom_css": "string"
}
{}
{
  "job_id": "job_a1b2c3",
  "status_url": "/api/v2/external/jobs/job_a1b2c3"
}
{
  "errors": [
    "Unauthorized"
  ]
}
{
  "errors": [
    "Offer not found"
  ]
}
{
  "errors": [
    "name is required"
  ]
}
{
  "errors": [
    "Rate limit exceeded"
  ]
}

Advanced Attach To Shopify Selling Plan

POST
https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/advanced/attach_to_shopify_selling_plan

Re-attach the offer to a Shopify selling plan group (resume syncing).

Parameters

idstringrequiredpath

Response

200OKobject

Success — the updated resource.

202AcceptedJobAccepted

Accepted — async/bulk work was queued. Poll the returned job.

401UnauthorizedError

Missing or invalid X-Auth-Token.

404Not FoundError

The resource does not exist for this shop, or the action path is not registered.

422Unprocessable EntityError

The request failed validation.

429Too Many RequestsError

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

Authorization

ApiKeyAuthapiKey in header

Send your shop’s STOQ API key in the X-Auth-Token header on every request. Find it in the STOQ app under Settings → Integrations → API Key. The key resolves the shop context; the same scheme is used by the MCP server and the v1 API.

Advanced Attach To Shopify Selling Plan
curl -X POST 'https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/advanced/attach_to_shopify_selling_plan'
const response = await fetch('https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/advanced/attach_to_shopify_selling_plan', {
  method: 'POST',
});

const data = await response.json();
import requests

response = requests.post('https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/advanced/attach_to_shopify_selling_plan')
data = response.json()
{}
{
  "job_id": "job_a1b2c3",
  "status_url": "/api/v2/external/jobs/job_a1b2c3"
}
{
  "errors": [
    "Unauthorized"
  ]
}
{
  "errors": [
    "Offer not found"
  ]
}
{
  "errors": [
    "name is required"
  ]
}
{
  "errors": [
    "Rate limit exceeded"
  ]
}

Advanced Detach From Shopify Selling Plan

POST
https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/advanced/detach_from_shopify_selling_plan

Detach the offer from Shopify selling plan groups; Stoq continues to manage it via the storefront integration.

Note: Strongly discouraged for most merchants. Breaks Shopify-native integrations like checkout selling plan display and third-party subscription apps. Does not delete the existing Shopify selling plan group — it just stops syncing.

Parameters

idstringrequiredpath

Response

200OKobject

Success — the updated resource.

202AcceptedJobAccepted

Accepted — async/bulk work was queued. Poll the returned job.

401UnauthorizedError

Missing or invalid X-Auth-Token.

404Not FoundError

The resource does not exist for this shop, or the action path is not registered.

422Unprocessable EntityError

The request failed validation.

429Too Many RequestsError

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

Authorization

ApiKeyAuthapiKey in header

Send your shop’s STOQ API key in the X-Auth-Token header on every request. Find it in the STOQ app under Settings → Integrations → API Key. The key resolves the shop context; the same scheme is used by the MCP server and the v1 API.

Advanced Detach From Shopify Selling Plan
curl -X POST 'https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/advanced/detach_from_shopify_selling_plan'
const response = await fetch('https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/advanced/detach_from_shopify_selling_plan', {
  method: 'POST',
});

const data = await response.json();
import requests

response = requests.post('https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/advanced/detach_from_shopify_selling_plan')
data = response.json()
{}
{
  "job_id": "job_a1b2c3",
  "status_url": "/api/v2/external/jobs/job_a1b2c3"
}
{
  "errors": [
    "Unauthorized"
  ]
}
{
  "errors": [
    "Offer not found"
  ]
}
{
  "errors": [
    "name is required"
  ]
}
{
  "errors": [
    "Rate limit exceeded"
  ]
}

Advanced Set Button Text Override

POST
https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/advanced/set_button_text_override

Override the widget button text for one state (before_launch, after_launch, or out_of_stock).

Body

application/json
stateanybefore_launchafter_launchout_of_stockrequired
textanyrequired

Parameters

idstringrequiredpath

Response

200OKobject

Success — the updated resource.

202AcceptedJobAccepted

Accepted — async/bulk work was queued. Poll the returned job.

401UnauthorizedError

Missing or invalid X-Auth-Token.

404Not FoundError

The resource does not exist for this shop, or the action path is not registered.

422Unprocessable EntityError

The request failed validation.

429Too Many RequestsError

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

Authorization

ApiKeyAuthapiKey in header

Send your shop’s STOQ API key in the X-Auth-Token header on every request. Find it in the STOQ app under Settings → Integrations → API Key. The key resolves the shop context; the same scheme is used by the MCP server and the v1 API.

Advanced Set Button Text Override
curl -X POST 'https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/advanced/set_button_text_override' \
  -H 'Content-Type: application/json' \
  -d '{
    "state": "before_launch",
    "text": "Preorder now"
  }'
const response = await fetch('https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/advanced/set_button_text_override', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
      "state": "before_launch",
      "text": "Preorder now"
    }),
});

const data = await response.json();
import requests

payload = {
  "state": "before_launch",
  "text": "Preorder now"
}

response = requests.post('https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/advanced/set_button_text_override', json=payload)
data = response.json()
Request Body
{
  "state": "before_launch",
  "text": "Preorder now"
}
{}
{
  "job_id": "job_a1b2c3",
  "status_url": "/api/v2/external/jobs/job_a1b2c3"
}
{
  "errors": [
    "Unauthorized"
  ]
}
{
  "errors": [
    "Offer not found"
  ]
}
{
  "errors": [
    "name is required"
  ]
}
{
  "errors": [
    "Rate limit exceeded"
  ]
}

Advanced Set Custom Css

POST
https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/advanced/set_custom_css

Set custom CSS overrides for this offer's storefront widget. Send an empty string to clear.

Body

application/json
cssany

Parameters

idstringrequiredpath

Response

200OKobject

Success — the updated resource.

202AcceptedJobAccepted

Accepted — async/bulk work was queued. Poll the returned job.

401UnauthorizedError

Missing or invalid X-Auth-Token.

404Not FoundError

The resource does not exist for this shop, or the action path is not registered.

422Unprocessable EntityError

The request failed validation.

429Too Many RequestsError

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

Authorization

ApiKeyAuthapiKey in header

Send your shop’s STOQ API key in the X-Auth-Token header on every request. Find it in the STOQ app under Settings → Integrations → API Key. The key resolves the shop context; the same scheme is used by the MCP server and the v1 API.

Advanced Set Custom Css
curl -X POST 'https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/advanced/set_custom_css' \
  -H 'Content-Type: application/json' \
  -d '{
    "css": "string"
  }'
const response = await fetch('https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/advanced/set_custom_css', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
      "css": "string"
    }),
});

const data = await response.json();
import requests

payload = {
  "css": "string"
}

response = requests.post('https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/advanced/set_custom_css', json=payload)
data = response.json()
Request Body
{
  "css": "string"
}
{}
{
  "job_id": "job_a1b2c3",
  "status_url": "/api/v2/external/jobs/job_a1b2c3"
}
{
  "errors": [
    "Unauthorized"
  ]
}
{
  "errors": [
    "Offer not found"
  ]
}
{
  "errors": [
    "name is required"
  ]
}
{
  "errors": [
    "Rate limit exceeded"
  ]
}

Advanced Set Custom Line Item Property

POST
https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/advanced/set_custom_line_item_property

Set a free-text custom line item property added to every preorder cart line.

Body

application/json
textany

Parameters

idstringrequiredpath

Response

200OKobject

Success — the updated resource.

202AcceptedJobAccepted

Accepted — async/bulk work was queued. Poll the returned job.

401UnauthorizedError

Missing or invalid X-Auth-Token.

404Not FoundError

The resource does not exist for this shop, or the action path is not registered.

422Unprocessable EntityError

The request failed validation.

429Too Many RequestsError

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

Authorization

ApiKeyAuthapiKey in header

Send your shop’s STOQ API key in the X-Auth-Token header on every request. Find it in the STOQ app under Settings → Integrations → API Key. The key resolves the shop context; the same scheme is used by the MCP server and the v1 API.

Advanced Set Custom Line Item Property
curl -X POST 'https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/advanced/set_custom_line_item_property' \
  -H 'Content-Type: application/json' \
  -d '{
    "text": "Preorder now"
  }'
const response = await fetch('https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/advanced/set_custom_line_item_property', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
      "text": "Preorder now"
    }),
});

const data = await response.json();
import requests

payload = {
  "text": "Preorder now"
}

response = requests.post('https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/advanced/set_custom_line_item_property', json=payload)
data = response.json()
Request Body
{
  "text": "Preorder now"
}
{}
{
  "job_id": "job_a1b2c3",
  "status_url": "/api/v2/external/jobs/job_a1b2c3"
}
{
  "errors": [
    "Unauthorized"
  ]
}
{
  "errors": [
    "Offer not found"
  ]
}
{
  "errors": [
    "name is required"
  ]
}
{
  "errors": [
    "Rate limit exceeded"
  ]
}

Checkout

GET
https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/checkout

Read checkout settings for a preorder offer.

Parameters

idstringrequiredpath

Response

200OKobject

Success — the requested resource.

401UnauthorizedError

Missing or invalid X-Auth-Token.

404Not FoundError

The resource does not exist for this shop, or the action path is not registered.

422Unprocessable EntityError

The request failed validation.

429Too Many RequestsError

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

Authorization

ApiKeyAuthapiKey in header

Send your shop’s STOQ API key in the X-Auth-Token header on every request. Find it in the STOQ app under Settings → Integrations → API Key. The key resolves the shop context; the same scheme is used by the MCP server and the v1 API.

Checkout
curl -X GET 'https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/checkout'
const response = await fetch('https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/checkout', {
  method: 'GET',
});

const data = await response.json();
import requests

response = requests.get('https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/checkout')
data = response.json()
{}
{
  "errors": [
    "Unauthorized"
  ]
}
{
  "errors": [
    "Offer not found"
  ]
}
{
  "errors": [
    "name is required"
  ]
}
{
  "errors": [
    "Rate limit exceeded"
  ]
}

Checkout

PATCH
https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/checkout

Update checkout settings on a preorder offer.

Note: Boolean toggles are set via this PATCH: terms.enabled, terms.disable_button_until_acknowledged, terms.include_in_line_item_properties, mixed_cart.allowed — this PATCH is how you turn these on/off, e.g. { terms: { enabled: true } } or { mixed_cart: { allowed: false } }.

Body

application/json
termsany
mixed_cartany
order_tagsany

Parameters

idstringrequiredpath

Response

200OKobject

Success — the updated resource.

202AcceptedJobAccepted

Accepted — async/bulk work was queued. Poll the returned job.

401UnauthorizedError

Missing or invalid X-Auth-Token.

404Not FoundError

The resource does not exist for this shop, or the action path is not registered.

422Unprocessable EntityError

The request failed validation.

429Too Many RequestsError

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

Authorization

ApiKeyAuthapiKey in header

Send your shop’s STOQ API key in the X-Auth-Token header on every request. Find it in the STOQ app under Settings → Integrations → API Key. The key resolves the shop context; the same scheme is used by the MCP server and the v1 API.

Checkout
curl -X PATCH 'https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/checkout' \
  -H 'Content-Type: application/json' \
  -d '{
    "terms": "string",
    "mixed_cart": "string",
    "order_tags": "string"
  }'
const response = await fetch('https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/checkout', {
  method: 'PATCH',
  headers: {
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
      "terms": "string",
      "mixed_cart": "string",
      "order_tags": "string"
    }),
});

const data = await response.json();
import requests

payload = {
  "terms": "string",
  "mixed_cart": "string",
  "order_tags": "string"
}

response = requests.patch('https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/checkout', json=payload)
data = response.json()
Request Body
{
  "terms": "string",
  "mixed_cart": "string",
  "order_tags": "string"
}
{}
{
  "job_id": "job_a1b2c3",
  "status_url": "/api/v2/external/jobs/job_a1b2c3"
}
{
  "errors": [
    "Unauthorized"
  ]
}
{
  "errors": [
    "Offer not found"
  ]
}
{
  "errors": [
    "name is required"
  ]
}
{
  "errors": [
    "Rate limit exceeded"
  ]
}

Checkout Add Order Tag

POST
https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/checkout/add_order_tag

Add a tag to the set applied to orders containing this offer.

Body

application/json
taganyrequired

Parameters

idstringrequiredpath

Response

200OKobject

Success — the updated resource.

202AcceptedJobAccepted

Accepted — async/bulk work was queued. Poll the returned job.

401UnauthorizedError

Missing or invalid X-Auth-Token.

404Not FoundError

The resource does not exist for this shop, or the action path is not registered.

422Unprocessable EntityError

The request failed validation.

429Too Many RequestsError

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

Authorization

ApiKeyAuthapiKey in header

Send your shop’s STOQ API key in the X-Auth-Token header on every request. Find it in the STOQ app under Settings → Integrations → API Key. The key resolves the shop context; the same scheme is used by the MCP server and the v1 API.

Checkout Add Order Tag
curl -X POST 'https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/checkout/add_order_tag' \
  -H 'Content-Type: application/json' \
  -d '{
    "tag": "string"
  }'
const response = await fetch('https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/checkout/add_order_tag', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
      "tag": "string"
    }),
});

const data = await response.json();
import requests

payload = {
  "tag": "string"
}

response = requests.post('https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/checkout/add_order_tag', json=payload)
data = response.json()
Request Body
{
  "tag": "string"
}
{}
{
  "job_id": "job_a1b2c3",
  "status_url": "/api/v2/external/jobs/job_a1b2c3"
}
{
  "errors": [
    "Unauthorized"
  ]
}
{
  "errors": [
    "Offer not found"
  ]
}
{
  "errors": [
    "name is required"
  ]
}
{
  "errors": [
    "Rate limit exceeded"
  ]
}

Checkout Remove Order Tag

POST
https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/checkout/remove_order_tag

Remove a tag from the set applied to orders containing this offer.

Body

application/json
taganyrequired

Parameters

idstringrequiredpath

Response

200OKobject

Success — the updated resource.

202AcceptedJobAccepted

Accepted — async/bulk work was queued. Poll the returned job.

401UnauthorizedError

Missing or invalid X-Auth-Token.

404Not FoundError

The resource does not exist for this shop, or the action path is not registered.

422Unprocessable EntityError

The request failed validation.

429Too Many RequestsError

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

Authorization

ApiKeyAuthapiKey in header

Send your shop’s STOQ API key in the X-Auth-Token header on every request. Find it in the STOQ app under Settings → Integrations → API Key. The key resolves the shop context; the same scheme is used by the MCP server and the v1 API.

Checkout Remove Order Tag
curl -X POST 'https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/checkout/remove_order_tag' \
  -H 'Content-Type: application/json' \
  -d '{
    "tag": "string"
  }'
const response = await fetch('https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/checkout/remove_order_tag', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
      "tag": "string"
    }),
});

const data = await response.json();
import requests

payload = {
  "tag": "string"
}

response = requests.post('https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/checkout/remove_order_tag', json=payload)
data = response.json()
Request Body
{
  "tag": "string"
}
{}
{
  "job_id": "job_a1b2c3",
  "status_url": "/api/v2/external/jobs/job_a1b2c3"
}
{
  "errors": [
    "Unauthorized"
  ]
}
{
  "errors": [
    "Offer not found"
  ]
}
{
  "errors": [
    "name is required"
  ]
}
{
  "errors": [
    "Rate limit exceeded"
  ]
}

Checkout Set Mixed Cart Error Message

POST
https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/checkout/set_mixed_cart_error_message

Set the error message shown when a blocked mixed cart reaches checkout.

Body

application/json
messageanyrequired

Parameters

idstringrequiredpath

Response

200OKobject

Success — the updated resource.

202AcceptedJobAccepted

Accepted — async/bulk work was queued. Poll the returned job.

401UnauthorizedError

Missing or invalid X-Auth-Token.

404Not FoundError

The resource does not exist for this shop, or the action path is not registered.

422Unprocessable EntityError

The request failed validation.

429Too Many RequestsError

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

Authorization

ApiKeyAuthapiKey in header

Send your shop’s STOQ API key in the X-Auth-Token header on every request. Find it in the STOQ app under Settings → Integrations → API Key. The key resolves the shop context; the same scheme is used by the MCP server and the v1 API.

Checkout Set Mixed Cart Error Message
curl -X POST 'https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/checkout/set_mixed_cart_error_message' \
  -H 'Content-Type: application/json' \
  -d '{
    "message": "string"
  }'
const response = await fetch('https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/checkout/set_mixed_cart_error_message', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
      "message": "string"
    }),
});

const data = await response.json();
import requests

payload = {
  "message": "string"
}

response = requests.post('https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/checkout/set_mixed_cart_error_message', json=payload)
data = response.json()
Request Body
{
  "message": "string"
}
{}
{
  "job_id": "job_a1b2c3",
  "status_url": "/api/v2/external/jobs/job_a1b2c3"
}
{
  "errors": [
    "Unauthorized"
  ]
}
{
  "errors": [
    "Offer not found"
  ]
}
{
  "errors": [
    "name is required"
  ]
}
{
  "errors": [
    "Rate limit exceeded"
  ]
}

Checkout Set Order Tags

POST
https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/checkout/set_order_tags

Replace the set of tags applied to orders containing this offer.

Body

application/json
tagsany

Parameters

idstringrequiredpath

Response

200OKobject

Success — the updated resource.

202AcceptedJobAccepted

Accepted — async/bulk work was queued. Poll the returned job.

401UnauthorizedError

Missing or invalid X-Auth-Token.

404Not FoundError

The resource does not exist for this shop, or the action path is not registered.

422Unprocessable EntityError

The request failed validation.

429Too Many RequestsError

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

Authorization

ApiKeyAuthapiKey in header

Send your shop’s STOQ API key in the X-Auth-Token header on every request. Find it in the STOQ app under Settings → Integrations → API Key. The key resolves the shop context; the same scheme is used by the MCP server and the v1 API.

Checkout Set Order Tags
curl -X POST 'https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/checkout/set_order_tags' \
  -H 'Content-Type: application/json' \
  -d '{
    "tags": "string"
  }'
const response = await fetch('https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/checkout/set_order_tags', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
      "tags": "string"
    }),
});

const data = await response.json();
import requests

payload = {
  "tags": "string"
}

response = requests.post('https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/checkout/set_order_tags', json=payload)
data = response.json()
Request Body
{
  "tags": "string"
}
{}
{
  "job_id": "job_a1b2c3",
  "status_url": "/api/v2/external/jobs/job_a1b2c3"
}
{
  "errors": [
    "Unauthorized"
  ]
}
{
  "errors": [
    "Offer not found"
  ]
}
{
  "errors": [
    "name is required"
  ]
}
{
  "errors": [
    "Rate limit exceeded"
  ]
}

Checkout Set Terms Text

POST
https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/checkout/set_terms_text

Set the terms-acceptance text shown next to the checkbox.

Body

application/json
textanyrequired

Parameters

idstringrequiredpath

Response

200OKobject

Success — the updated resource.

202AcceptedJobAccepted

Accepted — async/bulk work was queued. Poll the returned job.

401UnauthorizedError

Missing or invalid X-Auth-Token.

404Not FoundError

The resource does not exist for this shop, or the action path is not registered.

422Unprocessable EntityError

The request failed validation.

429Too Many RequestsError

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

Authorization

ApiKeyAuthapiKey in header

Send your shop’s STOQ API key in the X-Auth-Token header on every request. Find it in the STOQ app under Settings → Integrations → API Key. The key resolves the shop context; the same scheme is used by the MCP server and the v1 API.

Checkout Set Terms Text
curl -X POST 'https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/checkout/set_terms_text' \
  -H 'Content-Type: application/json' \
  -d '{
    "text": "Preorder now"
  }'
const response = await fetch('https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/checkout/set_terms_text', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
      "text": "Preorder now"
    }),
});

const data = await response.json();
import requests

payload = {
  "text": "Preorder now"
}

response = requests.post('https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/checkout/set_terms_text', json=payload)
data = response.json()
Request Body
{
  "text": "Preorder now"
}
{}
{
  "job_id": "job_a1b2c3",
  "status_url": "/api/v2/external/jobs/job_a1b2c3"
}
{
  "errors": [
    "Unauthorized"
  ]
}
{
  "errors": [
    "Offer not found"
  ]
}
{
  "errors": [
    "name is required"
  ]
}
{
  "errors": [
    "Rate limit exceeded"
  ]
}

Countdown

GET
https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/countdown

Read the countdown timer configuration for a preorder offer.

Parameters

idstringrequiredpath

Response

200OKobject

Success — the requested resource.

401UnauthorizedError

Missing or invalid X-Auth-Token.

404Not FoundError

The resource does not exist for this shop, or the action path is not registered.

422Unprocessable EntityError

The request failed validation.

429Too Many RequestsError

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

Authorization

ApiKeyAuthapiKey in header

Send your shop’s STOQ API key in the X-Auth-Token header on every request. Find it in the STOQ app under Settings → Integrations → API Key. The key resolves the shop context; the same scheme is used by the MCP server and the v1 API.

Countdown
curl -X GET 'https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/countdown'
const response = await fetch('https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/countdown', {
  method: 'GET',
});

const data = await response.json();
import requests

response = requests.get('https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/countdown')
data = response.json()
{}
{
  "errors": [
    "Unauthorized"
  ]
}
{
  "errors": [
    "Offer not found"
  ]
}
{
  "errors": [
    "name is required"
  ]
}
{
  "errors": [
    "Rate limit exceeded"
  ]
}

Countdown

PATCH
https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/countdown

Update countdown timer settings on a preorder offer.

Note: Deep partial. countdown.enabled is toggled via this PATCH (enabled true/false); text is an alias for ends_text — both write the same column, and an explicit ends_text wins when both are sent.

Body

application/json
enabledany
modeany
custom_end_dateany
custom_start_dateany
formatany
textany
starts_textany
ends_textany
unit_labelsany
styleany

Parameters

idstringrequiredpath

Response

200OKobject

Success — the updated resource.

202AcceptedJobAccepted

Accepted — async/bulk work was queued. Poll the returned job.

401UnauthorizedError

Missing or invalid X-Auth-Token.

404Not FoundError

The resource does not exist for this shop, or the action path is not registered.

422Unprocessable EntityError

The request failed validation.

429Too Many RequestsError

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

Authorization

ApiKeyAuthapiKey in header

Send your shop’s STOQ API key in the X-Auth-Token header on every request. Find it in the STOQ app under Settings → Integrations → API Key. The key resolves the shop context; the same scheme is used by the MCP server and the v1 API.

Countdown
curl -X PATCH 'https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/countdown' \
  -H 'Content-Type: application/json' \
  -d '{
    "enabled": true,
    "mode": "string",
    "custom_end_date": "2026-07-01T00:00:00Z",
    "custom_start_date": "2026-07-01T00:00:00Z",
    "format": "string",
    "text": "Preorder now",
    "starts_text": "Preorder now",
    "ends_text": "Preorder now",
    "unit_labels": "Preorder now",
    "style": "string"
  }'
const response = await fetch('https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/countdown', {
  method: 'PATCH',
  headers: {
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
      "enabled": true,
      "mode": "string",
      "custom_end_date": "2026-07-01T00:00:00Z",
      "custom_start_date": "2026-07-01T00:00:00Z",
      "format": "string",
      "text": "Preorder now",
      "starts_text": "Preorder now",
      "ends_text": "Preorder now",
      "unit_labels": "Preorder now",
      "style": "string"
    }),
});

const data = await response.json();
import requests

payload = {
  "enabled": True,
  "mode": "string",
  "custom_end_date": "2026-07-01T00:00:00Z",
  "custom_start_date": "2026-07-01T00:00:00Z",
  "format": "string",
  "text": "Preorder now",
  "starts_text": "Preorder now",
  "ends_text": "Preorder now",
  "unit_labels": "Preorder now",
  "style": "string"
}

response = requests.patch('https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/countdown', json=payload)
data = response.json()
Request Body
{
  "enabled": true,
  "mode": "string",
  "custom_end_date": "2026-07-01T00:00:00Z",
  "custom_start_date": "2026-07-01T00:00:00Z",
  "format": "string",
  "text": "Preorder now",
  "starts_text": "Preorder now",
  "ends_text": "Preorder now",
  "unit_labels": "Preorder now",
  "style": "string"
}
{}
{
  "job_id": "job_a1b2c3",
  "status_url": "/api/v2/external/jobs/job_a1b2c3"
}
{
  "errors": [
    "Unauthorized"
  ]
}
{
  "errors": [
    "Offer not found"
  ]
}
{
  "errors": [
    "name is required"
  ]
}
{
  "errors": [
    "Rate limit exceeded"
  ]
}

Countdown Set Custom End Date

POST
https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/countdown/set_custom_end_date

Set the custom end date for the countdown timer.

Note: Has no visible effect unless mode is to_custom_date.

Body

application/json
dateanyrequired

Parameters

idstringrequiredpath

Response

200OKobject

Success — the updated resource.

202AcceptedJobAccepted

Accepted — async/bulk work was queued. Poll the returned job.

401UnauthorizedError

Missing or invalid X-Auth-Token.

404Not FoundError

The resource does not exist for this shop, or the action path is not registered.

422Unprocessable EntityError

The request failed validation.

429Too Many RequestsError

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

Authorization

ApiKeyAuthapiKey in header

Send your shop’s STOQ API key in the X-Auth-Token header on every request. Find it in the STOQ app under Settings → Integrations → API Key. The key resolves the shop context; the same scheme is used by the MCP server and the v1 API.

Countdown Set Custom End Date
curl -X POST 'https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/countdown/set_custom_end_date' \
  -H 'Content-Type: application/json' \
  -d '{
    "date": "2026-07-01T00:00:00Z"
  }'
const response = await fetch('https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/countdown/set_custom_end_date', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
      "date": "2026-07-01T00:00:00Z"
    }),
});

const data = await response.json();
import requests

payload = {
  "date": "2026-07-01T00:00:00Z"
}

response = requests.post('https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/countdown/set_custom_end_date', json=payload)
data = response.json()
Request Body
{
  "date": "2026-07-01T00:00:00Z"
}
{}
{
  "job_id": "job_a1b2c3",
  "status_url": "/api/v2/external/jobs/job_a1b2c3"
}
{
  "errors": [
    "Unauthorized"
  ]
}
{
  "errors": [
    "Offer not found"
  ]
}
{
  "errors": [
    "name is required"
  ]
}
{
  "errors": [
    "Rate limit exceeded"
  ]
}

Countdown Set Ends Text

POST
https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/countdown/set_ends_text

Set the text shown next to the countdown timer when the offer is closing.

Body

application/json
textanyrequired

Parameters

idstringrequiredpath

Response

200OKobject

Success — the updated resource.

202AcceptedJobAccepted

Accepted — async/bulk work was queued. Poll the returned job.

401UnauthorizedError

Missing or invalid X-Auth-Token.

404Not FoundError

The resource does not exist for this shop, or the action path is not registered.

422Unprocessable EntityError

The request failed validation.

429Too Many RequestsError

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

Authorization

ApiKeyAuthapiKey in header

Send your shop’s STOQ API key in the X-Auth-Token header on every request. Find it in the STOQ app under Settings → Integrations → API Key. The key resolves the shop context; the same scheme is used by the MCP server and the v1 API.

Countdown Set Ends Text
curl -X POST 'https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/countdown/set_ends_text' \
  -H 'Content-Type: application/json' \
  -d '{
    "text": "Preorder now"
  }'
const response = await fetch('https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/countdown/set_ends_text', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
      "text": "Preorder now"
    }),
});

const data = await response.json();
import requests

payload = {
  "text": "Preorder now"
}

response = requests.post('https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/countdown/set_ends_text', json=payload)
data = response.json()
Request Body
{
  "text": "Preorder now"
}
{}
{
  "job_id": "job_a1b2c3",
  "status_url": "/api/v2/external/jobs/job_a1b2c3"
}
{
  "errors": [
    "Unauthorized"
  ]
}
{
  "errors": [
    "Offer not found"
  ]
}
{
  "errors": [
    "name is required"
  ]
}
{
  "errors": [
    "Rate limit exceeded"
  ]
}

Countdown Set Mode

POST
https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/countdown/set_mode

Set whether the countdown timer follows the offer's schedule or a custom date.

Body

application/json
modeanyto_schedule_endto_custom_daterequired

Parameters

idstringrequiredpath

Response

200OKobject

Success — the updated resource.

202AcceptedJobAccepted

Accepted — async/bulk work was queued. Poll the returned job.

401UnauthorizedError

Missing or invalid X-Auth-Token.

404Not FoundError

The resource does not exist for this shop, or the action path is not registered.

422Unprocessable EntityError

The request failed validation.

429Too Many RequestsError

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

Authorization

ApiKeyAuthapiKey in header

Send your shop’s STOQ API key in the X-Auth-Token header on every request. Find it in the STOQ app under Settings → Integrations → API Key. The key resolves the shop context; the same scheme is used by the MCP server and the v1 API.

Countdown Set Mode
curl -X POST 'https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/countdown/set_mode' \
  -H 'Content-Type: application/json' \
  -d '{
    "mode": "to_schedule_end"
  }'
const response = await fetch('https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/countdown/set_mode', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
      "mode": "to_schedule_end"
    }),
});

const data = await response.json();
import requests

payload = {
  "mode": "to_schedule_end"
}

response = requests.post('https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/countdown/set_mode', json=payload)
data = response.json()
Request Body
{
  "mode": "to_schedule_end"
}
{}
{
  "job_id": "job_a1b2c3",
  "status_url": "/api/v2/external/jobs/job_a1b2c3"
}
{
  "errors": [
    "Unauthorized"
  ]
}
{
  "errors": [
    "Offer not found"
  ]
}
{
  "errors": [
    "name is required"
  ]
}
{
  "errors": [
    "Rate limit exceeded"
  ]
}

Countdown Set Starts Text

POST
https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/countdown/set_starts_text

Set the text shown before the countdown timer when the offer hasn't started yet.

Body

application/json
textanyrequired

Parameters

idstringrequiredpath

Response

200OKobject

Success — the updated resource.

202AcceptedJobAccepted

Accepted — async/bulk work was queued. Poll the returned job.

401UnauthorizedError

Missing or invalid X-Auth-Token.

404Not FoundError

The resource does not exist for this shop, or the action path is not registered.

422Unprocessable EntityError

The request failed validation.

429Too Many RequestsError

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

Authorization

ApiKeyAuthapiKey in header

Send your shop’s STOQ API key in the X-Auth-Token header on every request. Find it in the STOQ app under Settings → Integrations → API Key. The key resolves the shop context; the same scheme is used by the MCP server and the v1 API.

Countdown Set Starts Text
curl -X POST 'https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/countdown/set_starts_text' \
  -H 'Content-Type: application/json' \
  -d '{
    "text": "Preorder now"
  }'
const response = await fetch('https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/countdown/set_starts_text', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
      "text": "Preorder now"
    }),
});

const data = await response.json();
import requests

payload = {
  "text": "Preorder now"
}

response = requests.post('https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/countdown/set_starts_text', json=payload)
data = response.json()
Request Body
{
  "text": "Preorder now"
}
{}
{
  "job_id": "job_a1b2c3",
  "status_url": "/api/v2/external/jobs/job_a1b2c3"
}
{
  "errors": [
    "Unauthorized"
  ]
}
{
  "errors": [
    "Offer not found"
  ]
}
{
  "errors": [
    "name is required"
  ]
}
{
  "errors": [
    "Rate limit exceeded"
  ]
}

Countdown Set Style

POST
https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/countdown/set_style

Set the countdown timer's visual style (type, colors, border radius).

Body

application/json
typeany
text_colorany
background_colorany
border_radiusany

Parameters

idstringrequiredpath

Response

200OKobject

Success — the updated resource.

202AcceptedJobAccepted

Accepted — async/bulk work was queued. Poll the returned job.

401UnauthorizedError

Missing or invalid X-Auth-Token.

404Not FoundError

The resource does not exist for this shop, or the action path is not registered.

422Unprocessable EntityError

The request failed validation.

429Too Many RequestsError

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

Authorization

ApiKeyAuthapiKey in header

Send your shop’s STOQ API key in the X-Auth-Token header on every request. Find it in the STOQ app under Settings → Integrations → API Key. The key resolves the shop context; the same scheme is used by the MCP server and the v1 API.

Countdown Set Style
curl -X POST 'https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/countdown/set_style' \
  -H 'Content-Type: application/json' \
  -d '{
    "type": "string",
    "text_color": "#1A1A1A",
    "background_color": "#1A1A1A",
    "border_radius": "string"
  }'
const response = await fetch('https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/countdown/set_style', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
      "type": "string",
      "text_color": "#1A1A1A",
      "background_color": "#1A1A1A",
      "border_radius": "string"
    }),
});

const data = await response.json();
import requests

payload = {
  "type": "string",
  "text_color": "#1A1A1A",
  "background_color": "#1A1A1A",
  "border_radius": "string"
}

response = requests.post('https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/countdown/set_style', json=payload)
data = response.json()
Request Body
{
  "type": "string",
  "text_color": "#1A1A1A",
  "background_color": "#1A1A1A",
  "border_radius": "string"
}
{}
{
  "job_id": "job_a1b2c3",
  "status_url": "/api/v2/external/jobs/job_a1b2c3"
}
{
  "errors": [
    "Unauthorized"
  ]
}
{
  "errors": [
    "Offer not found"
  ]
}
{
  "errors": [
    "name is required"
  ]
}
{
  "errors": [
    "Rate limit exceeded"
  ]
}

Countdown Set Unit Labels

POST
https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/countdown/set_unit_labels

Set the unit labels for the countdown timer (Days/Hours/Mins/Secs).

Body

application/json
daysany
hoursany
minutesany
secondsany

Parameters

idstringrequiredpath

Response

200OKobject

Success — the updated resource.

202AcceptedJobAccepted

Accepted — async/bulk work was queued. Poll the returned job.

401UnauthorizedError

Missing or invalid X-Auth-Token.

404Not FoundError

The resource does not exist for this shop, or the action path is not registered.

422Unprocessable EntityError

The request failed validation.

429Too Many RequestsError

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

Authorization

ApiKeyAuthapiKey in header

Send your shop’s STOQ API key in the X-Auth-Token header on every request. Find it in the STOQ app under Settings → Integrations → API Key. The key resolves the shop context; the same scheme is used by the MCP server and the v1 API.

Countdown Set Unit Labels
curl -X POST 'https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/countdown/set_unit_labels' \
  -H 'Content-Type: application/json' \
  -d '{
    "days": "string",
    "hours": "string",
    "minutes": "string",
    "seconds": "string"
  }'
const response = await fetch('https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/countdown/set_unit_labels', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
      "days": "string",
      "hours": "string",
      "minutes": "string",
      "seconds": "string"
    }),
});

const data = await response.json();
import requests

payload = {
  "days": "string",
  "hours": "string",
  "minutes": "string",
  "seconds": "string"
}

response = requests.post('https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/countdown/set_unit_labels', json=payload)
data = response.json()
Request Body
{
  "days": "string",
  "hours": "string",
  "minutes": "string",
  "seconds": "string"
}
{}
{
  "job_id": "job_a1b2c3",
  "status_url": "/api/v2/external/jobs/job_a1b2c3"
}
{
  "errors": [
    "Unauthorized"
  ]
}
{
  "errors": [
    "Offer not found"
  ]
}
{
  "errors": [
    "name is required"
  ]
}
{
  "errors": [
    "Rate limit exceeded"
  ]
}

Disable

POST
https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/disable

Disable (pause) a preorder offer. Optionally flip attached variants' inventory policy back to DENY.

Note: Variants are left at their existing inventory policy unless update_inventory_policy: true is passed.

Body

application/json
update_inventory_policyany
variant_idsany

Parameters

idstringrequiredpath

Response

200OKobject

Success — example response shown.

202AcceptedJobAccepted

Accepted — async/bulk work was queued. Poll the returned job.

401UnauthorizedError

Missing or invalid X-Auth-Token.

404Not FoundError

The resource does not exist for this shop, or the action path is not registered.

409ConflictError

Invalid lifecycle transition — read the message; don't retry blindly.

422Unprocessable EntityError

The request failed validation.

429Too Many RequestsError

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

Authorization

ApiKeyAuthapiKey in header

Send your shop’s STOQ API key in the X-Auth-Token header on every request. Find it in the STOQ app under Settings → Integrations → API Key. The key resolves the shop context; the same scheme is used by the MCP server and the v1 API.

Disable
curl -X POST 'https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/disable' \
  -H 'Content-Type: application/json' \
  -d '{
    "update_inventory_policy": true
  }'
const response = await fetch('https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/disable', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
      "update_inventory_policy": true
    }),
});

const data = await response.json();
import requests

payload = {
  "update_inventory_policy": True
}

response = requests.post('https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/disable', json=payload)
data = response.json()
Request Body
{
  "update_inventory_policy": true
}
{
  "id": "gid://shopify/SellingPlan/1",
  "name": "Summer Sneaker Drop",
  "internal_name": "summer-2026",
  "status": "paused",
  "updated_at": "2026-06-25T12:15:20Z",
  "variants": {
    "count": 3,
    "url": "/api/v2/external/preorders/offers/1/products/variants"
  }
}
{
  "job_id": "job_a1b2c3",
  "status_url": "/api/v2/external/jobs/job_a1b2c3"
}
{
  "errors": [
    "Unauthorized"
  ]
}
{
  "errors": [
    "Offer not found"
  ]
}
{
  "errors": [
    "Offer is already disabled"
  ]
}
{
  "errors": [
    "name is required"
  ]
}
{
  "errors": [
    "Rate limit exceeded"
  ]
}

Discard

POST
https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/discard

Discard (soft-delete) a preorder offer.

Note: Recoverable via restore indefinitely. Discarded offers are never hard-deleted.

Parameters

idstringrequiredpath

Response

200OKobject

Success — the updated resource.

202AcceptedJobAccepted

Accepted — async/bulk work was queued. Poll the returned job.

401UnauthorizedError

Missing or invalid X-Auth-Token.

404Not FoundError

The resource does not exist for this shop, or the action path is not registered.

409ConflictError

Invalid lifecycle transition — read the message; don't retry blindly.

422Unprocessable EntityError

The request failed validation.

429Too Many RequestsError

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

Authorization

ApiKeyAuthapiKey in header

Send your shop’s STOQ API key in the X-Auth-Token header on every request. Find it in the STOQ app under Settings → Integrations → API Key. The key resolves the shop context; the same scheme is used by the MCP server and the v1 API.

Discard
curl -X POST 'https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/discard'
const response = await fetch('https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/discard', {
  method: 'POST',
});

const data = await response.json();
import requests

response = requests.post('https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/discard')
data = response.json()
{}
{
  "job_id": "job_a1b2c3",
  "status_url": "/api/v2/external/jobs/job_a1b2c3"
}
{
  "errors": [
    "Unauthorized"
  ]
}
{
  "errors": [
    "Offer not found"
  ]
}
{
  "errors": [
    "Offer is already disabled"
  ]
}
{
  "errors": [
    "name is required"
  ]
}
{
  "errors": [
    "Rate limit exceeded"
  ]
}

Enable

POST
https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/enable

Enable a preorder offer. Optionally flip attached variants' inventory policy to CONTINUE.

Note: Variants are left at their existing inventory policy unless update_inventory_policy: true is passed.

Body

application/json
update_inventory_policyany
variant_idsany

Parameters

idstringrequiredpath

Response

200OKobject

Success — example response shown.

202AcceptedJobAccepted

Accepted — async/bulk work was queued. Poll the returned job.

401UnauthorizedError

Missing or invalid X-Auth-Token.

404Not FoundError

The resource does not exist for this shop, or the action path is not registered.

409ConflictError

Invalid lifecycle transition — read the message; don't retry blindly.

422Unprocessable EntityError

The request failed validation.

429Too Many RequestsError

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

Authorization

ApiKeyAuthapiKey in header

Send your shop’s STOQ API key in the X-Auth-Token header on every request. Find it in the STOQ app under Settings → Integrations → API Key. The key resolves the shop context; the same scheme is used by the MCP server and the v1 API.

Enable
curl -X POST 'https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/enable' \
  -H 'Content-Type: application/json' \
  -d '{
    "update_inventory_policy": true
  }'
const response = await fetch('https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/enable', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
      "update_inventory_policy": true
    }),
});

const data = await response.json();
import requests

payload = {
  "update_inventory_policy": True
}

response = requests.post('https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/enable', json=payload)
data = response.json()
Request Body
{
  "update_inventory_policy": true
}
{
  "id": "gid://shopify/SellingPlan/1",
  "name": "Summer Sneaker Drop",
  "internal_name": "summer-2026",
  "status": "active",
  "updated_at": "2026-06-25T11:45:30Z",
  "variants": {
    "count": 3,
    "url": "/api/v2/external/preorders/offers/1/products/variants"
  }
}
{
  "job_id": "job_a1b2c3",
  "status_url": "/api/v2/external/jobs/job_a1b2c3"
}
{
  "errors": [
    "Unauthorized"
  ]
}
{
  "errors": [
    "Offer not found"
  ]
}
{
  "errors": [
    "Offer is already disabled"
  ]
}
{
  "errors": [
    "name is required"
  ]
}
{
  "errors": [
    "Rate limit exceeded"
  ]
}

Integrations

GET
https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/integrations

Read integration settings for a preorder offer (POS, B2B).

Parameters

idstringrequiredpath

Response

200OKobject

Success — the requested resource.

401UnauthorizedError

Missing or invalid X-Auth-Token.

404Not FoundError

The resource does not exist for this shop, or the action path is not registered.

422Unprocessable EntityError

The request failed validation.

429Too Many RequestsError

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

Authorization

ApiKeyAuthapiKey in header

Send your shop’s STOQ API key in the X-Auth-Token header on every request. Find it in the STOQ app under Settings → Integrations → API Key. The key resolves the shop context; the same scheme is used by the MCP server and the v1 API.

Integrations
curl -X GET 'https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/integrations'
const response = await fetch('https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/integrations', {
  method: 'GET',
});

const data = await response.json();
import requests

response = requests.get('https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/integrations')
data = response.json()
{}
{
  "errors": [
    "Unauthorized"
  ]
}
{
  "errors": [
    "Offer not found"
  ]
}
{
  "errors": [
    "name is required"
  ]
}
{
  "errors": [
    "Rate limit exceeded"
  ]
}

Integrations

PATCH
https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/integrations

Update integration settings on a preorder offer.

Note: Boolean toggles are set via this PATCH: pos.enabled, pos.skip_inventory_check, b2b.enabled — e.g. { pos: { enabled: false } } or { b2b: { enabled: true } }.

Body

application/json
posany
b2bany

Parameters

idstringrequiredpath

Response

200OKobject

Success — the updated resource.

202AcceptedJobAccepted

Accepted — async/bulk work was queued. Poll the returned job.

401UnauthorizedError

Missing or invalid X-Auth-Token.

404Not FoundError

The resource does not exist for this shop, or the action path is not registered.

422Unprocessable EntityError

The request failed validation.

429Too Many RequestsError

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

Authorization

ApiKeyAuthapiKey in header

Send your shop’s STOQ API key in the X-Auth-Token header on every request. Find it in the STOQ app under Settings → Integrations → API Key. The key resolves the shop context; the same scheme is used by the MCP server and the v1 API.

Integrations
curl -X PATCH 'https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/integrations' \
  -H 'Content-Type: application/json' \
  -d '{
    "pos": "string",
    "b2b": "string"
  }'
const response = await fetch('https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/integrations', {
  method: 'PATCH',
  headers: {
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
      "pos": "string",
      "b2b": "string"
    }),
});

const data = await response.json();
import requests

payload = {
  "pos": "string",
  "b2b": "string"
}

response = requests.patch('https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/integrations', json=payload)
data = response.json()
Request Body
{
  "pos": "string",
  "b2b": "string"
}
{}
{
  "job_id": "job_a1b2c3",
  "status_url": "/api/v2/external/jobs/job_a1b2c3"
}
{
  "errors": [
    "Unauthorized"
  ]
}
{
  "errors": [
    "Offer not found"
  ]
}
{
  "errors": [
    "name is required"
  ]
}
{
  "errors": [
    "Rate limit exceeded"
  ]
}

Inventory

GET
https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/inventory

Read the inventory configuration for a preorder offer.

Parameters

idstringrequiredpath

Response

200OKobject

Success — the requested resource.

401UnauthorizedError

Missing or invalid X-Auth-Token.

404Not FoundError

The resource does not exist for this shop, or the action path is not registered.

422Unprocessable EntityError

The request failed validation.

429Too Many RequestsError

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

Authorization

ApiKeyAuthapiKey in header

Send your shop’s STOQ API key in the X-Auth-Token header on every request. Find it in the STOQ app under Settings → Integrations → API Key. The key resolves the shop context; the same scheme is used by the MCP server and the v1 API.

Inventory
curl -X GET 'https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/inventory'
const response = await fetch('https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/inventory', {
  method: 'GET',
});

const data = await response.json();
import requests

response = requests.get('https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/inventory')
data = response.json()
{}
{
  "errors": [
    "Unauthorized"
  ]
}
{
  "errors": [
    "Offer not found"
  ]
}
{
  "errors": [
    "name is required"
  ]
}
{
  "errors": [
    "Rate limit exceeded"
  ]
}

Inventory

PATCH
https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/inventory

Update inventory settings on a preorder offer.

Note: Deep partial. Setting provider to 'shopify' will force product_variants_source to 'custom' via the model callback. Continue-selling is toggled via this PATCH: continue_selling.enabled and continue_selling.auto_apply_to_new_variants BOTH map to the single underlying inventory_policy_auto_enable flag — the auto-flip-on-attach intent (newly-attached variants get their Shopify inventory_policy flipped to CONTINUE). When both fields are present, auto_apply_to_new_variants wins. Neither field flips EXISTING variants — to flip variants that are already attached, use POST .../products/bulk_toggle_inventory_policy, or pass the update_inventory_policy flag to the offer lifecycle enable/disable actions.

Body

application/json
providerany
reservationany
continue_sellingany

Parameters

idstringrequiredpath

Response

200OKobject

Success — example response shown.

202AcceptedJobAccepted

Accepted — async/bulk work was queued. Poll the returned job.

401UnauthorizedError

Missing or invalid X-Auth-Token.

404Not FoundError

The resource does not exist for this shop, or the action path is not registered.

422Unprocessable EntityError

The request failed validation.

429Too Many RequestsError

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

Authorization

ApiKeyAuthapiKey in header

Send your shop’s STOQ API key in the X-Auth-Token header on every request. Find it in the STOQ app under Settings → Integrations → API Key. The key resolves the shop context; the same scheme is used by the MCP server and the v1 API.

Inventory
curl -X PATCH 'https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/inventory' \
  -H 'Content-Type: application/json' \
  -d '{
    "continue_selling": {
      "enabled": true,
      "auto_apply_to_new_variants": true
    }
  }'
const response = await fetch('https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/inventory', {
  method: 'PATCH',
  headers: {
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
      "continue_selling": {
        "enabled": true,
        "auto_apply_to_new_variants": true
      }
    }),
});

const data = await response.json();
import requests

payload = {
  "continue_selling": {
    "enabled": True,
    "auto_apply_to_new_variants": True
  }
}

response = requests.patch('https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/inventory', json=payload)
data = response.json()
Request Body
{
  "continue_selling": {
    "enabled": true,
    "auto_apply_to_new_variants": true
  }
}
{
  "provider": "stoq",
  "reservation": {
    "timing": "on_sale"
  },
  "continue_selling": {
    "enabled": true,
    "auto_apply_to_new_variants": true
  }
}
{
  "job_id": "job_a1b2c3",
  "status_url": "/api/v2/external/jobs/job_a1b2c3"
}
{
  "errors": [
    "Unauthorized"
  ]
}
{
  "errors": [
    "Offer not found"
  ]
}
{
  "errors": [
    "name is required"
  ]
}
{
  "errors": [
    "Rate limit exceeded"
  ]
}

Inventory Set Provider

POST
https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/inventory/set_provider

Set the inventory provider for a preorder offer (stoq or shopify).

Body

application/json
provideranystoqshopifyrequired

Parameters

idstringrequiredpath

Response

200OKobject

Success — the updated resource.

202AcceptedJobAccepted

Accepted — async/bulk work was queued. Poll the returned job.

401UnauthorizedError

Missing or invalid X-Auth-Token.

404Not FoundError

The resource does not exist for this shop, or the action path is not registered.

422Unprocessable EntityError

The request failed validation.

429Too Many RequestsError

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

Authorization

ApiKeyAuthapiKey in header

Send your shop’s STOQ API key in the X-Auth-Token header on every request. Find it in the STOQ app under Settings → Integrations → API Key. The key resolves the shop context; the same scheme is used by the MCP server and the v1 API.

Inventory Set Provider
curl -X POST 'https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/inventory/set_provider' \
  -H 'Content-Type: application/json' \
  -d '{
    "provider": "stoq"
  }'
const response = await fetch('https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/inventory/set_provider', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
      "provider": "stoq"
    }),
});

const data = await response.json();
import requests

payload = {
  "provider": "stoq"
}

response = requests.post('https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/inventory/set_provider', json=payload)
data = response.json()
Request Body
{
  "provider": "stoq"
}
{}
{
  "job_id": "job_a1b2c3",
  "status_url": "/api/v2/external/jobs/job_a1b2c3"
}
{
  "errors": [
    "Unauthorized"
  ]
}
{
  "errors": [
    "Offer not found"
  ]
}
{
  "errors": [
    "name is required"
  ]
}
{
  "errors": [
    "Rate limit exceeded"
  ]
}

Inventory Set Reservation Timing

POST
https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/inventory/set_reservation_timing

Set when inventory is reserved (at sale or at fulfillment).

Body

application/json
timinganyon_saleon_fulfillmentrequired

Parameters

idstringrequiredpath

Response

200OKobject

Success — the updated resource.

202AcceptedJobAccepted

Accepted — async/bulk work was queued. Poll the returned job.

401UnauthorizedError

Missing or invalid X-Auth-Token.

404Not FoundError

The resource does not exist for this shop, or the action path is not registered.

422Unprocessable EntityError

The request failed validation.

429Too Many RequestsError

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

Authorization

ApiKeyAuthapiKey in header

Send your shop’s STOQ API key in the X-Auth-Token header on every request. Find it in the STOQ app under Settings → Integrations → API Key. The key resolves the shop context; the same scheme is used by the MCP server and the v1 API.

Inventory Set Reservation Timing
curl -X POST 'https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/inventory/set_reservation_timing' \
  -H 'Content-Type: application/json' \
  -d '{
    "timing": "on_sale"
  }'
const response = await fetch('https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/inventory/set_reservation_timing', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
      "timing": "on_sale"
    }),
});

const data = await response.json();
import requests

payload = {
  "timing": "on_sale"
}

response = requests.post('https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/inventory/set_reservation_timing', json=payload)
data = response.json()
Request Body
{
  "timing": "on_sale"
}
{}
{
  "job_id": "job_a1b2c3",
  "status_url": "/api/v2/external/jobs/job_a1b2c3"
}
{
  "errors": [
    "Unauthorized"
  ]
}
{
  "errors": [
    "Offer not found"
  ]
}
{
  "errors": [
    "name is required"
  ]
}
{
  "errors": [
    "Rate limit exceeded"
  ]
}

Limits

GET
https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/limits

Read order quantity limits for a preorder offer.

Parameters

idstringrequiredpath

Response

200OKobject

Success — the requested resource.

401UnauthorizedError

Missing or invalid X-Auth-Token.

404Not FoundError

The resource does not exist for this shop, or the action path is not registered.

422Unprocessable EntityError

The request failed validation.

429Too Many RequestsError

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

Authorization

ApiKeyAuthapiKey in header

Send your shop’s STOQ API key in the X-Auth-Token header on every request. Find it in the STOQ app under Settings → Integrations → API Key. The key resolves the shop context; the same scheme is used by the MCP server and the v1 API.

Limits
curl -X GET 'https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/limits'
const response = await fetch('https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/limits', {
  method: 'GET',
});

const data = await response.json();
import requests

response = requests.get('https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/limits')
data = response.json()
{}
{
  "errors": [
    "Unauthorized"
  ]
}
{
  "errors": [
    "Offer not found"
  ]
}
{
  "errors": [
    "name is required"
  ]
}
{
  "errors": [
    "Rate limit exceeded"
  ]
}

Limits

PATCH
https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/limits

Update quantity limits on a preorder offer.

Note: Deep partial. Toggles and clears are done via this PATCH: clear a limit by sending null — per_customer.max: null removes the per-customer limit, total.max: null removes the total cap; display.show_remaining (true/false) toggles the remaining-units display on the storefront. Note: per_customer.max and total.max are stored config — storefront enforcement of these limits is follow-up work and not live yet.

Body

application/json
per_orderany
per_customerany
totalany
displayany

Parameters

idstringrequiredpath

Response

200OKobject

Success — the updated resource.

202AcceptedJobAccepted

Accepted — async/bulk work was queued. Poll the returned job.

401UnauthorizedError

Missing or invalid X-Auth-Token.

404Not FoundError

The resource does not exist for this shop, or the action path is not registered.

422Unprocessable EntityError

The request failed validation.

429Too Many RequestsError

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

Authorization

ApiKeyAuthapiKey in header

Send your shop’s STOQ API key in the X-Auth-Token header on every request. Find it in the STOQ app under Settings → Integrations → API Key. The key resolves the shop context; the same scheme is used by the MCP server and the v1 API.

Limits
curl -X PATCH 'https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/limits' \
  -H 'Content-Type: application/json' \
  -d '{
    "per_order": "string",
    "per_customer": "string",
    "total": "string",
    "display": "string"
  }'
const response = await fetch('https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/limits', {
  method: 'PATCH',
  headers: {
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
      "per_order": "string",
      "per_customer": "string",
      "total": "string",
      "display": "string"
    }),
});

const data = await response.json();
import requests

payload = {
  "per_order": "string",
  "per_customer": "string",
  "total": "string",
  "display": "string"
}

response = requests.patch('https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/limits', json=payload)
data = response.json()
Request Body
{
  "per_order": "string",
  "per_customer": "string",
  "total": "string",
  "display": "string"
}
{}
{
  "job_id": "job_a1b2c3",
  "status_url": "/api/v2/external/jobs/job_a1b2c3"
}
{
  "errors": [
    "Unauthorized"
  ]
}
{
  "errors": [
    "Offer not found"
  ]
}
{
  "errors": [
    "name is required"
  ]
}
{
  "errors": [
    "Rate limit exceeded"
  ]
}

Limits Set Max Per Customer

POST
https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/limits/set_max_per_customer

Set the maximum quantity a single customer can preorder across all their orders.

Note: Stored config only today — storefront enforcement of the per-customer limit is follow-up work and not live yet. Clear the limit via PATCH .../limits with per_customer.max: null.

Body

application/json
maxany

Parameters

idstringrequiredpath

Response

200OKobject

Success — the updated resource.

202AcceptedJobAccepted

Accepted — async/bulk work was queued. Poll the returned job.

401UnauthorizedError

Missing or invalid X-Auth-Token.

404Not FoundError

The resource does not exist for this shop, or the action path is not registered.

422Unprocessable EntityError

The request failed validation.

429Too Many RequestsError

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

Authorization

ApiKeyAuthapiKey in header

Send your shop’s STOQ API key in the X-Auth-Token header on every request. Find it in the STOQ app under Settings → Integrations → API Key. The key resolves the shop context; the same scheme is used by the MCP server and the v1 API.

Limits Set Max Per Customer
curl -X POST 'https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/limits/set_max_per_customer' \
  -H 'Content-Type: application/json' \
  -d '{
    "max": 5
  }'
const response = await fetch('https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/limits/set_max_per_customer', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
      "max": 5
    }),
});

const data = await response.json();
import requests

payload = {
  "max": 5
}

response = requests.post('https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/limits/set_max_per_customer', json=payload)
data = response.json()
Request Body
{
  "max": 5
}
{}
{
  "job_id": "job_a1b2c3",
  "status_url": "/api/v2/external/jobs/job_a1b2c3"
}
{
  "errors": [
    "Unauthorized"
  ]
}
{
  "errors": [
    "Offer not found"
  ]
}
{
  "errors": [
    "name is required"
  ]
}
{
  "errors": [
    "Rate limit exceeded"
  ]
}

Limits Set Max Per Order

POST
https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/limits/set_max_per_order

Set the maximum quantity a customer can preorder per order.

Body

application/json
maxany

Parameters

idstringrequiredpath

Response

200OKobject

Success — the updated resource.

202AcceptedJobAccepted

Accepted — async/bulk work was queued. Poll the returned job.

401UnauthorizedError

Missing or invalid X-Auth-Token.

404Not FoundError

The resource does not exist for this shop, or the action path is not registered.

422Unprocessable EntityError

The request failed validation.

429Too Many RequestsError

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

Authorization

ApiKeyAuthapiKey in header

Send your shop’s STOQ API key in the X-Auth-Token header on every request. Find it in the STOQ app under Settings → Integrations → API Key. The key resolves the shop context; the same scheme is used by the MCP server and the v1 API.

Limits Set Max Per Order
curl -X POST 'https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/limits/set_max_per_order' \
  -H 'Content-Type: application/json' \
  -d '{
    "max": 5
  }'
const response = await fetch('https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/limits/set_max_per_order', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
      "max": 5
    }),
});

const data = await response.json();
import requests

payload = {
  "max": 5
}

response = requests.post('https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/limits/set_max_per_order', json=payload)
data = response.json()
Request Body
{
  "max": 5
}
{}
{
  "job_id": "job_a1b2c3",
  "status_url": "/api/v2/external/jobs/job_a1b2c3"
}
{
  "errors": [
    "Unauthorized"
  ]
}
{
  "errors": [
    "Offer not found"
  ]
}
{
  "errors": [
    "name is required"
  ]
}
{
  "errors": [
    "Rate limit exceeded"
  ]
}

Limits Set Min Per Order

POST
https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/limits/set_min_per_order

Set the minimum quantity a customer must preorder per order.

Body

application/json
minany

Parameters

idstringrequiredpath

Response

200OKobject

Success — the updated resource.

202AcceptedJobAccepted

Accepted — async/bulk work was queued. Poll the returned job.

401UnauthorizedError

Missing or invalid X-Auth-Token.

404Not FoundError

The resource does not exist for this shop, or the action path is not registered.

422Unprocessable EntityError

The request failed validation.

429Too Many RequestsError

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

Authorization

ApiKeyAuthapiKey in header

Send your shop’s STOQ API key in the X-Auth-Token header on every request. Find it in the STOQ app under Settings → Integrations → API Key. The key resolves the shop context; the same scheme is used by the MCP server and the v1 API.

Limits Set Min Per Order
curl -X POST 'https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/limits/set_min_per_order' \
  -H 'Content-Type: application/json' \
  -d '{
    "min": "string"
  }'
const response = await fetch('https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/limits/set_min_per_order', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
      "min": "string"
    }),
});

const data = await response.json();
import requests

payload = {
  "min": "string"
}

response = requests.post('https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/limits/set_min_per_order', json=payload)
data = response.json()
Request Body
{
  "min": "string"
}
{}
{
  "job_id": "job_a1b2c3",
  "status_url": "/api/v2/external/jobs/job_a1b2c3"
}
{
  "errors": [
    "Unauthorized"
  ]
}
{
  "errors": [
    "Offer not found"
  ]
}
{
  "errors": [
    "name is required"
  ]
}
{
  "errors": [
    "Rate limit exceeded"
  ]
}

Limits Set Total Max

POST
https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/limits/set_total_max

Set the total quantity that can be preordered across all customers.

Note: Stored config only today — storefront enforcement of the total cap is follow-up work and not live yet. Clear the cap via PATCH .../limits with total.max: null.

Body

application/json
maxany

Parameters

idstringrequiredpath

Response

200OKobject

Success — the updated resource.

202AcceptedJobAccepted

Accepted — async/bulk work was queued. Poll the returned job.

401UnauthorizedError

Missing or invalid X-Auth-Token.

404Not FoundError

The resource does not exist for this shop, or the action path is not registered.

422Unprocessable EntityError

The request failed validation.

429Too Many RequestsError

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

Authorization

ApiKeyAuthapiKey in header

Send your shop’s STOQ API key in the X-Auth-Token header on every request. Find it in the STOQ app under Settings → Integrations → API Key. The key resolves the shop context; the same scheme is used by the MCP server and the v1 API.

Limits Set Total Max
curl -X POST 'https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/limits/set_total_max' \
  -H 'Content-Type: application/json' \
  -d '{
    "max": 5
  }'
const response = await fetch('https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/limits/set_total_max', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
      "max": 5
    }),
});

const data = await response.json();
import requests

payload = {
  "max": 5
}

response = requests.post('https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/limits/set_total_max', json=payload)
data = response.json()
Request Body
{
  "max": 5
}
{}
{
  "job_id": "job_a1b2c3",
  "status_url": "/api/v2/external/jobs/job_a1b2c3"
}
{
  "errors": [
    "Unauthorized"
  ]
}
{
  "errors": [
    "Offer not found"
  ]
}
{
  "errors": [
    "name is required"
  ]
}
{
  "errors": [
    "Rate limit exceeded"
  ]
}

Markets

GET
https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/markets

Read market scoping for a preorder offer.

Parameters

idstringrequiredpath

Response

200OKobject

Success — the requested resource.

401UnauthorizedError

Missing or invalid X-Auth-Token.

404Not FoundError

The resource does not exist for this shop, or the action path is not registered.

422Unprocessable EntityError

The request failed validation.

429Too Many RequestsError

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

Authorization

ApiKeyAuthapiKey in header

Send your shop’s STOQ API key in the X-Auth-Token header on every request. Find it in the STOQ app under Settings → Integrations → API Key. The key resolves the shop context; the same scheme is used by the MCP server and the v1 API.

Markets
curl -X GET 'https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/markets'
const response = await fetch('https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/markets', {
  method: 'GET',
});

const data = await response.json();
import requests

response = requests.get('https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/markets')
data = response.json()
{}
{
  "errors": [
    "Unauthorized"
  ]
}
{
  "errors": [
    "Offer not found"
  ]
}
{
  "errors": [
    "name is required"
  ]
}
{
  "errors": [
    "Rate limit exceeded"
  ]
}

Markets

PATCH
https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/markets

Update market scoping on a preorder offer.

Note: Deep partial. Scoping is toggled via this PATCH: enabled (true/false). The offer applies to ALL markets when scoping is off ({ "enabled": false }) or when scoping is on with an empty market list — the serializer compiles applies_to_all_markets from exactly that state. PATCH bodies: all markets → { "enabled": true, "market_ids": [] } (or { "enabled": true, "applies_to_all_markets": true }, which also clears the list); specific markets → { "enabled": true, "market_ids": ["gid://shopify/Market/1", ...] } (GIDs or numeric IDs). For incremental edits keep using add_market / remove_market / set_markets.

Body

application/json
enabledany
applies_to_all_marketsany
market_idsany

Parameters

idstringrequiredpath

Response

200OKobject

Success — the updated resource.

202AcceptedJobAccepted

Accepted — async/bulk work was queued. Poll the returned job.

401UnauthorizedError

Missing or invalid X-Auth-Token.

404Not FoundError

The resource does not exist for this shop, or the action path is not registered.

422Unprocessable EntityError

The request failed validation.

429Too Many RequestsError

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

Authorization

ApiKeyAuthapiKey in header

Send your shop’s STOQ API key in the X-Auth-Token header on every request. Find it in the STOQ app under Settings → Integrations → API Key. The key resolves the shop context; the same scheme is used by the MCP server and the v1 API.

Markets
curl -X PATCH 'https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/markets' \
  -H 'Content-Type: application/json' \
  -d '{
    "enabled": true,
    "applies_to_all_markets": "gid://shopify/Market/12345",
    "market_ids": [
      "gid://shopify/Market/12345"
    ]
  }'
const response = await fetch('https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/markets', {
  method: 'PATCH',
  headers: {
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
      "enabled": true,
      "applies_to_all_markets": "gid://shopify/Market/12345",
      "market_ids": [
        "gid://shopify/Market/12345"
      ]
    }),
});

const data = await response.json();
import requests

payload = {
  "enabled": True,
  "applies_to_all_markets": "gid://shopify/Market/12345",
  "market_ids": [
    "gid://shopify/Market/12345"
  ]
}

response = requests.patch('https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/markets', json=payload)
data = response.json()
Request Body
{
  "enabled": true,
  "applies_to_all_markets": "gid://shopify/Market/12345",
  "market_ids": [
    "gid://shopify/Market/12345"
  ]
}
{}
{
  "job_id": "job_a1b2c3",
  "status_url": "/api/v2/external/jobs/job_a1b2c3"
}
{
  "errors": [
    "Unauthorized"
  ]
}
{
  "errors": [
    "Offer not found"
  ]
}
{
  "errors": [
    "name is required"
  ]
}
{
  "errors": [
    "Rate limit exceeded"
  ]
}

Markets Add Market

POST
https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/markets/add_market

Add a market to the preorder offer's scope.

Body

application/json
market_idanyrequired

Parameters

idstringrequiredpath

Response

200OKobject

Success — the updated resource.

202AcceptedJobAccepted

Accepted — async/bulk work was queued. Poll the returned job.

401UnauthorizedError

Missing or invalid X-Auth-Token.

404Not FoundError

The resource does not exist for this shop, or the action path is not registered.

422Unprocessable EntityError

The request failed validation.

429Too Many RequestsError

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

Authorization

ApiKeyAuthapiKey in header

Send your shop’s STOQ API key in the X-Auth-Token header on every request. Find it in the STOQ app under Settings → Integrations → API Key. The key resolves the shop context; the same scheme is used by the MCP server and the v1 API.

Markets Add Market
curl -X POST 'https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/markets/add_market' \
  -H 'Content-Type: application/json' \
  -d '{
    "market_id": "gid://shopify/Market/12345"
  }'
const response = await fetch('https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/markets/add_market', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
      "market_id": "gid://shopify/Market/12345"
    }),
});

const data = await response.json();
import requests

payload = {
  "market_id": "gid://shopify/Market/12345"
}

response = requests.post('https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/markets/add_market', json=payload)
data = response.json()
Request Body
{
  "market_id": "gid://shopify/Market/12345"
}
{}
{
  "job_id": "job_a1b2c3",
  "status_url": "/api/v2/external/jobs/job_a1b2c3"
}
{
  "errors": [
    "Unauthorized"
  ]
}
{
  "errors": [
    "Offer not found"
  ]
}
{
  "errors": [
    "name is required"
  ]
}
{
  "errors": [
    "Rate limit exceeded"
  ]
}

Markets Remove Market

POST
https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/markets/remove_market

Remove a market from the preorder offer's scope.

Body

application/json
market_idanyrequired

Parameters

idstringrequiredpath

Response

200OKobject

Success — the updated resource.

202AcceptedJobAccepted

Accepted — async/bulk work was queued. Poll the returned job.

401UnauthorizedError

Missing or invalid X-Auth-Token.

404Not FoundError

The resource does not exist for this shop, or the action path is not registered.

422Unprocessable EntityError

The request failed validation.

429Too Many RequestsError

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

Authorization

ApiKeyAuthapiKey in header

Send your shop’s STOQ API key in the X-Auth-Token header on every request. Find it in the STOQ app under Settings → Integrations → API Key. The key resolves the shop context; the same scheme is used by the MCP server and the v1 API.

Markets Remove Market
curl -X POST 'https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/markets/remove_market' \
  -H 'Content-Type: application/json' \
  -d '{
    "market_id": "gid://shopify/Market/12345"
  }'
const response = await fetch('https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/markets/remove_market', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
      "market_id": "gid://shopify/Market/12345"
    }),
});

const data = await response.json();
import requests

payload = {
  "market_id": "gid://shopify/Market/12345"
}

response = requests.post('https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/markets/remove_market', json=payload)
data = response.json()
Request Body
{
  "market_id": "gid://shopify/Market/12345"
}
{}
{
  "job_id": "job_a1b2c3",
  "status_url": "/api/v2/external/jobs/job_a1b2c3"
}
{
  "errors": [
    "Unauthorized"
  ]
}
{
  "errors": [
    "Offer not found"
  ]
}
{
  "errors": [
    "name is required"
  ]
}
{
  "errors": [
    "Rate limit exceeded"
  ]
}

Markets Set Markets

POST
https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/markets/set_markets

Replace the set of markets a preorder offer applies to.

Body

application/json
market_idsany

Parameters

idstringrequiredpath

Response

200OKobject

Success — the updated resource.

202AcceptedJobAccepted

Accepted — async/bulk work was queued. Poll the returned job.

401UnauthorizedError

Missing or invalid X-Auth-Token.

404Not FoundError

The resource does not exist for this shop, or the action path is not registered.

422Unprocessable EntityError

The request failed validation.

429Too Many RequestsError

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

Authorization

ApiKeyAuthapiKey in header

Send your shop’s STOQ API key in the X-Auth-Token header on every request. Find it in the STOQ app under Settings → Integrations → API Key. The key resolves the shop context; the same scheme is used by the MCP server and the v1 API.

Markets Set Markets
curl -X POST 'https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/markets/set_markets' \
  -H 'Content-Type: application/json' \
  -d '{
    "market_ids": [
      "gid://shopify/Market/12345"
    ]
  }'
const response = await fetch('https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/markets/set_markets', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
      "market_ids": [
        "gid://shopify/Market/12345"
      ]
    }),
});

const data = await response.json();
import requests

payload = {
  "market_ids": [
    "gid://shopify/Market/12345"
  ]
}

response = requests.post('https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/markets/set_markets', json=payload)
data = response.json()
Request Body
{
  "market_ids": [
    "gid://shopify/Market/12345"
  ]
}
{}
{
  "job_id": "job_a1b2c3",
  "status_url": "/api/v2/external/jobs/job_a1b2c3"
}
{
  "errors": [
    "Unauthorized"
  ]
}
{
  "errors": [
    "Offer not found"
  ]
}
{
  "errors": [
    "name is required"
  ]
}
{
  "errors": [
    "Rate limit exceeded"
  ]
}

Payments

GET
https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/payments

Read the payment configuration for a preorder offer.

Parameters

idstringrequiredpath

Response

200OKobject

Success — the requested resource.

401UnauthorizedError

Missing or invalid X-Auth-Token.

404Not FoundError

The resource does not exist for this shop, or the action path is not registered.

422Unprocessable EntityError

The request failed validation.

429Too Many RequestsError

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

Authorization

ApiKeyAuthapiKey in header

Send your shop’s STOQ API key in the X-Auth-Token header on every request. Find it in the STOQ app under Settings → Integrations → API Key. The key resolves the shop context; the same scheme is used by the MCP server and the v1 API.

Payments
curl -X GET 'https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/payments'
const response = await fetch('https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/payments', {
  method: 'GET',
});

const data = await response.json();
import requests

response = requests.get('https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/payments')
data = response.json()
{}
{
  "errors": [
    "Unauthorized"
  ]
}
{
  "errors": [
    "Offer not found"
  ]
}
{
  "errors": [
    "name is required"
  ]
}
{
  "errors": [
    "Rate limit exceeded"
  ]
}

Payments

PATCH
https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/payments

Update payment settings on a preorder offer.

Note: Use SetOptionCopy / EnableOption / DisableOption to edit individual payment options. Boolean toggles are set via this PATCH: remaining_balance.auto_collect, remaining_balance.auto_collect_on_fulfillment — e.g. { remaining_balance: { auto_collect: false } }. Clear the discount via { discount: { type: "no_discount" } } (the stored value is nulled automatically).

Body

application/json
discountany
remaining_balanceany

Parameters

idstringrequiredpath

Response

200OKobject

Success — the updated resource.

202AcceptedJobAccepted

Accepted — async/bulk work was queued. Poll the returned job.

401UnauthorizedError

Missing or invalid X-Auth-Token.

404Not FoundError

The resource does not exist for this shop, or the action path is not registered.

422Unprocessable EntityError

The request failed validation.

429Too Many RequestsError

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

Authorization

ApiKeyAuthapiKey in header

Send your shop’s STOQ API key in the X-Auth-Token header on every request. Find it in the STOQ app under Settings → Integrations → API Key. The key resolves the shop context; the same scheme is used by the MCP server and the v1 API.

Payments
curl -X PATCH 'https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/payments' \
  -H 'Content-Type: application/json' \
  -d '{
    "discount": 5,
    "remaining_balance": "string"
  }'
const response = await fetch('https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/payments', {
  method: 'PATCH',
  headers: {
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
      "discount": 5,
      "remaining_balance": "string"
    }),
});

const data = await response.json();
import requests

payload = {
  "discount": 5,
  "remaining_balance": "string"
}

response = requests.patch('https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/payments', json=payload)
data = response.json()
Request Body
{
  "discount": 5,
  "remaining_balance": "string"
}
{}
{
  "job_id": "job_a1b2c3",
  "status_url": "/api/v2/external/jobs/job_a1b2c3"
}
{
  "errors": [
    "Unauthorized"
  ]
}
{
  "errors": [
    "Offer not found"
  ]
}
{
  "errors": [
    "name is required"
  ]
}
{
  "errors": [
    "Rate limit exceeded"
  ]
}

Payments Disable Option

POST
https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/payments/disable_option

Remove a payment option (full or partial) from the offer.

Note: Only valid on full_and_partial offers — an offer must keep at least one payment option. Use set_mode to switch a single-mode offer.

Body

application/json
option_typeanyfullpartialrequired

Parameters

idstringrequiredpath

Response

200OKobject

Success — the updated resource.

202AcceptedJobAccepted

Accepted — async/bulk work was queued. Poll the returned job.

401UnauthorizedError

Missing or invalid X-Auth-Token.

404Not FoundError

The resource does not exist for this shop, or the action path is not registered.

422Unprocessable EntityError

The request failed validation.

429Too Many RequestsError

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

Authorization

ApiKeyAuthapiKey in header

Send your shop’s STOQ API key in the X-Auth-Token header on every request. Find it in the STOQ app under Settings → Integrations → API Key. The key resolves the shop context; the same scheme is used by the MCP server and the v1 API.

Payments Disable Option
curl -X POST 'https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/payments/disable_option' \
  -H 'Content-Type: application/json' \
  -d '{
    "option_type": "full"
  }'
const response = await fetch('https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/payments/disable_option', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
      "option_type": "full"
    }),
});

const data = await response.json();
import requests

payload = {
  "option_type": "full"
}

response = requests.post('https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/payments/disable_option', json=payload)
data = response.json()
Request Body
{
  "option_type": "full"
}
{}
{
  "job_id": "job_a1b2c3",
  "status_url": "/api/v2/external/jobs/job_a1b2c3"
}
{
  "errors": [
    "Unauthorized"
  ]
}
{
  "errors": [
    "Offer not found"
  ]
}
{
  "errors": [
    "name is required"
  ]
}
{
  "errors": [
    "Rate limit exceeded"
  ]
}

Payments Enable Option

POST
https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/payments/enable_option

Add a payment option (full or partial) to the offer.

Note: Idempotent. Newly added options start from the dashboard defaults — use set_deposit_percent / set_option_copy to fine-tune. Disable with disable_option.

Body

application/json
option_typeanyfullpartialrequired

Parameters

idstringrequiredpath

Response

200OKobject

Success — the updated resource.

202AcceptedJobAccepted

Accepted — async/bulk work was queued. Poll the returned job.

401UnauthorizedError

Missing or invalid X-Auth-Token.

404Not FoundError

The resource does not exist for this shop, or the action path is not registered.

422Unprocessable EntityError

The request failed validation.

429Too Many RequestsError

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

Authorization

ApiKeyAuthapiKey in header

Send your shop’s STOQ API key in the X-Auth-Token header on every request. Find it in the STOQ app under Settings → Integrations → API Key. The key resolves the shop context; the same scheme is used by the MCP server and the v1 API.

Payments Enable Option
curl -X POST 'https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/payments/enable_option' \
  -H 'Content-Type: application/json' \
  -d '{
    "option_type": "full"
  }'
const response = await fetch('https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/payments/enable_option', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
      "option_type": "full"
    }),
});

const data = await response.json();
import requests

payload = {
  "option_type": "full"
}

response = requests.post('https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/payments/enable_option', json=payload)
data = response.json()
Request Body
{
  "option_type": "full"
}
{}
{
  "job_id": "job_a1b2c3",
  "status_url": "/api/v2/external/jobs/job_a1b2c3"
}
{
  "errors": [
    "Unauthorized"
  ]
}
{
  "errors": [
    "Offer not found"
  ]
}
{
  "errors": [
    "name is required"
  ]
}
{
  "errors": [
    "Rate limit exceeded"
  ]
}

Payments Set Deposit Percent

POST
https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/payments/set_deposit_percent

Set the deposit percentage charged at checkout on the partial payment option.

Note: Requires a partial payment option (mode partial or full_and_partial) — use set_mode first. Percent must be between 1 and 99; 100% upfront is the full payment mode.

Body

application/json
percentinteger[1, 99]required

Parameters

idstringrequiredpath

Response

200OKobject

Success — the updated resource.

202AcceptedJobAccepted

Accepted — async/bulk work was queued. Poll the returned job.

401UnauthorizedError

Missing or invalid X-Auth-Token.

404Not FoundError

The resource does not exist for this shop, or the action path is not registered.

422Unprocessable EntityError

The request failed validation.

429Too Many RequestsError

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

Authorization

ApiKeyAuthapiKey in header

Send your shop’s STOQ API key in the X-Auth-Token header on every request. Find it in the STOQ app under Settings → Integrations → API Key. The key resolves the shop context; the same scheme is used by the MCP server and the v1 API.