Update a batch on an offer
API v2 is in public beta: endpoints and fields can change before general availability. See the changelog
/preorders/offers/{id}/batchesCosts 2 rate-limit points · Rate limits
Update any subset of the batch settings on a preorder offer, including the batches themselves.
Deep partial: absent fields are unchanged; items[].label is read-only.
Also searched asedit batcheschange batch settingsmodify batchesenable batchesturn on batchessell in batchesrelease in wavesdisable batchesturn off batchesstop selling in batchesadd a batchremove a batchreorder batchesset batch limitsset batch ship datesadvance batches automaticallyauto advance batchesadvance batches manuallybatch widget stylechange batch widgetbatch progress display
Path parameters
idstringRequired
Headers
Idempotency-KeystringA fresh unique key for every write (a new UUID, say); reuse it only to retry that write. Keys are remembered for 1 hour: the same key and the same request within that hour returns the first result, with
Idempotent-Replayed: true, without running again; the same key with a different method, path or body is refused (422idempotency_key_reused); a retry while the first is still running gets 409idempotency_key_in_progress. Keys are per store. Server errors and rate limits are not kept, so their retry runs.
Request body
release_strategystringsequential sells the batches one after another (needs at least two batches, a paid plan, and no market-specific offer); all_at_once turns batches off. Turning batches on uses one shipping timeline for every product and moves a Scheduled fulfillment status (shipping.delivery_timing exact_time) to Unfulfilled (asap), listed in also_changed, as the editor does.
One ofsequentialall_at_onceadvance_schedulestringautomatic moves to the next batch when one sells its quantity_limit (every batch then needs one); manual waits for the merchant.
One ofautomaticmanuallabel_formatstringBatch name; {{ n }} is replaced by the position. null uses "Batch {{ n }}".
status_textobjectShow 3 child attributesHide child attributes
paststringWord shown for a batch that has passed.
livestringWord shown for the batch on sale now.
upcomingstringWord shown for a batch still to come.
widgetobjectShow 4 child attributesHide child attributes
stylestringStorefront batch widget layout.
One ofroadmapstackedcompactsegmentedprogressstringcounts shows units sold of the limit; percent shows a percentage.
One ofcountspercentshow_other_ship_datesbooleanShow the other batches' ship dates on the storefront.
show_namesbooleanShow batch names on the storefront.
itemsarray of anysThe batches. A list replaces them: entries with an id keep that batch, entries without one are created, and batches left out are archived. An object keyed by batch id edits those batches (quantity_limit, shipping_text) and keeps the rest. Kept batches stay in their current order and new ones go at the end; positions end up 1..N. Each batch needs shipping_text; quantity_limit is all or none across batches.
Returns
release_strategystringExample:sequentialadvance_schedulestringExample:automaticlabel_formatstringExample:Batch {{ n }}status_textobjectShow 3 child attributesHide child attributes
paststringExample:Sold outlivestringExample:LiveupcomingstringExample:Coming soon
widgetobjectShow 4 child attributesHide child attributes
stylestringExample:roadmapprogressstringExample:countsshow_other_ship_datesbooleanExample:trueshow_namesbooleanExample:false
itemsarray of objectsShow 5 child attributesHide child attributes
idstringExample:6f1c9e2a-0d4b-4c1e-9a57-2f0e8d3b7c11positionintegerExample:1quantity_limitintegerExample:120shipping_textstringExample:Ships in JunelabelstringExample:Batch 1
Errors
Missing or invalid X-Auth-Token.
The resource does not exist for this shop, or the action path is not registered.
An earlier request with the same Idempotency-Key is still running. Wait, then resend the same request with the same key.
Invalid fields: one details entry per field error, its path the canonical section path. Nothing was saved.
Rate limited: cost-weighted per token (read 1, write 2; 360 points / 60s). Check Retry-After.
Every error has the same shape: see Errors.
curl -X PATCH "https://app.stoqapp.com/api/v2/external/preorders/offers/73a74948-2b57-4cc3-971f-2b441828c977/batches" \
-H "X-Auth-Token: $STOQ_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"release_strategy": "sequential",
"items": {
"6f1c9e2a-0d4b-4c1e-9a57-2f0e8d3b7c11": {
"quantity_limit": 120
}
}
}'const res = await fetch("https://app.stoqapp.com/api/v2/external/preorders/offers/73a74948-2b57-4cc3-971f-2b441828c977/batches", {
method: "PATCH",
headers: {
"X-Auth-Token": process.env.STOQ_API_KEY,
"Content-Type": "application/json",
},
body: JSON.stringify({
"release_strategy": "sequential",
"items": {
"6f1c9e2a-0d4b-4c1e-9a57-2f0e8d3b7c11": {
"quantity_limit": 120
}
}
}),
});
const data = await res.json();import os
import requests
res = requests.patch(
"https://app.stoqapp.com/api/v2/external/preorders/offers/73a74948-2b57-4cc3-971f-2b441828c977/batches",
headers={"X-Auth-Token": os.environ["STOQ_API_KEY"]},
json={
"release_strategy": "sequential",
"items": {
"6f1c9e2a-0d4b-4c1e-9a57-2f0e8d3b7c11": {
"quantity_limit": 120
}
}
},
)
data = res.json()require "net/http"
require "json"
uri = URI("https://app.stoqapp.com/api/v2/external/preorders/offers/73a74948-2b57-4cc3-971f-2b441828c977/batches")
req = Net::HTTP::Patch.new(uri, "X-Auth-Token" => ENV["STOQ_API_KEY"], "Content-Type" => "application/json")
req.body = {
release_strategy: "sequential",
items: {
"6f1c9e2a-0d4b-4c1e-9a57-2f0e8d3b7c11" => {
quantity_limit: 120
}
}
}.to_json
res = Net::HTTP.start(uri.host, uri.port, use_ssl: true) { |http| http.request(req) }
data = JSON.parse(res.body){
"release_strategy": "sequential",
"advance_schedule": "automatic",
"label_format": "Batch {{ n }}",
"status_text": {
"past": "Sold out",
"live": "Live",
"upcoming": "Coming soon"
},
"widget": {
"style": "roadmap",
"progress": "counts",
"show_other_ship_dates": true,
"show_names": false
},
"items": [
{
"id": "6f1c9e2a-0d4b-4c1e-9a57-2f0e8d3b7c11",
"position": 1,
"quantity_limit": 120,
"shipping_text": "Ships in June",
"label": "Batch 1"
},
{
"id": "a3d8b5f0-7e21-4b9c-8f64-1c2d9e0a5b37",
"position": 2,
"quantity_limit": 200,
"shipping_text": "Ships in July",
"label": "Batch 2"
}
]
}{
"errors": [
"Invalid API key"
],
"code": "auth_invalid",
"details": [
{
"code": "auth_invalid",
"message": "Invalid API key",
"path": null,
"value": null,
"expected": null
}
]
}{
"errors": [
"Offer not found"
],
"code": "not_found",
"details": [
{
"code": "not_found",
"message": "Offer not found",
"path": null,
"value": null,
"expected": null
}
]
}{
"errors": [
"A request with this Idempotency-Key is still running"
],
"code": "idempotency_key_in_progress",
"details": [
{
"code": "idempotency_key_in_progress",
"message": "A request with this Idempotency-Key is still running",
"path": null,
"value": null,
"expected": null
}
]
}{
"errors": [
"widget.button.text_color must be a hex color"
],
"code": "invalid_params",
"details": [
{
"code": "invalid_params",
"message": "must be a hex color",
"path": "widget.button.text_color",
"value": "blue",
"expected": {
"type": "string"
}
}
]
}{
"errors": [
"Rate limit exceeded"
],
"code": "rate_limited",
"details": [
{
"code": "rate_limited",
"message": "Rate limit exceeded",
"path": null,
"value": null,
"expected": null
}
]
}