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.

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

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

payload = {
  "percent": 25
}

response = requests.post('https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/payments/set_deposit_percent', json=payload)
data = response.json()
Request Body
{
  "percent": 25
}
{}
{
  "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 Discount

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

Set the preorder discount.

Body

application/json
typeanypercentagepricefixed_amountno_discountrequired
valueany

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 Set Discount
curl -X POST 'https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/payments/set_discount' \
  -H 'Content-Type: application/json' \
  -d '{
    "type": "percentage",
    "value": "string"
  }'
const response = await fetch('https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/payments/set_discount', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
      "type": "percentage",
      "value": "string"
    }),
});

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

payload = {
  "type": "percentage",
  "value": "string"
}

response = requests.post('https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/payments/set_discount', json=payload)
data = response.json()
Request Body
{
  "type": "percentage",
  "value": "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 Set Discount Text

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

Set the discount blurb shown on the offer's payment options.

Note: Pass option_type (full | partial) to target one payment option; omit it to apply the text to every option. Supports the {{ discount }} placeholder.

Body

application/json
textanyrequired
option_typeanyfullpartial

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 Set Discount Text
curl -X POST 'https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/payments/set_discount_text' \
  -H 'Content-Type: application/json' \
  -d '{
    "text": "Preorder now",
    "option_type": "full"
  }'
const response = await fetch('https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/payments/set_discount_text', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
      "text": "Preorder now",
      "option_type": "full"
    }),
});

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

payload = {
  "text": "Preorder now",
  "option_type": "full"
}

response = requests.post('https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/payments/set_discount_text', json=payload)
data = response.json()
Request Body
{
  "text": "Preorder now",
  "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 Mode

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

Switch the offer between full, partial, and full-and-partial payment modes.

Note: Idempotent. Collapsing from full_and_partial keeps the surviving option's copy; newly enabled modes start from the dashboard defaults. Use set_deposit_percent and set_option_copy afterwards to fine-tune.

Body

application/json
modeanyfullpartialfull_and_partialrequired

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 Set Mode
curl -X POST 'https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/payments/set_mode' \
  -H 'Content-Type: application/json' \
  -d '{
    "mode": "full"
  }'
const response = await fetch('https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/payments/set_mode', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
      "mode": "full"
    }),
});

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

payload = {
  "mode": "full"
}

response = requests.post('https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/payments/set_mode', json=payload)
data = response.json()
Request Body
{
  "mode": "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 Option Copy

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

Set the merchant-facing copy on a payment option (title, description, discount text).

Body

application/json
option_typeanyfullpartialrequired
billing_titleany
billing_descriptionany
discount_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.

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

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

payload = {
  "option_type": "full",
  "billing_title": "string",
  "billing_description": "string",
  "discount_text": "Preorder now"
}

response = requests.post('https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/payments/set_option_copy', json=payload)
data = response.json()
Request Body
{
  "option_type": "full",
  "billing_title": "string",
  "billing_description": "string",
  "discount_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"
  ]
}

Products

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

Read the products configuration for a preorder offer (source rule + variant summary).

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.

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

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

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

Products

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

Update the product selection on a preorder offer — set the source rule plus its matching sub-block.

Note: Delegates to the set_source_to_* actions; switching source resets the variant set. source 'all' requires confirm: true. Only the sub-block matching source may be provided.

Body

application/json
sourceanyallcollectioncustomrequired
customobject | null
collectionobject | null
allobject | null
confirmany

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.

Products
curl -X PATCH 'https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/products' \
  -H 'Content-Type: application/json' \
  -d '{
    "source": "all",
    "custom": "string",
    "collection": "string",
    "all": "string",
    "confirm": "string"
  }'
const response = await fetch('https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/products', {
  method: 'PATCH',
  headers: {
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
      "source": "all",
      "custom": "string",
      "collection": "string",
      "all": "string",
      "confirm": "string"
    }),
});

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

payload = {
  "source": "all",
  "custom": "string",
  "collection": "string",
  "all": "string",
  "confirm": "string"
}

response = requests.patch('https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/products', json=payload)
data = response.json()
Request Body
{
  "source": "all",
  "custom": "string",
  "collection": "string",
  "all": "string",
  "confirm": "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"
  ]
}

Products Add Variants

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

Attach variants to a custom-source preorder offer.

Note: Custom source only. Runs through BulkVariantAdditionService (async).

Body

application/json
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.

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 Add Variants
curl -X POST 'https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/products/add_variants' \
  -H 'Content-Type: application/json' \
  -d '{
    "variant_ids": [
      47284734423096,
      47284734455864,
      47284734488632
    ]
  }'
const response = await fetch('https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/products/add_variants', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
      "variant_ids": [
        47284734423096,
        47284734455864,
        47284734488632
      ]
    }),
});

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

payload = {
  "variant_ids": [
    47284734423096,
    47284734455864,
    47284734488632
  ]
}

response = requests.post('https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/products/add_variants', json=payload)
data = response.json()
Request Body
{
  "variant_ids": [
    47284734423096,
    47284734455864,
    47284734488632
  ]
}
{
  "source": "custom",
  "variants": {
    "count": 6,
    "url": "/api/v2/external/preorders/offers/1/products/variants"
  },
  "custom": {
    "variant_ids_sample": [
      47284734423096,
      47284734455864,
      47284734488632,
      47284734521400,
      47284734554168,
      47284734586936
    ]
  }
}
{
  "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"
  ]
}

Products Bulk Toggle Inventory Policy

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

Flip the Shopify inventory policy on variants attached to a preorder offer (CONTINUE or DENY).

Note: Async via SellingPlans::BulkInventoryPolicyUpdateJob. Omit variant_ids to apply to all attached variants.

Body

application/json
policyanyCONTINUEDENYrequired
variant_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.

Products Bulk Toggle Inventory Policy
curl -X POST 'https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/products/bulk_toggle_inventory_policy' \
  -H 'Content-Type: application/json' \
  -d '{
    "policy": "CONTINUE",
    "variant_ids": [
      "45000000001"
    ]
  }'
const response = await fetch('https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/products/bulk_toggle_inventory_policy', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
      "policy": "CONTINUE",
      "variant_ids": [
        "45000000001"
      ]
    }),
});

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

payload = {
  "policy": "CONTINUE",
  "variant_ids": [
    "45000000001"
  ]
}

response = requests.post('https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/products/bulk_toggle_inventory_policy', json=payload)
data = response.json()
Request Body
{
  "policy": "CONTINUE",
  "variant_ids": [
    "45000000001"
  ]
}
{}
{
  "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"
  ]
}

Products Remove Variants

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

Remove variants from a custom-source preorder offer.

Note: Custom source only. Resets per-variant metafields on Shopify.

Body

application/json
variant_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.

Products Remove Variants
curl -X POST 'https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/products/remove_variants' \
  -H 'Content-Type: application/json' \
  -d '{
    "variant_ids": [
      "45000000001"
    ]
  }'
const response = await fetch('https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/products/remove_variants', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
      "variant_ids": [
        "45000000001"
      ]
    }),
});

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

payload = {
  "variant_ids": [
    "45000000001"
  ]
}

response = requests.post('https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/products/remove_variants', json=payload)
data = response.json()
Request Body
{
  "variant_ids": [
    "45000000001"
  ]
}
{}
{
  "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"
  ]
}

Products Set Collection

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

Change the collection driving a collection-sourced preorder offer.

Note: Collection-sourced offers only — returns 409 Conflict otherwise. Use set_source_to_collection to switch a non-collection offer to collection source.

Body

application/json
collection_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.

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

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

payload = {
  "collection_id": "string"
}

response = requests.post('https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/products/set_collection', json=payload)
data = response.json()
Request Body
{
  "collection_id": "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"
  ]
}

Products Set Excluded Variants

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

Replace the explicit excluded-variant list for an all-source preorder offer.

Note: All-source offers only.

Body

application/json
variant_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.

Products Set Excluded Variants
curl -X POST 'https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/products/set_excluded_variants' \
  -H 'Content-Type: application/json' \
  -d '{
    "variant_ids": [
      "45000000001"
    ]
  }'
const response = await fetch('https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/products/set_excluded_variants', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
      "variant_ids": [
        "45000000001"
      ]
    }),
});

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

payload = {
  "variant_ids": [
    "45000000001"
  ]
}

response = requests.post('https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/products/set_excluded_variants', json=payload)
data = response.json()
Request Body
{
  "variant_ids": [
    "45000000001"
  ]
}
{}
{
  "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"
  ]
}

Products Set Exclusion Tag

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

Set the exclusion tag for an all-source preorder offer (variants with this tag are excluded).

Note: All-source offers only.

Body

application/json
tagany

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.

Products Set Exclusion Tag
curl -X POST 'https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/products/set_exclusion_tag' \
  -H 'Content-Type: application/json' \
  -d '{
    "tag": "string"
  }'
const response = await fetch('https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/products/set_exclusion_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}/products/set_exclusion_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"
  ]
}

Products Set Source To All

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

Switch the offer to apply to every variant in the shop, minus exclusions. Requires confirm: true.

Note: Requires confirm: true in the body. Resolution runs async over the entire catalog.

Body

application/json
confirmany
exclusion_tagany
excluded_variant_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.

Products Set Source To All
curl -X POST 'https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/products/set_source_to_all' \
  -H 'Content-Type: application/json' \
  -d '{
    "confirm": "string",
    "exclusion_tag": "string",
    "excluded_variant_ids": [
      "string"
    ]
  }'
const response = await fetch('https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/products/set_source_to_all', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
      "confirm": "string",
      "exclusion_tag": "string",
      "excluded_variant_ids": [
        "string"
      ]
    }),
});

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

