Skip to content

Offer

The preorder offer (selling plan) resource: CRUD, lifecycle, schedule, discard/restore.

BetaAPI v2 is in public beta: endpoints, fields and behaviour can change before general availability. See the changelog

Last updated

A preorder offer is the top-level entity merchants configure. It carries everything from deposit configuration to widget copy, and attaches to a set of product variants. v2 splits the surface into:

  • CRUD — list / read / create / update / discard / restore / duplicate.
  • Lifecycle — enable / disable / schedule / unschedule.
  • Capabilities — twelve sub-groups for each configuration concern. See Offer capabilities.

Path prefix: /preorders/offers

GET /preorders/offers

Open in the API reference

Returns paginated offers in the shop, newest first. The response key is offers:

{
"offers": [ { "id": "uuid", "name": "Spring Drop", "...": "..." } ],
"summary": { "total": 12, "live": 7, "scheduled": 1, "off": 4 },
"meta": { "total_count": 12, "page": 1, "per_page": 25, "total_pages": 1 }
}
Param Type Default
page integer 1
per_page integer 25
search string Matches offer name, internal name, or an attached product’s title
status all / live / scheduled / off / deleted all
shopify_market_ids array of Shopify Market GIDs (numeric ids also accepted)
sort created_at desc / created_at asc / internal_name asc / internal_name desc / preorder_revenue desc / preorder_revenue asc created_at desc
expand comma-separated or array: inventory, shipping, payments, markets, products none

expand adds those capability blocks to each row, in the same shape as the capability’s own read (for example GET /preorders/offers/:id/shipping). Use it to read a page of offers with their settings in one call. The products block has the collection id but not its name; read GET /preorders/offers/:id/products for the name.

status=deleted lists the deleted offers, the Deleted offer group of the Reports orders filter; every other value, all included, leaves them out. Pass their ids to the orders list’s offer_id.

summary counts every offer that matches the filters, not only this page, by its current_status (live, scheduled, off; with status=deleted, total and deleted).

Aliases: “list offers”, “show all offers”, “preorder offers”, “all preorders”

GET /preorders/offers/:id

Open in the API reference

Returns the full offer including a capabilities block summarizing every capability’s current state.

POST /preorders/offers

Open in the API reference

Body field Required Notes
name no Merchant-facing name (defaults to “Preorder”)
internal_name no Slug/reference (defaults to name)

Capability settings are configured after creation via their respective capability actions — there is intentionally no kitchen-sink create body.

Returns: 202 Accepted with the new offer (like every v2 write — see Errors & Responses).

PATCH /preorders/offers/:id

Open in the API reference

For only the fields not owned by a capability — name and internal_name. Deep partial: absent fields are unchanged; name cannot be blank; internal_name: null restores the default label (“Preorder N”). Capability keys and read-only fields return 422.

Aliases: “rename offer”, “change offer name”, “rename preorder”, “change internal name”, “relabel offer”, “edit offer”

Notes: everything else lives on a capability. Settings and toggles go through the capability’s PATCH; side-effectful operations have named POST actions. See Offer capabilities.

POST /preorders/offers/:id/discard

Open in the API reference

Aliases: “delete”, “remove”, “archive”, “trash”, “soft delete” Notes: The dashboard’s Archive: the offer is turned off, its schedule removed and its variants reset on Shopify before it is discarded. If Shopify refuses, the response is 502 and nothing changes. Recoverable indefinitely via restore.

POST /preorders/offers/:id/restore

Open in the API reference

Aliases: “undelete”, “undiscard”, “undo delete”, “bring back” Notes: The offer comes back off with no schedule. Variant attachments are not restored. Re-attach via the Products capability.

POST /preorders/offers/:id/duplicate

Open in the API reference

Aliases: “copy offer”, “clone offer”, “duplicate preorder”, “copy preorder” Notes: The dashboard’s Duplicate. Returns 202 with the new offer, in the same shape as GET /preorders/offers/:id. The copy keeps every setting, payment option and batch, is named “<internal_name> (Copy)”, and starts off with no products, no schedule and no automatic hold release. A ship or balance date already in the past is reset.

The lifecycle actions are intent-bearing wrappers around state changes that have side effects on inventory policy and Shopify selling-plan-group sync.

POST /preorders/offers/:id/enable

Open in the API reference

Body field Type Default Notes
update_inventory_policy boolean false If true, flips attached variants’ inventory_policy to CONTINUE
shopify_variant_ids array all attached Restrict the inventory-policy flip to these Shopify variant gids

Aliases: “turn on”, “activate”, “launch”, “go live”, “start offer” Notes: Variants are left at their existing inventory policy unless update_inventory_policy: true is passed. On a scheduled offer, enable starts it now, as the dashboard does: the start date is cleared, an end date is kept, and with no end date the schedule is removed.

POST /preorders/offers/:id/disable

Open in the API reference

Body field Type Default Notes
update_inventory_policy boolean false If true, flips attached variants’ inventory_policy back to DENY
shopify_variant_ids array all attached Restrict the inventory-policy flip to these Shopify variant gids

Aliases: “pause”, “turn off”, “deactivate”, “stop offer”, “end preorder”, “disable and stop overselling”, “close out preorder” Notes: On a scheduled or dated offer, disable also removes the schedule, as the dashboard does, so the offer stays off instead of starting on its start date.

POST /preorders/offers/:id/schedule

Open in the API reference

Body field Type Notes
start Shop-local time, e.g. 2026-09-30T18:00 (no Z or offset) Optional
end Shop-local time Optional

Aliases: “set schedule”, “schedule launch”, “set start date”, “set end date”, “schedule offer” Notes: Like the editor: start only, or a window, turns the offer off until the start; end only turns it on until the end. Changing the kind of schedule turns the countdown off, reported in also_changed.

POST /preorders/offers/:id/unschedule

Open in the API reference

Aliases: “clear schedule”, “remove schedule”, “no schedule”, “unschedule offer”

Removes the schedule. A live offer stays on; any other stays off.

POST /preorders/offers/bulk_enable
POST /preorders/offers/bulk_disable
Body field Type Default Notes
ids array of offer ids required The offers to turn on (or off)
update_inventory_policy boolean false bulk_enable: flips the attached variants to CONTINUE. bulk_disable: flips them to DENY

Aliases: “bulk enable offers”, “turn on offers”, “bulk disable offers”, “turn off offers” Notes: The Offers list’s bulk Enable / Disable. Each offer changes as the single enable / disable does (a scheduled offer starts now; disabling removes the schedule). The inventory policy flip applies to offers that use STOQ inventory; an offer with more than 250 variants is flipped in the background. An unknown id, another shop’s offer or a deleted offer returns 422 under errors.ids and nothing changes. An offer that cannot change (for example the plan’s offer limit) is counted in failed with its reason in failed_errors; the others still change. Returns 202:

{ "total": 2, "updated": 2, "inventory_updates_initiated": 1,
"offers": [{ "id": "…", "name": "…", "current_status": "live", "…": "…" }] }

Every other action on an offer is grouped under one of twelve capabilities — see Offer capabilities for the full tables. Each capability has:

  • a Read action (GET the capability’s current state)
  • an Update action (PATCH, deep partial) — the home of all settings and boolean toggles
  • named POST actions only where an operation has side effects beyond writing settings

(Translations is the one exception: it has no PATCH — translation writes are keyed set / unset / set_many actions.)

Was this page helpful?

Still stuck? Ask Quinn or chat with support