Update a countdown on an offer
API v2 is in public beta: endpoints and fields can change before general availability. See the changelog
/preorders/offers/{id}/countdownCosts 2 rate-limit points · Rate limits
Update any subset of the countdown timer settings on a preorder offer.
Deep partial: absent fields are unchanged; current is read-only.
Also searched asedit countdownchange timermodify countdown settingsenable countdownshow timerturn on countdownenable countdown timerdisable countdownhide timerturn off countdowndisable countdown timerset countdown textset timer textchange countdown labelset timer labelset custom end dateset timer end datechange timer deadlineset ends textset timer end textset 'ends in' textset countdown modechange timer modeuse schedule for timeruse custom date for timerset starts textset timer pre-launch textset 'starts in' textset timer stylechange timer styleset countdown stylechange timer colorscountdown labelstimer labelsrename days labelchange hours labelcountdown unit names
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
show_whenstringdisabled hides the timer; before_launch counts down to the start, during_preorder to the end, both to the start and then the end. It is read back from the dates: both switches date_source to schedule unless date_source is sent, and with custom dates before_launch clears ends_at and during_preorder clears starts_at.
One ofdisabledbefore_launchduring_preorderbothdate_sourcestringschedule uses the offer schedule start and end dates; custom uses starts_at and ends_at.
One ofschedulecustomstarts_atstringCustom launch date and time. Without Z or an offset it is the shop's local time (2026-09-30T18:00). null clears it. Used when date_source is custom.
ends_atstringCustom deadline date and time. Without Z or an offset it is the shop's local time (2026-09-30T18:00). null clears it. Used when date_source is custom.
starts_textstringHeading shown before launch.
ends_textstringHeading shown during the preorder.
labelsobjectShow 4 child attributesHide child attributes
daysstringDays label.
hoursstringHours label.
minutesstringMinutes label.
secondsstringSeconds label.
text_colorstringTimer text color. Hex.
background_colorstringTimer background color. Hex.
border_radiusintegerCorner radius in pixels.
unitsarray of anysTime units to display, any of days, hours, minutes, seconds.
localestringLanguage the translated fields are written in, such as 'fr' or 'pt-BR'. Omitted: the shop's default language. Untranslated fields ignore it.
Returns
show_whenstringExample:during_preorderdate_sourcestringExample:customstarts_atanyends_atstringExample:2026-09-30T18:00:00Zstarts_textanyends_textanylabelsobjectShow 4 child attributesHide child attributes
daysstringExample:DayshoursstringExample:HoursminutesstringExample:MinssecondsstringExample:Secs
text_colorstringExample:#000000background_colorstringExample:#f5f5f5border_radiusintegerExample:8unitsarray of stringscurrentobjectShow 3 child attributesHide child attributes
visible_phasestringExample:during_preordertarget_atstringExample:2026-09-30T18:00:00Zheading_textany
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/countdown" \
-H "X-Auth-Token: $STOQ_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"show_when": "during_preorder",
"date_source": "custom",
"ends_at": "2026-09-30T18:00:00Z"
}'const res = await fetch("https://app.stoqapp.com/api/v2/external/preorders/offers/73a74948-2b57-4cc3-971f-2b441828c977/countdown", {
method: "PATCH",
headers: {
"X-Auth-Token": process.env.STOQ_API_KEY,
"Content-Type": "application/json",
},
body: JSON.stringify({
"show_when": "during_preorder",
"date_source": "custom",
"ends_at": "2026-09-30T18:00:00Z"
}),
});
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/countdown",
headers={"X-Auth-Token": os.environ["STOQ_API_KEY"]},
json={
"show_when": "during_preorder",
"date_source": "custom",
"ends_at": "2026-09-30T18:00:00Z"
},
)
data = res.json()require "net/http"
require "json"
uri = URI("https://app.stoqapp.com/api/v2/external/preorders/offers/73a74948-2b57-4cc3-971f-2b441828c977/countdown")
req = Net::HTTP::Patch.new(uri, "X-Auth-Token" => ENV["STOQ_API_KEY"], "Content-Type" => "application/json")
req.body = {
show_when: "during_preorder",
date_source: "custom",
ends_at: "2026-09-30T18:00:00Z"
}.to_json
res = Net::HTTP.start(uri.host, uri.port, use_ssl: true) { |http| http.request(req) }
data = JSON.parse(res.body){
"show_when": "during_preorder",
"date_source": "custom",
"starts_at": null,
"ends_at": "2026-09-30T18:00:00Z",
"starts_text": null,
"ends_text": null,
"labels": {
"days": "Days",
"hours": "Hours",
"minutes": "Mins",
"seconds": "Secs"
},
"text_color": "#000000",
"background_color": "#f5f5f5",
"border_radius": 8,
"units": [
"days",
"hours",
"minutes",
"seconds"
],
"current": {
"visible_phase": "during_preorder",
"target_at": "2026-09-30T18:00:00Z",
"heading_text": null
}
}{
"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
}
]
}