payload = {
  "confirm": "string",
  "exclusion_tag": "string",
  "excluded_variant_ids": [
    "string"
  ]
}

response = requests.post('https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/products/set_source_to_all', json=payload)
data = response.json()
Request Body
{
  "confirm": "string",
  "exclusion_tag": "string",
  "excluded_variant_ids": [
    "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"
  ]
}

Products Set Source To Collection

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

Switch the offer to a collection-driven variant source.

Note: Resolution runs asynchronously. New variants added to the collection in Shopify are NOT auto-picked-up — call this action again to refresh.

Body

application/json
collection_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.

Products Set Source To Collection
curl -X POST 'https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/products/set_source_to_collection' \
  -H 'Content-Type: application/json' \
  -d '{
    "collection_id": "string"
  }'
const response = await fetch('https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/products/set_source_to_collection', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
      "collection_id": "string"
    }),
});

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

payload = {
  "collection_id": "string"
}

response = requests.post('https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/products/set_source_to_collection', json=payload)
data = response.json()
Request Body
{
  "collection_id": "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"
  ]
}

Products Set Source To Custom

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

Switch the offer to a custom variant list. Optionally seed it with variant IDs.

Note: Variant attachment runs through BulkVariantAdditionService and is async (202 + job_id).

Body

application/json
variant_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.

Products Set Source To Custom
curl -X POST 'https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/products/set_source_to_custom' \
  -H 'Content-Type: application/json' \
  -d '{
    "variant_ids": [
      "45000000001"
    ]
  }'
const response = await fetch('https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/products/set_source_to_custom', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
      "variant_ids": [
        "45000000001"
      ]
    }),
});

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

payload = {
  "variant_ids": [
    "45000000001"
  ]
}

response = requests.post('https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/products/set_source_to_custom', json=payload)
data = response.json()
Request Body
{
  "variant_ids": [
    "45000000001"
  ]
}
{}
{
  "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"
  ]
}

Products Variants

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

List the variants attached to a preorder offer with their per-variant settings, paginated.

Parameters

idstringrequiredpath
pageanyquery
per_pageanyquery

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.

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

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

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

Products Variants

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

Read the per-offer settings of a single variant attached to a preorder offer.

Parameters

idstringrequiredpath
variant_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.

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

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

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

Products Variants

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

Set per-offer overrides on an attached variant — shipping text, max preorder count, market-scoped overrides.

Note: null clears an override; the variant falls back to the offer-level value. market_overrides writes the per-market metafields (market_shipping_text, market_preorder_max_count) keyed by Shopify market GID.

Body

application/json
shipping_textstring | null
max_countinteger | null
market_overridesobject | null

Parameters

idstringrequiredpath
variant_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.

Products Variants
curl -X PATCH 'https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/products/variants/{variant_id}' \
  -H 'Content-Type: application/json' \
  -d '{
    "shipping_text": "Preorder now",
    "max_count": 5,
    "market_overrides": "gid://shopify/Market/12345"
  }'
const response = await fetch('https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/products/variants/{variant_id}', {
  method: 'PATCH',
  headers: {
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
      "shipping_text": "Preorder now",
      "max_count": 5,
      "market_overrides": "gid://shopify/Market/12345"
    }),
});

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

payload = {
  "shipping_text": "Preorder now",
  "max_count": 5,
  "market_overrides": "gid://shopify/Market/12345"
}

response = requests.patch('https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/products/variants/{variant_id}', json=payload)
data = response.json()
Request Body
{
  "shipping_text": "Preorder now",
  "max_count": 5,
  "market_overrides": "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"
  ]
}

Restore

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

Restore a discarded preorder offer.

Note: Variant attachments and metafields are not auto-restored. Re-attach via the products capability.

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.

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

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

response = requests.post('https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/restore')
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"
  ]
}

Schedule

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

Set the schedule window for a preorder offer.

Note: Does not auto-enable. Storefront reads the schedule live.

Body

application/json
startany
endany

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.

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

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

payload = {
  "start": "2026-07-01T00:00:00Z",
  "end": "2026-07-01T00:00:00Z"
}

response = requests.post('https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/schedule', json=payload)
data = response.json()
Request Body
{
  "start": "2026-07-01T00:00:00Z",
  "end": "2026-07-01T00:00:00Z"
}
{}
{
  "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"
  ]
}

Shipping

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

Read shipping 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.

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

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

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

Shipping

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

Update shipping settings on a preorder offer.

Note: Deep partial. Prefer the intent-bearing actions (set_delivery_*, set_shipping_text, set_split_order_tag, set_split_transaction_gateway) for narrow edits. Toggles are done via this PATCH: fulfillment.hold (true/false) holds/releases fulfillment orders containing preorder items; display.show_shipping_timeline (true shows the detailed PDP timeline, false the simplified text); fulfillment.split.enabled (true/false) turns order splitting on/off (flips both split flags); fulfillment.split.hold_fulfillments (true/false) holds the split order's fulfillments; fulfillment.split.sequential_number (true/false) gives split orders a sequential order name.

Body

application/json
deliveryany
displayany
fulfillmentany

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.

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

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

payload = {
  "delivery": "string",
  "display": "string",
  "fulfillment": "string"
}

response = requests.patch('https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/shipping', json=payload)
data = response.json()
Request Body
{
  "delivery": "string",
  "display": "string",
  "fulfillment": "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"
  ]
}

Shipping Set Delivery Asap

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

Set delivery to 'as soon as possible' (no specific date or window).

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.

Shipping Set Delivery Asap
curl -X POST 'https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/shipping/set_delivery_asap'
const response = await fetch('https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/shipping/set_delivery_asap', {
  method: 'POST',
});

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

response = requests.post('https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/shipping/set_delivery_asap')
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"
  ]
}

Shipping Set Delivery Date

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

Set an exact delivery date for the preorder.

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.

Shipping Set Delivery Date
curl -X POST 'https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/shipping/set_delivery_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}/shipping/set_delivery_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}/shipping/set_delivery_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"
  ]
}

Shipping Set Delivery Window

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

Set a delivery window in days from checkout (e.g. 'ships within 14 days').

Body

application/json
daysany

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.

Shipping Set Delivery Window
curl -X POST 'https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/shipping/set_delivery_window' \
  -H 'Content-Type: application/json' \
  -d '{
    "days": "string"
  }'
const response = await fetch('https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/shipping/set_delivery_window', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
      "days": "string"
    }),
});

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

payload = {
  "days": "string"
}

response = requests.post('https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/shipping/set_delivery_window', json=payload)
data = response.json()
Request Body
{
  "days": "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"
  ]
}

Shipping Set Shipping Text

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

Set the customer-facing shipping text shown on the PDP.

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.

Shipping Set Shipping Text
curl -X POST 'https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/shipping/set_shipping_text' \
  -H 'Content-Type: application/json' \
  -d '{
    "text": "Preorder now"
  }'
const response = await fetch('https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/shipping/set_shipping_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}/shipping/set_shipping_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"
  ]
}

Shipping Set Split Order Tag

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

Set the tag applied to split orders on Shopify.

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.

Shipping Set Split Order Tag
curl -X POST 'https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/shipping/set_split_order_tag' \
  -H 'Content-Type: application/json' \
  -d '{
    "tag": "string"
  }'
const response = await fetch('https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/shipping/set_split_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}/shipping/set_split_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"
  ]
}

Shipping Set Split Transaction Gateway

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

Set the payment gateway used for the split order transaction (e.g. 'Prepaid').

Body

application/json
gatewayanyrequired

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.

Shipping Set Split Transaction Gateway
curl -X POST 'https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/shipping/set_split_transaction_gateway' \
  -H 'Content-Type: application/json' \
  -d '{
    "gateway": "string"
  }'
const response = await fetch('https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/shipping/set_split_transaction_gateway', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
      "gateway": "string"
    }),
});

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

payload = {
  "gateway": "string"
}

response = requests.post('https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/shipping/set_split_transaction_gateway', json=payload)
data = response.json()
Request Body
{
  "gateway": "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"
  ]
}

Translations

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

Read every translation override on a preorder offer, plus the full enumeration of translatable field paths.

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.

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

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

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

Translations Clear Locale

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

Remove all translation overrides for one locale on a preorder offer.

Body

application/json
localeanyrequired

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.

Translations Clear Locale
curl -X POST 'https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/translations/clear_locale' \
  -H 'Content-Type: application/json' \
  -d '{
    "locale": "fr"
  }'
const response = await fetch('https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/translations/clear_locale', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
      "locale": "fr"
    }),
});

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

payload = {
  "locale": "fr"
}

response = requests.post('https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/translations/clear_locale', json=payload)
data = response.json()
Request Body
{
  "locale": "fr"
}
{}
{
  "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"
  ]
}

Translations Set

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

Set a single translation override (one locale, one field) on a preorder offer.

Body

application/json
localeanyrequired
fieldanyrequired
valueany

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.

Translations Set
curl -X POST 'https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/translations/set' \
  -H 'Content-Type: application/json' \
  -d '{
    "locale": "fr",
    "field": "string",
    "value": "string"
  }'
const response = await fetch('https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/translations/set', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
      "locale": "fr",
      "field": "string",
      "value": "string"
    }),
});

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

payload = {
  "locale": "fr",
  "field": "string",
  "value": "string"
}

response = requests.post('https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/translations/set', json=payload)
data = response.json()
Request Body
{
  "locale": "fr",
  "field": "string",
  "value": "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"
  ]
}

Translations Set Many

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

Set many translation overrides for one locale on a preorder offer, atomically.

Note: All-or-nothing. Pre-validates every field path before writing.

Body

