Update a widget on an offer
API v2 is in public beta: endpoints and fields can change before general availability. See the changelog
/preorders/offers/{id}/widgetCosts 2 rate-limit points · Rate limits
Update any subset of the widget configuration on a preorder offer.
Deep partial: absent fields are unchanged. Text can be cleared with null. Button colors only show with button.custom_colors_enabled: true, so send both.
Also searched asedit widgetchange widget settingsmodify widgetupdate preorder uienable badgeshow badgeturn on badgemake badge visibledisable badgehide badgeturn off badgeremove badgeenable disclaimershow disclaimerturn on disclaimershow fine printshow shipping noticedisable disclaimerhide disclaimerturn off disclaimerhide fine printremove shipping noticeremove disclaimerenable custom button colorsuse custom button colorsturn on button colorsapply custom colorsdisable custom button colorsuse theme button colorsturn off button colorsrevert to theme colorschange badge colorsset badge colorcustomize badge colorschange badge backgroundchange badge textset badge labelrename badgechange preorder badge textupdate badge textchange button colorsset button colorcustomize button colorschange button textrename buttonset button labelchange preorder button labelupdate button textchange disclaimer colorsset disclaimer stylestyle the disclaimerset disclaimer border radiuschange disclaimer backgroundchange disclaimer textset disclaimer textedit disclaimerchange disclaimer messageset shipping disclaimer
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
buttonobjectShow 4 child attributesHide child attributes
button_textstring, nullableButton text -- the preorder call-to-action label.
text_colorstringThe button's Text color. Hex. Only shows when button.custom_colors_enabled is true; send it too.
background_colorstringThe button's Background color. Hex. Only shows when button.custom_colors_enabled is true; send it too.
custom_colors_enabledbooleanUse custom colors for button. False falls back to the theme's own button colors.
disclaimerobjectShow 5 child attributesHide child attributes
show_disclaimerbooleanAdd disclaimer -- shows or hides the disclaimer line under the button.
disclaimer_textstring, nullableDisclaimer -- the line shown under the preorder button.
text_colorstringThe disclaimer's Text color. Hex.
background_colorstringThe disclaimer's Background color. Hex.
border_radiusintegerThe disclaimer's Border radius in pixels.
badgeobjectShow 4 child attributesHide child attributes
show_badgebooleanAdd badge -- shows or hides the preorder badge. On product pages it sits after the price by default. On home, collection and search pages it shows on the product card, only where Preorder pages turns the Preorder button on.
badge_textstring, nullableBadge -- the label printed on the preorder badge.
text_colorstringThe badge's Text color. Hex.
background_colorstringThe badge's Background color. Hex.
localestringLanguage the translated fields are written in, such as 'fr' or 'pt-BR'. Omitted: the shop's default language. Untranslated fields ignore it.
Returns
buttonobjectShow 4 child attributesHide child attributes
button_textstringExample:Reserve Nowcustom_colors_enabledbooleanExample:truetext_colorstringExample:#FFFFFFbackground_colorstringExample:#1a1a1a
disclaimerobjectShow 5 child attributesHide child attributes
show_disclaimerbooleanExample:truedisclaimer_textstringExample:Expected to ship by August 2026text_colorstringExample:#000000background_colorstringExample:#FFFFFFborder_radiusintegerExample:4
badgeobjectShow 4 child attributesHide child attributes
show_badgebooleanExample:truebadge_textstringExample:Pre-Ordertext_colorstringExample:#000000background_colorstringExample:#FFFFFF
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/widget" \
-H "X-Auth-Token: $STOQ_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"button": {
"button_text": "Reserve Now"
}
}'const res = await fetch("https://app.stoqapp.com/api/v2/external/preorders/offers/73a74948-2b57-4cc3-971f-2b441828c977/widget", {
method: "PATCH",
headers: {
"X-Auth-Token": process.env.STOQ_API_KEY,
"Content-Type": "application/json",
},
body: JSON.stringify({
"button": {
"button_text": "Reserve Now"
}
}),
});
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/widget",
headers={"X-Auth-Token": os.environ["STOQ_API_KEY"]},
json={
"button": {
"button_text": "Reserve Now"
}
},
)
data = res.json()require "net/http"
require "json"
uri = URI("https://app.stoqapp.com/api/v2/external/preorders/offers/73a74948-2b57-4cc3-971f-2b441828c977/widget")
req = Net::HTTP::Patch.new(uri, "X-Auth-Token" => ENV["STOQ_API_KEY"], "Content-Type" => "application/json")
req.body = {
button: {
button_text: "Reserve Now"
}
}.to_json
res = Net::HTTP.start(uri.host, uri.port, use_ssl: true) { |http| http.request(req) }
data = JSON.parse(res.body){
"button": {
"button_text": "Reserve Now",
"custom_colors_enabled": true,
"text_color": "#FFFFFF",
"background_color": "#1a1a1a"
},
"disclaimer": {
"show_disclaimer": true,
"disclaimer_text": "Expected to ship by August 2026",
"text_color": "#000000",
"background_color": "#FFFFFF",
"border_radius": 4
},
"badge": {
"show_badge": true,
"badge_text": "Pre-Order",
"text_color": "#000000",
"background_color": "#FFFFFF"
}
}{
"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
}
]
}