application/json
localeanyrequired
translationsanyrequired

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.

Translations Set Many
curl -X POST 'https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/translations/set_many' \
  -H 'Content-Type: application/json' \
  -d '{
    "locale": "fr",
    "translations": "string"
  }'
const response = await fetch('https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/translations/set_many', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
      "locale": "fr",
      "translations": "string"
    }),
});

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

payload = {
  "locale": "fr",
  "translations": "string"
}

response = requests.post('https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/translations/set_many', json=payload)
data = response.json()
Request Body
{
  "locale": "fr",
  "translations": "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"
  ]
}

Translations Unset

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

Remove a translation override (one locale, one field) from a preorder offer.

Body

application/json
localeanyrequired
fieldanyrequired

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.

Translations Unset
curl -X POST 'https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/translations/unset' \
  -H 'Content-Type: application/json' \
  -d '{
    "locale": "fr",
    "field": "string"
  }'
const response = await fetch('https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/translations/unset', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
      "locale": "fr",
      "field": "string"
    }),
});

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

payload = {
  "locale": "fr",
  "field": "string"
}

response = requests.post('https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/translations/unset', json=payload)
data = response.json()
Request Body
{
  "locale": "fr",
  "field": "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"
  ]
}

Unschedule

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

Clear the schedule window on a preorder offer.

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.

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

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

response = requests.post('https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/unschedule')
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"
  ]
}

Widget

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

Read the widget 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.

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

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

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

Widget

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

Update any subset of the widget configuration on a preorder offer.

Note: Deep partial. Use the intent-bearing widget actions for narrow edits. Boolean toggles are set via this PATCH: badge.enabled, disclaimer.enabled, button.colors.enabled, billing_widget.enabled — e.g. { badge: { enabled: false } }. Clearing a value: send null.

Body

application/json
buttonany
disclaimerany
badgeany
billing_widgetany

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.

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

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

payload = {
  "button": "string",
  "disclaimer": "string",
  "badge": "string",
  "billing_widget": "string"
}

response = requests.patch('https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/widget', json=payload)
data = response.json()
Request Body
{
  "button": "string",
  "disclaimer": "string",
  "badge": "string",
  "billing_widget": "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"
  ]
}

Widget Set Badge Colors

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

Set the preorder badge's text and background colors.

Body

application/json
text_colorany
background_colorany

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.

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

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

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

response = requests.post('https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/widget/set_badge_colors', json=payload)
data = response.json()
Request Body
{
  "text_color": "#1A1A1A",
  "background_color": "#1A1A1A"
}
{}
{
  "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"
  ]
}

Widget Set Badge Text

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

Set the preorder badge text.

Note: Use enable_badge / disable_badge to control visibility.

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.

Widget Set Badge Text
curl -X POST 'https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/widget/set_badge_text' \
  -H 'Content-Type: application/json' \
  -d '{
    "text": "Preorder now"
  }'
const response = await fetch('https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/widget/set_badge_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}/widget/set_badge_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"
  ]
}

Widget Set Billing Widget Text

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

Set the billing widget's title and description (the PDP payment-breakdown block).

Note: These fields are shared with the first payment option's copy (see payments/set_option_copy). Use enable_billing_widget / disable_billing_widget to control visibility.

Body

application/json
titleany
descriptionany

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.

Widget Set Billing Widget Text
curl -X POST 'https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/widget/set_billing_widget_text' \
  -H 'Content-Type: application/json' \
  -d '{
    "title": "string",
    "description": "string"
  }'
const response = await fetch('https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/widget/set_billing_widget_text', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
      "title": "string",
      "description": "string"
    }),
});

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

payload = {
  "title": "string",
  "description": "string"
}

response = requests.post('https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/widget/set_billing_widget_text', json=payload)
data = response.json()
Request Body
{
  "title": "string",
  "description": "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"
  ]
}

Widget Set Button Colors

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

Set the preorder button's text and background colors (implicitly enables custom colors).

Note: Setting either color implicitly enables custom colors. Use disable_button_colors to revert to the theme's defaults.

Body

application/json
text_colorany
background_colorany

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.

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

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

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

response = requests.post('https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/widget/set_button_colors', json=payload)
data = response.json()
Request Body
{
  "text_color": "#1A1A1A",
  "background_color": "#1A1A1A"
}
{}
{
  "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"
  ]
}

Widget Set Button Text

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

Set the preorder button's call-to-action label.

Body

application/json
textanyrequired

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.

Widget Set Button Text
curl -X POST 'https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/widget/set_button_text' \
  -H 'Content-Type: application/json' \
  -d '{
    "text": "Reserve Now"
  }'
const response = await fetch('https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/widget/set_button_text', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
      "text": "Reserve Now"
    }),
});

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

payload = {
  "text": "Reserve Now"
}

response = requests.post('https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/widget/set_button_text', json=payload)
data = response.json()
Request Body
{
  "text": "Reserve Now"
}
{
  "button": {
    "text": "Reserve Now",
    "colors": {
      "enabled": true,
      "text_color": "#FFFFFF",
      "background_color": "#1a1a1a"
    }
  },
  "disclaimer": {
    "enabled": true,
    "text": "Expected to ship by August 2026"
  },
  "badge": {
    "enabled": true,
    "text": "Pre-Order"
  }
}
{
  "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"
  ]
}

Widget Set Disclaimer Style

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

Set the disclaimer banner's colors and border radius.

Body

application/json
text_colorany
background_colorany
border_radiusinteger>= 0

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.

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

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

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

response = requests.post('https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/widget/set_disclaimer_style', json=payload)
data = response.json()
Request Body
{
  "text_color": "#1A1A1A",
  "background_color": "#1A1A1A",
  "border_radius": 0
}
{}
{
  "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"
  ]
}

Widget Set Disclaimer Text

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

Set the disclaimer banner text shown under the preorder button.

Note: Use enable_disclaimer / disable_disclaimer to control visibility.

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.

Widget Set Disclaimer Text
curl -X POST 'https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/widget/set_disclaimer_text' \
  -H 'Content-Type: application/json' \
  -d '{
    "text": "Preorder now"
  }'
const response = await fetch('https://app.stoqapp.com/api/v2/external/preorders/offers/{id}/widget/set_disclaimer_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}/widget/set_disclaimer_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"
  ]
}

Preorders · Orders

List

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

List preorder orders in this shop, paginated.

Parameters

pageanyquery
per_pageanyquery
stateanyquery
offer_idanyquery
variant_idanyquery
customer_idanyquery
fromanyquery
toanyquery

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/preorders/orders'
const response = await fetch('https://app.stoqapp.com/api/v2/external/preorders/orders', {
  method: 'GET',
});

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

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

Read

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

Read a preorder order'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/preorders/orders/{id}'
const response = await fetch('https://app.stoqapp.com/api/v2/external/preorders/orders/{id}', {
  method: 'GET',
});

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

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

Cancel

POST
https://app.stoqapp.com/api/v2/external/preorders/orders/{id}/cancel

Cancel a preorder. Optionally refund deposit / balance and notify the customer.

Note: Does not cancel the Shopify order; sets cancelled_at on the preorder attribution. Use the refund flags for refunds.

Body

application/json
refund_depositany
refund_balanceany
notify_customerany
reasonany

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.

Cancel
curl -X POST 'https://app.stoqapp.com/api/v2/external/preorders/orders/{id}/cancel' \
  -H 'Content-Type: application/json' \
  -d '{
    "refund_deposit": "string",
    "refund_balance": "string",
    "notify_customer": "string",
    "reason": "string"
  }'
const response = await fetch('https://app.stoqapp.com/api/v2/external/preorders/orders/{id}/cancel', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
      "refund_deposit": "string",
      "refund_balance": "string",
      "notify_customer": "string",
      "reason": "string"
    }),
});

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

payload = {
  "refund_deposit": "string",
  "refund_balance": "string",
  "notify_customer": "string",
  "reason": "string"
}

response = requests.post('https://app.stoqapp.com/api/v2/external/preorders/orders/{id}/cancel', json=payload)
data = response.json()
Request Body
{
  "refund_deposit": "string",
  "refund_balance": "string",
  "notify_customer": "string",
  "reason": "string"
}
{}
{
  "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"
  ]
}

Fulfillment

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

Read the fulfillment hold state and fulfillment-order summary of a preorder order.

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.

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

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

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

Fulfillment

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

Update fulfillment attributes on a preorder order. Only hold_reason_note is writable.

Note: Hold state changes go through release_holds / apply_holds. all_held, any_held, and fulfillment_orders are read-only. Delegates to SetHoldReason; existing holds on Shopify aren't re-written.

Body

application/json
hold_reason_notestring | null

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.

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

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

payload = {
  "hold_reason_note": "string"
}

response = requests.patch('https://app.stoqapp.com/api/v2/external/preorders/orders/{id}/fulfillment', json=payload)
data = response.json()
Request Body
{
  "hold_reason_note": "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"
  ]
}

Fulfillment Apply Holds

POST
https://app.stoqapp.com/api/v2/external/preorders/orders/{id}/fulfillment/apply_holds

Apply fulfillment holds on the order's fulfillment orders. Idempotent.

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.

Fulfillment Apply Holds
curl -X POST 'https://app.stoqapp.com/api/v2/external/preorders/orders/{id}/fulfillment/apply_holds'
const response = await fetch('https://app.stoqapp.com/api/v2/external/preorders/orders/{id}/fulfillment/apply_holds', {
  method: 'POST',
});

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

response = requests.post('https://app.stoqapp.com/api/v2/external/preorders/orders/{id}/fulfillment/apply_holds')
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"
  ]
}

Fulfillment Release Holds

POST
https://app.stoqapp.com/api/v2/external/preorders/orders/{id}/fulfillment/release_holds

Release fulfillment holds on the order without applying offer-configured tags.

Note: Use the top-level release action when you want tags applied too.

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.

Fulfillment Release Holds
curl -X POST 'https://app.stoqapp.com/api/v2/external/preorders/orders/{id}/fulfillment/release_holds'
const response = await fetch('https://app.stoqapp.com/api/v2/external/preorders/orders/{id}/fulfillment/release_holds', {
  method: 'POST',
});

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

response = requests.post('https://app.stoqapp.com/api/v2/external/preorders/orders/{id}/fulfillment/release_holds')
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"
  ]
}

Fulfillment Set Hold Reason

POST
https://app.stoqapp.com/api/v2/external/preorders/orders/{id}/fulfillment/set_hold_reason

Set the hold-reason note that will be used the next time the order is held.

Note: Updates the note on the first attributed preorder offer. Existing holds on Shopify aren't re-written.

Body

application/json
reason_noteanyrequired

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.

Fulfillment Set Hold Reason
curl -X POST 'https://app.stoqapp.com/api/v2/external/preorders/orders/{id}/fulfillment/set_hold_reason' \
  -H 'Content-Type: application/json' \
  -d '{
    "reason_note": "string"
  }'
const response = await fetch('https://app.stoqapp.com/api/v2/external/preorders/orders/{id}/fulfillment/set_hold_reason', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
      "reason_note": "string"
    }),
});

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

payload = {
  "reason_note": "string"
}

response = requests.post('https://app.stoqapp.com/api/v2/external/preorders/orders/{id}/fulfillment/set_hold_reason', json=payload)
data = response.json()
Request Body
{
  "reason_note": "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"
  ]
}

Hold Fulfillments

POST
https://app.stoqapp.com/api/v2/external/preorders/orders/{id}/hold_fulfillments

Apply fulfillment holds on the preorder order's fulfillment orders.

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.

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

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

response = requests.post('https://app.stoqapp.com/api/v2/external/preorders/orders/{id}/hold_fulfillments')
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"
  ]
}

Payments

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

Read the deposit, remaining balance, and refund state of a preorder order.

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/orders/{id}/payments'
const response = await fetch('https://app.stoqapp.com/api/v2/external/preorders/orders/{id}/payments', {
  method: 'GET',
});

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

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

Payments Charge Balance

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

Charge the remaining balance. auto uses the customer's saved payment method; manual just marks balance collected.

Note: auto may fail if no saved payment method or declined; check the response or poll status.

Body

application/json
modeany

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 Charge Balance
curl -X POST 'https://app.stoqapp.com/api/v2/external/preorders/orders/{id}/payments/charge_balance' \
  -H 'Content-Type: application/json' \
  -d '{
    "mode": "string"
  }'
const response = await fetch('https://app.stoqapp.com/api/v2/external/preorders/orders/{id}/payments/charge_balance', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
      "mode": "string"
    }),
});

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

payload = {
  "mode": "string"
}

response = requests.post('https://app.stoqapp.com/api/v2/external/preorders/orders/{id}/payments/charge_balance', json=payload)
data = response.json()
Request Body
{
  "mode": "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 Refund

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

Refund the entire preorder (deposit + balance).

Body

application/json
notify_customerany
noteany

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 Refund
curl -X POST 'https://app.stoqapp.com/api/v2/external/preorders/orders/{id}/payments/refund' \
  -H 'Content-Type: application/json' \
  -d '{
    "notify_customer": "string",
    "note": "string"
  }'
const response = await fetch('https://app.stoqapp.com/api/v2/external/preorders/orders/{id}/payments/refund', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
      "notify_customer": "string",
      "note": "string"
    }),
});

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

payload = {
  "notify_customer": "string",
  "note": "string"
}

response = requests.post('https://app.stoqapp.com/api/v2/external/preorders/orders/{id}/payments/refund', json=payload)
data = response.json()
Request Body
{
  "notify_customer": "string",
  "note": "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 Refund Balance

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

Refund the remaining-balance portion of a preorder (only valid after the balance was collected).

Body

application/json
notify_customerany
noteany

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 Refund Balance
curl -X POST 'https://app.stoqapp.com/api/v2/external/preorders/orders/{id}/payments/refund_balance' \
  -H 'Content-Type: application/json' \
  -d '{
    "notify_customer": "string",
    "note": "string"
  }'
const response = await fetch('https://app.stoqapp.com/api/v2/external/preorders/orders/{id}/payments/refund_balance', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
      "notify_customer": "string",
      "note": "string"
    }),
});

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

payload = {
  "notify_customer": "string",
  "note": "string"
}

response = requests.post('https://app.stoqapp.com/api/v2/external/preorders/orders/{id}/payments/refund_balance', json=payload)
data = response.json()
Request Body
{
  "notify_customer": "string",
  "note": "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 Refund Deposit

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

Refund the deposit portion of a preorder.

Body

application/json
notify_customerany
noteany

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 Refund Deposit
curl -X POST 'https://app.stoqapp.com/api/v2/external/preorders/orders/{id}/payments/refund_deposit' \
  -H 'Content-Type: application/json' \
  -d '{
    "notify_customer": "string",
    "note": "string"
  }'
const response = await fetch('https://app.stoqapp.com/api/v2/external/preorders/orders/{id}/payments/refund_deposit', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
      "notify_customer": "string",
      "note": "string"
    }),
});

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

payload = {
  "notify_customer": "string",
  "note": "string"
}

response = requests.post('https://app.stoqapp.com/api/v2/external/preorders/orders/{id}/payments/refund_deposit', json=payload)
data = response.json()
Request Body
{
  "notify_customer": "string",
  "note": "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 Send Collection Url

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

Send the remaining-balance payment-collection URL to the customer.

Note: Idempotent — calling twice resends the email with a fresh URL.

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 Send Collection Url
curl -X POST 'https://app.stoqapp.com/api/v2/external/preorders/orders/{id}/payments/send_collection_url'
const response = await fetch('https://app.stoqapp.com/api/v2/external/preorders/orders/{id}/payments/send_collection_url', {
  method: 'POST',
});

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

response = requests.post('https://app.stoqapp.com/api/v2/external/preorders/orders/{id}/payments/send_collection_url')
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"
  ]
}

Release

POST
https://app.stoqapp.com/api/v2/external/preorders/orders/{id}/release

Release the order's fulfillment holds and apply offer-configured order tags.

Note: Returns 409 if balance hasn't been collected; pass force: true to override.

Body

application/json
forceany
tag_withany

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.

Release
curl -X POST 'https://app.stoqapp.com/api/v2/external/preorders/orders/{id}/release' \
  -H 'Content-Type: application/json' \
  -d '{
    "force": "string",
    "tag_with": "string"
  }'
const response = await fetch('https://app.stoqapp.com/api/v2/external/preorders/orders/{id}/release', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
      "force": "string",
      "tag_with": "string"
    }),
});

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

payload = {
  "force": "string",
  "tag_with": "string"
}

response = requests.post('https://app.stoqapp.com/api/v2/external/preorders/orders/{id}/release', json=payload)
data = response.json()
Request Body
{
  "force": "string",
  "tag_with": "string"
}
{}
{
  "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"
  ]
}

Split Fulfillment Orders

POST
https://app.stoqapp.com/api/v2/external/preorders/orders/{id}/split_fulfillment_orders

Split the order's fulfillment orders so preorder items ship separately from regular items.

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.

Split Fulfillment Orders
curl -X POST 'https://app.stoqapp.com/api/v2/external/preorders/orders/{id}/split_fulfillment_orders'
const response = await fetch('https://app.stoqapp.com/api/v2/external/preorders/orders/{id}/split_fulfillment_orders', {
  method: 'POST',
});

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

response = requests.post('https://app.stoqapp.com/api/v2/external/preorders/orders/{id}/split_fulfillment_orders')
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"
  ]
}

Tags

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

Read the order tags applied by Stoq.

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.

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

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

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

Tags

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

Replace the order's tag set. PATCH form of tags/set.

Note: tags is replaced wholesale (delegates to tags/set). applied_by_stoq and applied_by_merchant are read-only.

Body

application/json
tagsarray | null

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.

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

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

payload = {
  "tags": "string"
}

response = requests.patch('https://app.stoqapp.com/api/v2/external/preorders/orders/{id}/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"
  ]
}

Tags Add

POST
https://app.stoqapp.com/api/v2/external/preorders/orders/{id}/tags/add

Add one or more tags to the Shopify order.

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.

Tags Add
curl -X POST 'https://app.stoqapp.com/api/v2/external/preorders/orders/{id}/tags/add' \
  -H 'Content-Type: application/json' \
  -d '{
    "tags": "string"
  }'
const response = await fetch('https://app.stoqapp.com/api/v2/external/preorders/orders/{id}/tags/add', {
  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/orders/{id}/tags/add', 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"
  ]
}

Tags Remove

POST
https://app.stoqapp.com/api/v2/external/preorders/orders/{id}/tags/remove

Remove one or more tags from the Shopify order.

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.

Tags Remove
curl -X POST 'https://app.stoqapp.com/api/v2/external/preorders/orders/{id}/tags/remove' \
  -H 'Content-Type: application/json' \
  -d '{
    "tags": "string"
  }'
const response = await fetch('https://app.stoqapp.com/api/v2/external/preorders/orders/{id}/tags/remove', {
  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/orders/{id}/tags/remove', 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"
  ]
}

Tags Set

POST
https://app.stoqapp.com/api/v2/external/preorders/orders/{id}/tags/set

Replace every tag on the Shopify order with the supplied list.

Note: Pass an empty list to clear all tags. Implemented as fetch-current + remove stale + add new on the Shopify side.

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.

Tags Set
curl -X POST 'https://app.stoqapp.com/api/v2/external/preorders/orders/{id}/tags/set' \
  -H 'Content-Type: application/json' \
  -d '{
    "tags": "string"
  }'
const response = await fetch('https://app.stoqapp.com/api/v2/external/preorders/orders/{id}/tags/set', {
  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/orders/{id}/tags/set', 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"
  ]
}

Bulk Cancel

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

Cancel many preorder orders (max 1000), with optional refund flags.

Body

application/json
order_idsany
refund_depositany
refund_balanceany
notify_customerany
reasonany

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 Cancel
curl -X POST 'https://app.stoqapp.com/api/v2/external/preorders/orders/bulk_cancel' \
  -H 'Content-Type: application/json' \
  -d '{
    "order_ids": [
      "string"
    ],
    "refund_deposit": "string",
    "refund_balance": "string",
    "notify_customer": "string",
    "reason": "string"
  }'
const response = await fetch('https://app.stoqapp.com/api/v2/external/preorders/orders/bulk_cancel', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
      "order_ids": [
        "string"
      ],
      "refund_deposit": "string",
      "refund_balance": "string",
      "notify_customer": "string",
      "reason": "string"
    }),
});

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

payload = {
  "order_ids": [
    "string"
  ],
  "refund_deposit": "string",
  "refund_balance": "string",
  "notify_customer": "string",
  "reason": "string"
}

response = requests.post('https://app.stoqapp.com/api/v2/external/preorders/orders/bulk_cancel', json=payload)
data = response.json()
Request Body
{
  "order_ids": [
    "string"
  ],
  "refund_deposit": "string",
  "refund_balance": "string",
  "notify_customer": "string",
  "reason": "string"
}
{}
{
  "job_id": "job_a1b2c3",
  "status_url": "/api/v2/external/jobs/job_a1b2c3"
}
{
  "errors": [
    "Unauthorized"
  ]
}
{
  "errors": [
    "name is required"
  ]
}
{
  "errors": [
    "Rate limit exceeded"
  ]
}

Bulk Release

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

Release fulfillments on many preorder orders (max 1000).

Body

application/json
order_idsany
forceany
tag_withany

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 Release
curl -X POST 'https://app.stoqapp.com/api/v2/external/preorders/orders/bulk_release' \
  -H 'Content-Type: application/json' \
  -d '{
    "order_ids": [
      "string"
    ],
    "force": "string",
    "tag_with": "string"
  }'
const response = await fetch('https://app.stoqapp.com/api/v2/external/preorders/orders/bulk_release', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
      "order_ids": [
        "string"
      ],
      "force": "string",
      "tag_with": "string"
    }),
});

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

payload = {
  "order_ids": [
    "string"
  ],
  "force": "string",
  "tag_with": "string"
}

response = requests.post('https://app.stoqapp.com/api/v2/external/preorders/orders/bulk_release', json=payload)
data = response.json()
Request Body
{
  "order_ids": [
    "string"
  ],
  "force": "string",
  "tag_with": "string"
}
{}
{
  "job_id": "job_a1b2c3",
  "status_url": "/api/v2/external/jobs/job_a1b2c3"
}
{
  "errors": [
    "Unauthorized"
  ]
}
{
  "errors": [
    "name is required"
  ]
}
{
  "errors": [
    "Rate limit exceeded"
  ]
}

Bulk Send Payment Collection Url

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

Send payment-collection URLs to many preorder customers (max 1000).

Body

application/json
order_idsany

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 Send Payment Collection Url
curl -X POST 'https://app.stoqapp.com/api/v2/external/preorders/orders/bulk_send_payment_collection_url' \
  -H 'Content-Type: application/json' \
  -d '{
    "order_ids": [
      "string"
    ]
  }'
const response = await fetch('https://app.stoqapp.com/api/v2/external/preorders/orders/bulk_send_payment_collection_url', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
      "order_ids": [
        "string"
      ]
    }),
});

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

payload = {
  "order_ids": [
    "string"
  ]
}

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

Bulk Set Tags

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

Apply tags to many preorder orders in one job (max 1000).

Note: mode is one of add | remove | replace (default add). replace overwrites each order's full tag set.

Body

application/json
order_idsany
tagsany
modestring | null

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 Set Tags
curl -X POST 'https://app.stoqapp.com/api/v2/external/preorders/orders/bulk_set_tags' \
  -H 'Content-Type: application/json' \
  -d '{
    "order_ids": [
      "string"
    ],
    "tags": "string",
    "mode": "string"
  }'
const response = await fetch('https://app.stoqapp.com/api/v2/external/preorders/orders/bulk_set_tags', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
      "order_ids": [
        "string"
      ],
      "tags": "string",
      "mode": "string"
    }),
});

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

payload = {
  "order_ids": [
    "string"
  ],
  "tags": "string",
  "mode": "string"
}

response = requests.post('https://app.stoqapp.com/api/v2/external/preorders/orders/bulk_set_tags', json=payload)
data = response.json()
Request Body
{
  "order_ids": [
    "string"
  ],
  "tags": "string",
  "mode": "string"
}
{}
{
  "job_id": "job_a1b2c3",
  "status_url": "/api/v2/external/jobs/job_a1b2c3"
}
{
  "errors": [
    "Unauthorized"
  ]
}
{
  "errors": [
    "name is required"
  ]
}
{
  "errors": [
    "Rate limit exceeded"
  ]
}

Jobs

GET
https://app.stoqapp.com/api/v2/external/preorders/orders/jobs/{job_id}

Check the status of a bulk-order job.

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.

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

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

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

Preorders · Product Variants

List

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

List Shopify variants attached to any preorder offer in this shop.

Parameters

pageanyquery
per_pageanyquery
offer_idanyquery
product_idanyquery
variant_idsanyquery

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/preorders/product_variants'
const response = await fetch('https://app.stoqapp.com/api/v2/external/preorders/product_variants', {
  method: 'GET',
});

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

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

Read

GET
https://app.stoqapp.com/api/v2/external/preorders/product_variants/{variant_id}

Read a Shopify variant's preorder context: every offer it's in, aggregate counts, and current metafield state.

Parameters

variant_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/preorders/product_variants/{variant_id}'
const response = await fetch('https://app.stoqapp.com/api/v2/external/preorders/product_variants/{variant_id}', {
  method: 'GET',
});

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

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

Detach From All Offers

POST
https://app.stoqapp.com/api/v2/external/preorders/product_variants/{variant_id}/detach_from_all_offers

Remove a variant from every preorder offer it's attached to. Customer orders are unaffected.

Note: Destructive. Same effect as calling Offer::Products::RemoveVariants against every offer the variant is in.

Parameters

variant_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.

Detach From All Offers
curl -X POST 'https://app.stoqapp.com/api/v2/external/preorders/product_variants/{variant_id}/detach_from_all_offers'
const response = await fetch('https://app.stoqapp.com/api/v2/external/preorders/product_variants/{variant_id}/detach_from_all_offers', {
  method: 'POST',
});

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

response = requests.post('https://app.stoqapp.com/api/v2/external/preorders/product_variants/{variant_id}/detach_from_all_offers')
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"
  ]
}

Offers

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

List the preorder offers a Shopify variant is attached to.

Parameters

variant_idstringrequiredpath
stateanyquery

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.

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

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

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

Recalculate Preorder Count

POST
https://app.stoqapp.com/api/v2/external/preorders/product_variants/{variant_id}/recalculate_preorder_count

Recompute preorder_count for a variant from active order line items, then push to Shopify.

Parameters

variant_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.

Recalculate Preorder Count
curl -X POST 'https://app.stoqapp.com/api/v2/external/preorders/product_variants/{variant_id}/recalculate_preorder_count'
const response = await fetch('https://app.stoqapp.com/api/v2/external/preorders/product_variants/{variant_id}/recalculate_preorder_count', {
  method: 'POST',
});

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

response = requests.post('https://app.stoqapp.com/api/v2/external/preorders/product_variants/{variant_id}/recalculate_preorder_count')
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"
  ]
}

Reset Metafields

POST
https://app.stoqapp.com/api/v2/external/preorders/product_variants/{variant_id}/reset_metafields

Clear all preorder-related Shopify metafields on a variant. Keeps the variant attached to its offers.

Note: Doesn't detach. Next offer settings change will re-write the metafields from current state.

Parameters

variant_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.

Reset Metafields
curl -X POST 'https://app.stoqapp.com/api/v2/external/preorders/product_variants/{variant_id}/reset_metafields'
const response = await fetch('https://app.stoqapp.com/api/v2/external/preorders/product_variants/{variant_id}/reset_metafields', {
  method: 'POST',
});

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

response = requests.post('https://app.stoqapp.com/api/v2/external/preorders/product_variants/{variant_id}/reset_metafields')
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"
  ]
}

Reset Preorder Count

POST
https://app.stoqapp.com/api/v2/external/preorders/product_variants/{variant_id}/reset_preorder_count

Hard-reset the preorder_count metafield + DB columns on a variant to zero.

Note: Use recalculate_preorder_count for a recompute from real orders; this is a destructive zero.

Parameters

variant_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.

Reset Preorder Count
curl -X POST 'https://app.stoqapp.com/api/v2/external/preorders/product_variants/{variant_id}/reset_preorder_count'
const response = await fetch('https://app.stoqapp.com/api/v2/external/preorders/product_variants/{variant_id}/reset_preorder_count', {
  method: 'POST',
});

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

response = requests.post('https://app.stoqapp.com/api/v2/external/preorders/product_variants/{variant_id}/reset_preorder_count')
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"
  ]
}

Sync Metafields

POST
https://app.stoqapp.com/api/v2/external/preorders/product_variants/{variant_id}/sync_metafields

Force-resync every preorder metafield for a variant from local DB state to Shopify.

Note: Idempotent. Useful when a previous metafield write failed.

Parameters

variant_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.

Sync Metafields
curl -X POST 'https://app.stoqapp.com/api/v2/external/preorders/product_variants/{variant_id}/sync_metafields'
const response = await fetch('https://app.stoqapp.com/api/v2/external/preorders/product_variants/{variant_id}/sync_metafields', {
  method: 'POST',
});

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

response = requests.post('https://app.stoqapp.com/api/v2/external/preorders/product_variants/{variant_id}/sync_metafields')
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"
  ]
}

Bulk Recalculate Preorder Counts

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

Recompute preorder_count for many variants in one job (max 5000).

Body

application/json
variant_idsany

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 Recalculate Preorder Counts
curl -X POST 'https://app.stoqapp.com/api/v2/external/preorders/product_variants/bulk_recalculate_preorder_counts' \
  -H 'Content-Type: application/json' \
  -d '{
    "variant_ids": [
      "45000000001"
    ]
  }'
const response = await fetch('https://app.stoqapp.com/api/v2/external/preorders/product_variants/bulk_recalculate_preorder_counts', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
      "variant_ids": [
        "45000000001"
      ]
    }),
});

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

payload = {
  "variant_ids": [
    "45000000001"
  ]
}

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

Bulk Reset Metafields

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

Reset preorder metafields for many variants in one job (max 5000).

Body

application/json
variant_idsany

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 Reset Metafields
curl -X POST 'https://app.stoqapp.com/api/v2/external/preorders/product_variants/bulk_reset_metafields' \
  -H 'Content-Type: application/json' \
  -d '{
    "variant_ids": [
      "45000000001"
    ]
  }'
const response = await fetch('https://app.stoqapp.com/api/v2/external/preorders/product_variants/bulk_reset_metafields', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
      "variant_ids": [
        "45000000001"
      ]
    }),
});

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

payload = {
  "variant_ids": [
    "45000000001"
  ]
}

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

Bulk Sync Metafields

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

Force-resync preorder metafields for many variants in one job (max 5000).

Body

application/json
variant_idsany

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 Sync Metafields
curl -X POST 'https://app.stoqapp.com/api/v2/external/preorders/product_variants/bulk_sync_metafields' \
  -H 'Content-Type: application/json' \
  -d '{
    "variant_ids": [
      "45000000001"
    ]
  }'
const response = await fetch('https://app.stoqapp.com/api/v2/external/preorders/product_variants/bulk_sync_metafields', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
      "variant_ids": [
        "45000000001"
      ]
    }),
});

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

payload = {
  "variant_ids": [
    "45000000001"
  ]
}

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

Jobs

GET
https://app.stoqapp.com/api/v2/external/preorders/product_variants/jobs/{job_id}

Check the status of a bulk variant-admin job.

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.

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

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

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

Preorders · Reports

List

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

List every available preorder 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/preorders/reports'
const response = await fetch('https://app.stoqapp.com/api/v2/external/preorders/reports', {
  method: 'GET',
});

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

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

Balance Collection

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

Outstanding preorder balances and balance-collection performance metrics.

Parameters

fromanyquery
toanyquery
offer_idanyquery
offer_idsanyquery
currencyanyquery

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.

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

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

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

Balance Collection Export

POST
https://app.stoqapp.com/api/v2/external/preorders/reports/balance_collection/export

Async CSV export of the balance-collection report.

Body

application/json
fromany
toany
offer_idany
offer_idsany
product_idany
variant_idany
market_idany
currencyany
granularityany
metricsany
include_depositsany
include_balancesany
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.

Balance Collection Export
curl -X POST 'https://app.stoqapp.com/api/v2/external/preorders/reports/balance_collection/export' \
  -H 'Content-Type: application/json' \
  -d '{
    "from": "string",
    "to": "string",
    "offer_id": "string",
    "offer_ids": [
      "string"
    ],
    "product_id": "78000000001",
    "variant_id": "45000000001",
    "market_id": "gid://shopify/Market/12345",
    "currency": "string",
    "granularity": "string",
    "metrics": "string",
    "include_deposits": "string",
    "include_balances": "string",
    "page": "string",
    "per_page": "string"
  }'
const response = await fetch('https://app.stoqapp.com/api/v2/external/preorders/reports/balance_collection/export', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
      "from": "string",
      "to": "string",
      "offer_id": "string",
      "offer_ids": [
        "string"
      ],
      "product_id": "78000000001",
      "variant_id": "45000000001",
      "market_id": "gid://shopify/Market/12345",
      "currency": "string",
      "granularity": "string",
      "metrics": "string",
      "include_deposits": "string",
      "include_balances": "string",
      "page": "string",
      "per_page": "string"
    }),
});

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

payload = {
  "from": "string",
  "to": "string",
  "offer_id": "string",
  "offer_ids": [
    "string"
  ],
  "product_id": "78000000001",
  "variant_id": "45000000001",
  "market_id": "gid://shopify/Market/12345",
  "currency": "string",
  "granularity": "string",
  "metrics": "string",
  "include_deposits": "string",
  "include_balances": "string",
  "page": "string",
  "per_page": "string"
}

response = requests.post('https://app.stoqapp.com/api/v2/external/preorders/reports/balance_collection/export', json=payload)
data = response.json()
Request Body
{
  "from": "string",
  "to": "string",
  "offer_id": "string",
  "offer_ids": [
    "string"
  ],
  "product_id": "78000000001",
  "variant_id": "45000000001",
  "market_id": "gid://shopify/Market/12345",
  "currency": "string",
  "granularity": "string",
  "metrics": "string",
  "include_deposits": "string",
  "include_balances": "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"
  ]
}

By Date

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

Time-series of all preorder metrics at the chosen granularity (day/week/month).

Parameters

fromanyquery
toanyquery
offer_idanyquery
offer_idsanyquery
product_idanyquery
variant_idanyquery
currencyanyquery
granularityanyquery
metricsanyquery

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.

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

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

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

By Date Export

POST
https://app.stoqapp.com/api/v2/external/preorders/reports/by_date/export

Async CSV export of the time-series preorder report.

Body

application/json
fromany
toany
offer_idany
offer_idsany
product_idany
variant_idany
market_idany
currencyany
granularityany
metricsany
include_depositsany
include_balancesany
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.

By Date Export
curl -X POST 'https://app.stoqapp.com/api/v2/external/preorders/reports/by_date/export' \
  -H 'Content-Type: application/json' \
  -d '{
    "from": "string",
    "to": "string",
    "offer_id": "string",
    "offer_ids": [
      "string"
    ],
    "product_id": "78000000001",
    "variant_id": "45000000001",
    "market_id": "gid://shopify/Market/12345",
    "currency": "string",
    "granularity": "string",
    "metrics": "string",
    "include_deposits": "string",
    "include_balances": "string",
    "page": "string",
    "per_page": "string"
  }'
const response = await fetch('https://app.stoqapp.com/api/v2/external/preorders/reports/by_date/export', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
      "from": "string",
      "to": "string",
      "offer_id": "string",
      "offer_ids": [
        "string"
      ],
      "product_id": "78000000001",
      "variant_id": "45000000001",
      "market_id": "gid://shopify/Market/12345",
      "currency": "string",
      "granularity": "string",
      "metrics": "string",
      "include_deposits": "string",
      "include_balances": "string",
      "page": "string",
      "per_page": "string"
    }),
});

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

payload = {
  "from": "string",
  "to": "string",
  "offer_id": "string",
  "offer_ids": [
    "string"
  ],
  "product_id": "78000000001",
  "variant_id": "45000000001",
  "market_id": "gid://shopify/Market/12345",
  "currency": "string",
  "granularity": "string",
  "metrics": "string",
  "include_deposits": "string",
  "include_balances": "string",
  "page": "string",
  "per_page": "string"
}

response = requests.post('https://app.stoqapp.com/api/v2/external/preorders/reports/by_date/export', json=payload)
data = response.json()
Request Body
{
  "from": "string",
  "to": "string",
  "offer_id": "string",
  "offer_ids": [
    "string"
  ],
  "product_id": "78000000001",
  "variant_id": "45000000001",
  "market_id": "gid://shopify/Market/12345",
  "currency": "string",
  "granularity": "string",
  "metrics": "string",
  "include_deposits": "string",
  "include_balances": "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"
  ]
}

By Offer

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

Per-offer breakdown of preorder activity (orders, units, revenue, customers).

Parameters

fromanyquery
toanyquery
offer_idsanyquery
market_idanyquery
currencyanyquery

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.

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

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

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

By Offer Export

POST
https://app.stoqapp.com/api/v2/external/preorders/reports/by_offer/export

Async CSV export of the per-offer preorder report.

Body

application/json
fromany
toany
offer_idany
offer_idsany
product_idany
variant_idany
market_idany
currencyany
granularityany
metricsany
include_depositsany
include_balancesany
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.

By Offer Export
curl -X POST 'https://app.stoqapp.com/api/v2/external/preorders/reports/by_offer/export' \
  -H 'Content-Type: application/json' \
  -d '{
    "from": "string",
    "to": "string",
    "offer_id": "string",
    "offer_ids": [
      "string"
    ],
    "product_id": "78000000001",
    "variant_id": "45000000001",
    "market_id": "gid://shopify/Market/12345",
    "currency": "string",
    "granularity": "string",
    "metrics": "string",
    "include_deposits": "string",
    "include_balances": "string",
    "page": "string",
    "per_page": "string"
  }'
const response = await fetch('https://app.stoqapp.com/api/v2/external/preorders/reports/by_offer/export', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
      "from": "string",
      "to": "string",
      "offer_id": "string",
      "offer_ids": [
        "string"
      ],
      "product_id": "78000000001",
      "variant_id": "45000000001",
      "market_id": "gid://shopify/Market/12345",
      "currency": "string",
      "granularity": "string",
      "metrics": "string",
      "include_deposits": "string",
      "include_balances": "string",
      "page": "string",
      "per_page": "string"
    }),
});

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

payload = {
  "from": "string",
  "to": "string",
  "offer_id": "string",
  "offer_ids": [
    "string"
  ],
  "product_id": "78000000001",
  "variant_id": "45000000001",
  "market_id": "gid://shopify/Market/12345",
  "currency": "string",
  "granularity": "string",
  "metrics": "string",
  "include_deposits": "string",
  "include_balances": "string",
  "page": "string",
  "per_page": "string"
}

response = requests.post('https://app.stoqapp.com/api/v2/external/preorders/reports/by_offer/export', json=payload)
data = response.json()
Request Body
{
  "from": "string",
  "to": "string",
  "offer_id": "string",
  "offer_ids": [
    "string"
  ],
  "product_id": "78000000001",
  "variant_id": "45000000001",
  "market_id": "gid://shopify/Market/12345",
  "currency": "string",
  "granularity": "string",
  "metrics": "string",
  "include_deposits": "string",
  "include_balances": "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"
  ]
}

By Product

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

Per-product preorder performance, rolled up across variants.

Parameters

fromanyquery
toanyquery
offer_idanyquery
offer_idsanyquery
product_idanyquery
currencyanyquery

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.

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

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

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

By Product Export

POST
https://app.stoqapp.com/api/v2/external/preorders/reports/by_product/export

Async CSV export of the per-product preorder report.

Body

application/json
fromany
toany
offer_idany
offer_idsany
product_idany
variant_idany
market_idany
currencyany
granularityany
metricsany
include_depositsany
include_balancesany
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.

By Product Export
curl -X POST 'https://app.stoqapp.com/api/v2/external/preorders/reports/by_product/export' \
  -H 'Content-Type: application/json' \
  -d '{
    "from": "string",
    "to": "string",
    "offer_id": "string",
    "offer_ids": [
      "string"
    ],
    "product_id": "78000000001",
    "variant_id": "45000000001",
    "market_id": "gid://shopify/Market/12345",
    "currency": "string",
    "granularity": "string",
    "metrics": "string",
    "include_deposits": "string",
    "include_balances": "string",
    "page": "string",
    "per_page": "string"
  }'
const response = await fetch('https://app.stoqapp.com/api/v2/external/preorders/reports/by_product/export', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
      "from": "string",
      "to": "string",
      "offer_id": "string",
      "offer_ids": [
        "string"
      ],
      "product_id": "78000000001",
      "variant_id": "45000000001",
      "market_id": "gid://shopify/Market/12345",
      "currency": "string",
      "granularity": "string",
      "metrics": "string",
      "include_deposits": "string",
      "include_balances": "string",
      "page": "string",
      "per_page": "string"
    }),
});

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

payload = {
  "from": "string",
  "to": "string",
  "offer_id": "string",
  "offer_ids": [
    "string"
  ],
  "product_id": "78000000001",
  "variant_id": "45000000001",
  "market_id": "gid://shopify/Market/12345",
  "currency": "string",
  "granularity": "string",
  "metrics": "string",
  "include_deposits": "string",
  "include_balances": "string",
  "page": "string",
  "per_page": "string"
}

response = requests.post('https://app.stoqapp.com/api/v2/external/preorders/reports/by_product/export', json=payload)
data = response.json()
Request Body
{
  "from": "string",
  "to": "string",
  "offer_id": "string",
  "offer_ids": [
    "string"
  ],
  "product_id": "78000000001",
  "variant_id": "45000000001",
  "market_id": "gid://shopify/Market/12345",
  "currency": "string",
  "granularity": "string",
  "metrics": "string",
  "include_deposits": "string",
  "include_balances": "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"
  ]
}

By Variant

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

Per-variant preorder performance for a specific offer.

Note: Requires offer_id (or offer_ids[]). Variant-level data without an offer scope isn't supported.

Parameters

fromanyquery
toanyquery
offer_idanyquery
offer_idsanyquery
product_idanyquery
variant_idanyquery
currencyanyquery

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.

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

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

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

By Variant Export

POST
https://app.stoqapp.com/api/v2/external/preorders/reports/by_variant/export

Async CSV export of the per-variant preorder report.

Body

application/json
fromany
toany
offer_idany
offer_idsany
product_idany
variant_idany
market_idany
currencyany
granularityany
metricsany
include_depositsany
include_balancesany
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.

By Variant Export
curl -X POST 'https://app.stoqapp.com/api/v2/external/preorders/reports/by_variant/export' \
  -H 'Content-Type: application/json' \
  -d '{
    "from": "string",
    "to": "string",
    "offer_id": "string",
    "offer_ids": [
      "string"
    ],
    "product_id": "78000000001",
    "variant_id": "45000000001",
    "market_id": "gid://shopify/Market/12345",
    "currency": "string",
    "granularity": "string",
    "metrics": "string",
    "include_deposits": "string",
    "include_balances": "string",
    "page": "string",
    "per_page": "string"
  }'
const response = await fetch('https://app.stoqapp.com/api/v2/external/preorders/reports/by_variant/export', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
      "from": "string",
      "to": "string",
      "offer_id": "string",
      "offer_ids": [
        "string"
      ],
      "product_id": "78000000001",
      "variant_id": "45000000001",
      "market_id": "gid://shopify/Market/12345",
      "currency": "string",
      "granularity": "string",
      "metrics": "string",
      "include_deposits": "string",
      "include_balances": "string",
      "page": "string",
      "per_page": "string"
    }),
});

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

payload = {
  "from": "string",
  "to": "string",
  "offer_id": "string",
  "offer_ids": [
    "string"
  ],
  "product_id": "78000000001",
  "variant_id": "45000000001",
  "market_id": "gid://shopify/Market/12345",
  "currency": "string",
  "granularity": "string",
  "metrics": "string",
  "include_deposits": "string",
  "include_balances": "string",
  "page": "string",
  "per_page": "string"
}

response = requests.post('https://app.stoqapp.com/api/v2/external/preorders/reports/by_variant/export', json=payload)
data = response.json()
Request Body
{
  "from": "string",
  "to": "string",
  "offer_id": "string",
  "offer_ids": [
    "string"
  ],
  "product_id": "78000000001",
  "variant_id": "45000000001",
  "market_id": "gid://shopify/Market/12345",
  "currency": "string",
  "granularity": "string",
  "metrics": "string",
  "include_deposits": "string",
  "include_balances": "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"
  ]
}

Cancellations

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

Preorder cancellation metrics with reason and per-offer breakdowns.

Note: Reason breakdown requires the cancel_reason field on OrderAttribution. Reasons not yet captured will appear as 'unknown'.

Parameters

fromanyquery
toanyquery
offer_idanyquery
offer_idsanyquery
currencyanyquery

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.

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

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

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

Cancellations Export

POST
https://app.stoqapp.com/api/v2/external/preorders/reports/cancellations/export

Async CSV export of the cancellations report.

Body

application/json
fromany
toany
offer_idany
offer_idsany
product_idany
variant_idany
market_idany
currencyany
granularityany
metricsany
include_depositsany
include_balancesany
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.

Cancellations Export
curl -X POST 'https://app.stoqapp.com/api/v2/external/preorders/reports/cancellations/export' \
  -H 'Content-Type: application/json' \
  -d '{
    "from": "string",
    "to": "string",
    "offer_id": "string",
    "offer_ids": [
      "string"
    ],
    "product_id": "78000000001",
    "variant_id": "45000000001",
    "market_id": "gid://shopify/Market/12345",
    "currency": "string",
    "granularity": "string",
    "metrics": "string",
    "include_deposits": "string",
    "include_balances": "string",
    "page": "string",
    "per_page": "string"
  }'
const response = await fetch('https://app.stoqapp.com/api/v2/external/preorders/reports/cancellations/export', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
      "from": "string",
      "to": "string",
      "offer_id": "string",
      "offer_ids": [
        "string"
      ],
      "product_id": "78000000001",
      "variant_id": "45000000001",
      "market_id": "gid://shopify/Market/12345",
      "currency": "string",
      "granularity": "string",
      "metrics": "string",
      "include_deposits": "string",
      "include_balances": "string",
      "page": "string",
      "per_page": "string"
    }),
});

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

payload = {
  "from": "string",
  "to": "string",
  "offer_id": "string",
  "offer_ids": [
    "string"
  ],
  "product_id": "78000000001",
  "variant_id": "45000000001",
  "market_id": "gid://shopify/Market/12345",
  "currency": "string",
  "granularity": "string",
  "metrics": "string",
  "include_deposits": "string",
  "include_balances": "string",
  "page": "string",
  "per_page": "string"
}

response = requests.post('https://app.stoqapp.com/api/v2/external/preorders/reports/cancellations/export', json=payload)
data = response.json()
Request Body
{
  "from": "string",
  "to": "string",
  "offer_id": "string",
  "offer_ids": [
    "string"
  ],
  "product_id": "78000000001",
  "variant_id": "45000000001",
  "market_id": "gid://shopify/Market/12345",
  "currency": "string",
  "granularity": "string",
  "metrics": "string",
  "include_deposits": "string",
  "include_balances": "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"
  ]
}

Customers

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

Paginated list of customers with preorder activity in the window.

Parameters

fromanyquery
toanyquery
offer_idanyquery
offer_idsanyquery
currencyanyquery
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.

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

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

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

Customers Export

POST
https://app.stoqapp.com/api/v2/external/preorders/reports/customers/export

Async CSV export of the customers report.

Body

application/json
fromany
toany
offer_idany
offer_idsany
product_idany
variant_idany
market_idany
currencyany
granularityany
metricsany
include_depositsany
include_balancesany
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.

Customers Export
curl -X POST 'https://app.stoqapp.com/api/v2/external/preorders/reports/customers/export' \
  -H 'Content-Type: application/json' \
  -d '{
    "from": "string",
    "to": "string",
    "offer_id": "string",
    "offer_ids": [
      "string"
    ],
    "product_id": "78000000001",
    "variant_id": "45000000001",
    "market_id": "gid://shopify/Market/12345",
    "currency": "string",
    "granularity": "string",
    "metrics": "string",
    "include_deposits": "string",
    "include_balances": "string",
    "page": "string",
    "per_page": "string"
  }'
const response = await fetch('https://app.stoqapp.com/api/v2/external/preorders/reports/customers/export', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
      "from": "string",
      "to": "string",
      "offer_id": "string",
      "offer_ids": [
        "string"
      ],
      "product_id": "78000000001",
      "variant_id": "45000000001",
      "market_id": "gid://shopify/Market/12345",
      "currency": "string",
      "granularity": "string",
      "metrics": "string",
      "include_deposits": "string",
      "include_balances": "string",
      "page": "string",
      "per_page": "string"
    }),
});

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

payload = {
  "from": "string",
  "to": "string",
  "offer_id": "string",
  "offer_ids": [
    "string"
  ],
  "product_id": "78000000001",
  "variant_id": "45000000001",
  "market_id": "gid://shopify/Market/12345",
  "currency": "string",
  "granularity": "string",
  "metrics": "string",
  "include_deposits": "string",
  "include_balances": "string",
  "page": "string",
  "per_page": "string"
}

response = requests.post('https://app.stoqapp.com/api/v2/external/preorders/reports/customers/export', json=payload)
data = response.json()
Request Body
{
  "from": "string",
  "to": "string",
  "offer_id": "string",
  "offer_ids": [
    "string"
  ],
  "product_id": "78000000001",
  "variant_id": "45000000001",
  "market_id": "gid://shopify/Market/12345",
  "currency": "string",
  "granularity": "string",
  "metrics": "string",
  "include_deposits": "string",
  "include_balances": "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/preorders/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/preorders/reports/exports/{job_id}'
const response = await fetch('https://app.stoqapp.com/api/v2/external/preorders/reports/exports/{job_id}', {
  method: 'GET',
});

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

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

Revenue

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

Preorder revenue over a date window, bucketed by day/week/month.

Parameters

fromanyquery
toanyquery
offer_idanyquery
offer_idsanyquery
product_idanyquery
variant_idanyquery
market_idanyquery
currencyanyquery
granularityanyquery
include_depositsanyquery
include_balancesanyquery

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.

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

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

response = requests.get('https://app.stoqapp.com/api/v2/external/preorders/reports/revenue')
data = response.json()
{
  "window": {
    "from": "2026-05-26T00:00:00Z",
    "to": "2026-06-25T23:59:59Z"
  },
  "granularity": "day",
  "currency": "USD",
  "include_deposits": true,
  "include_balances": true,
  "total_revenue": "47825.50",
  "series": [
    {
      "date": "2026-06-25T00:00:00Z",
      "revenue": "2450.75",
      "orders": 18
    },
    {
      "date": "2026-06-24T00:00:00Z",
      "revenue": "3180.25",
      "orders": 24
    }
  ],
  "by_offer": [
    {
      "offer_id": 1,
      "offer_name": "Summer Sneaker Drop",
      "revenue": "28500.00"
    },
    {
      "offer_id": 2,
      "offer_name": "Winter Collection",
      "revenue": "19325.50"
    }
  ]
}
{
  "errors": [
    "Unauthorized"
  ]
}
{
  "errors": [
    "name is required"
  ]
}
{
  "errors": [
    "Rate limit exceeded"
  ]
}

Revenue Export

POST
https://app.stoqapp.com/api/v2/external/preorders/reports/revenue/export

Async CSV export of the preorder revenue report.

Body

application/json
fromany
toany
offer_idany
offer_idsany
product_idany
variant_idany
market_idany
currencyany
granularityany
metricsany
include_depositsany
include_balancesany
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.

Revenue Export
curl -X POST 'https://app.stoqapp.com/api/v2/external/preorders/reports/revenue/export' \
  -H 'Content-Type: application/json' \
  -d '{
    "from": "string",
    "to": "string",
    "offer_id": "string",
    "offer_ids": [
      "string"
    ],
    "product_id": "78000000001",
    "variant_id": "45000000001",
    "market_id": "gid://shopify/Market/12345",
    "currency": "string",
    "granularity": "string",
    "metrics": "string",
    "include_deposits": "string",
    "include_balances": "string",
    "page": "string",
    "per_page": "string"
  }'
const response = await fetch('https://app.stoqapp.com/api/v2/external/preorders/reports/revenue/export', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
      "from": "string",
      "to": "string",
      "offer_id": "string",
      "offer_ids": [
        "string"
      ],
      "product_id": "78000000001",
      "variant_id": "45000000001",
      "market_id": "gid://shopify/Market/12345",
      "currency": "string",
      "granularity": "string",
      "metrics": "string",
      "include_deposits": "string",
      "include_balances": "string",
      "page": "string",
      "per_page": "string"
    }),
});

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

payload = {
  "from": "string",
  "to": "string",
  "offer_id": "string",
  "offer_ids": [
    "string"
  ],
  "product_id": "78000000001",
  "variant_id": "45000000001",
  "market_id": "gid://shopify/Market/12345",
  "currency": "string",
  "granularity": "string",
  "metrics": "string",
  "include_deposits": "string",
  "include_balances": "string",
  "page": "string",
  "per_page": "string"
}

response = requests.post('https://app.stoqapp.com/api/v2/external/preorders/reports/revenue/export', json=payload)
data = response.json()
Request Body
{
  "from": "string",
  "to": "string",
  "offer_id": "string",
  "offer_ids": [
    "string"
  ],
  "product_id": "78000000001",
  "variant_id": "45000000001",
  "market_id": "gid://shopify/Market/12345",
  "currency": "string",
  "granularity": "string",
  "metrics": "string",
  "include_deposits": "string",
  "include_balances": "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/preorders/reports/summary

High-level overview of preorder activity over a date window.

Parameters

fromanyquery
toanyquery
offer_idanyquery
offer_idsanyquery
product_idanyquery
variant_idanyquery
market_idanyquery
currencyanyquery

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/preorders/reports/summary'
const response = await fetch('https://app.stoqapp.com/api/v2/external/preorders/reports/summary', {
  method: 'GET',
});

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

response = requests.get('https://app.stoqapp.com/api/v2/external/preorders/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/preorders/reports/summary/export

Async CSV export of the preorder summary report.

Body

application/json
fromany
toany
offer_idany
offer_idsany
product_idany
variant_idany
market_idany
currencyany
granularityany
metricsany
include_depositsany
include_balancesany
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/preorders/reports/summary/export' \
  -H 'Content-Type: application/json' \
  -d '{
    "from": "string",
    "to": "string",
    "offer_id": "string",
    "offer_ids": [
      "string"
    ],
    "product_id": "78000000001",
    "variant_id": "45000000001",
    "market_id": "gid://shopify/Market/12345",
    "currency": "string",
    "granularity": "string",
    "metrics": "string",
    "include_deposits": "string",
    "include_balances": "string",
    "page": "string",
    "per_page": "string"
  }'
const response = await fetch('https://app.stoqapp.com/api/v2/external/preorders/reports/summary/export', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
      "from": "string",
      "to": "string",
      "offer_id": "string",
      "offer_ids": [
        "string"
      ],
      "product_id": "78000000001",
      "variant_id": "45000000001",
      "market_id": "gid://shopify/Market/12345",
      "currency": "string",
      "granularity": "string",
      "metrics": "string",
      "include_deposits": "string",
      "include_balances": "string",
      "page": "string",
      "per_page": "string"
    }),
});

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

payload = {
  "from": "string",
  "to": "string",
  "offer_id": "string",
  "offer_ids": [
    "string"
  ],
  "product_id": "78000000001",
  "variant_id": "45000000001",
  "market_id": "gid://shopify/Market/12345",
  "currency": "string",
  "granularity": "string",
  "metrics": "string",
  "include_deposits": "string",
  "include_balances": "string",
  "page": "string",
  "per_page": "string"
}

response = requests.post('https://app.stoqapp.com/api/v2/external/preorders/reports/summary/export', json=payload)
data = response.json()
Request Body
{
  "from": "string",
  "to": "string",
  "offer_id": "string",
  "offer_ids": [
    "string"
  ],
  "product_id": "78000000001",
  "variant_id": "45000000001",
  "market_id": "gid://shopify/Market/12345",
  "currency": "string",
  "granularity": "string",
  "metrics": "string",
  "include_deposits": "string",
  "include_balances": "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"
  ]
}

Models

Error

object

Error envelope returned by every failed request.

errorsArray<string>required
Example
{
  "errors": [
    "name is required"
  ]
}

JobAccepted

object

Returned for async/bulk work — poll the job until it reaches a terminal state.

job_idstring
status_urlstring
Example
{
  "job_id": "job_a1b2c3",
  "status_url": "/api/v2/external/jobs/job_a1b2c3"
}