{"openapi":"3.1.0","info":{"title":"Offer Suite API","version":"1.0.0","description":"Offers as validated documents: author through this API or the MCP, publish once, verify with a real cart, hand brands the resolved offer and the cart. Authenticate with `Authorization: Bearer <api key>`.","contact":{"name":"Blackout Media","url":"https://offersuite.io"},"license":{"name":"Proprietary","url":"https://offersuite.io/terms"}},"servers":[{"url":"https://api.offersuite.io","description":"Production"},{"url":"https://dev-api.offersuite.io","description":"Development"}],"tags":[{"name":"Offers","description":"Offer documents and their versions"},{"name":"Stores","description":"Connected Shopify stores"},{"name":"Orders","description":"Orders ingested from the connected stores' webhooks"},{"name":"Costs","description":"Cost kinds and versioned cost rows behind the margin numbers"},{"name":"Items","description":"Physical SKUs, the variant map, bills of materials, and realized profit per item"},{"name":"Experiments","description":"Profit-per-visitor experiments between versions of an offer"},{"name":"Events","description":"The funnel event ladder from the browser SDK and the Web Pixel"},{"name":"Privacy","description":"Shopify's mandatory compliance requests and what was done about each"},{"name":"Tenant","description":"The tenant's own settings"}],"components":{"securitySchemes":{"apiKey":{"type":"http","scheme":"bearer","description":"Offer Suite API key: `os_sk_…` (secret, full access) or `os_pk_…` (public, read-only routes). A public key is rate-limited per key and client address. A server calling the public routes for its visitors (a server-rendered page) uses a secret key and sends each visitor's address in `Offer-Suite-Buyer-IP`: it is then limited per visitor, as a browser would be, and the cart forwards that address to Shopify."}},"schemas":{},"parameters":{}},"paths":{"/offers":{"get":{"operationId":"listOffers","summary":"List offers","description":"Every offer of the tenant, newest change first, summarized at its current version with a verification summary.","tags":["Offers"],"security":[{"apiKey":[]}],"parameters":[{"schema":{"type":"integer","minimum":1,"maximum":200,"default":50},"required":false,"name":"limit","in":"query"},{"schema":{"type":["integer","null"],"minimum":0,"default":0},"required":false,"name":"offset","in":"query"}],"responses":{"200":{"description":"The page of offers","content":{"application/json":{"schema":{"type":"object","properties":{"offers":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"code":{"type":"string","description":"The offer's code; unique per tenant, immutable"},"experienceName":{"type":"string","description":"`tracking.experienceName` of the summarized version: the human handle for the offer"},"defaultOptionKey":{"type":"string","description":"The option a renderer preselects, in the summarized version"},"status":{"type":"string","enum":["draft","verified","live","retired"],"description":"The live version's status when one exists, else the current version's"},"currentVersion":{"type":"integer","exclusiveMinimum":0},"liveVersion":{"type":["integer","null"],"exclusiveMinimum":0},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"},"version":{"type":"object","properties":{"number":{"type":"integer","exclusiveMinimum":0},"status":{"type":"string","enum":["draft","verified","live","retired"]},"createdAt":{"type":"string","format":"date-time"}},"required":["number","status","createdAt"]},"options":{"type":"array","items":{"type":"object","properties":{"key":{"type":"string","description":"The option key"},"title":{"type":"string","description":"The option's `display.title`"},"visible":{"type":"boolean","description":"Whether a renderer may show the option; only visible options are verified"},"promise":{"type":"object","properties":{"firstChargeCents":{"type":["integer","null"],"minimum":0,"description":"What the buyer is charged on the first order, before shipping and tax; required on a visible option. Publish checks a real cart charges it"},"renewalChargeCents":{"type":["integer","null"],"minimum":0,"description":"What each renewal charges, before shipping and tax; required when the option has a subscription line"}},"required":["firstChargeCents","renewalChargeCents"],"additionalProperties":false,"description":"What the option promises the buyer is charged"},"mechanisms":{"type":"array","items":{"type":"string"},"description":"The option's pricing mechanism types, in document order"},"verificationStatus":{"type":"string","enum":["matched","mismatched","unverifiable","unverified"],"description":"Whether a real cart charges what the option promises: `matched`; `mismatched` when a check failed or Shopify refused the cart; `unverifiable` when a check of the promise could not run; `unverified` when never checked (a hidden option). An option goes live only when `matched`"}},"required":["key","title","visible","promise","mechanisms","verificationStatus"]}},"verification":{"type":"object","properties":{"options":{"type":"integer","minimum":0,"description":"Every option of the version, visible or not"},"matched":{"type":"integer","minimum":0,"description":"Options a real cart charges exactly as promised"},"mismatched":{"type":"integer","minimum":0,"description":"Options a check failed on, or whose cart Shopify refused"},"unverifiable":{"type":"integer","minimum":0,"description":"Options a check of the promise could not run on"},"unverified":{"type":"integer","minimum":0,"description":"Options never checked: every hidden option, and every option of a version never published"},"lastCheckedAt":{"type":["string","null"],"format":"date-time","description":"When the verifier last ran on any option of the version"}},"required":["options","matched","mismatched","unverifiable","unverified","lastCheckedAt"],"description":"Verification status counts across the version's options"},"orderCount":{"type":"integer","minimum":0,"description":"Ingested orders attributed to this offer, across versions"}},"required":["id","code","experienceName","defaultOptionKey","status","currentVersion","liveVersion","createdAt","updatedAt","version","options","verification","orderCount"]}},"limit":{"type":"integer","exclusiveMinimum":0},"offset":{"type":"integer","minimum":0}},"required":["offers","limit","offset"]}}}},"400":{"description":"Invalid query","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}},"401":{"description":"Missing, unknown or revoked API key","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}},"403":{"description":"The key is public; this route needs a secret key","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}}}},"post":{"operationId":"createOffer","summary":"Create an offer","description":"Validates the document against the offer schema and stores it as version 1 in status draft. `id`, `version` and `status` are assigned by the server; `code` must be unique per tenant.","tags":["Offers"],"security":[{"apiKey":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"schemaVersion":{"type":"string","enum":["offer/1"],"description":"The document format: `offer/1`"},"code":{"type":"string","maxLength":31,"pattern":"^[^,\\s](?:[^,]*[^,\\s])?$","description":"The offer's code: unique per tenant, immutable once created, and how an agent, `lookup_offer` and the order tag `os_offer:<code>` name the offer"},"tracking":{"type":"object","properties":{"experienceName":{"type":"string","minLength":1,"description":"A label for the page or funnel this offer runs in; the offers list shows it"},"campaignName":{"type":"string","minLength":1,"description":"A label for the marketing campaign this offer belongs to"},"presellPageName":{"type":["string","null"],"minLength":1,"description":"A label for the presell page in front of the offer, or null"},"preservedCartAttributes":{"type":"array","items":{"type":"string","minLength":1},"description":"The brand's own cart attribute names a cart request may set and the API keeps on the cart (`preservedCartAttributes` on the cart request)"}},"required":["experienceName","campaignName","presellPageName","preservedCartAttributes"],"additionalProperties":false,"description":"The labels reports group by, and the brand's own cart attributes a cart keeps"},"store":{"type":"object","properties":{"myshopifyDomain":{"type":"string","minLength":1,"description":"The connected store's myshopify domain (`brand.myshopify.com`); publish and serving use this store"},"market":{"type":"object","properties":{"countryCode":{"type":"string","pattern":"^[A-Z]{2}$","description":"The buyer's country, ISO 3166-1 alpha-2; carts are priced in its market"},"currencyCode":{"type":"string","pattern":"^[A-Z]{3}$","description":"The market's currency, ISO 4217; every amount in the document is in it"}},"required":["countryCode","currencyCode"],"additionalProperties":false,"description":"The one market the offer is priced in"}},"required":["myshopifyDomain","market"],"additionalProperties":false,"description":"The connected store and the market the offer is priced in"},"axes":{"type":"array","items":{"type":"object","properties":{"key":{"type":"string","maxLength":64,"pattern":"^[a-z0-9][a-z0-9_-]*$","description":"Names the axis; options and axis-mapped lines refer to it"},"values":{"type":"array","items":{"type":"string","minLength":1},"minItems":1,"description":"Every value the axis takes"}},"required":["key","values"],"additionalProperties":false},"description":"Dimensions the options vary along (flavour, size); they name and enumerate options, never patch one"},"pools":{"type":"array","items":{"type":"object","properties":{"key":{"type":"string","maxLength":64,"pattern":"^[a-z0-9][a-z0-9_-]*$","description":"Names the pool; a pool-bound line refers to it"},"variantIds":{"type":"array","items":{"type":"string","pattern":"^gid:\\/\\/shopify\\/ProductVariant\\/\\d+$","description":"A Shopify ProductVariant gid (`gid://shopify/ProductVariant/<id>`)"},"minItems":1,"description":"The pool's variants"},"allowRepeats":{"type":"boolean","description":"Whether one variant may be chosen more than once"}},"required":["key","variantIds","allowRepeats"],"additionalProperties":false},"description":"Pools a buyer chooses variants from, through a line bound to the pool"},"defaultOptionKey":{"type":"string","maxLength":64,"pattern":"^[a-z0-9][a-z0-9_-]*$","description":"The option a renderer preselects; must name a visible option"},"options":{"type":"array","items":{"type":"object","properties":{"key":{"type":"string","maxLength":30,"pattern":"^[a-z0-9][a-z0-9_-]*$","description":"Names the option: unique in the document, carried in the cart pointer, the order tag `os_option:<key>` (so at most 30 characters) and the economics. Keep it stable"},"display":{"type":"object","properties":{"title":{"type":"string","minLength":1,"description":"The option's name as a buyer reads it"}},"required":["title"],"additionalProperties":false,"description":"What a renderer shows for the option"},"visible":{"type":"boolean","description":"Whether a renderer may show the option and publish verifies it; a hidden option still resolves and builds carts"},"axisValues":{"type":"object","additionalProperties":{"type":"string"},"description":"The option's value on each document axis, by axis key"},"unitCount":{"type":"integer","exclusiveMinimum":0,"description":"The quantity the buyer perceives (\"4 units\"); not the sum of line quantities"},"cardKey":{"type":"string","maxLength":64,"pattern":"^[a-z0-9][a-z0-9_-]*$","description":"Options sharing a card key are drawn as one card (a subscribe and one-time pair of one product)"},"lines":{"type":"array","items":{"oneOf":[{"type":"object","properties":{"role":{"type":"string","enum":["main","add_on"],"description":"`main` is what the buyer pays for; `add_on` an extra"},"key":{"type":"string","maxLength":64,"pattern":"^[a-z0-9][a-z0-9_-]*$","description":"Names the line inside its option; required on an optional non-gift line, which a cart opts into by this key (`addOnLineKeys`)"},"quantity":{"type":"integer","exclusiveMinimum":0,"description":"Units of the variant in the cart; on a pool-bound line, the fewest the buyer may choose"},"maxQuantity":{"type":"integer","exclusiveMinimum":0,"description":"A pool-bound line only: the most units the buyer may choose"},"required":{"type":"boolean","description":"Whether every cart for the option holds the line; an optional line is added only when the cart request names its key"},"variantSource":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","enum":["fixed"],"description":"The line is one named variant"},"productId":{"type":"string","pattern":"^gid:\\/\\/shopify\\/Product\\/\\d+$","description":"The variant's product"},"variantId":{"type":"string","pattern":"^gid:\\/\\/shopify\\/ProductVariant\\/\\d+$","description":"The variant the line puts in the cart"}},"required":["type","productId","variantId"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","enum":["axis_map"],"description":"The variant follows the option's axis values, through `variantIdByAxisValue`"},"productId":{"type":"string","pattern":"^gid:\\/\\/shopify\\/Product\\/\\d+$","description":"The product every mapped variant belongs to"},"axisKeys":{"type":"array","items":{"type":"string","maxLength":64,"pattern":"^[a-z0-9][a-z0-9_-]*$","description":"A key the brand authors: lower-case letters, digits, `_` and `-`"},"minItems":1,"description":"The document axes whose values choose the variant, in `variantIdByAxisValue`'s key order"},"variantIdByAxisValue":{"type":"object","additionalProperties":{"type":"string","pattern":"^gid:\\/\\/shopify\\/ProductVariant\\/\\d+$","description":"A Shopify ProductVariant gid (`gid://shopify/ProductVariant/<id>`)"},"description":"Variant id by axis value; for several `axisKeys`, keyed by the values joined with \"/\" in `axisKeys` order. Must cover exactly the declared values"}},"required":["type","productId","axisKeys","variantIdByAxisValue"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","enum":["pool"],"description":"The buyer chooses the variants from a pool: `quantity` units, up to `maxQuantity`, any mix of the pool's variants; the cart gets one line per distinct variant"},"poolKey":{"type":"string","maxLength":64,"pattern":"^[a-z0-9][a-z0-9_-]*$","description":"The `pools[].key` the buyer chooses from"}},"required":["type","poolKey"],"additionalProperties":false}],"description":"Where the line's variant comes from"},"purchase":{"type":"object","properties":{"type":{"type":"string","enum":["one_time","subscription"],"description":"Bought once, or on a selling plan"},"sellingPlanId":{"type":"string","pattern":"^gid:\\/\\/shopify\\/SellingPlan\\/\\d+$","description":"The selling plan a subscription line is bought on; required when `type` is `subscription`"},"intervalDays":{"type":"integer","exclusiveMinimum":0,"description":"Days between a subscription's charges, as shown to the buyer"},"plans":{"type":"array","items":{"type":"object","properties":{"fromUnits":{"type":"integer","exclusiveMinimum":0,"description":"The fewest units of the group this plan's tier applies to; the first tier is 1"},"intervalDays":{"type":"integer","exclusiveMinimum":0,"description":"The cadence this plan renews on, one of the option's `cadence` intervals"},"sellingPlanId":{"type":"string","pattern":"^gid:\\/\\/shopify\\/SellingPlan\\/\\d+$","description":"The selling plan the group's lines go on at this tier and cadence"}},"required":["fromUnits","intervalDays","sellingPlanId"],"additionalProperties":false},"minItems":1,"description":"A subscription group's plan for each tier and cadence a cart can reach; `sellingPlanId` is one of them"}},"required":["type"],"additionalProperties":false,"description":"How the line is bought: once, or on a selling plan"},"bundleComponents":{"type":"array","items":{"type":"object","properties":{"variantId":{"type":"string","pattern":"^gid:\\/\\/shopify\\/ProductVariant\\/\\d+$","description":"A component variant of the fixed bundle"},"quantity":{"type":"integer","exclusiveMinimum":0,"description":"Units of that component in one bundle"}},"required":["variantId","quantity"],"additionalProperties":false},"minItems":1,"description":"What one unit holds, when the variant is a Shopify fixed bundle"},"catalogPrice":{"type":"object","properties":{"amountCents":{"type":"integer","minimum":0,"description":"The variant's catalog price when the document was written; line pricing starts from it"},"compareAtAmountCents":{"type":["integer","null"],"minimum":0,"description":"The variant's catalog compare-at price then, or null"},"capturedAt":{"type":"string","format":"date-time","description":"When the price was read from the catalog"}},"required":["amountCents","compareAtAmountCents","capturedAt"],"additionalProperties":false,"description":"The catalog price line pricing starts from"}},"required":["role","quantity","required","variantSource","purchase","catalogPrice"],"additionalProperties":false},{"type":"object","properties":{"role":{"type":"string","enum":["gift"],"description":"A real product the discount function prices to zero"},"key":{"type":"string","maxLength":64,"pattern":"^[a-z0-9][a-z0-9_-]*$","description":"Names the line inside its option; required on an optional non-gift line, which a cart opts into by this key (`addOnLineKeys`)"},"quantity":{"type":"integer","exclusiveMinimum":0,"description":"Units of the variant in the cart; on a pool-bound line, the fewest the buyer may choose"},"maxQuantity":{"type":"integer","exclusiveMinimum":0,"description":"A pool-bound line only: the most units the buyer may choose"},"required":{"type":"boolean","description":"Whether every cart for the option holds the line; an optional line is added only when the cart request names its key"},"variantSource":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","enum":["fixed"],"description":"The line is one named variant"},"productId":{"type":"string","pattern":"^gid:\\/\\/shopify\\/Product\\/\\d+$","description":"The variant's product"},"variantId":{"type":"string","pattern":"^gid:\\/\\/shopify\\/ProductVariant\\/\\d+$","description":"The variant the line puts in the cart"}},"required":["type","productId","variantId"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","enum":["axis_map"],"description":"The variant follows the option's axis values, through `variantIdByAxisValue`"},"productId":{"type":"string","pattern":"^gid:\\/\\/shopify\\/Product\\/\\d+$","description":"The product every mapped variant belongs to"},"axisKeys":{"type":"array","items":{"type":"string","maxLength":64,"pattern":"^[a-z0-9][a-z0-9_-]*$","description":"A key the brand authors: lower-case letters, digits, `_` and `-`"},"minItems":1,"description":"The document axes whose values choose the variant, in `variantIdByAxisValue`'s key order"},"variantIdByAxisValue":{"type":"object","additionalProperties":{"type":"string","pattern":"^gid:\\/\\/shopify\\/ProductVariant\\/\\d+$","description":"A Shopify ProductVariant gid (`gid://shopify/ProductVariant/<id>`)"},"description":"Variant id by axis value; for several `axisKeys`, keyed by the values joined with \"/\" in `axisKeys` order. Must cover exactly the declared values"}},"required":["type","productId","axisKeys","variantIdByAxisValue"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","enum":["pool"],"description":"The buyer chooses the variants from a pool: `quantity` units, up to `maxQuantity`, any mix of the pool's variants; the cart gets one line per distinct variant"},"poolKey":{"type":"string","maxLength":64,"pattern":"^[a-z0-9][a-z0-9_-]*$","description":"The `pools[].key` the buyer chooses from"}},"required":["type","poolKey"],"additionalProperties":false}],"description":"Where the line's variant comes from"},"purchase":{"type":"object","properties":{"type":{"type":"string","enum":["one_time","subscription"],"description":"Bought once, or on a selling plan"},"sellingPlanId":{"type":"string","pattern":"^gid:\\/\\/shopify\\/SellingPlan\\/\\d+$","description":"The selling plan a subscription line is bought on; required when `type` is `subscription`"},"intervalDays":{"type":"integer","exclusiveMinimum":0,"description":"Days between a subscription's charges, as shown to the buyer"},"plans":{"type":"array","items":{"type":"object","properties":{"fromUnits":{"type":"integer","exclusiveMinimum":0,"description":"The fewest units of the group this plan's tier applies to; the first tier is 1"},"intervalDays":{"type":"integer","exclusiveMinimum":0,"description":"The cadence this plan renews on, one of the option's `cadence` intervals"},"sellingPlanId":{"type":"string","pattern":"^gid:\\/\\/shopify\\/SellingPlan\\/\\d+$","description":"The selling plan the group's lines go on at this tier and cadence"}},"required":["fromUnits","intervalDays","sellingPlanId"],"additionalProperties":false},"minItems":1,"description":"A subscription group's plan for each tier and cadence a cart can reach; `sellingPlanId` is one of them"}},"required":["type"],"additionalProperties":false,"description":"How the line is bought: once, or on a selling plan"},"bundleComponents":{"type":"array","items":{"type":"object","properties":{"variantId":{"type":"string","pattern":"^gid:\\/\\/shopify\\/ProductVariant\\/\\d+$","description":"A component variant of the fixed bundle"},"quantity":{"type":"integer","exclusiveMinimum":0,"description":"Units of that component in one bundle"}},"required":["variantId","quantity"],"additionalProperties":false},"minItems":1,"description":"What one unit holds, when the variant is a Shopify fixed bundle"},"catalogPrice":{"type":"object","properties":{"amountCents":{"type":"integer","minimum":0,"description":"The variant's catalog price when the document was written; line pricing starts from it"},"compareAtAmountCents":{"type":["integer","null"],"minimum":0,"description":"The variant's catalog compare-at price then, or null"},"capturedAt":{"type":"string","format":"date-time","description":"When the price was read from the catalog"}},"required":["amountCents","compareAtAmountCents","capturedAt"],"additionalProperties":false,"description":"The catalog price line pricing starts from"},"claimedValueCents":{"type":"integer","minimum":0,"description":"The value the page shows for the gift (struck through); never charged: the function zeroes the line, and its cost comes from the ledger"}},"required":["role","quantity","required","variantSource","purchase","catalogPrice","claimedValueCents"],"additionalProperties":false}]},"minItems":1,"description":"What the option puts in the cart"},"maxUnits":{"type":"integer","exclusiveMinimum":0,"description":"A category builder: the most units the option's non-gift lines may hold in all"},"cadence":{"type":"object","properties":{"tiers":{"type":"array","items":{"type":"object","properties":{"fromUnits":{"type":"integer","exclusiveMinimum":0,"description":"The fewest units of the largest subscription group this interval applies to; the first tier is 1"},"intervalDays":{"type":"integer","exclusiveMinimum":0,"description":"Days between charges of every subscription line"}},"required":["fromUnits","intervalDays"],"additionalProperties":false},"minItems":1,"description":"The tiers, ascending from 1; above the last tier the last interval holds"}},"required":["tiers"],"additionalProperties":false,"description":"A category builder: the one interval every subscription line renews on, by the units of the largest subscription group in the cart; required when a line has `purchase.plans`"},"pricing":{"type":"object","properties":{"promise":{"type":"object","properties":{"firstChargeCents":{"type":["integer","null"],"minimum":0,"description":"What the buyer is charged on the first order, before shipping and tax; required on a visible option. Publish checks a real cart charges it"},"renewalChargeCents":{"type":["integer","null"],"minimum":0,"description":"What each renewal charges, before shipping and tax; required when the option has a subscription line"}},"required":["firstChargeCents","renewalChargeCents"],"additionalProperties":false,"description":"What the option promises the buyer is charged"},"compareAtPrice":{"type":"object","properties":{"amountCents":{"type":"integer","minimum":0,"description":"The struck-through amount, in cents"},"source":{"type":"string","enum":["variant","selling_plan","unit_price_times_quantity","metafield","page_copy"],"description":"Where it comes from: the variant's compare-at price, the selling plan's compare-at price, the unit price times the quantity, a metafield, or page copy"}},"required":["amountCents","source"],"additionalProperties":false,"description":"The struck-through price the page shows beside the promise"},"shipping":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","enum":["free"],"description":"The discount function makes the named rates free for carts carrying this option"},"rates":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","enum":["cheapest"],"description":"The cheapest shipping rate in each delivery group"}},"required":["type"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","enum":["all"],"description":"Every shipping rate, express included"}},"required":["type"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","enum":["titles"],"description":"The rates whose title is one of `titles`, ignoring case"},"titles":{"type":"array","items":{"type":"string","minLength":1},"minItems":1,"description":"Rate titles as checkout shows them"}},"required":["type","titles"],"additionalProperties":false}],"description":"Which rates are free"},"charges":{"type":"string","enum":["first","every"],"description":"Which shipments are free: `every` charge (a subscription's renewals too) or the `first` only"},"claimedValueCents":{"type":"integer","minimum":0,"description":"The shipping value the page claims for the free shipment (\"a $6.99 value\"); never charged"},"renewalChargeCents":{"type":"integer","minimum":0,"description":"On a subscription option free on the first charge only: what each renewal's shipping charges. Required there, refused elsewhere"}},"required":["type","rates","charges"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","enum":["charged"],"description":"Shipping is charged at checkout's rates"},"expectedChargeCents":{"type":"integer","minimum":0,"description":"What the forecast assumes a shipment charges, in cents; 0 for none"}},"required":["type","expectedChargeCents"],"additionalProperties":false}],"description":"What the option promises about shipping"},"mechanisms":{"type":"array","items":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","enum":["managed_discount"],"description":"Our app discount prices the lines, from the option map publish writes; works on subscription lines"},"lineRoles":{"type":"array","items":{"type":"string","enum":["main","add_on","gift"],"description":"What a line is in its option: `main` is what the buyer pays for, `add_on` an extra the buyer opts into or is always added, `gift` a real product the discount function prices to zero"},"minItems":1,"description":"The roles of the option's lines this mechanism prices"},"discount":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","enum":["percent"],"description":"A percentage off"},"percent":{"type":"number","minimum":0,"maximum":100,"description":"The percentage off, 0 to 100"}},"required":["type","percent"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","enum":["fixed_amount"],"description":"A fixed amount off"},"amountCents":{"type":"integer","minimum":0,"description":"The amount off, in cents"},"per":{"type":"string","enum":["line","unit"],"description":"Off each line, or off each unit of the line"}},"required":["type","amountCents","per"],"additionalProperties":false}],"description":"How much comes off"},"charges":{"type":"string","enum":["first","every"],"description":"Which charges it prices: `first` the first order only; `every` the first order and every renewal of a subscription line"}},"required":["type","lineRoles","discount","charges"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","enum":["discount_code"],"description":"A Shopify discount code publish creates, applied to the cart the API builds"},"code":{"type":"string","minLength":1,"description":"The code the brand chose; absent, publish mints one"},"purchaseType":{"type":"string","enum":["one_time","subscription","subscription_first_payment_only"],"description":"Which purchases the code prices: one-time lines once, every charge of a subscription line, or a subscription's first order only"},"discount":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","enum":["percent"],"description":"A percentage off"},"percent":{"type":"number","minimum":0,"maximum":100,"description":"The percentage off, 0 to 100"}},"required":["type","percent"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","enum":["fixed_amount"],"description":"A fixed amount off"},"amountCents":{"type":"integer","minimum":0,"description":"The amount off, in cents"}},"required":["type","amountCents"],"additionalProperties":false}],"description":"How much comes off"},"lineRoles":{"type":"array","items":{"type":"string","enum":["main","add_on","gift"],"description":"What a line is in its option: `main` is what the buyer pays for, `add_on` an extra the buyer opts into or is always added, `gift` a real product the discount function prices to zero"},"minItems":1,"description":"The roles of the option's lines this mechanism prices"}},"required":["type","purchaseType","discount","lineRoles"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","enum":["selling_plan_adjustment"],"description":"The selling plan's own price adjustments price the subscription lines on that plan"},"sellingPlanId":{"type":"string","pattern":"^gid:\\/\\/shopify\\/SellingPlan\\/\\d+$","description":"The selling plan, carried by a subscription line of the option"},"adjustments":{"type":"array","items":{"type":"object","properties":{"fromOrder":{"anyOf":[{"type":"integer","exclusiveMinimum":0},{"type":"string","enum":["after_last"]}],"description":"The order from which the adjustment is in effect: N from the Nth order on, until a later one takes over; \"after_last\" after every numbered one (alone, from the first order). Before the first, the catalog price"},"discount":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","enum":["percent"],"description":"A percentage off"},"percent":{"type":"number","minimum":0,"maximum":100,"description":"The percentage off, 0 to 100"}},"required":["type","percent"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","enum":["fixed_amount"],"description":"A fixed amount off"},"amountCents":{"type":"integer","minimum":0,"description":"The amount off, in cents"}},"required":["type","amountCents"],"additionalProperties":false}],"description":"How much the plan takes off the variant's price, per unit"}},"required":["fromOrder","discount"],"additionalProperties":false},"minItems":1,"description":"The plan's price adjustments as Shopify holds them, at most two"}},"required":["type","sellingPlanId","adjustments"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","enum":["catalog_price"],"description":"The variant's catalog price is already the offer price; nothing is discounted"}},"required":["type"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","enum":["existing_automatic_discount"],"description":"An automatic discount the store already runs; we only describe it"},"lineRoles":{"type":"array","items":{"type":"string","enum":["main","add_on","gift"],"description":"What a line is in its option: `main` is what the buyer pays for, `add_on` an extra the buyer opts into or is always added, `gift` a real product the discount function prices to zero"},"minItems":1,"description":"The roles of the option's lines this mechanism prices"},"discount":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","enum":["percent"],"description":"A percentage off"},"percent":{"type":"number","minimum":0,"maximum":100,"description":"The percentage off, 0 to 100"}},"required":["type","percent"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","enum":["fixed_amount"],"description":"A fixed amount off"},"amountCents":{"type":"integer","minimum":0,"description":"The amount off, in cents"}},"required":["type","amountCents"],"additionalProperties":false}],"description":"How much comes off"},"charges":{"type":"string","enum":["first","every"],"description":"Which charges it prices: `first` the first order only; `every` the first order and every renewal of a subscription line"}},"required":["type","lineRoles","discount","charges"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","enum":["unit_price_tiers"],"description":"A category group's first-order unit price by how many units of it the cart holds; our app discount charges it, and the group's selling plans price the renewals"},"lineKey":{"type":"string","maxLength":64,"pattern":"^[a-z0-9][a-z0-9_-]*$","description":"The group: an optional, non-gift line bound to a pool, which a cart opts into by this key"},"tiers":{"type":"array","items":{"type":"object","properties":{"fromUnits":{"type":"integer","exclusiveMinimum":0,"description":"The fewest units of the group this tier's price applies to; the first tier is 1"},"unitCents":{"type":"integer","minimum":0,"description":"What each unit of the group charges on the first order at this tier, in cents"}},"required":["fromUnits","unitCents"],"additionalProperties":false},"minItems":1,"description":"The tiers, ascending from 1; above the last tier the last price holds"}},"required":["type","lineKey","tiers"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","enum":["line_price"],"description":"Our cart transform sets the lines' unit price as their own price, at or below each line's catalog price (never above: a raise is refused): shown as the product's price, with no saving at checkout. One-time lines only, on any store with our cart transform registered: `lineUpdate` on Shopify Plus, the line expanded into itself on every other plan"},"lineKeys":{"type":"array","items":{"type":"string","maxLength":64,"pattern":"^[a-z0-9][a-z0-9_-]*$","description":"A key the brand authors: lower-case letters, digits, `_` and `-`"},"minItems":1,"description":"The one-time lines priced, by key"},"unitCents":{"type":"integer","minimum":0,"description":"What each unit of those lines charges on the first order, in cents"}},"required":["type","lineKeys","unitCents"],"additionalProperties":false}]},"description":"How the promise is made real on Shopify; at most one product discount per line and charge"}},"required":["promise","compareAtPrice","shipping","mechanisms"],"additionalProperties":false,"description":"What the option promises and how Shopify charges it"},"presentations":{"type":"array","items":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","enum":["line_override"],"description":"One line shown with another title or image. It exists only on the cart line: the order keeps the product's real title. Shopify Plus only, except on a line with a line price, where it rides in the line expanded into itself on any plan"},"lineKey":{"type":"string","maxLength":64,"pattern":"^[a-z0-9][a-z0-9_-]*$","description":"The one-time line shown differently"},"title":{"type":"string","minLength":1,"maxLength":255,"description":"What the cart and checkout show as the line's title; the order keeps the product's own title"},"imageUrl":{"type":"string","pattern":"^https:\\/\\/cdn\\.shopify\\.com\\/\\S+$","description":"What the cart and checkout show as the line's image; never kept on the order"}},"required":["type","lineKey"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","enum":["merged_bundle"],"description":"Several lines merged into one titled parent line in the cart and at checkout; on the order, the lines are a bundle group under the parent's title. A merged bundle has no stock of its own"},"lineKeys":{"type":"array","items":{"type":"string","maxLength":64,"pattern":"^[a-z0-9][a-z0-9_-]*$","description":"A key the brand authors: lower-case letters, digits, `_` and `-`"},"minItems":1,"description":"The required one-time lines merged into the parent, each at its own quantity"},"parentVariantId":{"type":"string","pattern":"^gid:\\/\\/shopify\\/ProductVariant\\/\\d+$","description":"The variant the parent line shows as: a bundle product whose variant requires components, so it can never be bought on its own"},"title":{"type":"string","minLength":1,"maxLength":255,"description":"What the cart and checkout show as the line's title; the order keeps the product's own title"},"imageUrl":{"type":"string","pattern":"^https:\\/\\/cdn\\.shopify\\.com\\/\\S+$","description":"What the cart and checkout show as the line's image; never kept on the order"},"attributes":{"type":"array","items":{"type":"object","properties":{"key":{"type":"string","minLength":1,"description":"The attribute's key"},"value":{"type":"string","description":"The attribute's value"}},"required":["key","value"],"additionalProperties":false},"description":"Attributes Shopify puts on the order's bundle group (not in the order webhook)"},"price":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","enum":["percent_off"],"description":"The bundle costs its lines' catalog price less a percentage, shown as the bundle's own price with no saving at checkout"},"percent":{"type":"number","minimum":0,"maximum":100,"description":"The percentage off, 0 to 100"}},"required":["type","percent"],"additionalProperties":false}],"description":"The bundle's price from our cart transform; absent, each line keeps its own price and our discount prices the parent"}},"required":["type","lineKeys","parentVariantId"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","enum":["expanded_bundle"],"description":"One line expanded into components in the cart and at checkout; on the order, the components are a bundle group under the line's title. The line's variant is the parent"},"lineKey":{"type":"string","maxLength":64,"pattern":"^[a-z0-9][a-z0-9_-]*$","description":"The one-time line expanded"},"components":{"type":"array","items":{"type":"object","properties":{"variantId":{"type":"string","pattern":"^gid:\\/\\/shopify\\/ProductVariant\\/\\d+$","description":"A variant that ships inside each unit of the line"},"quantity":{"type":"integer","exclusiveMinimum":0,"description":"Units of the component in each unit of the line"},"unitCents":{"type":"integer","minimum":0,"description":"The component's own price per unit, in cents; set on every component or on none. A gift that ships inside the bundle is a component at 0"},"role":{"type":"string","enum":["main","add_on","gift"],"description":"What the component is on the order, for costing: `main`, `add_on` or `gift`; the expanded line's own role when absent"}},"required":["variantId","quantity"],"additionalProperties":false},"minItems":1,"maxItems":150,"description":"What each unit of the line ships as, at most 150 components (Shopify's limit)"},"title":{"type":"string","minLength":1,"maxLength":255,"description":"What the cart and checkout show as the line's title; the order keeps the product's own title"},"imageUrl":{"type":"string","pattern":"^https:\\/\\/cdn\\.shopify\\.com\\/\\S+$","description":"What the cart and checkout show as the line's image; never kept on the order"},"price":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","enum":["percent_off"],"description":"The bundle costs its lines' catalog price less a percentage, shown as the bundle's own price with no saving at checkout"},"percent":{"type":"number","minimum":0,"maximum":100,"description":"The percentage off, 0 to 100"}},"required":["type","percent"],"additionalProperties":false}],"description":"A percentage off the line's catalog price; refused beside component prices. Absent with no component prices, the line keeps its price and our discount can price it"}},"required":["type","lineKey","components"],"additionalProperties":false}]},"description":"How our cart transform presents the option's one-time lines in the cart and at checkout: line overrides, merged bundles and expanded bundles. Each needs the store's capability for it (`GET /stores/{id}` `capability`); a line appears in one presentation at most"},"checkoutMode":{"type":"string","enum":["cart_page","cart_drawer","direct_to_checkout","landing_cart","external"],"description":"Where the brand's page sends the buyer after the choice: the cart page, a cart drawer, straight to checkout, a cart on the landing page, or an external flow"},"landingPageUrl":{"type":"string","minLength":1,"description":"The page that renders this option; publish checks the page shows it (`page_bind`)"}},"required":["key","display","visible","axisValues","unitCount","cardKey","lines","pricing","checkoutMode"],"additionalProperties":false},"minItems":1,"description":"Everything a buyer can choose, one resolved option per combination"},"valueClaims":{"type":"array","items":{"type":"object","properties":{"title":{"type":"string","minLength":1,"description":"The claim as the page words it"},"claimedValueCents":{"type":"integer","minimum":0,"description":"The value claimed, in cents; absent when the page states none"}},"required":["title"],"additionalProperties":false},"description":"Value claims the page makes (bonuses, prizes); never enter a cart"},"terms":{"type":"object","properties":{"guaranteeDays":{"type":"integer","exclusiveMinimum":0,"description":"The money-back guarantee the page states, in days"}},"additionalProperties":false,"description":"Terms the page states"},"costProfile":{"type":"string","minLength":1,"description":"The cost profile the forecast and the realized cost basis use: which cost kinds apply to this offer's orders"}},"required":["schemaVersion","code","tracking","store","axes","pools","defaultOptionKey","options","valueClaims","terms","costProfile"],"additionalProperties":false}}}},"responses":{"201":{"description":"The stored offer at version 1","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"code":{"type":"string","description":"The offer's code; unique per tenant, immutable"},"experienceName":{"type":"string","description":"`tracking.experienceName` of the summarized version: the human handle for the offer"},"defaultOptionKey":{"type":"string","description":"The option a renderer preselects, in the summarized version"},"status":{"type":"string","enum":["draft","verified","live","retired"],"description":"The live version's status when one exists, else the current version's"},"currentVersion":{"type":"integer","exclusiveMinimum":0},"liveVersion":{"type":["integer","null"],"exclusiveMinimum":0},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"},"version":{"type":"object","properties":{"number":{"type":"integer","exclusiveMinimum":0},"status":{"type":"string","enum":["draft","verified","live","retired"]},"createdAt":{"type":"string","format":"date-time"}},"required":["number","status","createdAt"]},"options":{"type":"array","items":{"type":"object","properties":{"key":{"type":"string","description":"The option key"},"title":{"type":"string","description":"The option's `display.title`"},"visible":{"type":"boolean","description":"Whether a renderer may show the option; only visible options are verified"},"promise":{"type":"object","properties":{"firstChargeCents":{"type":["integer","null"],"minimum":0,"description":"What the buyer is charged on the first order, before shipping and tax; required on a visible option. Publish checks a real cart charges it"},"renewalChargeCents":{"type":["integer","null"],"minimum":0,"description":"What each renewal charges, before shipping and tax; required when the option has a subscription line"}},"required":["firstChargeCents","renewalChargeCents"],"additionalProperties":false,"description":"What the option promises the buyer is charged"},"mechanisms":{"type":"array","items":{"type":"string"},"description":"The option's pricing mechanism types, in document order"},"verificationStatus":{"type":"string","enum":["matched","mismatched","unverifiable","unverified"],"description":"Whether a real cart charges what the option promises: `matched`; `mismatched` when a check failed or Shopify refused the cart; `unverifiable` when a check of the promise could not run; `unverified` when never checked (a hidden option). An option goes live only when `matched`"}},"required":["key","title","visible","promise","mechanisms","verificationStatus"]}},"verification":{"type":"object","properties":{"options":{"type":"integer","minimum":0,"description":"Every option of the version, visible or not"},"matched":{"type":"integer","minimum":0,"description":"Options a real cart charges exactly as promised"},"mismatched":{"type":"integer","minimum":0,"description":"Options a check failed on, or whose cart Shopify refused"},"unverifiable":{"type":"integer","minimum":0,"description":"Options a check of the promise could not run on"},"unverified":{"type":"integer","minimum":0,"description":"Options never checked: every hidden option, and every option of a version never published"},"lastCheckedAt":{"type":["string","null"],"format":"date-time","description":"When the verifier last ran on any option of the version"}},"required":["options","matched","mismatched","unverifiable","unverified","lastCheckedAt"],"description":"Verification status counts across the version's options"},"orderCount":{"type":"integer","minimum":0,"description":"Ingested orders attributed to this offer, across versions"},"document":{"type":"object","properties":{"schemaVersion":{"type":"string","enum":["offer/1"],"description":"The document format: `offer/1`"},"id":{"type":"string","minLength":1,"description":"The offer id; assigned by the server"},"version":{"type":"integer","exclusiveMinimum":0,"description":"The offer's version number; assigned by the server on every write"},"status":{"type":"string","enum":["draft","verified","live","retired"],"description":"`draft` until published, `live` while served, `retired` once replaced; assigned by the server"},"code":{"type":"string","maxLength":31,"pattern":"^[^,\\s](?:[^,]*[^,\\s])?$","description":"The offer's code: unique per tenant, immutable once created, and how an agent, `lookup_offer` and the order tag `os_offer:<code>` name the offer"},"tracking":{"type":"object","properties":{"experienceName":{"type":"string","minLength":1,"description":"A label for the page or funnel this offer runs in; the offers list shows it"},"campaignName":{"type":"string","minLength":1,"description":"A label for the marketing campaign this offer belongs to"},"presellPageName":{"type":["string","null"],"minLength":1,"description":"A label for the presell page in front of the offer, or null"},"preservedCartAttributes":{"type":"array","items":{"type":"string","minLength":1},"description":"The brand's own cart attribute names a cart request may set and the API keeps on the cart (`preservedCartAttributes` on the cart request)"}},"required":["experienceName","campaignName","presellPageName","preservedCartAttributes"],"additionalProperties":false,"description":"The labels reports group by, and the brand's own cart attributes a cart keeps"},"store":{"type":"object","properties":{"myshopifyDomain":{"type":"string","minLength":1,"description":"The connected store's myshopify domain (`brand.myshopify.com`); publish and serving use this store"},"market":{"type":"object","properties":{"countryCode":{"type":"string","pattern":"^[A-Z]{2}$","description":"The buyer's country, ISO 3166-1 alpha-2; carts are priced in its market"},"currencyCode":{"type":"string","pattern":"^[A-Z]{3}$","description":"The market's currency, ISO 4217; every amount in the document is in it"}},"required":["countryCode","currencyCode"],"additionalProperties":false,"description":"The one market the offer is priced in"}},"required":["myshopifyDomain","market"],"additionalProperties":false,"description":"The connected store and the market the offer is priced in"},"axes":{"type":"array","items":{"type":"object","properties":{"key":{"type":"string","maxLength":64,"pattern":"^[a-z0-9][a-z0-9_-]*$","description":"Names the axis; options and axis-mapped lines refer to it"},"values":{"type":"array","items":{"type":"string","minLength":1},"minItems":1,"description":"Every value the axis takes"}},"required":["key","values"],"additionalProperties":false},"description":"Dimensions the options vary along (flavour, size); they name and enumerate options, never patch one"},"pools":{"type":"array","items":{"type":"object","properties":{"key":{"type":"string","maxLength":64,"pattern":"^[a-z0-9][a-z0-9_-]*$","description":"Names the pool; a pool-bound line refers to it"},"variantIds":{"type":"array","items":{"type":"string","pattern":"^gid:\\/\\/shopify\\/ProductVariant\\/\\d+$","description":"A Shopify ProductVariant gid (`gid://shopify/ProductVariant/<id>`)"},"minItems":1,"description":"The pool's variants"},"allowRepeats":{"type":"boolean","description":"Whether one variant may be chosen more than once"}},"required":["key","variantIds","allowRepeats"],"additionalProperties":false},"description":"Pools a buyer chooses variants from, through a line bound to the pool"},"defaultOptionKey":{"type":"string","maxLength":64,"pattern":"^[a-z0-9][a-z0-9_-]*$","description":"The option a renderer preselects; must name a visible option"},"options":{"type":"array","items":{"type":"object","properties":{"key":{"type":"string","maxLength":30,"pattern":"^[a-z0-9][a-z0-9_-]*$","description":"Names the option: unique in the document, carried in the cart pointer, the order tag `os_option:<key>` (so at most 30 characters) and the economics. Keep it stable"},"display":{"type":"object","properties":{"title":{"type":"string","minLength":1,"description":"The option's name as a buyer reads it"}},"required":["title"],"additionalProperties":false,"description":"What a renderer shows for the option"},"visible":{"type":"boolean","description":"Whether a renderer may show the option and publish verifies it; a hidden option still resolves and builds carts"},"axisValues":{"type":"object","additionalProperties":{"type":"string"},"description":"The option's value on each document axis, by axis key"},"unitCount":{"type":"integer","exclusiveMinimum":0,"description":"The quantity the buyer perceives (\"4 units\"); not the sum of line quantities"},"cardKey":{"type":"string","maxLength":64,"pattern":"^[a-z0-9][a-z0-9_-]*$","description":"Options sharing a card key are drawn as one card (a subscribe and one-time pair of one product)"},"lines":{"type":"array","items":{"oneOf":[{"type":"object","properties":{"role":{"type":"string","enum":["main","add_on"],"description":"`main` is what the buyer pays for; `add_on` an extra"},"key":{"type":"string","maxLength":64,"pattern":"^[a-z0-9][a-z0-9_-]*$","description":"Names the line inside its option; required on an optional non-gift line, which a cart opts into by this key (`addOnLineKeys`)"},"quantity":{"type":"integer","exclusiveMinimum":0,"description":"Units of the variant in the cart; on a pool-bound line, the fewest the buyer may choose"},"maxQuantity":{"type":"integer","exclusiveMinimum":0,"description":"A pool-bound line only: the most units the buyer may choose"},"required":{"type":"boolean","description":"Whether every cart for the option holds the line; an optional line is added only when the cart request names its key"},"variantSource":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","enum":["fixed"],"description":"The line is one named variant"},"productId":{"type":"string","pattern":"^gid:\\/\\/shopify\\/Product\\/\\d+$","description":"The variant's product"},"variantId":{"type":"string","pattern":"^gid:\\/\\/shopify\\/ProductVariant\\/\\d+$","description":"The variant the line puts in the cart"}},"required":["type","productId","variantId"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","enum":["axis_map"],"description":"The variant follows the option's axis values, through `variantIdByAxisValue`"},"productId":{"type":"string","pattern":"^gid:\\/\\/shopify\\/Product\\/\\d+$","description":"The product every mapped variant belongs to"},"axisKeys":{"type":"array","items":{"type":"string","maxLength":64,"pattern":"^[a-z0-9][a-z0-9_-]*$","description":"A key the brand authors: lower-case letters, digits, `_` and `-`"},"minItems":1,"description":"The document axes whose values choose the variant, in `variantIdByAxisValue`'s key order"},"variantIdByAxisValue":{"type":"object","additionalProperties":{"type":"string","pattern":"^gid:\\/\\/shopify\\/ProductVariant\\/\\d+$","description":"A Shopify ProductVariant gid (`gid://shopify/ProductVariant/<id>`)"},"description":"Variant id by axis value; for several `axisKeys`, keyed by the values joined with \"/\" in `axisKeys` order. Must cover exactly the declared values"}},"required":["type","productId","axisKeys","variantIdByAxisValue"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","enum":["pool"],"description":"The buyer chooses the variants from a pool: `quantity` units, up to `maxQuantity`, any mix of the pool's variants; the cart gets one line per distinct variant"},"poolKey":{"type":"string","maxLength":64,"pattern":"^[a-z0-9][a-z0-9_-]*$","description":"The `pools[].key` the buyer chooses from"}},"required":["type","poolKey"],"additionalProperties":false}],"description":"Where the line's variant comes from"},"purchase":{"type":"object","properties":{"type":{"type":"string","enum":["one_time","subscription"],"description":"Bought once, or on a selling plan"},"sellingPlanId":{"type":"string","pattern":"^gid:\\/\\/shopify\\/SellingPlan\\/\\d+$","description":"The selling plan a subscription line is bought on; required when `type` is `subscription`"},"intervalDays":{"type":"integer","exclusiveMinimum":0,"description":"Days between a subscription's charges, as shown to the buyer"},"plans":{"type":"array","items":{"type":"object","properties":{"fromUnits":{"type":"integer","exclusiveMinimum":0,"description":"The fewest units of the group this plan's tier applies to; the first tier is 1"},"intervalDays":{"type":"integer","exclusiveMinimum":0,"description":"The cadence this plan renews on, one of the option's `cadence` intervals"},"sellingPlanId":{"type":"string","pattern":"^gid:\\/\\/shopify\\/SellingPlan\\/\\d+$","description":"The selling plan the group's lines go on at this tier and cadence"}},"required":["fromUnits","intervalDays","sellingPlanId"],"additionalProperties":false},"minItems":1,"description":"A subscription group's plan for each tier and cadence a cart can reach; `sellingPlanId` is one of them"}},"required":["type"],"additionalProperties":false,"description":"How the line is bought: once, or on a selling plan"},"bundleComponents":{"type":"array","items":{"type":"object","properties":{"variantId":{"type":"string","pattern":"^gid:\\/\\/shopify\\/ProductVariant\\/\\d+$","description":"A component variant of the fixed bundle"},"quantity":{"type":"integer","exclusiveMinimum":0,"description":"Units of that component in one bundle"}},"required":["variantId","quantity"],"additionalProperties":false},"minItems":1,"description":"What one unit holds, when the variant is a Shopify fixed bundle"},"catalogPrice":{"type":"object","properties":{"amountCents":{"type":"integer","minimum":0,"description":"The variant's catalog price when the document was written; line pricing starts from it"},"compareAtAmountCents":{"type":["integer","null"],"minimum":0,"description":"The variant's catalog compare-at price then, or null"},"capturedAt":{"type":"string","format":"date-time","description":"When the price was read from the catalog"}},"required":["amountCents","compareAtAmountCents","capturedAt"],"additionalProperties":false,"description":"The catalog price line pricing starts from"}},"required":["role","quantity","required","variantSource","purchase","catalogPrice"],"additionalProperties":false},{"type":"object","properties":{"role":{"type":"string","enum":["gift"],"description":"A real product the discount function prices to zero"},"key":{"type":"string","maxLength":64,"pattern":"^[a-z0-9][a-z0-9_-]*$","description":"Names the line inside its option; required on an optional non-gift line, which a cart opts into by this key (`addOnLineKeys`)"},"quantity":{"type":"integer","exclusiveMinimum":0,"description":"Units of the variant in the cart; on a pool-bound line, the fewest the buyer may choose"},"maxQuantity":{"type":"integer","exclusiveMinimum":0,"description":"A pool-bound line only: the most units the buyer may choose"},"required":{"type":"boolean","description":"Whether every cart for the option holds the line; an optional line is added only when the cart request names its key"},"variantSource":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","enum":["fixed"],"description":"The line is one named variant"},"productId":{"type":"string","pattern":"^gid:\\/\\/shopify\\/Product\\/\\d+$","description":"The variant's product"},"variantId":{"type":"string","pattern":"^gid:\\/\\/shopify\\/ProductVariant\\/\\d+$","description":"The variant the line puts in the cart"}},"required":["type","productId","variantId"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","enum":["axis_map"],"description":"The variant follows the option's axis values, through `variantIdByAxisValue`"},"productId":{"type":"string","pattern":"^gid:\\/\\/shopify\\/Product\\/\\d+$","description":"The product every mapped variant belongs to"},"axisKeys":{"type":"array","items":{"type":"string","maxLength":64,"pattern":"^[a-z0-9][a-z0-9_-]*$","description":"A key the brand authors: lower-case letters, digits, `_` and `-`"},"minItems":1,"description":"The document axes whose values choose the variant, in `variantIdByAxisValue`'s key order"},"variantIdByAxisValue":{"type":"object","additionalProperties":{"type":"string","pattern":"^gid:\\/\\/shopify\\/ProductVariant\\/\\d+$","description":"A Shopify ProductVariant gid (`gid://shopify/ProductVariant/<id>`)"},"description":"Variant id by axis value; for several `axisKeys`, keyed by the values joined with \"/\" in `axisKeys` order. Must cover exactly the declared values"}},"required":["type","productId","axisKeys","variantIdByAxisValue"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","enum":["pool"],"description":"The buyer chooses the variants from a pool: `quantity` units, up to `maxQuantity`, any mix of the pool's variants; the cart gets one line per distinct variant"},"poolKey":{"type":"string","maxLength":64,"pattern":"^[a-z0-9][a-z0-9_-]*$","description":"The `pools[].key` the buyer chooses from"}},"required":["type","poolKey"],"additionalProperties":false}],"description":"Where the line's variant comes from"},"purchase":{"type":"object","properties":{"type":{"type":"string","enum":["one_time","subscription"],"description":"Bought once, or on a selling plan"},"sellingPlanId":{"type":"string","pattern":"^gid:\\/\\/shopify\\/SellingPlan\\/\\d+$","description":"The selling plan a subscription line is bought on; required when `type` is `subscription`"},"intervalDays":{"type":"integer","exclusiveMinimum":0,"description":"Days between a subscription's charges, as shown to the buyer"},"plans":{"type":"array","items":{"type":"object","properties":{"fromUnits":{"type":"integer","exclusiveMinimum":0,"description":"The fewest units of the group this plan's tier applies to; the first tier is 1"},"intervalDays":{"type":"integer","exclusiveMinimum":0,"description":"The cadence this plan renews on, one of the option's `cadence` intervals"},"sellingPlanId":{"type":"string","pattern":"^gid:\\/\\/shopify\\/SellingPlan\\/\\d+$","description":"The selling plan the group's lines go on at this tier and cadence"}},"required":["fromUnits","intervalDays","sellingPlanId"],"additionalProperties":false},"minItems":1,"description":"A subscription group's plan for each tier and cadence a cart can reach; `sellingPlanId` is one of them"}},"required":["type"],"additionalProperties":false,"description":"How the line is bought: once, or on a selling plan"},"bundleComponents":{"type":"array","items":{"type":"object","properties":{"variantId":{"type":"string","pattern":"^gid:\\/\\/shopify\\/ProductVariant\\/\\d+$","description":"A component variant of the fixed bundle"},"quantity":{"type":"integer","exclusiveMinimum":0,"description":"Units of that component in one bundle"}},"required":["variantId","quantity"],"additionalProperties":false},"minItems":1,"description":"What one unit holds, when the variant is a Shopify fixed bundle"},"catalogPrice":{"type":"object","properties":{"amountCents":{"type":"integer","minimum":0,"description":"The variant's catalog price when the document was written; line pricing starts from it"},"compareAtAmountCents":{"type":["integer","null"],"minimum":0,"description":"The variant's catalog compare-at price then, or null"},"capturedAt":{"type":"string","format":"date-time","description":"When the price was read from the catalog"}},"required":["amountCents","compareAtAmountCents","capturedAt"],"additionalProperties":false,"description":"The catalog price line pricing starts from"},"claimedValueCents":{"type":"integer","minimum":0,"description":"The value the page shows for the gift (struck through); never charged: the function zeroes the line, and its cost comes from the ledger"}},"required":["role","quantity","required","variantSource","purchase","catalogPrice","claimedValueCents"],"additionalProperties":false}]},"minItems":1,"description":"What the option puts in the cart"},"maxUnits":{"type":"integer","exclusiveMinimum":0,"description":"A category builder: the most units the option's non-gift lines may hold in all"},"cadence":{"type":"object","properties":{"tiers":{"type":"array","items":{"type":"object","properties":{"fromUnits":{"type":"integer","exclusiveMinimum":0,"description":"The fewest units of the largest subscription group this interval applies to; the first tier is 1"},"intervalDays":{"type":"integer","exclusiveMinimum":0,"description":"Days between charges of every subscription line"}},"required":["fromUnits","intervalDays"],"additionalProperties":false},"minItems":1,"description":"The tiers, ascending from 1; above the last tier the last interval holds"}},"required":["tiers"],"additionalProperties":false,"description":"A category builder: the one interval every subscription line renews on, by the units of the largest subscription group in the cart; required when a line has `purchase.plans`"},"pricing":{"type":"object","properties":{"promise":{"type":"object","properties":{"firstChargeCents":{"type":["integer","null"],"minimum":0,"description":"What the buyer is charged on the first order, before shipping and tax; required on a visible option. Publish checks a real cart charges it"},"renewalChargeCents":{"type":["integer","null"],"minimum":0,"description":"What each renewal charges, before shipping and tax; required when the option has a subscription line"}},"required":["firstChargeCents","renewalChargeCents"],"additionalProperties":false,"description":"What the option promises the buyer is charged"},"compareAtPrice":{"type":"object","properties":{"amountCents":{"type":"integer","minimum":0,"description":"The struck-through amount, in cents"},"source":{"type":"string","enum":["variant","selling_plan","unit_price_times_quantity","metafield","page_copy"],"description":"Where it comes from: the variant's compare-at price, the selling plan's compare-at price, the unit price times the quantity, a metafield, or page copy"}},"required":["amountCents","source"],"additionalProperties":false,"description":"The struck-through price the page shows beside the promise"},"shipping":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","enum":["free"],"description":"The discount function makes the named rates free for carts carrying this option"},"rates":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","enum":["cheapest"],"description":"The cheapest shipping rate in each delivery group"}},"required":["type"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","enum":["all"],"description":"Every shipping rate, express included"}},"required":["type"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","enum":["titles"],"description":"The rates whose title is one of `titles`, ignoring case"},"titles":{"type":"array","items":{"type":"string","minLength":1},"minItems":1,"description":"Rate titles as checkout shows them"}},"required":["type","titles"],"additionalProperties":false}],"description":"Which rates are free"},"charges":{"type":"string","enum":["first","every"],"description":"Which shipments are free: `every` charge (a subscription's renewals too) or the `first` only"},"claimedValueCents":{"type":"integer","minimum":0,"description":"The shipping value the page claims for the free shipment (\"a $6.99 value\"); never charged"},"renewalChargeCents":{"type":"integer","minimum":0,"description":"On a subscription option free on the first charge only: what each renewal's shipping charges. Required there, refused elsewhere"}},"required":["type","rates","charges"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","enum":["charged"],"description":"Shipping is charged at checkout's rates"},"expectedChargeCents":{"type":"integer","minimum":0,"description":"What the forecast assumes a shipment charges, in cents; 0 for none"}},"required":["type","expectedChargeCents"],"additionalProperties":false}],"description":"What the option promises about shipping"},"mechanisms":{"type":"array","items":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","enum":["managed_discount"],"description":"Our app discount prices the lines, from the option map publish writes; works on subscription lines"},"lineRoles":{"type":"array","items":{"type":"string","enum":["main","add_on","gift"],"description":"What a line is in its option: `main` is what the buyer pays for, `add_on` an extra the buyer opts into or is always added, `gift` a real product the discount function prices to zero"},"minItems":1,"description":"The roles of the option's lines this mechanism prices"},"discount":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","enum":["percent"],"description":"A percentage off"},"percent":{"type":"number","minimum":0,"maximum":100,"description":"The percentage off, 0 to 100"}},"required":["type","percent"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","enum":["fixed_amount"],"description":"A fixed amount off"},"amountCents":{"type":"integer","minimum":0,"description":"The amount off, in cents"},"per":{"type":"string","enum":["line","unit"],"description":"Off each line, or off each unit of the line"}},"required":["type","amountCents","per"],"additionalProperties":false}],"description":"How much comes off"},"charges":{"type":"string","enum":["first","every"],"description":"Which charges it prices: `first` the first order only; `every` the first order and every renewal of a subscription line"}},"required":["type","lineRoles","discount","charges"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","enum":["discount_code"],"description":"A Shopify discount code publish creates, applied to the cart the API builds"},"code":{"type":"string","minLength":1,"description":"The code the brand chose; absent, publish mints one"},"purchaseType":{"type":"string","enum":["one_time","subscription","subscription_first_payment_only"],"description":"Which purchases the code prices: one-time lines once, every charge of a subscription line, or a subscription's first order only"},"discount":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","enum":["percent"],"description":"A percentage off"},"percent":{"type":"number","minimum":0,"maximum":100,"description":"The percentage off, 0 to 100"}},"required":["type","percent"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","enum":["fixed_amount"],"description":"A fixed amount off"},"amountCents":{"type":"integer","minimum":0,"description":"The amount off, in cents"}},"required":["type","amountCents"],"additionalProperties":false}],"description":"How much comes off"},"lineRoles":{"type":"array","items":{"type":"string","enum":["main","add_on","gift"],"description":"What a line is in its option: `main` is what the buyer pays for, `add_on` an extra the buyer opts into or is always added, `gift` a real product the discount function prices to zero"},"minItems":1,"description":"The roles of the option's lines this mechanism prices"},"shopify":{"type":"object","properties":{"discountId":{"type":"string","pattern":"^gid:\\/\\/shopify\\/DiscountCodeNode\\/\\d+$","description":"The discount publish created on Shopify"},"code":{"type":"string","minLength":1,"description":"The code live on Shopify: the authored one, or the one publish minted"}},"required":["discountId","code"],"additionalProperties":false,"description":"What publish created on Shopify for the code; absent until publish runs. Server state, never authored"}},"required":["type","purchaseType","discount","lineRoles"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","enum":["selling_plan_adjustment"],"description":"The selling plan's own price adjustments price the subscription lines on that plan"},"sellingPlanId":{"type":"string","pattern":"^gid:\\/\\/shopify\\/SellingPlan\\/\\d+$","description":"The selling plan, carried by a subscription line of the option"},"adjustments":{"type":"array","items":{"type":"object","properties":{"fromOrder":{"anyOf":[{"type":"integer","exclusiveMinimum":0},{"type":"string","enum":["after_last"]}],"description":"The order from which the adjustment is in effect: N from the Nth order on, until a later one takes over; \"after_last\" after every numbered one (alone, from the first order). Before the first, the catalog price"},"discount":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","enum":["percent"],"description":"A percentage off"},"percent":{"type":"number","minimum":0,"maximum":100,"description":"The percentage off, 0 to 100"}},"required":["type","percent"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","enum":["fixed_amount"],"description":"A fixed amount off"},"amountCents":{"type":"integer","minimum":0,"description":"The amount off, in cents"}},"required":["type","amountCents"],"additionalProperties":false}],"description":"How much the plan takes off the variant's price, per unit"}},"required":["fromOrder","discount"],"additionalProperties":false},"minItems":1,"description":"The plan's price adjustments as Shopify holds them, at most two"}},"required":["type","sellingPlanId","adjustments"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","enum":["catalog_price"],"description":"The variant's catalog price is already the offer price; nothing is discounted"}},"required":["type"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","enum":["existing_automatic_discount"],"description":"An automatic discount the store already runs; we only describe it"},"lineRoles":{"type":"array","items":{"type":"string","enum":["main","add_on","gift"],"description":"What a line is in its option: `main` is what the buyer pays for, `add_on` an extra the buyer opts into or is always added, `gift` a real product the discount function prices to zero"},"minItems":1,"description":"The roles of the option's lines this mechanism prices"},"discount":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","enum":["percent"],"description":"A percentage off"},"percent":{"type":"number","minimum":0,"maximum":100,"description":"The percentage off, 0 to 100"}},"required":["type","percent"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","enum":["fixed_amount"],"description":"A fixed amount off"},"amountCents":{"type":"integer","minimum":0,"description":"The amount off, in cents"}},"required":["type","amountCents"],"additionalProperties":false}],"description":"How much comes off"},"charges":{"type":"string","enum":["first","every"],"description":"Which charges it prices: `first` the first order only; `every` the first order and every renewal of a subscription line"}},"required":["type","lineRoles","discount","charges"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","enum":["unit_price_tiers"],"description":"A category group's first-order unit price by how many units of it the cart holds; our app discount charges it, and the group's selling plans price the renewals"},"lineKey":{"type":"string","maxLength":64,"pattern":"^[a-z0-9][a-z0-9_-]*$","description":"The group: an optional, non-gift line bound to a pool, which a cart opts into by this key"},"tiers":{"type":"array","items":{"type":"object","properties":{"fromUnits":{"type":"integer","exclusiveMinimum":0,"description":"The fewest units of the group this tier's price applies to; the first tier is 1"},"unitCents":{"type":"integer","minimum":0,"description":"What each unit of the group charges on the first order at this tier, in cents"}},"required":["fromUnits","unitCents"],"additionalProperties":false},"minItems":1,"description":"The tiers, ascending from 1; above the last tier the last price holds"}},"required":["type","lineKey","tiers"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","enum":["line_price"],"description":"Our cart transform sets the lines' unit price as their own price, at or below each line's catalog price (never above: a raise is refused): shown as the product's price, with no saving at checkout. One-time lines only, on any store with our cart transform registered: `lineUpdate` on Shopify Plus, the line expanded into itself on every other plan"},"lineKeys":{"type":"array","items":{"type":"string","maxLength":64,"pattern":"^[a-z0-9][a-z0-9_-]*$","description":"A key the brand authors: lower-case letters, digits, `_` and `-`"},"minItems":1,"description":"The one-time lines priced, by key"},"unitCents":{"type":"integer","minimum":0,"description":"What each unit of those lines charges on the first order, in cents"}},"required":["type","lineKeys","unitCents"],"additionalProperties":false}]},"description":"How the promise is made real on Shopify; at most one product discount per line and charge"}},"required":["promise","compareAtPrice","shipping","mechanisms"],"additionalProperties":false,"description":"What the option promises and how Shopify charges it"},"presentations":{"type":"array","items":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","enum":["line_override"],"description":"One line shown with another title or image. It exists only on the cart line: the order keeps the product's real title. Shopify Plus only, except on a line with a line price, where it rides in the line expanded into itself on any plan"},"lineKey":{"type":"string","maxLength":64,"pattern":"^[a-z0-9][a-z0-9_-]*$","description":"The one-time line shown differently"},"title":{"type":"string","minLength":1,"maxLength":255,"description":"What the cart and checkout show as the line's title; the order keeps the product's own title"},"imageUrl":{"type":"string","pattern":"^https:\\/\\/cdn\\.shopify\\.com\\/\\S+$","description":"What the cart and checkout show as the line's image; never kept on the order"}},"required":["type","lineKey"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","enum":["merged_bundle"],"description":"Several lines merged into one titled parent line in the cart and at checkout; on the order, the lines are a bundle group under the parent's title. A merged bundle has no stock of its own"},"lineKeys":{"type":"array","items":{"type":"string","maxLength":64,"pattern":"^[a-z0-9][a-z0-9_-]*$","description":"A key the brand authors: lower-case letters, digits, `_` and `-`"},"minItems":1,"description":"The required one-time lines merged into the parent, each at its own quantity"},"parentVariantId":{"type":"string","pattern":"^gid:\\/\\/shopify\\/ProductVariant\\/\\d+$","description":"The variant the parent line shows as: a bundle product whose variant requires components, so it can never be bought on its own"},"title":{"type":"string","minLength":1,"maxLength":255,"description":"What the cart and checkout show as the line's title; the order keeps the product's own title"},"imageUrl":{"type":"string","pattern":"^https:\\/\\/cdn\\.shopify\\.com\\/\\S+$","description":"What the cart and checkout show as the line's image; never kept on the order"},"attributes":{"type":"array","items":{"type":"object","properties":{"key":{"type":"string","minLength":1,"description":"The attribute's key"},"value":{"type":"string","description":"The attribute's value"}},"required":["key","value"],"additionalProperties":false},"description":"Attributes Shopify puts on the order's bundle group (not in the order webhook)"},"price":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","enum":["percent_off"],"description":"The bundle costs its lines' catalog price less a percentage, shown as the bundle's own price with no saving at checkout"},"percent":{"type":"number","minimum":0,"maximum":100,"description":"The percentage off, 0 to 100"}},"required":["type","percent"],"additionalProperties":false}],"description":"The bundle's price from our cart transform; absent, each line keeps its own price and our discount prices the parent"}},"required":["type","lineKeys","parentVariantId"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","enum":["expanded_bundle"],"description":"One line expanded into components in the cart and at checkout; on the order, the components are a bundle group under the line's title. The line's variant is the parent"},"lineKey":{"type":"string","maxLength":64,"pattern":"^[a-z0-9][a-z0-9_-]*$","description":"The one-time line expanded"},"components":{"type":"array","items":{"type":"object","properties":{"variantId":{"type":"string","pattern":"^gid:\\/\\/shopify\\/ProductVariant\\/\\d+$","description":"A variant that ships inside each unit of the line"},"quantity":{"type":"integer","exclusiveMinimum":0,"description":"Units of the component in each unit of the line"},"unitCents":{"type":"integer","minimum":0,"description":"The component's own price per unit, in cents; set on every component or on none. A gift that ships inside the bundle is a component at 0"},"role":{"type":"string","enum":["main","add_on","gift"],"description":"What the component is on the order, for costing: `main`, `add_on` or `gift`; the expanded line's own role when absent"}},"required":["variantId","quantity"],"additionalProperties":false},"minItems":1,"maxItems":150,"description":"What each unit of the line ships as, at most 150 components (Shopify's limit)"},"title":{"type":"string","minLength":1,"maxLength":255,"description":"What the cart and checkout show as the line's title; the order keeps the product's own title"},"imageUrl":{"type":"string","pattern":"^https:\\/\\/cdn\\.shopify\\.com\\/\\S+$","description":"What the cart and checkout show as the line's image; never kept on the order"},"price":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","enum":["percent_off"],"description":"The bundle costs its lines' catalog price less a percentage, shown as the bundle's own price with no saving at checkout"},"percent":{"type":"number","minimum":0,"maximum":100,"description":"The percentage off, 0 to 100"}},"required":["type","percent"],"additionalProperties":false}],"description":"A percentage off the line's catalog price; refused beside component prices. Absent with no component prices, the line keeps its price and our discount can price it"}},"required":["type","lineKey","components"],"additionalProperties":false}]},"description":"How our cart transform presents the option's one-time lines in the cart and at checkout: line overrides, merged bundles and expanded bundles. Each needs the store's capability for it (`GET /stores/{id}` `capability`); a line appears in one presentation at most"},"checkoutMode":{"type":"string","enum":["cart_page","cart_drawer","direct_to_checkout","landing_cart","external"],"description":"Where the brand's page sends the buyer after the choice: the cart page, a cart drawer, straight to checkout, a cart on the landing page, or an external flow"},"landingPageUrl":{"type":"string","minLength":1,"description":"The page that renders this option; publish checks the page shows it (`page_bind`)"},"verification":{"type":"object","properties":{"status":{"type":"string","enum":["matched","mismatched","unverifiable","unverified"],"description":"Whether a real cart charges what the option promises: `matched`; `mismatched` when a check failed or Shopify refused the cart; `unverifiable` when a check of the promise could not run; `unverified` when never checked (a hidden option). An option goes live only when `matched`"},"evidenceSource":{"type":"string","enum":["none","cart_response","cart_rejection","commerce_api","page_copy"],"description":"What the verdict rests on: nothing yet, a real cart Shopify built, Shopify refusing the cart, the Commerce API, or page copy"},"checkedAt":{"type":["string","null"],"format":"date-time","description":"When the verifier last ran on this option, or null"},"validForSeconds":{"type":"integer","exclusiveMinimum":0,"description":"Seconds the verdict is trusted after `checkedAt`"},"checks":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string","minLength":1,"description":"What was checked (`promised_first_charge`, `line_net:0`, `free_shipping:0:Standard`…); a check that does not apply to the option is not listed"},"covers":{"type":"string","enum":["option","add_on","shipping","renewal","page","presentation"],"description":"What part of the promise the check proves: `option` the option's first-order cart, `add_on` a line of an opt-in add-on, `shipping` the free shipping, `renewal` what renewals charge, `page` the landing page, `presentation` a title or image our cart transform shows (no Storefront cart field carries it, so it never holds an option back)"},"result":{"type":"string","enum":["passed","failed","skipped"],"description":"`passed`, `failed`, or `skipped` when the check could not run"},"detail":{"type":["string","null"],"description":"What was expected and found, or null"}},"required":["name","covers","result","detail"],"additionalProperties":false},"description":"Every check the verifier ran on the option"}},"required":["status","evidenceSource","checkedAt","validForSeconds","checks"],"additionalProperties":false,"description":"What the verifier found; written by publish and re-verification, never authored"}},"required":["key","display","visible","axisValues","unitCount","cardKey","lines","pricing","checkoutMode","verification"],"additionalProperties":false},"minItems":1,"description":"Everything a buyer can choose, one resolved option per combination"},"valueClaims":{"type":"array","items":{"type":"object","properties":{"title":{"type":"string","minLength":1,"description":"The claim as the page words it"},"claimedValueCents":{"type":"integer","minimum":0,"description":"The value claimed, in cents; absent when the page states none"}},"required":["title"],"additionalProperties":false},"description":"Value claims the page makes (bonuses, prizes); never enter a cart"},"terms":{"type":"object","properties":{"guaranteeDays":{"type":"integer","exclusiveMinimum":0,"description":"The money-back guarantee the page states, in days"}},"additionalProperties":false,"description":"Terms the page states"},"costProfile":{"type":"string","minLength":1,"description":"The cost profile the forecast and the realized cost basis use: which cost kinds apply to this offer's orders"}},"required":["schemaVersion","id","version","status","code","tracking","store","axes","pools","defaultOptionKey","options","valueClaims","terms","costProfile"],"additionalProperties":false}},"required":["id","code","experienceName","defaultOptionKey","status","currentVersion","liveVersion","createdAt","updatedAt","version","options","verification","orderCount","document"]}}}},"400":{"description":"The document failed validation; `issues` lists each path","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}},"401":{"description":"Missing, unknown or revoked API key","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}},"403":{"description":"The key is public; this route needs a secret key","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}},"409":{"description":"An offer with this code already exists","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}}}}},"/offers/lookup":{"get":{"operationId":"lookupOffer","summary":"Find an offer by id, code or URL","description":"The resolver every agent calls first (decision 4): `reference` may be the offer id, its `code`, or a URL containing either (the last path segment is read as a code). Returns the same shape as GET /offers/{id} so the offer can be confirmed before any write. `view=concise` omits the document.","tags":["Offers"],"security":[{"apiKey":[]}],"parameters":[{"schema":{"type":"string","minLength":1,"description":"An offer id, code, or a URL containing either"},"required":true,"description":"An offer id, code, or a URL containing either","name":"reference","in":"query"},{"schema":{"type":"string","enum":["concise","detailed"],"default":"concise"},"required":false,"name":"view","in":"query"}],"responses":{"200":{"description":"The offer","content":{"application/json":{"schema":{"anyOf":[{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"code":{"type":"string","description":"The offer's code; unique per tenant, immutable"},"experienceName":{"type":"string","description":"`tracking.experienceName` of the summarized version: the human handle for the offer"},"defaultOptionKey":{"type":"string","description":"The option a renderer preselects, in the summarized version"},"status":{"type":"string","enum":["draft","verified","live","retired"],"description":"The live version's status when one exists, else the current version's"},"currentVersion":{"type":"integer","exclusiveMinimum":0},"liveVersion":{"type":["integer","null"],"exclusiveMinimum":0},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"},"version":{"type":"object","properties":{"number":{"type":"integer","exclusiveMinimum":0},"status":{"type":"string","enum":["draft","verified","live","retired"]},"createdAt":{"type":"string","format":"date-time"}},"required":["number","status","createdAt"]},"options":{"type":"array","items":{"type":"object","properties":{"key":{"type":"string","description":"The option key"},"title":{"type":"string","description":"The option's `display.title`"},"visible":{"type":"boolean","description":"Whether a renderer may show the option; only visible options are verified"},"promise":{"type":"object","properties":{"firstChargeCents":{"type":["integer","null"],"minimum":0,"description":"What the buyer is charged on the first order, before shipping and tax; required on a visible option. Publish checks a real cart charges it"},"renewalChargeCents":{"type":["integer","null"],"minimum":0,"description":"What each renewal charges, before shipping and tax; required when the option has a subscription line"}},"required":["firstChargeCents","renewalChargeCents"],"additionalProperties":false,"description":"What the option promises the buyer is charged"},"mechanisms":{"type":"array","items":{"type":"string"},"description":"The option's pricing mechanism types, in document order"},"verificationStatus":{"type":"string","enum":["matched","mismatched","unverifiable","unverified"],"description":"Whether a real cart charges what the option promises: `matched`; `mismatched` when a check failed or Shopify refused the cart; `unverifiable` when a check of the promise could not run; `unverified` when never checked (a hidden option). An option goes live only when `matched`"}},"required":["key","title","visible","promise","mechanisms","verificationStatus"]}},"verification":{"type":"object","properties":{"options":{"type":"integer","minimum":0,"description":"Every option of the version, visible or not"},"matched":{"type":"integer","minimum":0,"description":"Options a real cart charges exactly as promised"},"mismatched":{"type":"integer","minimum":0,"description":"Options a check failed on, or whose cart Shopify refused"},"unverifiable":{"type":"integer","minimum":0,"description":"Options a check of the promise could not run on"},"unverified":{"type":"integer","minimum":0,"description":"Options never checked: every hidden option, and every option of a version never published"},"lastCheckedAt":{"type":["string","null"],"format":"date-time","description":"When the verifier last ran on any option of the version"}},"required":["options","matched","mismatched","unverifiable","unverified","lastCheckedAt"],"description":"Verification status counts across the version's options"},"orderCount":{"type":"integer","minimum":0,"description":"Ingested orders attributed to this offer, across versions"},"document":{"type":"object","properties":{"schemaVersion":{"type":"string","enum":["offer/1"],"description":"The document format: `offer/1`"},"id":{"type":"string","minLength":1,"description":"The offer id; assigned by the server"},"version":{"type":"integer","exclusiveMinimum":0,"description":"The offer's version number; assigned by the server on every write"},"status":{"type":"string","enum":["draft","verified","live","retired"],"description":"`draft` until published, `live` while served, `retired` once replaced; assigned by the server"},"code":{"type":"string","maxLength":31,"pattern":"^[^,\\s](?:[^,]*[^,\\s])?$","description":"The offer's code: unique per tenant, immutable once created, and how an agent, `lookup_offer` and the order tag `os_offer:<code>` name the offer"},"tracking":{"type":"object","properties":{"experienceName":{"type":"string","minLength":1,"description":"A label for the page or funnel this offer runs in; the offers list shows it"},"campaignName":{"type":"string","minLength":1,"description":"A label for the marketing campaign this offer belongs to"},"presellPageName":{"type":["string","null"],"minLength":1,"description":"A label for the presell page in front of the offer, or null"},"preservedCartAttributes":{"type":"array","items":{"type":"string","minLength":1},"description":"The brand's own cart attribute names a cart request may set and the API keeps on the cart (`preservedCartAttributes` on the cart request)"}},"required":["experienceName","campaignName","presellPageName","preservedCartAttributes"],"additionalProperties":false,"description":"The labels reports group by, and the brand's own cart attributes a cart keeps"},"store":{"type":"object","properties":{"myshopifyDomain":{"type":"string","minLength":1,"description":"The connected store's myshopify domain (`brand.myshopify.com`); publish and serving use this store"},"market":{"type":"object","properties":{"countryCode":{"type":"string","pattern":"^[A-Z]{2}$","description":"The buyer's country, ISO 3166-1 alpha-2; carts are priced in its market"},"currencyCode":{"type":"string","pattern":"^[A-Z]{3}$","description":"The market's currency, ISO 4217; every amount in the document is in it"}},"required":["countryCode","currencyCode"],"additionalProperties":false,"description":"The one market the offer is priced in"}},"required":["myshopifyDomain","market"],"additionalProperties":false,"description":"The connected store and the market the offer is priced in"},"axes":{"type":"array","items":{"type":"object","properties":{"key":{"type":"string","maxLength":64,"pattern":"^[a-z0-9][a-z0-9_-]*$","description":"Names the axis; options and axis-mapped lines refer to it"},"values":{"type":"array","items":{"type":"string","minLength":1},"minItems":1,"description":"Every value the axis takes"}},"required":["key","values"],"additionalProperties":false},"description":"Dimensions the options vary along (flavour, size); they name and enumerate options, never patch one"},"pools":{"type":"array","items":{"type":"object","properties":{"key":{"type":"string","maxLength":64,"pattern":"^[a-z0-9][a-z0-9_-]*$","description":"Names the pool; a pool-bound line refers to it"},"variantIds":{"type":"array","items":{"type":"string","pattern":"^gid:\\/\\/shopify\\/ProductVariant\\/\\d+$","description":"A Shopify ProductVariant gid (`gid://shopify/ProductVariant/<id>`)"},"minItems":1,"description":"The pool's variants"},"allowRepeats":{"type":"boolean","description":"Whether one variant may be chosen more than once"}},"required":["key","variantIds","allowRepeats"],"additionalProperties":false},"description":"Pools a buyer chooses variants from, through a line bound to the pool"},"defaultOptionKey":{"type":"string","maxLength":64,"pattern":"^[a-z0-9][a-z0-9_-]*$","description":"The option a renderer preselects; must name a visible option"},"options":{"type":"array","items":{"type":"object","properties":{"key":{"type":"string","maxLength":30,"pattern":"^[a-z0-9][a-z0-9_-]*$","description":"Names the option: unique in the document, carried in the cart pointer, the order tag `os_option:<key>` (so at most 30 characters) and the economics. Keep it stable"},"display":{"type":"object","properties":{"title":{"type":"string","minLength":1,"description":"The option's name as a buyer reads it"}},"required":["title"],"additionalProperties":false,"description":"What a renderer shows for the option"},"visible":{"type":"boolean","description":"Whether a renderer may show the option and publish verifies it; a hidden option still resolves and builds carts"},"axisValues":{"type":"object","additionalProperties":{"type":"string"},"description":"The option's value on each document axis, by axis key"},"unitCount":{"type":"integer","exclusiveMinimum":0,"description":"The quantity the buyer perceives (\"4 units\"); not the sum of line quantities"},"cardKey":{"type":"string","maxLength":64,"pattern":"^[a-z0-9][a-z0-9_-]*$","description":"Options sharing a card key are drawn as one card (a subscribe and one-time pair of one product)"},"lines":{"type":"array","items":{"oneOf":[{"type":"object","properties":{"role":{"type":"string","enum":["main","add_on"],"description":"`main` is what the buyer pays for; `add_on` an extra"},"key":{"type":"string","maxLength":64,"pattern":"^[a-z0-9][a-z0-9_-]*$","description":"Names the line inside its option; required on an optional non-gift line, which a cart opts into by this key (`addOnLineKeys`)"},"quantity":{"type":"integer","exclusiveMinimum":0,"description":"Units of the variant in the cart; on a pool-bound line, the fewest the buyer may choose"},"maxQuantity":{"type":"integer","exclusiveMinimum":0,"description":"A pool-bound line only: the most units the buyer may choose"},"required":{"type":"boolean","description":"Whether every cart for the option holds the line; an optional line is added only when the cart request names its key"},"variantSource":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","enum":["fixed"],"description":"The line is one named variant"},"productId":{"type":"string","pattern":"^gid:\\/\\/shopify\\/Product\\/\\d+$","description":"The variant's product"},"variantId":{"type":"string","pattern":"^gid:\\/\\/shopify\\/ProductVariant\\/\\d+$","description":"The variant the line puts in the cart"}},"required":["type","productId","variantId"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","enum":["axis_map"],"description":"The variant follows the option's axis values, through `variantIdByAxisValue`"},"productId":{"type":"string","pattern":"^gid:\\/\\/shopify\\/Product\\/\\d+$","description":"The product every mapped variant belongs to"},"axisKeys":{"type":"array","items":{"type":"string","maxLength":64,"pattern":"^[a-z0-9][a-z0-9_-]*$","description":"A key the brand authors: lower-case letters, digits, `_` and `-`"},"minItems":1,"description":"The document axes whose values choose the variant, in `variantIdByAxisValue`'s key order"},"variantIdByAxisValue":{"type":"object","additionalProperties":{"type":"string","pattern":"^gid:\\/\\/shopify\\/ProductVariant\\/\\d+$","description":"A Shopify ProductVariant gid (`gid://shopify/ProductVariant/<id>`)"},"description":"Variant id by axis value; for several `axisKeys`, keyed by the values joined with \"/\" in `axisKeys` order. Must cover exactly the declared values"}},"required":["type","productId","axisKeys","variantIdByAxisValue"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","enum":["pool"],"description":"The buyer chooses the variants from a pool: `quantity` units, up to `maxQuantity`, any mix of the pool's variants; the cart gets one line per distinct variant"},"poolKey":{"type":"string","maxLength":64,"pattern":"^[a-z0-9][a-z0-9_-]*$","description":"The `pools[].key` the buyer chooses from"}},"required":["type","poolKey"],"additionalProperties":false}],"description":"Where the line's variant comes from"},"purchase":{"type":"object","properties":{"type":{"type":"string","enum":["one_time","subscription"],"description":"Bought once, or on a selling plan"},"sellingPlanId":{"type":"string","pattern":"^gid:\\/\\/shopify\\/SellingPlan\\/\\d+$","description":"The selling plan a subscription line is bought on; required when `type` is `subscription`"},"intervalDays":{"type":"integer","exclusiveMinimum":0,"description":"Days between a subscription's charges, as shown to the buyer"},"plans":{"type":"array","items":{"type":"object","properties":{"fromUnits":{"type":"integer","exclusiveMinimum":0,"description":"The fewest units of the group this plan's tier applies to; the first tier is 1"},"intervalDays":{"type":"integer","exclusiveMinimum":0,"description":"The cadence this plan renews on, one of the option's `cadence` intervals"},"sellingPlanId":{"type":"string","pattern":"^gid:\\/\\/shopify\\/SellingPlan\\/\\d+$","description":"The selling plan the group's lines go on at this tier and cadence"}},"required":["fromUnits","intervalDays","sellingPlanId"],"additionalProperties":false},"minItems":1,"description":"A subscription group's plan for each tier and cadence a cart can reach; `sellingPlanId` is one of them"}},"required":["type"],"additionalProperties":false,"description":"How the line is bought: once, or on a selling plan"},"bundleComponents":{"type":"array","items":{"type":"object","properties":{"variantId":{"type":"string","pattern":"^gid:\\/\\/shopify\\/ProductVariant\\/\\d+$","description":"A component variant of the fixed bundle"},"quantity":{"type":"integer","exclusiveMinimum":0,"description":"Units of that component in one bundle"}},"required":["variantId","quantity"],"additionalProperties":false},"minItems":1,"description":"What one unit holds, when the variant is a Shopify fixed bundle"},"catalogPrice":{"type":"object","properties":{"amountCents":{"type":"integer","minimum":0,"description":"The variant's catalog price when the document was written; line pricing starts from it"},"compareAtAmountCents":{"type":["integer","null"],"minimum":0,"description":"The variant's catalog compare-at price then, or null"},"capturedAt":{"type":"string","format":"date-time","description":"When the price was read from the catalog"}},"required":["amountCents","compareAtAmountCents","capturedAt"],"additionalProperties":false,"description":"The catalog price line pricing starts from"}},"required":["role","quantity","required","variantSource","purchase","catalogPrice"],"additionalProperties":false},{"type":"object","properties":{"role":{"type":"string","enum":["gift"],"description":"A real product the discount function prices to zero"},"key":{"type":"string","maxLength":64,"pattern":"^[a-z0-9][a-z0-9_-]*$","description":"Names the line inside its option; required on an optional non-gift line, which a cart opts into by this key (`addOnLineKeys`)"},"quantity":{"type":"integer","exclusiveMinimum":0,"description":"Units of the variant in the cart; on a pool-bound line, the fewest the buyer may choose"},"maxQuantity":{"type":"integer","exclusiveMinimum":0,"description":"A pool-bound line only: the most units the buyer may choose"},"required":{"type":"boolean","description":"Whether every cart for the option holds the line; an optional line is added only when the cart request names its key"},"variantSource":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","enum":["fixed"],"description":"The line is one named variant"},"productId":{"type":"string","pattern":"^gid:\\/\\/shopify\\/Product\\/\\d+$","description":"The variant's product"},"variantId":{"type":"string","pattern":"^gid:\\/\\/shopify\\/ProductVariant\\/\\d+$","description":"The variant the line puts in the cart"}},"required":["type","productId","variantId"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","enum":["axis_map"],"description":"The variant follows the option's axis values, through `variantIdByAxisValue`"},"productId":{"type":"string","pattern":"^gid:\\/\\/shopify\\/Product\\/\\d+$","description":"The product every mapped variant belongs to"},"axisKeys":{"type":"array","items":{"type":"string","maxLength":64,"pattern":"^[a-z0-9][a-z0-9_-]*$","description":"A key the brand authors: lower-case letters, digits, `_` and `-`"},"minItems":1,"description":"The document axes whose values choose the variant, in `variantIdByAxisValue`'s key order"},"variantIdByAxisValue":{"type":"object","additionalProperties":{"type":"string","pattern":"^gid:\\/\\/shopify\\/ProductVariant\\/\\d+$","description":"A Shopify ProductVariant gid (`gid://shopify/ProductVariant/<id>`)"},"description":"Variant id by axis value; for several `axisKeys`, keyed by the values joined with \"/\" in `axisKeys` order. Must cover exactly the declared values"}},"required":["type","productId","axisKeys","variantIdByAxisValue"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","enum":["pool"],"description":"The buyer chooses the variants from a pool: `quantity` units, up to `maxQuantity`, any mix of the pool's variants; the cart gets one line per distinct variant"},"poolKey":{"type":"string","maxLength":64,"pattern":"^[a-z0-9][a-z0-9_-]*$","description":"The `pools[].key` the buyer chooses from"}},"required":["type","poolKey"],"additionalProperties":false}],"description":"Where the line's variant comes from"},"purchase":{"type":"object","properties":{"type":{"type":"string","enum":["one_time","subscription"],"description":"Bought once, or on a selling plan"},"sellingPlanId":{"type":"string","pattern":"^gid:\\/\\/shopify\\/SellingPlan\\/\\d+$","description":"The selling plan a subscription line is bought on; required when `type` is `subscription`"},"intervalDays":{"type":"integer","exclusiveMinimum":0,"description":"Days between a subscription's charges, as shown to the buyer"},"plans":{"type":"array","items":{"type":"object","properties":{"fromUnits":{"type":"integer","exclusiveMinimum":0,"description":"The fewest units of the group this plan's tier applies to; the first tier is 1"},"intervalDays":{"type":"integer","exclusiveMinimum":0,"description":"The cadence this plan renews on, one of the option's `cadence` intervals"},"sellingPlanId":{"type":"string","pattern":"^gid:\\/\\/shopify\\/SellingPlan\\/\\d+$","description":"The selling plan the group's lines go on at this tier and cadence"}},"required":["fromUnits","intervalDays","sellingPlanId"],"additionalProperties":false},"minItems":1,"description":"A subscription group's plan for each tier and cadence a cart can reach; `sellingPlanId` is one of them"}},"required":["type"],"additionalProperties":false,"description":"How the line is bought: once, or on a selling plan"},"bundleComponents":{"type":"array","items":{"type":"object","properties":{"variantId":{"type":"string","pattern":"^gid:\\/\\/shopify\\/ProductVariant\\/\\d+$","description":"A component variant of the fixed bundle"},"quantity":{"type":"integer","exclusiveMinimum":0,"description":"Units of that component in one bundle"}},"required":["variantId","quantity"],"additionalProperties":false},"minItems":1,"description":"What one unit holds, when the variant is a Shopify fixed bundle"},"catalogPrice":{"type":"object","properties":{"amountCents":{"type":"integer","minimum":0,"description":"The variant's catalog price when the document was written; line pricing starts from it"},"compareAtAmountCents":{"type":["integer","null"],"minimum":0,"description":"The variant's catalog compare-at price then, or null"},"capturedAt":{"type":"string","format":"date-time","description":"When the price was read from the catalog"}},"required":["amountCents","compareAtAmountCents","capturedAt"],"additionalProperties":false,"description":"The catalog price line pricing starts from"},"claimedValueCents":{"type":"integer","minimum":0,"description":"The value the page shows for the gift (struck through); never charged: the function zeroes the line, and its cost comes from the ledger"}},"required":["role","quantity","required","variantSource","purchase","catalogPrice","claimedValueCents"],"additionalProperties":false}]},"minItems":1,"description":"What the option puts in the cart"},"maxUnits":{"type":"integer","exclusiveMinimum":0,"description":"A category builder: the most units the option's non-gift lines may hold in all"},"cadence":{"type":"object","properties":{"tiers":{"type":"array","items":{"type":"object","properties":{"fromUnits":{"type":"integer","exclusiveMinimum":0,"description":"The fewest units of the largest subscription group this interval applies to; the first tier is 1"},"intervalDays":{"type":"integer","exclusiveMinimum":0,"description":"Days between charges of every subscription line"}},"required":["fromUnits","intervalDays"],"additionalProperties":false},"minItems":1,"description":"The tiers, ascending from 1; above the last tier the last interval holds"}},"required":["tiers"],"additionalProperties":false,"description":"A category builder: the one interval every subscription line renews on, by the units of the largest subscription group in the cart; required when a line has `purchase.plans`"},"pricing":{"type":"object","properties":{"promise":{"type":"object","properties":{"firstChargeCents":{"type":["integer","null"],"minimum":0,"description":"What the buyer is charged on the first order, before shipping and tax; required on a visible option. Publish checks a real cart charges it"},"renewalChargeCents":{"type":["integer","null"],"minimum":0,"description":"What each renewal charges, before shipping and tax; required when the option has a subscription line"}},"required":["firstChargeCents","renewalChargeCents"],"additionalProperties":false,"description":"What the option promises the buyer is charged"},"compareAtPrice":{"type":"object","properties":{"amountCents":{"type":"integer","minimum":0,"description":"The struck-through amount, in cents"},"source":{"type":"string","enum":["variant","selling_plan","unit_price_times_quantity","metafield","page_copy"],"description":"Where it comes from: the variant's compare-at price, the selling plan's compare-at price, the unit price times the quantity, a metafield, or page copy"}},"required":["amountCents","source"],"additionalProperties":false,"description":"The struck-through price the page shows beside the promise"},"shipping":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","enum":["free"],"description":"The discount function makes the named rates free for carts carrying this option"},"rates":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","enum":["cheapest"],"description":"The cheapest shipping rate in each delivery group"}},"required":["type"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","enum":["all"],"description":"Every shipping rate, express included"}},"required":["type"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","enum":["titles"],"description":"The rates whose title is one of `titles`, ignoring case"},"titles":{"type":"array","items":{"type":"string","minLength":1},"minItems":1,"description":"Rate titles as checkout shows them"}},"required":["type","titles"],"additionalProperties":false}],"description":"Which rates are free"},"charges":{"type":"string","enum":["first","every"],"description":"Which shipments are free: `every` charge (a subscription's renewals too) or the `first` only"},"claimedValueCents":{"type":"integer","minimum":0,"description":"The shipping value the page claims for the free shipment (\"a $6.99 value\"); never charged"},"renewalChargeCents":{"type":"integer","minimum":0,"description":"On a subscription option free on the first charge only: what each renewal's shipping charges. Required there, refused elsewhere"}},"required":["type","rates","charges"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","enum":["charged"],"description":"Shipping is charged at checkout's rates"},"expectedChargeCents":{"type":"integer","minimum":0,"description":"What the forecast assumes a shipment charges, in cents; 0 for none"}},"required":["type","expectedChargeCents"],"additionalProperties":false}],"description":"What the option promises about shipping"},"mechanisms":{"type":"array","items":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","enum":["managed_discount"],"description":"Our app discount prices the lines, from the option map publish writes; works on subscription lines"},"lineRoles":{"type":"array","items":{"type":"string","enum":["main","add_on","gift"],"description":"What a line is in its option: `main` is what the buyer pays for, `add_on` an extra the buyer opts into or is always added, `gift` a real product the discount function prices to zero"},"minItems":1,"description":"The roles of the option's lines this mechanism prices"},"discount":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","enum":["percent"],"description":"A percentage off"},"percent":{"type":"number","minimum":0,"maximum":100,"description":"The percentage off, 0 to 100"}},"required":["type","percent"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","enum":["fixed_amount"],"description":"A fixed amount off"},"amountCents":{"type":"integer","minimum":0,"description":"The amount off, in cents"},"per":{"type":"string","enum":["line","unit"],"description":"Off each line, or off each unit of the line"}},"required":["type","amountCents","per"],"additionalProperties":false}],"description":"How much comes off"},"charges":{"type":"string","enum":["first","every"],"description":"Which charges it prices: `first` the first order only; `every` the first order and every renewal of a subscription line"}},"required":["type","lineRoles","discount","charges"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","enum":["discount_code"],"description":"A Shopify discount code publish creates, applied to the cart the API builds"},"code":{"type":"string","minLength":1,"description":"The code the brand chose; absent, publish mints one"},"purchaseType":{"type":"string","enum":["one_time","subscription","subscription_first_payment_only"],"description":"Which purchases the code prices: one-time lines once, every charge of a subscription line, or a subscription's first order only"},"discount":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","enum":["percent"],"description":"A percentage off"},"percent":{"type":"number","minimum":0,"maximum":100,"description":"The percentage off, 0 to 100"}},"required":["type","percent"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","enum":["fixed_amount"],"description":"A fixed amount off"},"amountCents":{"type":"integer","minimum":0,"description":"The amount off, in cents"}},"required":["type","amountCents"],"additionalProperties":false}],"description":"How much comes off"},"lineRoles":{"type":"array","items":{"type":"string","enum":["main","add_on","gift"],"description":"What a line is in its option: `main` is what the buyer pays for, `add_on` an extra the buyer opts into or is always added, `gift` a real product the discount function prices to zero"},"minItems":1,"description":"The roles of the option's lines this mechanism prices"},"shopify":{"type":"object","properties":{"discountId":{"type":"string","pattern":"^gid:\\/\\/shopify\\/DiscountCodeNode\\/\\d+$","description":"The discount publish created on Shopify"},"code":{"type":"string","minLength":1,"description":"The code live on Shopify: the authored one, or the one publish minted"}},"required":["discountId","code"],"additionalProperties":false,"description":"What publish created on Shopify for the code; absent until publish runs. Server state, never authored"}},"required":["type","purchaseType","discount","lineRoles"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","enum":["selling_plan_adjustment"],"description":"The selling plan's own price adjustments price the subscription lines on that plan"},"sellingPlanId":{"type":"string","pattern":"^gid:\\/\\/shopify\\/SellingPlan\\/\\d+$","description":"The selling plan, carried by a subscription line of the option"},"adjustments":{"type":"array","items":{"type":"object","properties":{"fromOrder":{"anyOf":[{"type":"integer","exclusiveMinimum":0},{"type":"string","enum":["after_last"]}],"description":"The order from which the adjustment is in effect: N from the Nth order on, until a later one takes over; \"after_last\" after every numbered one (alone, from the first order). Before the first, the catalog price"},"discount":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","enum":["percent"],"description":"A percentage off"},"percent":{"type":"number","minimum":0,"maximum":100,"description":"The percentage off, 0 to 100"}},"required":["type","percent"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","enum":["fixed_amount"],"description":"A fixed amount off"},"amountCents":{"type":"integer","minimum":0,"description":"The amount off, in cents"}},"required":["type","amountCents"],"additionalProperties":false}],"description":"How much the plan takes off the variant's price, per unit"}},"required":["fromOrder","discount"],"additionalProperties":false},"minItems":1,"description":"The plan's price adjustments as Shopify holds them, at most two"}},"required":["type","sellingPlanId","adjustments"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","enum":["catalog_price"],"description":"The variant's catalog price is already the offer price; nothing is discounted"}},"required":["type"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","enum":["existing_automatic_discount"],"description":"An automatic discount the store already runs; we only describe it"},"lineRoles":{"type":"array","items":{"type":"string","enum":["main","add_on","gift"],"description":"What a line is in its option: `main` is what the buyer pays for, `add_on` an extra the buyer opts into or is always added, `gift` a real product the discount function prices to zero"},"minItems":1,"description":"The roles of the option's lines this mechanism prices"},"discount":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","enum":["percent"],"description":"A percentage off"},"percent":{"type":"number","minimum":0,"maximum":100,"description":"The percentage off, 0 to 100"}},"required":["type","percent"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","enum":["fixed_amount"],"description":"A fixed amount off"},"amountCents":{"type":"integer","minimum":0,"description":"The amount off, in cents"}},"required":["type","amountCents"],"additionalProperties":false}],"description":"How much comes off"},"charges":{"type":"string","enum":["first","every"],"description":"Which charges it prices: `first` the first order only; `every` the first order and every renewal of a subscription line"}},"required":["type","lineRoles","discount","charges"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","enum":["unit_price_tiers"],"description":"A category group's first-order unit price by how many units of it the cart holds; our app discount charges it, and the group's selling plans price the renewals"},"lineKey":{"type":"string","maxLength":64,"pattern":"^[a-z0-9][a-z0-9_-]*$","description":"The group: an optional, non-gift line bound to a pool, which a cart opts into by this key"},"tiers":{"type":"array","items":{"type":"object","properties":{"fromUnits":{"type":"integer","exclusiveMinimum":0,"description":"The fewest units of the group this tier's price applies to; the first tier is 1"},"unitCents":{"type":"integer","minimum":0,"description":"What each unit of the group charges on the first order at this tier, in cents"}},"required":["fromUnits","unitCents"],"additionalProperties":false},"minItems":1,"description":"The tiers, ascending from 1; above the last tier the last price holds"}},"required":["type","lineKey","tiers"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","enum":["line_price"],"description":"Our cart transform sets the lines' unit price as their own price, at or below each line's catalog price (never above: a raise is refused): shown as the product's price, with no saving at checkout. One-time lines only, on any store with our cart transform registered: `lineUpdate` on Shopify Plus, the line expanded into itself on every other plan"},"lineKeys":{"type":"array","items":{"type":"string","maxLength":64,"pattern":"^[a-z0-9][a-z0-9_-]*$","description":"A key the brand authors: lower-case letters, digits, `_` and `-`"},"minItems":1,"description":"The one-time lines priced, by key"},"unitCents":{"type":"integer","minimum":0,"description":"What each unit of those lines charges on the first order, in cents"}},"required":["type","lineKeys","unitCents"],"additionalProperties":false}]},"description":"How the promise is made real on Shopify; at most one product discount per line and charge"}},"required":["promise","compareAtPrice","shipping","mechanisms"],"additionalProperties":false,"description":"What the option promises and how Shopify charges it"},"presentations":{"type":"array","items":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","enum":["line_override"],"description":"One line shown with another title or image. It exists only on the cart line: the order keeps the product's real title. Shopify Plus only, except on a line with a line price, where it rides in the line expanded into itself on any plan"},"lineKey":{"type":"string","maxLength":64,"pattern":"^[a-z0-9][a-z0-9_-]*$","description":"The one-time line shown differently"},"title":{"type":"string","minLength":1,"maxLength":255,"description":"What the cart and checkout show as the line's title; the order keeps the product's own title"},"imageUrl":{"type":"string","pattern":"^https:\\/\\/cdn\\.shopify\\.com\\/\\S+$","description":"What the cart and checkout show as the line's image; never kept on the order"}},"required":["type","lineKey"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","enum":["merged_bundle"],"description":"Several lines merged into one titled parent line in the cart and at checkout; on the order, the lines are a bundle group under the parent's title. A merged bundle has no stock of its own"},"lineKeys":{"type":"array","items":{"type":"string","maxLength":64,"pattern":"^[a-z0-9][a-z0-9_-]*$","description":"A key the brand authors: lower-case letters, digits, `_` and `-`"},"minItems":1,"description":"The required one-time lines merged into the parent, each at its own quantity"},"parentVariantId":{"type":"string","pattern":"^gid:\\/\\/shopify\\/ProductVariant\\/\\d+$","description":"The variant the parent line shows as: a bundle product whose variant requires components, so it can never be bought on its own"},"title":{"type":"string","minLength":1,"maxLength":255,"description":"What the cart and checkout show as the line's title; the order keeps the product's own title"},"imageUrl":{"type":"string","pattern":"^https:\\/\\/cdn\\.shopify\\.com\\/\\S+$","description":"What the cart and checkout show as the line's image; never kept on the order"},"attributes":{"type":"array","items":{"type":"object","properties":{"key":{"type":"string","minLength":1,"description":"The attribute's key"},"value":{"type":"string","description":"The attribute's value"}},"required":["key","value"],"additionalProperties":false},"description":"Attributes Shopify puts on the order's bundle group (not in the order webhook)"},"price":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","enum":["percent_off"],"description":"The bundle costs its lines' catalog price less a percentage, shown as the bundle's own price with no saving at checkout"},"percent":{"type":"number","minimum":0,"maximum":100,"description":"The percentage off, 0 to 100"}},"required":["type","percent"],"additionalProperties":false}],"description":"The bundle's price from our cart transform; absent, each line keeps its own price and our discount prices the parent"}},"required":["type","lineKeys","parentVariantId"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","enum":["expanded_bundle"],"description":"One line expanded into components in the cart and at checkout; on the order, the components are a bundle group under the line's title. The line's variant is the parent"},"lineKey":{"type":"string","maxLength":64,"pattern":"^[a-z0-9][a-z0-9_-]*$","description":"The one-time line expanded"},"components":{"type":"array","items":{"type":"object","properties":{"variantId":{"type":"string","pattern":"^gid:\\/\\/shopify\\/ProductVariant\\/\\d+$","description":"A variant that ships inside each unit of the line"},"quantity":{"type":"integer","exclusiveMinimum":0,"description":"Units of the component in each unit of the line"},"unitCents":{"type":"integer","minimum":0,"description":"The component's own price per unit, in cents; set on every component or on none. A gift that ships inside the bundle is a component at 0"},"role":{"type":"string","enum":["main","add_on","gift"],"description":"What the component is on the order, for costing: `main`, `add_on` or `gift`; the expanded line's own role when absent"}},"required":["variantId","quantity"],"additionalProperties":false},"minItems":1,"maxItems":150,"description":"What each unit of the line ships as, at most 150 components (Shopify's limit)"},"title":{"type":"string","minLength":1,"maxLength":255,"description":"What the cart and checkout show as the line's title; the order keeps the product's own title"},"imageUrl":{"type":"string","pattern":"^https:\\/\\/cdn\\.shopify\\.com\\/\\S+$","description":"What the cart and checkout show as the line's image; never kept on the order"},"price":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","enum":["percent_off"],"description":"The bundle costs its lines' catalog price less a percentage, shown as the bundle's own price with no saving at checkout"},"percent":{"type":"number","minimum":0,"maximum":100,"description":"The percentage off, 0 to 100"}},"required":["type","percent"],"additionalProperties":false}],"description":"A percentage off the line's catalog price; refused beside component prices. Absent with no component prices, the line keeps its price and our discount can price it"}},"required":["type","lineKey","components"],"additionalProperties":false}]},"description":"How our cart transform presents the option's one-time lines in the cart and at checkout: line overrides, merged bundles and expanded bundles. Each needs the store's capability for it (`GET /stores/{id}` `capability`); a line appears in one presentation at most"},"checkoutMode":{"type":"string","enum":["cart_page","cart_drawer","direct_to_checkout","landing_cart","external"],"description":"Where the brand's page sends the buyer after the choice: the cart page, a cart drawer, straight to checkout, a cart on the landing page, or an external flow"},"landingPageUrl":{"type":"string","minLength":1,"description":"The page that renders this option; publish checks the page shows it (`page_bind`)"},"verification":{"type":"object","properties":{"status":{"type":"string","enum":["matched","mismatched","unverifiable","unverified"],"description":"Whether a real cart charges what the option promises: `matched`; `mismatched` when a check failed or Shopify refused the cart; `unverifiable` when a check of the promise could not run; `unverified` when never checked (a hidden option). An option goes live only when `matched`"},"evidenceSource":{"type":"string","enum":["none","cart_response","cart_rejection","commerce_api","page_copy"],"description":"What the verdict rests on: nothing yet, a real cart Shopify built, Shopify refusing the cart, the Commerce API, or page copy"},"checkedAt":{"type":["string","null"],"format":"date-time","description":"When the verifier last ran on this option, or null"},"validForSeconds":{"type":"integer","exclusiveMinimum":0,"description":"Seconds the verdict is trusted after `checkedAt`"},"checks":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string","minLength":1,"description":"What was checked (`promised_first_charge`, `line_net:0`, `free_shipping:0:Standard`…); a check that does not apply to the option is not listed"},"covers":{"type":"string","enum":["option","add_on","shipping","renewal","page","presentation"],"description":"What part of the promise the check proves: `option` the option's first-order cart, `add_on` a line of an opt-in add-on, `shipping` the free shipping, `renewal` what renewals charge, `page` the landing page, `presentation` a title or image our cart transform shows (no Storefront cart field carries it, so it never holds an option back)"},"result":{"type":"string","enum":["passed","failed","skipped"],"description":"`passed`, `failed`, or `skipped` when the check could not run"},"detail":{"type":["string","null"],"description":"What was expected and found, or null"}},"required":["name","covers","result","detail"],"additionalProperties":false},"description":"Every check the verifier ran on the option"}},"required":["status","evidenceSource","checkedAt","validForSeconds","checks"],"additionalProperties":false,"description":"What the verifier found; written by publish and re-verification, never authored"}},"required":["key","display","visible","axisValues","unitCount","cardKey","lines","pricing","checkoutMode","verification"],"additionalProperties":false},"minItems":1,"description":"Everything a buyer can choose, one resolved option per combination"},"valueClaims":{"type":"array","items":{"type":"object","properties":{"title":{"type":"string","minLength":1,"description":"The claim as the page words it"},"claimedValueCents":{"type":"integer","minimum":0,"description":"The value claimed, in cents; absent when the page states none"}},"required":["title"],"additionalProperties":false},"description":"Value claims the page makes (bonuses, prizes); never enter a cart"},"terms":{"type":"object","properties":{"guaranteeDays":{"type":"integer","exclusiveMinimum":0,"description":"The money-back guarantee the page states, in days"}},"additionalProperties":false,"description":"Terms the page states"},"costProfile":{"type":"string","minLength":1,"description":"The cost profile the forecast and the realized cost basis use: which cost kinds apply to this offer's orders"}},"required":["schemaVersion","id","version","status","code","tracking","store","axes","pools","defaultOptionKey","options","valueClaims","terms","costProfile"],"additionalProperties":false}},"required":["id","code","experienceName","defaultOptionKey","status","currentVersion","liveVersion","createdAt","updatedAt","version","options","verification","orderCount","document"]},{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"code":{"type":"string","description":"The offer's code; unique per tenant, immutable"},"experienceName":{"type":"string","description":"`tracking.experienceName` of the summarized version: the human handle for the offer"},"defaultOptionKey":{"type":"string","description":"The option a renderer preselects, in the summarized version"},"status":{"type":"string","enum":["draft","verified","live","retired"],"description":"The live version's status when one exists, else the current version's"},"currentVersion":{"type":"integer","exclusiveMinimum":0},"liveVersion":{"type":["integer","null"],"exclusiveMinimum":0},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"},"version":{"type":"object","properties":{"number":{"type":"integer","exclusiveMinimum":0},"status":{"type":"string","enum":["draft","verified","live","retired"]},"createdAt":{"type":"string","format":"date-time"}},"required":["number","status","createdAt"]},"options":{"type":"array","items":{"type":"object","properties":{"key":{"type":"string","description":"The option key"},"title":{"type":"string","description":"The option's `display.title`"},"visible":{"type":"boolean","description":"Whether a renderer may show the option; only visible options are verified"},"promise":{"type":"object","properties":{"firstChargeCents":{"type":["integer","null"],"minimum":0,"description":"What the buyer is charged on the first order, before shipping and tax; required on a visible option. Publish checks a real cart charges it"},"renewalChargeCents":{"type":["integer","null"],"minimum":0,"description":"What each renewal charges, before shipping and tax; required when the option has a subscription line"}},"required":["firstChargeCents","renewalChargeCents"],"additionalProperties":false,"description":"What the option promises the buyer is charged"},"mechanisms":{"type":"array","items":{"type":"string"},"description":"The option's pricing mechanism types, in document order"},"verificationStatus":{"type":"string","enum":["matched","mismatched","unverifiable","unverified"],"description":"Whether a real cart charges what the option promises: `matched`; `mismatched` when a check failed or Shopify refused the cart; `unverifiable` when a check of the promise could not run; `unverified` when never checked (a hidden option). An option goes live only when `matched`"}},"required":["key","title","visible","promise","mechanisms","verificationStatus"]}},"verification":{"type":"object","properties":{"options":{"type":"integer","minimum":0,"description":"Every option of the version, visible or not"},"matched":{"type":"integer","minimum":0,"description":"Options a real cart charges exactly as promised"},"mismatched":{"type":"integer","minimum":0,"description":"Options a check failed on, or whose cart Shopify refused"},"unverifiable":{"type":"integer","minimum":0,"description":"Options a check of the promise could not run on"},"unverified":{"type":"integer","minimum":0,"description":"Options never checked: every hidden option, and every option of a version never published"},"lastCheckedAt":{"type":["string","null"],"format":"date-time","description":"When the verifier last ran on any option of the version"}},"required":["options","matched","mismatched","unverifiable","unverified","lastCheckedAt"],"description":"Verification status counts across the version's options"},"orderCount":{"type":"integer","minimum":0,"description":"Ingested orders attributed to this offer, across versions"}},"required":["id","code","experienceName","defaultOptionKey","status","currentVersion","liveVersion","createdAt","updatedAt","version","options","verification","orderCount"]}]}}}},"400":{"description":"Invalid query","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}},"401":{"description":"Missing, unknown or revoked API key","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}},"403":{"description":"The key is public; this route needs a secret key","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}},"404":{"description":"No offer of this tenant matches the reference","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}}}}},"/offers/document-check":{"get":{"operationId":"checkOfferDocuments","summary":"Check every stored offer document against today's schema","description":"Read-only. Validates, for every offer of the tenant, the live version, the current version and any verified experiment arm against the offer schema as it is today, and lists the versions that fail with each issue's path and message. A rule added to the schema applies to what is written from then on: a version stored before it keeps serving visitors, but `replace_offer` refuses it sent back unchanged, so the offer cannot be edited until someone fixes it. Run it after a schema change, before editing an old offer, or when `replace_offer` refuses a document you did not change. To repair a failing version: `get_offer_version` it, change exactly what each issue names (the error catalogue gives the fix per message), send it to `replace_offer` with a `reason` (a new draft version; the failing one is never edited, and the audit row records what it supersedes), then `publish_offer` it. A failing live version stays listed until its replacement is published. `checked` counts the versions read; an empty `failing` means every one passes.","tags":["Offers"],"security":[{"apiKey":[]}],"responses":{"200":{"description":"The versions checked and those that fail","content":{"application/json":{"schema":{"type":"object","properties":{"checked":{"type":"integer","minimum":0,"description":"Versions checked: each offer's live and current version, and every verified experiment arm"},"failing":{"type":"array","items":{"type":"object","properties":{"offerId":{"type":"string","format":"uuid"},"code":{"type":"string"},"version":{"type":"integer","exclusiveMinimum":0},"status":{"type":"string","enum":["draft","verified","live","retired"]},"live":{"type":"boolean","description":"This version is what visitors are served"},"current":{"type":"boolean","description":"This version is the offer's current one, what an edit starts from"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string","description":"Dotted path in the document, as validation errors report it"},"message":{"type":"string"}},"required":["path","message"]},"minItems":1,"description":"What today's schema refuses in this version; fix each path in the new version"}},"required":["offerId","code","version","status","live","current","issues"]},"description":"The versions that fail, by code then version; empty when every checked version passes"}},"required":["checked","failing"]}}}},"401":{"description":"Missing, unknown or revoked API key","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}},"403":{"description":"The key is public; this route needs a secret key","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}}}}},"/offers/{id}":{"get":{"operationId":"getOffer","summary":"Get an offer at its current version","description":"`view=concise` omits the document.","tags":["Offers"],"security":[{"apiKey":[]}],"parameters":[{"schema":{"type":"string","format":"uuid","description":"The offer id"},"required":true,"description":"The offer id","name":"id","in":"path"},{"schema":{"type":"string","enum":["concise","detailed"],"default":"detailed"},"required":false,"name":"view","in":"query"}],"responses":{"200":{"description":"The offer","content":{"application/json":{"schema":{"anyOf":[{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"code":{"type":"string","description":"The offer's code; unique per tenant, immutable"},"experienceName":{"type":"string","description":"`tracking.experienceName` of the summarized version: the human handle for the offer"},"defaultOptionKey":{"type":"string","description":"The option a renderer preselects, in the summarized version"},"status":{"type":"string","enum":["draft","verified","live","retired"],"description":"The live version's status when one exists, else the current version's"},"currentVersion":{"type":"integer","exclusiveMinimum":0},"liveVersion":{"type":["integer","null"],"exclusiveMinimum":0},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"},"version":{"type":"object","properties":{"number":{"type":"integer","exclusiveMinimum":0},"status":{"type":"string","enum":["draft","verified","live","retired"]},"createdAt":{"type":"string","format":"date-time"}},"required":["number","status","createdAt"]},"options":{"type":"array","items":{"type":"object","properties":{"key":{"type":"string","description":"The option key"},"title":{"type":"string","description":"The option's `display.title`"},"visible":{"type":"boolean","description":"Whether a renderer may show the option; only visible options are verified"},"promise":{"type":"object","properties":{"firstChargeCents":{"type":["integer","null"],"minimum":0,"description":"What the buyer is charged on the first order, before shipping and tax; required on a visible option. Publish checks a real cart charges it"},"renewalChargeCents":{"type":["integer","null"],"minimum":0,"description":"What each renewal charges, before shipping and tax; required when the option has a subscription line"}},"required":["firstChargeCents","renewalChargeCents"],"additionalProperties":false,"description":"What the option promises the buyer is charged"},"mechanisms":{"type":"array","items":{"type":"string"},"description":"The option's pricing mechanism types, in document order"},"verificationStatus":{"type":"string","enum":["matched","mismatched","unverifiable","unverified"],"description":"Whether a real cart charges what the option promises: `matched`; `mismatched` when a check failed or Shopify refused the cart; `unverifiable` when a check of the promise could not run; `unverified` when never checked (a hidden option). An option goes live only when `matched`"}},"required":["key","title","visible","promise","mechanisms","verificationStatus"]}},"verification":{"type":"object","properties":{"options":{"type":"integer","minimum":0,"description":"Every option of the version, visible or not"},"matched":{"type":"integer","minimum":0,"description":"Options a real cart charges exactly as promised"},"mismatched":{"type":"integer","minimum":0,"description":"Options a check failed on, or whose cart Shopify refused"},"unverifiable":{"type":"integer","minimum":0,"description":"Options a check of the promise could not run on"},"unverified":{"type":"integer","minimum":0,"description":"Options never checked: every hidden option, and every option of a version never published"},"lastCheckedAt":{"type":["string","null"],"format":"date-time","description":"When the verifier last ran on any option of the version"}},"required":["options","matched","mismatched","unverifiable","unverified","lastCheckedAt"],"description":"Verification status counts across the version's options"},"orderCount":{"type":"integer","minimum":0,"description":"Ingested orders attributed to this offer, across versions"},"document":{"type":"object","properties":{"schemaVersion":{"type":"string","enum":["offer/1"],"description":"The document format: `offer/1`"},"id":{"type":"string","minLength":1,"description":"The offer id; assigned by the server"},"version":{"type":"integer","exclusiveMinimum":0,"description":"The offer's version number; assigned by the server on every write"},"status":{"type":"string","enum":["draft","verified","live","retired"],"description":"`draft` until published, `live` while served, `retired` once replaced; assigned by the server"},"code":{"type":"string","maxLength":31,"pattern":"^[^,\\s](?:[^,]*[^,\\s])?$","description":"The offer's code: unique per tenant, immutable once created, and how an agent, `lookup_offer` and the order tag `os_offer:<code>` name the offer"},"tracking":{"type":"object","properties":{"experienceName":{"type":"string","minLength":1,"description":"A label for the page or funnel this offer runs in; the offers list shows it"},"campaignName":{"type":"string","minLength":1,"description":"A label for the marketing campaign this offer belongs to"},"presellPageName":{"type":["string","null"],"minLength":1,"description":"A label for the presell page in front of the offer, or null"},"preservedCartAttributes":{"type":"array","items":{"type":"string","minLength":1},"description":"The brand's own cart attribute names a cart request may set and the API keeps on the cart (`preservedCartAttributes` on the cart request)"}},"required":["experienceName","campaignName","presellPageName","preservedCartAttributes"],"additionalProperties":false,"description":"The labels reports group by, and the brand's own cart attributes a cart keeps"},"store":{"type":"object","properties":{"myshopifyDomain":{"type":"string","minLength":1,"description":"The connected store's myshopify domain (`brand.myshopify.com`); publish and serving use this store"},"market":{"type":"object","properties":{"countryCode":{"type":"string","pattern":"^[A-Z]{2}$","description":"The buyer's country, ISO 3166-1 alpha-2; carts are priced in its market"},"currencyCode":{"type":"string","pattern":"^[A-Z]{3}$","description":"The market's currency, ISO 4217; every amount in the document is in it"}},"required":["countryCode","currencyCode"],"additionalProperties":false,"description":"The one market the offer is priced in"}},"required":["myshopifyDomain","market"],"additionalProperties":false,"description":"The connected store and the market the offer is priced in"},"axes":{"type":"array","items":{"type":"object","properties":{"key":{"type":"string","maxLength":64,"pattern":"^[a-z0-9][a-z0-9_-]*$","description":"Names the axis; options and axis-mapped lines refer to it"},"values":{"type":"array","items":{"type":"string","minLength":1},"minItems":1,"description":"Every value the axis takes"}},"required":["key","values"],"additionalProperties":false},"description":"Dimensions the options vary along (flavour, size); they name and enumerate options, never patch one"},"pools":{"type":"array","items":{"type":"object","properties":{"key":{"type":"string","maxLength":64,"pattern":"^[a-z0-9][a-z0-9_-]*$","description":"Names the pool; a pool-bound line refers to it"},"variantIds":{"type":"array","items":{"type":"string","pattern":"^gid:\\/\\/shopify\\/ProductVariant\\/\\d+$","description":"A Shopify ProductVariant gid (`gid://shopify/ProductVariant/<id>`)"},"minItems":1,"description":"The pool's variants"},"allowRepeats":{"type":"boolean","description":"Whether one variant may be chosen more than once"}},"required":["key","variantIds","allowRepeats"],"additionalProperties":false},"description":"Pools a buyer chooses variants from, through a line bound to the pool"},"defaultOptionKey":{"type":"string","maxLength":64,"pattern":"^[a-z0-9][a-z0-9_-]*$","description":"The option a renderer preselects; must name a visible option"},"options":{"type":"array","items":{"type":"object","properties":{"key":{"type":"string","maxLength":30,"pattern":"^[a-z0-9][a-z0-9_-]*$","description":"Names the option: unique in the document, carried in the cart pointer, the order tag `os_option:<key>` (so at most 30 characters) and the economics. Keep it stable"},"display":{"type":"object","properties":{"title":{"type":"string","minLength":1,"description":"The option's name as a buyer reads it"}},"required":["title"],"additionalProperties":false,"description":"What a renderer shows for the option"},"visible":{"type":"boolean","description":"Whether a renderer may show the option and publish verifies it; a hidden option still resolves and builds carts"},"axisValues":{"type":"object","additionalProperties":{"type":"string"},"description":"The option's value on each document axis, by axis key"},"unitCount":{"type":"integer","exclusiveMinimum":0,"description":"The quantity the buyer perceives (\"4 units\"); not the sum of line quantities"},"cardKey":{"type":"string","maxLength":64,"pattern":"^[a-z0-9][a-z0-9_-]*$","description":"Options sharing a card key are drawn as one card (a subscribe and one-time pair of one product)"},"lines":{"type":"array","items":{"oneOf":[{"type":"object","properties":{"role":{"type":"string","enum":["main","add_on"],"description":"`main` is what the buyer pays for; `add_on` an extra"},"key":{"type":"string","maxLength":64,"pattern":"^[a-z0-9][a-z0-9_-]*$","description":"Names the line inside its option; required on an optional non-gift line, which a cart opts into by this key (`addOnLineKeys`)"},"quantity":{"type":"integer","exclusiveMinimum":0,"description":"Units of the variant in the cart; on a pool-bound line, the fewest the buyer may choose"},"maxQuantity":{"type":"integer","exclusiveMinimum":0,"description":"A pool-bound line only: the most units the buyer may choose"},"required":{"type":"boolean","description":"Whether every cart for the option holds the line; an optional line is added only when the cart request names its key"},"variantSource":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","enum":["fixed"],"description":"The line is one named variant"},"productId":{"type":"string","pattern":"^gid:\\/\\/shopify\\/Product\\/\\d+$","description":"The variant's product"},"variantId":{"type":"string","pattern":"^gid:\\/\\/shopify\\/ProductVariant\\/\\d+$","description":"The variant the line puts in the cart"}},"required":["type","productId","variantId"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","enum":["axis_map"],"description":"The variant follows the option's axis values, through `variantIdByAxisValue`"},"productId":{"type":"string","pattern":"^gid:\\/\\/shopify\\/Product\\/\\d+$","description":"The product every mapped variant belongs to"},"axisKeys":{"type":"array","items":{"type":"string","maxLength":64,"pattern":"^[a-z0-9][a-z0-9_-]*$","description":"A key the brand authors: lower-case letters, digits, `_` and `-`"},"minItems":1,"description":"The document axes whose values choose the variant, in `variantIdByAxisValue`'s key order"},"variantIdByAxisValue":{"type":"object","additionalProperties":{"type":"string","pattern":"^gid:\\/\\/shopify\\/ProductVariant\\/\\d+$","description":"A Shopify ProductVariant gid (`gid://shopify/ProductVariant/<id>`)"},"description":"Variant id by axis value; for several `axisKeys`, keyed by the values joined with \"/\" in `axisKeys` order. Must cover exactly the declared values"}},"required":["type","productId","axisKeys","variantIdByAxisValue"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","enum":["pool"],"description":"The buyer chooses the variants from a pool: `quantity` units, up to `maxQuantity`, any mix of the pool's variants; the cart gets one line per distinct variant"},"poolKey":{"type":"string","maxLength":64,"pattern":"^[a-z0-9][a-z0-9_-]*$","description":"The `pools[].key` the buyer chooses from"}},"required":["type","poolKey"],"additionalProperties":false}],"description":"Where the line's variant comes from"},"purchase":{"type":"object","properties":{"type":{"type":"string","enum":["one_time","subscription"],"description":"Bought once, or on a selling plan"},"sellingPlanId":{"type":"string","pattern":"^gid:\\/\\/shopify\\/SellingPlan\\/\\d+$","description":"The selling plan a subscription line is bought on; required when `type` is `subscription`"},"intervalDays":{"type":"integer","exclusiveMinimum":0,"description":"Days between a subscription's charges, as shown to the buyer"},"plans":{"type":"array","items":{"type":"object","properties":{"fromUnits":{"type":"integer","exclusiveMinimum":0,"description":"The fewest units of the group this plan's tier applies to; the first tier is 1"},"intervalDays":{"type":"integer","exclusiveMinimum":0,"description":"The cadence this plan renews on, one of the option's `cadence` intervals"},"sellingPlanId":{"type":"string","pattern":"^gid:\\/\\/shopify\\/SellingPlan\\/\\d+$","description":"The selling plan the group's lines go on at this tier and cadence"}},"required":["fromUnits","intervalDays","sellingPlanId"],"additionalProperties":false},"minItems":1,"description":"A subscription group's plan for each tier and cadence a cart can reach; `sellingPlanId` is one of them"}},"required":["type"],"additionalProperties":false,"description":"How the line is bought: once, or on a selling plan"},"bundleComponents":{"type":"array","items":{"type":"object","properties":{"variantId":{"type":"string","pattern":"^gid:\\/\\/shopify\\/ProductVariant\\/\\d+$","description":"A component variant of the fixed bundle"},"quantity":{"type":"integer","exclusiveMinimum":0,"description":"Units of that component in one bundle"}},"required":["variantId","quantity"],"additionalProperties":false},"minItems":1,"description":"What one unit holds, when the variant is a Shopify fixed bundle"},"catalogPrice":{"type":"object","properties":{"amountCents":{"type":"integer","minimum":0,"description":"The variant's catalog price when the document was written; line pricing starts from it"},"compareAtAmountCents":{"type":["integer","null"],"minimum":0,"description":"The variant's catalog compare-at price then, or null"},"capturedAt":{"type":"string","format":"date-time","description":"When the price was read from the catalog"}},"required":["amountCents","compareAtAmountCents","capturedAt"],"additionalProperties":false,"description":"The catalog price line pricing starts from"}},"required":["role","quantity","required","variantSource","purchase","catalogPrice"],"additionalProperties":false},{"type":"object","properties":{"role":{"type":"string","enum":["gift"],"description":"A real product the discount function prices to zero"},"key":{"type":"string","maxLength":64,"pattern":"^[a-z0-9][a-z0-9_-]*$","description":"Names the line inside its option; required on an optional non-gift line, which a cart opts into by this key (`addOnLineKeys`)"},"quantity":{"type":"integer","exclusiveMinimum":0,"description":"Units of the variant in the cart; on a pool-bound line, the fewest the buyer may choose"},"maxQuantity":{"type":"integer","exclusiveMinimum":0,"description":"A pool-bound line only: the most units the buyer may choose"},"required":{"type":"boolean","description":"Whether every cart for the option holds the line; an optional line is added only when the cart request names its key"},"variantSource":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","enum":["fixed"],"description":"The line is one named variant"},"productId":{"type":"string","pattern":"^gid:\\/\\/shopify\\/Product\\/\\d+$","description":"The variant's product"},"variantId":{"type":"string","pattern":"^gid:\\/\\/shopify\\/ProductVariant\\/\\d+$","description":"The variant the line puts in the cart"}},"required":["type","productId","variantId"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","enum":["axis_map"],"description":"The variant follows the option's axis values, through `variantIdByAxisValue`"},"productId":{"type":"string","pattern":"^gid:\\/\\/shopify\\/Product\\/\\d+$","description":"The product every mapped variant belongs to"},"axisKeys":{"type":"array","items":{"type":"string","maxLength":64,"pattern":"^[a-z0-9][a-z0-9_-]*$","description":"A key the brand authors: lower-case letters, digits, `_` and `-`"},"minItems":1,"description":"The document axes whose values choose the variant, in `variantIdByAxisValue`'s key order"},"variantIdByAxisValue":{"type":"object","additionalProperties":{"type":"string","pattern":"^gid:\\/\\/shopify\\/ProductVariant\\/\\d+$","description":"A Shopify ProductVariant gid (`gid://shopify/ProductVariant/<id>`)"},"description":"Variant id by axis value; for several `axisKeys`, keyed by the values joined with \"/\" in `axisKeys` order. Must cover exactly the declared values"}},"required":["type","productId","axisKeys","variantIdByAxisValue"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","enum":["pool"],"description":"The buyer chooses the variants from a pool: `quantity` units, up to `maxQuantity`, any mix of the pool's variants; the cart gets one line per distinct variant"},"poolKey":{"type":"string","maxLength":64,"pattern":"^[a-z0-9][a-z0-9_-]*$","description":"The `pools[].key` the buyer chooses from"}},"required":["type","poolKey"],"additionalProperties":false}],"description":"Where the line's variant comes from"},"purchase":{"type":"object","properties":{"type":{"type":"string","enum":["one_time","subscription"],"description":"Bought once, or on a selling plan"},"sellingPlanId":{"type":"string","pattern":"^gid:\\/\\/shopify\\/SellingPlan\\/\\d+$","description":"The selling plan a subscription line is bought on; required when `type` is `subscription`"},"intervalDays":{"type":"integer","exclusiveMinimum":0,"description":"Days between a subscription's charges, as shown to the buyer"},"plans":{"type":"array","items":{"type":"object","properties":{"fromUnits":{"type":"integer","exclusiveMinimum":0,"description":"The fewest units of the group this plan's tier applies to; the first tier is 1"},"intervalDays":{"type":"integer","exclusiveMinimum":0,"description":"The cadence this plan renews on, one of the option's `cadence` intervals"},"sellingPlanId":{"type":"string","pattern":"^gid:\\/\\/shopify\\/SellingPlan\\/\\d+$","description":"The selling plan the group's lines go on at this tier and cadence"}},"required":["fromUnits","intervalDays","sellingPlanId"],"additionalProperties":false},"minItems":1,"description":"A subscription group's plan for each tier and cadence a cart can reach; `sellingPlanId` is one of them"}},"required":["type"],"additionalProperties":false,"description":"How the line is bought: once, or on a selling plan"},"bundleComponents":{"type":"array","items":{"type":"object","properties":{"variantId":{"type":"string","pattern":"^gid:\\/\\/shopify\\/ProductVariant\\/\\d+$","description":"A component variant of the fixed bundle"},"quantity":{"type":"integer","exclusiveMinimum":0,"description":"Units of that component in one bundle"}},"required":["variantId","quantity"],"additionalProperties":false},"minItems":1,"description":"What one unit holds, when the variant is a Shopify fixed bundle"},"catalogPrice":{"type":"object","properties":{"amountCents":{"type":"integer","minimum":0,"description":"The variant's catalog price when the document was written; line pricing starts from it"},"compareAtAmountCents":{"type":["integer","null"],"minimum":0,"description":"The variant's catalog compare-at price then, or null"},"capturedAt":{"type":"string","format":"date-time","description":"When the price was read from the catalog"}},"required":["amountCents","compareAtAmountCents","capturedAt"],"additionalProperties":false,"description":"The catalog price line pricing starts from"},"claimedValueCents":{"type":"integer","minimum":0,"description":"The value the page shows for the gift (struck through); never charged: the function zeroes the line, and its cost comes from the ledger"}},"required":["role","quantity","required","variantSource","purchase","catalogPrice","claimedValueCents"],"additionalProperties":false}]},"minItems":1,"description":"What the option puts in the cart"},"maxUnits":{"type":"integer","exclusiveMinimum":0,"description":"A category builder: the most units the option's non-gift lines may hold in all"},"cadence":{"type":"object","properties":{"tiers":{"type":"array","items":{"type":"object","properties":{"fromUnits":{"type":"integer","exclusiveMinimum":0,"description":"The fewest units of the largest subscription group this interval applies to; the first tier is 1"},"intervalDays":{"type":"integer","exclusiveMinimum":0,"description":"Days between charges of every subscription line"}},"required":["fromUnits","intervalDays"],"additionalProperties":false},"minItems":1,"description":"The tiers, ascending from 1; above the last tier the last interval holds"}},"required":["tiers"],"additionalProperties":false,"description":"A category builder: the one interval every subscription line renews on, by the units of the largest subscription group in the cart; required when a line has `purchase.plans`"},"pricing":{"type":"object","properties":{"promise":{"type":"object","properties":{"firstChargeCents":{"type":["integer","null"],"minimum":0,"description":"What the buyer is charged on the first order, before shipping and tax; required on a visible option. Publish checks a real cart charges it"},"renewalChargeCents":{"type":["integer","null"],"minimum":0,"description":"What each renewal charges, before shipping and tax; required when the option has a subscription line"}},"required":["firstChargeCents","renewalChargeCents"],"additionalProperties":false,"description":"What the option promises the buyer is charged"},"compareAtPrice":{"type":"object","properties":{"amountCents":{"type":"integer","minimum":0,"description":"The struck-through amount, in cents"},"source":{"type":"string","enum":["variant","selling_plan","unit_price_times_quantity","metafield","page_copy"],"description":"Where it comes from: the variant's compare-at price, the selling plan's compare-at price, the unit price times the quantity, a metafield, or page copy"}},"required":["amountCents","source"],"additionalProperties":false,"description":"The struck-through price the page shows beside the promise"},"shipping":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","enum":["free"],"description":"The discount function makes the named rates free for carts carrying this option"},"rates":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","enum":["cheapest"],"description":"The cheapest shipping rate in each delivery group"}},"required":["type"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","enum":["all"],"description":"Every shipping rate, express included"}},"required":["type"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","enum":["titles"],"description":"The rates whose title is one of `titles`, ignoring case"},"titles":{"type":"array","items":{"type":"string","minLength":1},"minItems":1,"description":"Rate titles as checkout shows them"}},"required":["type","titles"],"additionalProperties":false}],"description":"Which rates are free"},"charges":{"type":"string","enum":["first","every"],"description":"Which shipments are free: `every` charge (a subscription's renewals too) or the `first` only"},"claimedValueCents":{"type":"integer","minimum":0,"description":"The shipping value the page claims for the free shipment (\"a $6.99 value\"); never charged"},"renewalChargeCents":{"type":"integer","minimum":0,"description":"On a subscription option free on the first charge only: what each renewal's shipping charges. Required there, refused elsewhere"}},"required":["type","rates","charges"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","enum":["charged"],"description":"Shipping is charged at checkout's rates"},"expectedChargeCents":{"type":"integer","minimum":0,"description":"What the forecast assumes a shipment charges, in cents; 0 for none"}},"required":["type","expectedChargeCents"],"additionalProperties":false}],"description":"What the option promises about shipping"},"mechanisms":{"type":"array","items":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","enum":["managed_discount"],"description":"Our app discount prices the lines, from the option map publish writes; works on subscription lines"},"lineRoles":{"type":"array","items":{"type":"string","enum":["main","add_on","gift"],"description":"What a line is in its option: `main` is what the buyer pays for, `add_on` an extra the buyer opts into or is always added, `gift` a real product the discount function prices to zero"},"minItems":1,"description":"The roles of the option's lines this mechanism prices"},"discount":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","enum":["percent"],"description":"A percentage off"},"percent":{"type":"number","minimum":0,"maximum":100,"description":"The percentage off, 0 to 100"}},"required":["type","percent"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","enum":["fixed_amount"],"description":"A fixed amount off"},"amountCents":{"type":"integer","minimum":0,"description":"The amount off, in cents"},"per":{"type":"string","enum":["line","unit"],"description":"Off each line, or off each unit of the line"}},"required":["type","amountCents","per"],"additionalProperties":false}],"description":"How much comes off"},"charges":{"type":"string","enum":["first","every"],"description":"Which charges it prices: `first` the first order only; `every` the first order and every renewal of a subscription line"}},"required":["type","lineRoles","discount","charges"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","enum":["discount_code"],"description":"A Shopify discount code publish creates, applied to the cart the API builds"},"code":{"type":"string","minLength":1,"description":"The code the brand chose; absent, publish mints one"},"purchaseType":{"type":"string","enum":["one_time","subscription","subscription_first_payment_only"],"description":"Which purchases the code prices: one-time lines once, every charge of a subscription line, or a subscription's first order only"},"discount":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","enum":["percent"],"description":"A percentage off"},"percent":{"type":"number","minimum":0,"maximum":100,"description":"The percentage off, 0 to 100"}},"required":["type","percent"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","enum":["fixed_amount"],"description":"A fixed amount off"},"amountCents":{"type":"integer","minimum":0,"description":"The amount off, in cents"}},"required":["type","amountCents"],"additionalProperties":false}],"description":"How much comes off"},"lineRoles":{"type":"array","items":{"type":"string","enum":["main","add_on","gift"],"description":"What a line is in its option: `main` is what the buyer pays for, `add_on` an extra the buyer opts into or is always added, `gift` a real product the discount function prices to zero"},"minItems":1,"description":"The roles of the option's lines this mechanism prices"},"shopify":{"type":"object","properties":{"discountId":{"type":"string","pattern":"^gid:\\/\\/shopify\\/DiscountCodeNode\\/\\d+$","description":"The discount publish created on Shopify"},"code":{"type":"string","minLength":1,"description":"The code live on Shopify: the authored one, or the one publish minted"}},"required":["discountId","code"],"additionalProperties":false,"description":"What publish created on Shopify for the code; absent until publish runs. Server state, never authored"}},"required":["type","purchaseType","discount","lineRoles"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","enum":["selling_plan_adjustment"],"description":"The selling plan's own price adjustments price the subscription lines on that plan"},"sellingPlanId":{"type":"string","pattern":"^gid:\\/\\/shopify\\/SellingPlan\\/\\d+$","description":"The selling plan, carried by a subscription line of the option"},"adjustments":{"type":"array","items":{"type":"object","properties":{"fromOrder":{"anyOf":[{"type":"integer","exclusiveMinimum":0},{"type":"string","enum":["after_last"]}],"description":"The order from which the adjustment is in effect: N from the Nth order on, until a later one takes over; \"after_last\" after every numbered one (alone, from the first order). Before the first, the catalog price"},"discount":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","enum":["percent"],"description":"A percentage off"},"percent":{"type":"number","minimum":0,"maximum":100,"description":"The percentage off, 0 to 100"}},"required":["type","percent"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","enum":["fixed_amount"],"description":"A fixed amount off"},"amountCents":{"type":"integer","minimum":0,"description":"The amount off, in cents"}},"required":["type","amountCents"],"additionalProperties":false}],"description":"How much the plan takes off the variant's price, per unit"}},"required":["fromOrder","discount"],"additionalProperties":false},"minItems":1,"description":"The plan's price adjustments as Shopify holds them, at most two"}},"required":["type","sellingPlanId","adjustments"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","enum":["catalog_price"],"description":"The variant's catalog price is already the offer price; nothing is discounted"}},"required":["type"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","enum":["existing_automatic_discount"],"description":"An automatic discount the store already runs; we only describe it"},"lineRoles":{"type":"array","items":{"type":"string","enum":["main","add_on","gift"],"description":"What a line is in its option: `main` is what the buyer pays for, `add_on` an extra the buyer opts into or is always added, `gift` a real product the discount function prices to zero"},"minItems":1,"description":"The roles of the option's lines this mechanism prices"},"discount":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","enum":["percent"],"description":"A percentage off"},"percent":{"type":"number","minimum":0,"maximum":100,"description":"The percentage off, 0 to 100"}},"required":["type","percent"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","enum":["fixed_amount"],"description":"A fixed amount off"},"amountCents":{"type":"integer","minimum":0,"description":"The amount off, in cents"}},"required":["type","amountCents"],"additionalProperties":false}],"description":"How much comes off"},"charges":{"type":"string","enum":["first","every"],"description":"Which charges it prices: `first` the first order only; `every` the first order and every renewal of a subscription line"}},"required":["type","lineRoles","discount","charges"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","enum":["unit_price_tiers"],"description":"A category group's first-order unit price by how many units of it the cart holds; our app discount charges it, and the group's selling plans price the renewals"},"lineKey":{"type":"string","maxLength":64,"pattern":"^[a-z0-9][a-z0-9_-]*$","description":"The group: an optional, non-gift line bound to a pool, which a cart opts into by this key"},"tiers":{"type":"array","items":{"type":"object","properties":{"fromUnits":{"type":"integer","exclusiveMinimum":0,"description":"The fewest units of the group this tier's price applies to; the first tier is 1"},"unitCents":{"type":"integer","minimum":0,"description":"What each unit of the group charges on the first order at this tier, in cents"}},"required":["fromUnits","unitCents"],"additionalProperties":false},"minItems":1,"description":"The tiers, ascending from 1; above the last tier the last price holds"}},"required":["type","lineKey","tiers"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","enum":["line_price"],"description":"Our cart transform sets the lines' unit price as their own price, at or below each line's catalog price (never above: a raise is refused): shown as the product's price, with no saving at checkout. One-time lines only, on any store with our cart transform registered: `lineUpdate` on Shopify Plus, the line expanded into itself on every other plan"},"lineKeys":{"type":"array","items":{"type":"string","maxLength":64,"pattern":"^[a-z0-9][a-z0-9_-]*$","description":"A key the brand authors: lower-case letters, digits, `_` and `-`"},"minItems":1,"description":"The one-time lines priced, by key"},"unitCents":{"type":"integer","minimum":0,"description":"What each unit of those lines charges on the first order, in cents"}},"required":["type","lineKeys","unitCents"],"additionalProperties":false}]},"description":"How the promise is made real on Shopify; at most one product discount per line and charge"}},"required":["promise","compareAtPrice","shipping","mechanisms"],"additionalProperties":false,"description":"What the option promises and how Shopify charges it"},"presentations":{"type":"array","items":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","enum":["line_override"],"description":"One line shown with another title or image. It exists only on the cart line: the order keeps the product's real title. Shopify Plus only, except on a line with a line price, where it rides in the line expanded into itself on any plan"},"lineKey":{"type":"string","maxLength":64,"pattern":"^[a-z0-9][a-z0-9_-]*$","description":"The one-time line shown differently"},"title":{"type":"string","minLength":1,"maxLength":255,"description":"What the cart and checkout show as the line's title; the order keeps the product's own title"},"imageUrl":{"type":"string","pattern":"^https:\\/\\/cdn\\.shopify\\.com\\/\\S+$","description":"What the cart and checkout show as the line's image; never kept on the order"}},"required":["type","lineKey"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","enum":["merged_bundle"],"description":"Several lines merged into one titled parent line in the cart and at checkout; on the order, the lines are a bundle group under the parent's title. A merged bundle has no stock of its own"},"lineKeys":{"type":"array","items":{"type":"string","maxLength":64,"pattern":"^[a-z0-9][a-z0-9_-]*$","description":"A key the brand authors: lower-case letters, digits, `_` and `-`"},"minItems":1,"description":"The required one-time lines merged into the parent, each at its own quantity"},"parentVariantId":{"type":"string","pattern":"^gid:\\/\\/shopify\\/ProductVariant\\/\\d+$","description":"The variant the parent line shows as: a bundle product whose variant requires components, so it can never be bought on its own"},"title":{"type":"string","minLength":1,"maxLength":255,"description":"What the cart and checkout show as the line's title; the order keeps the product's own title"},"imageUrl":{"type":"string","pattern":"^https:\\/\\/cdn\\.shopify\\.com\\/\\S+$","description":"What the cart and checkout show as the line's image; never kept on the order"},"attributes":{"type":"array","items":{"type":"object","properties":{"key":{"type":"string","minLength":1,"description":"The attribute's key"},"value":{"type":"string","description":"The attribute's value"}},"required":["key","value"],"additionalProperties":false},"description":"Attributes Shopify puts on the order's bundle group (not in the order webhook)"},"price":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","enum":["percent_off"],"description":"The bundle costs its lines' catalog price less a percentage, shown as the bundle's own price with no saving at checkout"},"percent":{"type":"number","minimum":0,"maximum":100,"description":"The percentage off, 0 to 100"}},"required":["type","percent"],"additionalProperties":false}],"description":"The bundle's price from our cart transform; absent, each line keeps its own price and our discount prices the parent"}},"required":["type","lineKeys","parentVariantId"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","enum":["expanded_bundle"],"description":"One line expanded into components in the cart and at checkout; on the order, the components are a bundle group under the line's title. The line's variant is the parent"},"lineKey":{"type":"string","maxLength":64,"pattern":"^[a-z0-9][a-z0-9_-]*$","description":"The one-time line expanded"},"components":{"type":"array","items":{"type":"object","properties":{"variantId":{"type":"string","pattern":"^gid:\\/\\/shopify\\/ProductVariant\\/\\d+$","description":"A variant that ships inside each unit of the line"},"quantity":{"type":"integer","exclusiveMinimum":0,"description":"Units of the component in each unit of the line"},"unitCents":{"type":"integer","minimum":0,"description":"The component's own price per unit, in cents; set on every component or on none. A gift that ships inside the bundle is a component at 0"},"role":{"type":"string","enum":["main","add_on","gift"],"description":"What the component is on the order, for costing: `main`, `add_on` or `gift`; the expanded line's own role when absent"}},"required":["variantId","quantity"],"additionalProperties":false},"minItems":1,"maxItems":150,"description":"What each unit of the line ships as, at most 150 components (Shopify's limit)"},"title":{"type":"string","minLength":1,"maxLength":255,"description":"What the cart and checkout show as the line's title; the order keeps the product's own title"},"imageUrl":{"type":"string","pattern":"^https:\\/\\/cdn\\.shopify\\.com\\/\\S+$","description":"What the cart and checkout show as the line's image; never kept on the order"},"price":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","enum":["percent_off"],"description":"The bundle costs its lines' catalog price less a percentage, shown as the bundle's own price with no saving at checkout"},"percent":{"type":"number","minimum":0,"maximum":100,"description":"The percentage off, 0 to 100"}},"required":["type","percent"],"additionalProperties":false}],"description":"A percentage off the line's catalog price; refused beside component prices. Absent with no component prices, the line keeps its price and our discount can price it"}},"required":["type","lineKey","components"],"additionalProperties":false}]},"description":"How our cart transform presents the option's one-time lines in the cart and at checkout: line overrides, merged bundles and expanded bundles. Each needs the store's capability for it (`GET /stores/{id}` `capability`); a line appears in one presentation at most"},"checkoutMode":{"type":"string","enum":["cart_page","cart_drawer","direct_to_checkout","landing_cart","external"],"description":"Where the brand's page sends the buyer after the choice: the cart page, a cart drawer, straight to checkout, a cart on the landing page, or an external flow"},"landingPageUrl":{"type":"string","minLength":1,"description":"The page that renders this option; publish checks the page shows it (`page_bind`)"},"verification":{"type":"object","properties":{"status":{"type":"string","enum":["matched","mismatched","unverifiable","unverified"],"description":"Whether a real cart charges what the option promises: `matched`; `mismatched` when a check failed or Shopify refused the cart; `unverifiable` when a check of the promise could not run; `unverified` when never checked (a hidden option). An option goes live only when `matched`"},"evidenceSource":{"type":"string","enum":["none","cart_response","cart_rejection","commerce_api","page_copy"],"description":"What the verdict rests on: nothing yet, a real cart Shopify built, Shopify refusing the cart, the Commerce API, or page copy"},"checkedAt":{"type":["string","null"],"format":"date-time","description":"When the verifier last ran on this option, or null"},"validForSeconds":{"type":"integer","exclusiveMinimum":0,"description":"Seconds the verdict is trusted after `checkedAt`"},"checks":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string","minLength":1,"description":"What was checked (`promised_first_charge`, `line_net:0`, `free_shipping:0:Standard`…); a check that does not apply to the option is not listed"},"covers":{"type":"string","enum":["option","add_on","shipping","renewal","page","presentation"],"description":"What part of the promise the check proves: `option` the option's first-order cart, `add_on` a line of an opt-in add-on, `shipping` the free shipping, `renewal` what renewals charge, `page` the landing page, `presentation` a title or image our cart transform shows (no Storefront cart field carries it, so it never holds an option back)"},"result":{"type":"string","enum":["passed","failed","skipped"],"description":"`passed`, `failed`, or `skipped` when the check could not run"},"detail":{"type":["string","null"],"description":"What was expected and found, or null"}},"required":["name","covers","result","detail"],"additionalProperties":false},"description":"Every check the verifier ran on the option"}},"required":["status","evidenceSource","checkedAt","validForSeconds","checks"],"additionalProperties":false,"description":"What the verifier found; written by publish and re-verification, never authored"}},"required":["key","display","visible","axisValues","unitCount","cardKey","lines","pricing","checkoutMode","verification"],"additionalProperties":false},"minItems":1,"description":"Everything a buyer can choose, one resolved option per combination"},"valueClaims":{"type":"array","items":{"type":"object","properties":{"title":{"type":"string","minLength":1,"description":"The claim as the page words it"},"claimedValueCents":{"type":"integer","minimum":0,"description":"The value claimed, in cents; absent when the page states none"}},"required":["title"],"additionalProperties":false},"description":"Value claims the page makes (bonuses, prizes); never enter a cart"},"terms":{"type":"object","properties":{"guaranteeDays":{"type":"integer","exclusiveMinimum":0,"description":"The money-back guarantee the page states, in days"}},"additionalProperties":false,"description":"Terms the page states"},"costProfile":{"type":"string","minLength":1,"description":"The cost profile the forecast and the realized cost basis use: which cost kinds apply to this offer's orders"}},"required":["schemaVersion","id","version","status","code","tracking","store","axes","pools","defaultOptionKey","options","valueClaims","terms","costProfile"],"additionalProperties":false}},"required":["id","code","experienceName","defaultOptionKey","status","currentVersion","liveVersion","createdAt","updatedAt","version","options","verification","orderCount","document"]},{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"code":{"type":"string","description":"The offer's code; unique per tenant, immutable"},"experienceName":{"type":"string","description":"`tracking.experienceName` of the summarized version: the human handle for the offer"},"defaultOptionKey":{"type":"string","description":"The option a renderer preselects, in the summarized version"},"status":{"type":"string","enum":["draft","verified","live","retired"],"description":"The live version's status when one exists, else the current version's"},"currentVersion":{"type":"integer","exclusiveMinimum":0},"liveVersion":{"type":["integer","null"],"exclusiveMinimum":0},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"},"version":{"type":"object","properties":{"number":{"type":"integer","exclusiveMinimum":0},"status":{"type":"string","enum":["draft","verified","live","retired"]},"createdAt":{"type":"string","format":"date-time"}},"required":["number","status","createdAt"]},"options":{"type":"array","items":{"type":"object","properties":{"key":{"type":"string","description":"The option key"},"title":{"type":"string","description":"The option's `display.title`"},"visible":{"type":"boolean","description":"Whether a renderer may show the option; only visible options are verified"},"promise":{"type":"object","properties":{"firstChargeCents":{"type":["integer","null"],"minimum":0,"description":"What the buyer is charged on the first order, before shipping and tax; required on a visible option. Publish checks a real cart charges it"},"renewalChargeCents":{"type":["integer","null"],"minimum":0,"description":"What each renewal charges, before shipping and tax; required when the option has a subscription line"}},"required":["firstChargeCents","renewalChargeCents"],"additionalProperties":false,"description":"What the option promises the buyer is charged"},"mechanisms":{"type":"array","items":{"type":"string"},"description":"The option's pricing mechanism types, in document order"},"verificationStatus":{"type":"string","enum":["matched","mismatched","unverifiable","unverified"],"description":"Whether a real cart charges what the option promises: `matched`; `mismatched` when a check failed or Shopify refused the cart; `unverifiable` when a check of the promise could not run; `unverified` when never checked (a hidden option). An option goes live only when `matched`"}},"required":["key","title","visible","promise","mechanisms","verificationStatus"]}},"verification":{"type":"object","properties":{"options":{"type":"integer","minimum":0,"description":"Every option of the version, visible or not"},"matched":{"type":"integer","minimum":0,"description":"Options a real cart charges exactly as promised"},"mismatched":{"type":"integer","minimum":0,"description":"Options a check failed on, or whose cart Shopify refused"},"unverifiable":{"type":"integer","minimum":0,"description":"Options a check of the promise could not run on"},"unverified":{"type":"integer","minimum":0,"description":"Options never checked: every hidden option, and every option of a version never published"},"lastCheckedAt":{"type":["string","null"],"format":"date-time","description":"When the verifier last ran on any option of the version"}},"required":["options","matched","mismatched","unverifiable","unverified","lastCheckedAt"],"description":"Verification status counts across the version's options"},"orderCount":{"type":"integer","minimum":0,"description":"Ingested orders attributed to this offer, across versions"}},"required":["id","code","experienceName","defaultOptionKey","status","currentVersion","liveVersion","createdAt","updatedAt","version","options","verification","orderCount"]}]}}}},"400":{"description":"Invalid id or query","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}},"401":{"description":"Missing, unknown or revoked API key","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}},"403":{"description":"The key is public; this route needs a secret key","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}},"404":{"description":"No such offer for this tenant","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}}}},"put":{"operationId":"replaceOffer","summary":"Replace the document as a new draft version","description":"Stores the document as version n+1 in status draft and leaves every earlier version untouched. `code` cannot change. A live version keeps serving until the new one is published. Every new version is recorded in the audit log with `reason` when given; say why when the version repairs one that fails today's schema (`check_offer_documents`).","tags":["Offers"],"security":[{"apiKey":[]}],"parameters":[{"schema":{"type":"string","format":"uuid","description":"The offer id"},"required":true,"description":"The offer id","name":"id","in":"path"},{"schema":{"type":"string","minLength":1,"maxLength":500,"description":"Why this version is written, kept on its audit row: say what it repairs when it fixes a version that fails today's schema"},"required":false,"description":"Why this version is written, kept on its audit row: say what it repairs when it fixes a version that fails today's schema","name":"reason","in":"query"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"schemaVersion":{"type":"string","enum":["offer/1"],"description":"The document format: `offer/1`"},"code":{"type":"string","maxLength":31,"pattern":"^[^,\\s](?:[^,]*[^,\\s])?$","description":"The offer's code: unique per tenant, immutable once created, and how an agent, `lookup_offer` and the order tag `os_offer:<code>` name the offer"},"tracking":{"type":"object","properties":{"experienceName":{"type":"string","minLength":1,"description":"A label for the page or funnel this offer runs in; the offers list shows it"},"campaignName":{"type":"string","minLength":1,"description":"A label for the marketing campaign this offer belongs to"},"presellPageName":{"type":["string","null"],"minLength":1,"description":"A label for the presell page in front of the offer, or null"},"preservedCartAttributes":{"type":"array","items":{"type":"string","minLength":1},"description":"The brand's own cart attribute names a cart request may set and the API keeps on the cart (`preservedCartAttributes` on the cart request)"}},"required":["experienceName","campaignName","presellPageName","preservedCartAttributes"],"additionalProperties":false,"description":"The labels reports group by, and the brand's own cart attributes a cart keeps"},"store":{"type":"object","properties":{"myshopifyDomain":{"type":"string","minLength":1,"description":"The connected store's myshopify domain (`brand.myshopify.com`); publish and serving use this store"},"market":{"type":"object","properties":{"countryCode":{"type":"string","pattern":"^[A-Z]{2}$","description":"The buyer's country, ISO 3166-1 alpha-2; carts are priced in its market"},"currencyCode":{"type":"string","pattern":"^[A-Z]{3}$","description":"The market's currency, ISO 4217; every amount in the document is in it"}},"required":["countryCode","currencyCode"],"additionalProperties":false,"description":"The one market the offer is priced in"}},"required":["myshopifyDomain","market"],"additionalProperties":false,"description":"The connected store and the market the offer is priced in"},"axes":{"type":"array","items":{"type":"object","properties":{"key":{"type":"string","maxLength":64,"pattern":"^[a-z0-9][a-z0-9_-]*$","description":"Names the axis; options and axis-mapped lines refer to it"},"values":{"type":"array","items":{"type":"string","minLength":1},"minItems":1,"description":"Every value the axis takes"}},"required":["key","values"],"additionalProperties":false},"description":"Dimensions the options vary along (flavour, size); they name and enumerate options, never patch one"},"pools":{"type":"array","items":{"type":"object","properties":{"key":{"type":"string","maxLength":64,"pattern":"^[a-z0-9][a-z0-9_-]*$","description":"Names the pool; a pool-bound line refers to it"},"variantIds":{"type":"array","items":{"type":"string","pattern":"^gid:\\/\\/shopify\\/ProductVariant\\/\\d+$","description":"A Shopify ProductVariant gid (`gid://shopify/ProductVariant/<id>`)"},"minItems":1,"description":"The pool's variants"},"allowRepeats":{"type":"boolean","description":"Whether one variant may be chosen more than once"}},"required":["key","variantIds","allowRepeats"],"additionalProperties":false},"description":"Pools a buyer chooses variants from, through a line bound to the pool"},"defaultOptionKey":{"type":"string","maxLength":64,"pattern":"^[a-z0-9][a-z0-9_-]*$","description":"The option a renderer preselects; must name a visible option"},"options":{"type":"array","items":{"type":"object","properties":{"key":{"type":"string","maxLength":30,"pattern":"^[a-z0-9][a-z0-9_-]*$","description":"Names the option: unique in the document, carried in the cart pointer, the order tag `os_option:<key>` (so at most 30 characters) and the economics. Keep it stable"},"display":{"type":"object","properties":{"title":{"type":"string","minLength":1,"description":"The option's name as a buyer reads it"}},"required":["title"],"additionalProperties":false,"description":"What a renderer shows for the option"},"visible":{"type":"boolean","description":"Whether a renderer may show the option and publish verifies it; a hidden option still resolves and builds carts"},"axisValues":{"type":"object","additionalProperties":{"type":"string"},"description":"The option's value on each document axis, by axis key"},"unitCount":{"type":"integer","exclusiveMinimum":0,"description":"The quantity the buyer perceives (\"4 units\"); not the sum of line quantities"},"cardKey":{"type":"string","maxLength":64,"pattern":"^[a-z0-9][a-z0-9_-]*$","description":"Options sharing a card key are drawn as one card (a subscribe and one-time pair of one product)"},"lines":{"type":"array","items":{"oneOf":[{"type":"object","properties":{"role":{"type":"string","enum":["main","add_on"],"description":"`main` is what the buyer pays for; `add_on` an extra"},"key":{"type":"string","maxLength":64,"pattern":"^[a-z0-9][a-z0-9_-]*$","description":"Names the line inside its option; required on an optional non-gift line, which a cart opts into by this key (`addOnLineKeys`)"},"quantity":{"type":"integer","exclusiveMinimum":0,"description":"Units of the variant in the cart; on a pool-bound line, the fewest the buyer may choose"},"maxQuantity":{"type":"integer","exclusiveMinimum":0,"description":"A pool-bound line only: the most units the buyer may choose"},"required":{"type":"boolean","description":"Whether every cart for the option holds the line; an optional line is added only when the cart request names its key"},"variantSource":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","enum":["fixed"],"description":"The line is one named variant"},"productId":{"type":"string","pattern":"^gid:\\/\\/shopify\\/Product\\/\\d+$","description":"The variant's product"},"variantId":{"type":"string","pattern":"^gid:\\/\\/shopify\\/ProductVariant\\/\\d+$","description":"The variant the line puts in the cart"}},"required":["type","productId","variantId"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","enum":["axis_map"],"description":"The variant follows the option's axis values, through `variantIdByAxisValue`"},"productId":{"type":"string","pattern":"^gid:\\/\\/shopify\\/Product\\/\\d+$","description":"The product every mapped variant belongs to"},"axisKeys":{"type":"array","items":{"type":"string","maxLength":64,"pattern":"^[a-z0-9][a-z0-9_-]*$","description":"A key the brand authors: lower-case letters, digits, `_` and `-`"},"minItems":1,"description":"The document axes whose values choose the variant, in `variantIdByAxisValue`'s key order"},"variantIdByAxisValue":{"type":"object","additionalProperties":{"type":"string","pattern":"^gid:\\/\\/shopify\\/ProductVariant\\/\\d+$","description":"A Shopify ProductVariant gid (`gid://shopify/ProductVariant/<id>`)"},"description":"Variant id by axis value; for several `axisKeys`, keyed by the values joined with \"/\" in `axisKeys` order. Must cover exactly the declared values"}},"required":["type","productId","axisKeys","variantIdByAxisValue"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","enum":["pool"],"description":"The buyer chooses the variants from a pool: `quantity` units, up to `maxQuantity`, any mix of the pool's variants; the cart gets one line per distinct variant"},"poolKey":{"type":"string","maxLength":64,"pattern":"^[a-z0-9][a-z0-9_-]*$","description":"The `pools[].key` the buyer chooses from"}},"required":["type","poolKey"],"additionalProperties":false}],"description":"Where the line's variant comes from"},"purchase":{"type":"object","properties":{"type":{"type":"string","enum":["one_time","subscription"],"description":"Bought once, or on a selling plan"},"sellingPlanId":{"type":"string","pattern":"^gid:\\/\\/shopify\\/SellingPlan\\/\\d+$","description":"The selling plan a subscription line is bought on; required when `type` is `subscription`"},"intervalDays":{"type":"integer","exclusiveMinimum":0,"description":"Days between a subscription's charges, as shown to the buyer"},"plans":{"type":"array","items":{"type":"object","properties":{"fromUnits":{"type":"integer","exclusiveMinimum":0,"description":"The fewest units of the group this plan's tier applies to; the first tier is 1"},"intervalDays":{"type":"integer","exclusiveMinimum":0,"description":"The cadence this plan renews on, one of the option's `cadence` intervals"},"sellingPlanId":{"type":"string","pattern":"^gid:\\/\\/shopify\\/SellingPlan\\/\\d+$","description":"The selling plan the group's lines go on at this tier and cadence"}},"required":["fromUnits","intervalDays","sellingPlanId"],"additionalProperties":false},"minItems":1,"description":"A subscription group's plan for each tier and cadence a cart can reach; `sellingPlanId` is one of them"}},"required":["type"],"additionalProperties":false,"description":"How the line is bought: once, or on a selling plan"},"bundleComponents":{"type":"array","items":{"type":"object","properties":{"variantId":{"type":"string","pattern":"^gid:\\/\\/shopify\\/ProductVariant\\/\\d+$","description":"A component variant of the fixed bundle"},"quantity":{"type":"integer","exclusiveMinimum":0,"description":"Units of that component in one bundle"}},"required":["variantId","quantity"],"additionalProperties":false},"minItems":1,"description":"What one unit holds, when the variant is a Shopify fixed bundle"},"catalogPrice":{"type":"object","properties":{"amountCents":{"type":"integer","minimum":0,"description":"The variant's catalog price when the document was written; line pricing starts from it"},"compareAtAmountCents":{"type":["integer","null"],"minimum":0,"description":"The variant's catalog compare-at price then, or null"},"capturedAt":{"type":"string","format":"date-time","description":"When the price was read from the catalog"}},"required":["amountCents","compareAtAmountCents","capturedAt"],"additionalProperties":false,"description":"The catalog price line pricing starts from"}},"required":["role","quantity","required","variantSource","purchase","catalogPrice"],"additionalProperties":false},{"type":"object","properties":{"role":{"type":"string","enum":["gift"],"description":"A real product the discount function prices to zero"},"key":{"type":"string","maxLength":64,"pattern":"^[a-z0-9][a-z0-9_-]*$","description":"Names the line inside its option; required on an optional non-gift line, which a cart opts into by this key (`addOnLineKeys`)"},"quantity":{"type":"integer","exclusiveMinimum":0,"description":"Units of the variant in the cart; on a pool-bound line, the fewest the buyer may choose"},"maxQuantity":{"type":"integer","exclusiveMinimum":0,"description":"A pool-bound line only: the most units the buyer may choose"},"required":{"type":"boolean","description":"Whether every cart for the option holds the line; an optional line is added only when the cart request names its key"},"variantSource":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","enum":["fixed"],"description":"The line is one named variant"},"productId":{"type":"string","pattern":"^gid:\\/\\/shopify\\/Product\\/\\d+$","description":"The variant's product"},"variantId":{"type":"string","pattern":"^gid:\\/\\/shopify\\/ProductVariant\\/\\d+$","description":"The variant the line puts in the cart"}},"required":["type","productId","variantId"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","enum":["axis_map"],"description":"The variant follows the option's axis values, through `variantIdByAxisValue`"},"productId":{"type":"string","pattern":"^gid:\\/\\/shopify\\/Product\\/\\d+$","description":"The product every mapped variant belongs to"},"axisKeys":{"type":"array","items":{"type":"string","maxLength":64,"pattern":"^[a-z0-9][a-z0-9_-]*$","description":"A key the brand authors: lower-case letters, digits, `_` and `-`"},"minItems":1,"description":"The document axes whose values choose the variant, in `variantIdByAxisValue`'s key order"},"variantIdByAxisValue":{"type":"object","additionalProperties":{"type":"string","pattern":"^gid:\\/\\/shopify\\/ProductVariant\\/\\d+$","description":"A Shopify ProductVariant gid (`gid://shopify/ProductVariant/<id>`)"},"description":"Variant id by axis value; for several `axisKeys`, keyed by the values joined with \"/\" in `axisKeys` order. Must cover exactly the declared values"}},"required":["type","productId","axisKeys","variantIdByAxisValue"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","enum":["pool"],"description":"The buyer chooses the variants from a pool: `quantity` units, up to `maxQuantity`, any mix of the pool's variants; the cart gets one line per distinct variant"},"poolKey":{"type":"string","maxLength":64,"pattern":"^[a-z0-9][a-z0-9_-]*$","description":"The `pools[].key` the buyer chooses from"}},"required":["type","poolKey"],"additionalProperties":false}],"description":"Where the line's variant comes from"},"purchase":{"type":"object","properties":{"type":{"type":"string","enum":["one_time","subscription"],"description":"Bought once, or on a selling plan"},"sellingPlanId":{"type":"string","pattern":"^gid:\\/\\/shopify\\/SellingPlan\\/\\d+$","description":"The selling plan a subscription line is bought on; required when `type` is `subscription`"},"intervalDays":{"type":"integer","exclusiveMinimum":0,"description":"Days between a subscription's charges, as shown to the buyer"},"plans":{"type":"array","items":{"type":"object","properties":{"fromUnits":{"type":"integer","exclusiveMinimum":0,"description":"The fewest units of the group this plan's tier applies to; the first tier is 1"},"intervalDays":{"type":"integer","exclusiveMinimum":0,"description":"The cadence this plan renews on, one of the option's `cadence` intervals"},"sellingPlanId":{"type":"string","pattern":"^gid:\\/\\/shopify\\/SellingPlan\\/\\d+$","description":"The selling plan the group's lines go on at this tier and cadence"}},"required":["fromUnits","intervalDays","sellingPlanId"],"additionalProperties":false},"minItems":1,"description":"A subscription group's plan for each tier and cadence a cart can reach; `sellingPlanId` is one of them"}},"required":["type"],"additionalProperties":false,"description":"How the line is bought: once, or on a selling plan"},"bundleComponents":{"type":"array","items":{"type":"object","properties":{"variantId":{"type":"string","pattern":"^gid:\\/\\/shopify\\/ProductVariant\\/\\d+$","description":"A component variant of the fixed bundle"},"quantity":{"type":"integer","exclusiveMinimum":0,"description":"Units of that component in one bundle"}},"required":["variantId","quantity"],"additionalProperties":false},"minItems":1,"description":"What one unit holds, when the variant is a Shopify fixed bundle"},"catalogPrice":{"type":"object","properties":{"amountCents":{"type":"integer","minimum":0,"description":"The variant's catalog price when the document was written; line pricing starts from it"},"compareAtAmountCents":{"type":["integer","null"],"minimum":0,"description":"The variant's catalog compare-at price then, or null"},"capturedAt":{"type":"string","format":"date-time","description":"When the price was read from the catalog"}},"required":["amountCents","compareAtAmountCents","capturedAt"],"additionalProperties":false,"description":"The catalog price line pricing starts from"},"claimedValueCents":{"type":"integer","minimum":0,"description":"The value the page shows for the gift (struck through); never charged: the function zeroes the line, and its cost comes from the ledger"}},"required":["role","quantity","required","variantSource","purchase","catalogPrice","claimedValueCents"],"additionalProperties":false}]},"minItems":1,"description":"What the option puts in the cart"},"maxUnits":{"type":"integer","exclusiveMinimum":0,"description":"A category builder: the most units the option's non-gift lines may hold in all"},"cadence":{"type":"object","properties":{"tiers":{"type":"array","items":{"type":"object","properties":{"fromUnits":{"type":"integer","exclusiveMinimum":0,"description":"The fewest units of the largest subscription group this interval applies to; the first tier is 1"},"intervalDays":{"type":"integer","exclusiveMinimum":0,"description":"Days between charges of every subscription line"}},"required":["fromUnits","intervalDays"],"additionalProperties":false},"minItems":1,"description":"The tiers, ascending from 1; above the last tier the last interval holds"}},"required":["tiers"],"additionalProperties":false,"description":"A category builder: the one interval every subscription line renews on, by the units of the largest subscription group in the cart; required when a line has `purchase.plans`"},"pricing":{"type":"object","properties":{"promise":{"type":"object","properties":{"firstChargeCents":{"type":["integer","null"],"minimum":0,"description":"What the buyer is charged on the first order, before shipping and tax; required on a visible option. Publish checks a real cart charges it"},"renewalChargeCents":{"type":["integer","null"],"minimum":0,"description":"What each renewal charges, before shipping and tax; required when the option has a subscription line"}},"required":["firstChargeCents","renewalChargeCents"],"additionalProperties":false,"description":"What the option promises the buyer is charged"},"compareAtPrice":{"type":"object","properties":{"amountCents":{"type":"integer","minimum":0,"description":"The struck-through amount, in cents"},"source":{"type":"string","enum":["variant","selling_plan","unit_price_times_quantity","metafield","page_copy"],"description":"Where it comes from: the variant's compare-at price, the selling plan's compare-at price, the unit price times the quantity, a metafield, or page copy"}},"required":["amountCents","source"],"additionalProperties":false,"description":"The struck-through price the page shows beside the promise"},"shipping":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","enum":["free"],"description":"The discount function makes the named rates free for carts carrying this option"},"rates":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","enum":["cheapest"],"description":"The cheapest shipping rate in each delivery group"}},"required":["type"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","enum":["all"],"description":"Every shipping rate, express included"}},"required":["type"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","enum":["titles"],"description":"The rates whose title is one of `titles`, ignoring case"},"titles":{"type":"array","items":{"type":"string","minLength":1},"minItems":1,"description":"Rate titles as checkout shows them"}},"required":["type","titles"],"additionalProperties":false}],"description":"Which rates are free"},"charges":{"type":"string","enum":["first","every"],"description":"Which shipments are free: `every` charge (a subscription's renewals too) or the `first` only"},"claimedValueCents":{"type":"integer","minimum":0,"description":"The shipping value the page claims for the free shipment (\"a $6.99 value\"); never charged"},"renewalChargeCents":{"type":"integer","minimum":0,"description":"On a subscription option free on the first charge only: what each renewal's shipping charges. Required there, refused elsewhere"}},"required":["type","rates","charges"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","enum":["charged"],"description":"Shipping is charged at checkout's rates"},"expectedChargeCents":{"type":"integer","minimum":0,"description":"What the forecast assumes a shipment charges, in cents; 0 for none"}},"required":["type","expectedChargeCents"],"additionalProperties":false}],"description":"What the option promises about shipping"},"mechanisms":{"type":"array","items":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","enum":["managed_discount"],"description":"Our app discount prices the lines, from the option map publish writes; works on subscription lines"},"lineRoles":{"type":"array","items":{"type":"string","enum":["main","add_on","gift"],"description":"What a line is in its option: `main` is what the buyer pays for, `add_on` an extra the buyer opts into or is always added, `gift` a real product the discount function prices to zero"},"minItems":1,"description":"The roles of the option's lines this mechanism prices"},"discount":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","enum":["percent"],"description":"A percentage off"},"percent":{"type":"number","minimum":0,"maximum":100,"description":"The percentage off, 0 to 100"}},"required":["type","percent"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","enum":["fixed_amount"],"description":"A fixed amount off"},"amountCents":{"type":"integer","minimum":0,"description":"The amount off, in cents"},"per":{"type":"string","enum":["line","unit"],"description":"Off each line, or off each unit of the line"}},"required":["type","amountCents","per"],"additionalProperties":false}],"description":"How much comes off"},"charges":{"type":"string","enum":["first","every"],"description":"Which charges it prices: `first` the first order only; `every` the first order and every renewal of a subscription line"}},"required":["type","lineRoles","discount","charges"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","enum":["discount_code"],"description":"A Shopify discount code publish creates, applied to the cart the API builds"},"code":{"type":"string","minLength":1,"description":"The code the brand chose; absent, publish mints one"},"purchaseType":{"type":"string","enum":["one_time","subscription","subscription_first_payment_only"],"description":"Which purchases the code prices: one-time lines once, every charge of a subscription line, or a subscription's first order only"},"discount":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","enum":["percent"],"description":"A percentage off"},"percent":{"type":"number","minimum":0,"maximum":100,"description":"The percentage off, 0 to 100"}},"required":["type","percent"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","enum":["fixed_amount"],"description":"A fixed amount off"},"amountCents":{"type":"integer","minimum":0,"description":"The amount off, in cents"}},"required":["type","amountCents"],"additionalProperties":false}],"description":"How much comes off"},"lineRoles":{"type":"array","items":{"type":"string","enum":["main","add_on","gift"],"description":"What a line is in its option: `main` is what the buyer pays for, `add_on` an extra the buyer opts into or is always added, `gift` a real product the discount function prices to zero"},"minItems":1,"description":"The roles of the option's lines this mechanism prices"}},"required":["type","purchaseType","discount","lineRoles"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","enum":["selling_plan_adjustment"],"description":"The selling plan's own price adjustments price the subscription lines on that plan"},"sellingPlanId":{"type":"string","pattern":"^gid:\\/\\/shopify\\/SellingPlan\\/\\d+$","description":"The selling plan, carried by a subscription line of the option"},"adjustments":{"type":"array","items":{"type":"object","properties":{"fromOrder":{"anyOf":[{"type":"integer","exclusiveMinimum":0},{"type":"string","enum":["after_last"]}],"description":"The order from which the adjustment is in effect: N from the Nth order on, until a later one takes over; \"after_last\" after every numbered one (alone, from the first order). Before the first, the catalog price"},"discount":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","enum":["percent"],"description":"A percentage off"},"percent":{"type":"number","minimum":0,"maximum":100,"description":"The percentage off, 0 to 100"}},"required":["type","percent"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","enum":["fixed_amount"],"description":"A fixed amount off"},"amountCents":{"type":"integer","minimum":0,"description":"The amount off, in cents"}},"required":["type","amountCents"],"additionalProperties":false}],"description":"How much the plan takes off the variant's price, per unit"}},"required":["fromOrder","discount"],"additionalProperties":false},"minItems":1,"description":"The plan's price adjustments as Shopify holds them, at most two"}},"required":["type","sellingPlanId","adjustments"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","enum":["catalog_price"],"description":"The variant's catalog price is already the offer price; nothing is discounted"}},"required":["type"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","enum":["existing_automatic_discount"],"description":"An automatic discount the store already runs; we only describe it"},"lineRoles":{"type":"array","items":{"type":"string","enum":["main","add_on","gift"],"description":"What a line is in its option: `main` is what the buyer pays for, `add_on` an extra the buyer opts into or is always added, `gift` a real product the discount function prices to zero"},"minItems":1,"description":"The roles of the option's lines this mechanism prices"},"discount":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","enum":["percent"],"description":"A percentage off"},"percent":{"type":"number","minimum":0,"maximum":100,"description":"The percentage off, 0 to 100"}},"required":["type","percent"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","enum":["fixed_amount"],"description":"A fixed amount off"},"amountCents":{"type":"integer","minimum":0,"description":"The amount off, in cents"}},"required":["type","amountCents"],"additionalProperties":false}],"description":"How much comes off"},"charges":{"type":"string","enum":["first","every"],"description":"Which charges it prices: `first` the first order only; `every` the first order and every renewal of a subscription line"}},"required":["type","lineRoles","discount","charges"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","enum":["unit_price_tiers"],"description":"A category group's first-order unit price by how many units of it the cart holds; our app discount charges it, and the group's selling plans price the renewals"},"lineKey":{"type":"string","maxLength":64,"pattern":"^[a-z0-9][a-z0-9_-]*$","description":"The group: an optional, non-gift line bound to a pool, which a cart opts into by this key"},"tiers":{"type":"array","items":{"type":"object","properties":{"fromUnits":{"type":"integer","exclusiveMinimum":0,"description":"The fewest units of the group this tier's price applies to; the first tier is 1"},"unitCents":{"type":"integer","minimum":0,"description":"What each unit of the group charges on the first order at this tier, in cents"}},"required":["fromUnits","unitCents"],"additionalProperties":false},"minItems":1,"description":"The tiers, ascending from 1; above the last tier the last price holds"}},"required":["type","lineKey","tiers"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","enum":["line_price"],"description":"Our cart transform sets the lines' unit price as their own price, at or below each line's catalog price (never above: a raise is refused): shown as the product's price, with no saving at checkout. One-time lines only, on any store with our cart transform registered: `lineUpdate` on Shopify Plus, the line expanded into itself on every other plan"},"lineKeys":{"type":"array","items":{"type":"string","maxLength":64,"pattern":"^[a-z0-9][a-z0-9_-]*$","description":"A key the brand authors: lower-case letters, digits, `_` and `-`"},"minItems":1,"description":"The one-time lines priced, by key"},"unitCents":{"type":"integer","minimum":0,"description":"What each unit of those lines charges on the first order, in cents"}},"required":["type","lineKeys","unitCents"],"additionalProperties":false}]},"description":"How the promise is made real on Shopify; at most one product discount per line and charge"}},"required":["promise","compareAtPrice","shipping","mechanisms"],"additionalProperties":false,"description":"What the option promises and how Shopify charges it"},"presentations":{"type":"array","items":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","enum":["line_override"],"description":"One line shown with another title or image. It exists only on the cart line: the order keeps the product's real title. Shopify Plus only, except on a line with a line price, where it rides in the line expanded into itself on any plan"},"lineKey":{"type":"string","maxLength":64,"pattern":"^[a-z0-9][a-z0-9_-]*$","description":"The one-time line shown differently"},"title":{"type":"string","minLength":1,"maxLength":255,"description":"What the cart and checkout show as the line's title; the order keeps the product's own title"},"imageUrl":{"type":"string","pattern":"^https:\\/\\/cdn\\.shopify\\.com\\/\\S+$","description":"What the cart and checkout show as the line's image; never kept on the order"}},"required":["type","lineKey"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","enum":["merged_bundle"],"description":"Several lines merged into one titled parent line in the cart and at checkout; on the order, the lines are a bundle group under the parent's title. A merged bundle has no stock of its own"},"lineKeys":{"type":"array","items":{"type":"string","maxLength":64,"pattern":"^[a-z0-9][a-z0-9_-]*$","description":"A key the brand authors: lower-case letters, digits, `_` and `-`"},"minItems":1,"description":"The required one-time lines merged into the parent, each at its own quantity"},"parentVariantId":{"type":"string","pattern":"^gid:\\/\\/shopify\\/ProductVariant\\/\\d+$","description":"The variant the parent line shows as: a bundle product whose variant requires components, so it can never be bought on its own"},"title":{"type":"string","minLength":1,"maxLength":255,"description":"What the cart and checkout show as the line's title; the order keeps the product's own title"},"imageUrl":{"type":"string","pattern":"^https:\\/\\/cdn\\.shopify\\.com\\/\\S+$","description":"What the cart and checkout show as the line's image; never kept on the order"},"attributes":{"type":"array","items":{"type":"object","properties":{"key":{"type":"string","minLength":1,"description":"The attribute's key"},"value":{"type":"string","description":"The attribute's value"}},"required":["key","value"],"additionalProperties":false},"description":"Attributes Shopify puts on the order's bundle group (not in the order webhook)"},"price":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","enum":["percent_off"],"description":"The bundle costs its lines' catalog price less a percentage, shown as the bundle's own price with no saving at checkout"},"percent":{"type":"number","minimum":0,"maximum":100,"description":"The percentage off, 0 to 100"}},"required":["type","percent"],"additionalProperties":false}],"description":"The bundle's price from our cart transform; absent, each line keeps its own price and our discount prices the parent"}},"required":["type","lineKeys","parentVariantId"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","enum":["expanded_bundle"],"description":"One line expanded into components in the cart and at checkout; on the order, the components are a bundle group under the line's title. The line's variant is the parent"},"lineKey":{"type":"string","maxLength":64,"pattern":"^[a-z0-9][a-z0-9_-]*$","description":"The one-time line expanded"},"components":{"type":"array","items":{"type":"object","properties":{"variantId":{"type":"string","pattern":"^gid:\\/\\/shopify\\/ProductVariant\\/\\d+$","description":"A variant that ships inside each unit of the line"},"quantity":{"type":"integer","exclusiveMinimum":0,"description":"Units of the component in each unit of the line"},"unitCents":{"type":"integer","minimum":0,"description":"The component's own price per unit, in cents; set on every component or on none. A gift that ships inside the bundle is a component at 0"},"role":{"type":"string","enum":["main","add_on","gift"],"description":"What the component is on the order, for costing: `main`, `add_on` or `gift`; the expanded line's own role when absent"}},"required":["variantId","quantity"],"additionalProperties":false},"minItems":1,"maxItems":150,"description":"What each unit of the line ships as, at most 150 components (Shopify's limit)"},"title":{"type":"string","minLength":1,"maxLength":255,"description":"What the cart and checkout show as the line's title; the order keeps the product's own title"},"imageUrl":{"type":"string","pattern":"^https:\\/\\/cdn\\.shopify\\.com\\/\\S+$","description":"What the cart and checkout show as the line's image; never kept on the order"},"price":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","enum":["percent_off"],"description":"The bundle costs its lines' catalog price less a percentage, shown as the bundle's own price with no saving at checkout"},"percent":{"type":"number","minimum":0,"maximum":100,"description":"The percentage off, 0 to 100"}},"required":["type","percent"],"additionalProperties":false}],"description":"A percentage off the line's catalog price; refused beside component prices. Absent with no component prices, the line keeps its price and our discount can price it"}},"required":["type","lineKey","components"],"additionalProperties":false}]},"description":"How our cart transform presents the option's one-time lines in the cart and at checkout: line overrides, merged bundles and expanded bundles. Each needs the store's capability for it (`GET /stores/{id}` `capability`); a line appears in one presentation at most"},"checkoutMode":{"type":"string","enum":["cart_page","cart_drawer","direct_to_checkout","landing_cart","external"],"description":"Where the brand's page sends the buyer after the choice: the cart page, a cart drawer, straight to checkout, a cart on the landing page, or an external flow"},"landingPageUrl":{"type":"string","minLength":1,"description":"The page that renders this option; publish checks the page shows it (`page_bind`)"}},"required":["key","display","visible","axisValues","unitCount","cardKey","lines","pricing","checkoutMode"],"additionalProperties":false},"minItems":1,"description":"Everything a buyer can choose, one resolved option per combination"},"valueClaims":{"type":"array","items":{"type":"object","properties":{"title":{"type":"string","minLength":1,"description":"The claim as the page words it"},"claimedValueCents":{"type":"integer","minimum":0,"description":"The value claimed, in cents; absent when the page states none"}},"required":["title"],"additionalProperties":false},"description":"Value claims the page makes (bonuses, prizes); never enter a cart"},"terms":{"type":"object","properties":{"guaranteeDays":{"type":"integer","exclusiveMinimum":0,"description":"The money-back guarantee the page states, in days"}},"additionalProperties":false,"description":"Terms the page states"},"costProfile":{"type":"string","minLength":1,"description":"The cost profile the forecast and the realized cost basis use: which cost kinds apply to this offer's orders"}},"required":["schemaVersion","code","tracking","store","axes","pools","defaultOptionKey","options","valueClaims","terms","costProfile"],"additionalProperties":false}}}},"responses":{"200":{"description":"The offer at the new version","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"code":{"type":"string","description":"The offer's code; unique per tenant, immutable"},"experienceName":{"type":"string","description":"`tracking.experienceName` of the summarized version: the human handle for the offer"},"defaultOptionKey":{"type":"string","description":"The option a renderer preselects, in the summarized version"},"status":{"type":"string","enum":["draft","verified","live","retired"],"description":"The live version's status when one exists, else the current version's"},"currentVersion":{"type":"integer","exclusiveMinimum":0},"liveVersion":{"type":["integer","null"],"exclusiveMinimum":0},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"},"version":{"type":"object","properties":{"number":{"type":"integer","exclusiveMinimum":0},"status":{"type":"string","enum":["draft","verified","live","retired"]},"createdAt":{"type":"string","format":"date-time"}},"required":["number","status","createdAt"]},"options":{"type":"array","items":{"type":"object","properties":{"key":{"type":"string","description":"The option key"},"title":{"type":"string","description":"The option's `display.title`"},"visible":{"type":"boolean","description":"Whether a renderer may show the option; only visible options are verified"},"promise":{"type":"object","properties":{"firstChargeCents":{"type":["integer","null"],"minimum":0,"description":"What the buyer is charged on the first order, before shipping and tax; required on a visible option. Publish checks a real cart charges it"},"renewalChargeCents":{"type":["integer","null"],"minimum":0,"description":"What each renewal charges, before shipping and tax; required when the option has a subscription line"}},"required":["firstChargeCents","renewalChargeCents"],"additionalProperties":false,"description":"What the option promises the buyer is charged"},"mechanisms":{"type":"array","items":{"type":"string"},"description":"The option's pricing mechanism types, in document order"},"verificationStatus":{"type":"string","enum":["matched","mismatched","unverifiable","unverified"],"description":"Whether a real cart charges what the option promises: `matched`; `mismatched` when a check failed or Shopify refused the cart; `unverifiable` when a check of the promise could not run; `unverified` when never checked (a hidden option). An option goes live only when `matched`"}},"required":["key","title","visible","promise","mechanisms","verificationStatus"]}},"verification":{"type":"object","properties":{"options":{"type":"integer","minimum":0,"description":"Every option of the version, visible or not"},"matched":{"type":"integer","minimum":0,"description":"Options a real cart charges exactly as promised"},"mismatched":{"type":"integer","minimum":0,"description":"Options a check failed on, or whose cart Shopify refused"},"unverifiable":{"type":"integer","minimum":0,"description":"Options a check of the promise could not run on"},"unverified":{"type":"integer","minimum":0,"description":"Options never checked: every hidden option, and every option of a version never published"},"lastCheckedAt":{"type":["string","null"],"format":"date-time","description":"When the verifier last ran on any option of the version"}},"required":["options","matched","mismatched","unverifiable","unverified","lastCheckedAt"],"description":"Verification status counts across the version's options"},"orderCount":{"type":"integer","minimum":0,"description":"Ingested orders attributed to this offer, across versions"},"document":{"type":"object","properties":{"schemaVersion":{"type":"string","enum":["offer/1"],"description":"The document format: `offer/1`"},"id":{"type":"string","minLength":1,"description":"The offer id; assigned by the server"},"version":{"type":"integer","exclusiveMinimum":0,"description":"The offer's version number; assigned by the server on every write"},"status":{"type":"string","enum":["draft","verified","live","retired"],"description":"`draft` until published, `live` while served, `retired` once replaced; assigned by the server"},"code":{"type":"string","maxLength":31,"pattern":"^[^,\\s](?:[^,]*[^,\\s])?$","description":"The offer's code: unique per tenant, immutable once created, and how an agent, `lookup_offer` and the order tag `os_offer:<code>` name the offer"},"tracking":{"type":"object","properties":{"experienceName":{"type":"string","minLength":1,"description":"A label for the page or funnel this offer runs in; the offers list shows it"},"campaignName":{"type":"string","minLength":1,"description":"A label for the marketing campaign this offer belongs to"},"presellPageName":{"type":["string","null"],"minLength":1,"description":"A label for the presell page in front of the offer, or null"},"preservedCartAttributes":{"type":"array","items":{"type":"string","minLength":1},"description":"The brand's own cart attribute names a cart request may set and the API keeps on the cart (`preservedCartAttributes` on the cart request)"}},"required":["experienceName","campaignName","presellPageName","preservedCartAttributes"],"additionalProperties":false,"description":"The labels reports group by, and the brand's own cart attributes a cart keeps"},"store":{"type":"object","properties":{"myshopifyDomain":{"type":"string","minLength":1,"description":"The connected store's myshopify domain (`brand.myshopify.com`); publish and serving use this store"},"market":{"type":"object","properties":{"countryCode":{"type":"string","pattern":"^[A-Z]{2}$","description":"The buyer's country, ISO 3166-1 alpha-2; carts are priced in its market"},"currencyCode":{"type":"string","pattern":"^[A-Z]{3}$","description":"The market's currency, ISO 4217; every amount in the document is in it"}},"required":["countryCode","currencyCode"],"additionalProperties":false,"description":"The one market the offer is priced in"}},"required":["myshopifyDomain","market"],"additionalProperties":false,"description":"The connected store and the market the offer is priced in"},"axes":{"type":"array","items":{"type":"object","properties":{"key":{"type":"string","maxLength":64,"pattern":"^[a-z0-9][a-z0-9_-]*$","description":"Names the axis; options and axis-mapped lines refer to it"},"values":{"type":"array","items":{"type":"string","minLength":1},"minItems":1,"description":"Every value the axis takes"}},"required":["key","values"],"additionalProperties":false},"description":"Dimensions the options vary along (flavour, size); they name and enumerate options, never patch one"},"pools":{"type":"array","items":{"type":"object","properties":{"key":{"type":"string","maxLength":64,"pattern":"^[a-z0-9][a-z0-9_-]*$","description":"Names the pool; a pool-bound line refers to it"},"variantIds":{"type":"array","items":{"type":"string","pattern":"^gid:\\/\\/shopify\\/ProductVariant\\/\\d+$","description":"A Shopify ProductVariant gid (`gid://shopify/ProductVariant/<id>`)"},"minItems":1,"description":"The pool's variants"},"allowRepeats":{"type":"boolean","description":"Whether one variant may be chosen more than once"}},"required":["key","variantIds","allowRepeats"],"additionalProperties":false},"description":"Pools a buyer chooses variants from, through a line bound to the pool"},"defaultOptionKey":{"type":"string","maxLength":64,"pattern":"^[a-z0-9][a-z0-9_-]*$","description":"The option a renderer preselects; must name a visible option"},"options":{"type":"array","items":{"type":"object","properties":{"key":{"type":"string","maxLength":30,"pattern":"^[a-z0-9][a-z0-9_-]*$","description":"Names the option: unique in the document, carried in the cart pointer, the order tag `os_option:<key>` (so at most 30 characters) and the economics. Keep it stable"},"display":{"type":"object","properties":{"title":{"type":"string","minLength":1,"description":"The option's name as a buyer reads it"}},"required":["title"],"additionalProperties":false,"description":"What a renderer shows for the option"},"visible":{"type":"boolean","description":"Whether a renderer may show the option and publish verifies it; a hidden option still resolves and builds carts"},"axisValues":{"type":"object","additionalProperties":{"type":"string"},"description":"The option's value on each document axis, by axis key"},"unitCount":{"type":"integer","exclusiveMinimum":0,"description":"The quantity the buyer perceives (\"4 units\"); not the sum of line quantities"},"cardKey":{"type":"string","maxLength":64,"pattern":"^[a-z0-9][a-z0-9_-]*$","description":"Options sharing a card key are drawn as one card (a subscribe and one-time pair of one product)"},"lines":{"type":"array","items":{"oneOf":[{"type":"object","properties":{"role":{"type":"string","enum":["main","add_on"],"description":"`main` is what the buyer pays for; `add_on` an extra"},"key":{"type":"string","maxLength":64,"pattern":"^[a-z0-9][a-z0-9_-]*$","description":"Names the line inside its option; required on an optional non-gift line, which a cart opts into by this key (`addOnLineKeys`)"},"quantity":{"type":"integer","exclusiveMinimum":0,"description":"Units of the variant in the cart; on a pool-bound line, the fewest the buyer may choose"},"maxQuantity":{"type":"integer","exclusiveMinimum":0,"description":"A pool-bound line only: the most units the buyer may choose"},"required":{"type":"boolean","description":"Whether every cart for the option holds the line; an optional line is added only when the cart request names its key"},"variantSource":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","enum":["fixed"],"description":"The line is one named variant"},"productId":{"type":"string","pattern":"^gid:\\/\\/shopify\\/Product\\/\\d+$","description":"The variant's product"},"variantId":{"type":"string","pattern":"^gid:\\/\\/shopify\\/ProductVariant\\/\\d+$","description":"The variant the line puts in the cart"}},"required":["type","productId","variantId"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","enum":["axis_map"],"description":"The variant follows the option's axis values, through `variantIdByAxisValue`"},"productId":{"type":"string","pattern":"^gid:\\/\\/shopify\\/Product\\/\\d+$","description":"The product every mapped variant belongs to"},"axisKeys":{"type":"array","items":{"type":"string","maxLength":64,"pattern":"^[a-z0-9][a-z0-9_-]*$","description":"A key the brand authors: lower-case letters, digits, `_` and `-`"},"minItems":1,"description":"The document axes whose values choose the variant, in `variantIdByAxisValue`'s key order"},"variantIdByAxisValue":{"type":"object","additionalProperties":{"type":"string","pattern":"^gid:\\/\\/shopify\\/ProductVariant\\/\\d+$","description":"A Shopify ProductVariant gid (`gid://shopify/ProductVariant/<id>`)"},"description":"Variant id by axis value; for several `axisKeys`, keyed by the values joined with \"/\" in `axisKeys` order. Must cover exactly the declared values"}},"required":["type","productId","axisKeys","variantIdByAxisValue"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","enum":["pool"],"description":"The buyer chooses the variants from a pool: `quantity` units, up to `maxQuantity`, any mix of the pool's variants; the cart gets one line per distinct variant"},"poolKey":{"type":"string","maxLength":64,"pattern":"^[a-z0-9][a-z0-9_-]*$","description":"The `pools[].key` the buyer chooses from"}},"required":["type","poolKey"],"additionalProperties":false}],"description":"Where the line's variant comes from"},"purchase":{"type":"object","properties":{"type":{"type":"string","enum":["one_time","subscription"],"description":"Bought once, or on a selling plan"},"sellingPlanId":{"type":"string","pattern":"^gid:\\/\\/shopify\\/SellingPlan\\/\\d+$","description":"The selling plan a subscription line is bought on; required when `type` is `subscription`"},"intervalDays":{"type":"integer","exclusiveMinimum":0,"description":"Days between a subscription's charges, as shown to the buyer"},"plans":{"type":"array","items":{"type":"object","properties":{"fromUnits":{"type":"integer","exclusiveMinimum":0,"description":"The fewest units of the group this plan's tier applies to; the first tier is 1"},"intervalDays":{"type":"integer","exclusiveMinimum":0,"description":"The cadence this plan renews on, one of the option's `cadence` intervals"},"sellingPlanId":{"type":"string","pattern":"^gid:\\/\\/shopify\\/SellingPlan\\/\\d+$","description":"The selling plan the group's lines go on at this tier and cadence"}},"required":["fromUnits","intervalDays","sellingPlanId"],"additionalProperties":false},"minItems":1,"description":"A subscription group's plan for each tier and cadence a cart can reach; `sellingPlanId` is one of them"}},"required":["type"],"additionalProperties":false,"description":"How the line is bought: once, or on a selling plan"},"bundleComponents":{"type":"array","items":{"type":"object","properties":{"variantId":{"type":"string","pattern":"^gid:\\/\\/shopify\\/ProductVariant\\/\\d+$","description":"A component variant of the fixed bundle"},"quantity":{"type":"integer","exclusiveMinimum":0,"description":"Units of that component in one bundle"}},"required":["variantId","quantity"],"additionalProperties":false},"minItems":1,"description":"What one unit holds, when the variant is a Shopify fixed bundle"},"catalogPrice":{"type":"object","properties":{"amountCents":{"type":"integer","minimum":0,"description":"The variant's catalog price when the document was written; line pricing starts from it"},"compareAtAmountCents":{"type":["integer","null"],"minimum":0,"description":"The variant's catalog compare-at price then, or null"},"capturedAt":{"type":"string","format":"date-time","description":"When the price was read from the catalog"}},"required":["amountCents","compareAtAmountCents","capturedAt"],"additionalProperties":false,"description":"The catalog price line pricing starts from"}},"required":["role","quantity","required","variantSource","purchase","catalogPrice"],"additionalProperties":false},{"type":"object","properties":{"role":{"type":"string","enum":["gift"],"description":"A real product the discount function prices to zero"},"key":{"type":"string","maxLength":64,"pattern":"^[a-z0-9][a-z0-9_-]*$","description":"Names the line inside its option; required on an optional non-gift line, which a cart opts into by this key (`addOnLineKeys`)"},"quantity":{"type":"integer","exclusiveMinimum":0,"description":"Units of the variant in the cart; on a pool-bound line, the fewest the buyer may choose"},"maxQuantity":{"type":"integer","exclusiveMinimum":0,"description":"A pool-bound line only: the most units the buyer may choose"},"required":{"type":"boolean","description":"Whether every cart for the option holds the line; an optional line is added only when the cart request names its key"},"variantSource":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","enum":["fixed"],"description":"The line is one named variant"},"productId":{"type":"string","pattern":"^gid:\\/\\/shopify\\/Product\\/\\d+$","description":"The variant's product"},"variantId":{"type":"string","pattern":"^gid:\\/\\/shopify\\/ProductVariant\\/\\d+$","description":"The variant the line puts in the cart"}},"required":["type","productId","variantId"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","enum":["axis_map"],"description":"The variant follows the option's axis values, through `variantIdByAxisValue`"},"productId":{"type":"string","pattern":"^gid:\\/\\/shopify\\/Product\\/\\d+$","description":"The product every mapped variant belongs to"},"axisKeys":{"type":"array","items":{"type":"string","maxLength":64,"pattern":"^[a-z0-9][a-z0-9_-]*$","description":"A key the brand authors: lower-case letters, digits, `_` and `-`"},"minItems":1,"description":"The document axes whose values choose the variant, in `variantIdByAxisValue`'s key order"},"variantIdByAxisValue":{"type":"object","additionalProperties":{"type":"string","pattern":"^gid:\\/\\/shopify\\/ProductVariant\\/\\d+$","description":"A Shopify ProductVariant gid (`gid://shopify/ProductVariant/<id>`)"},"description":"Variant id by axis value; for several `axisKeys`, keyed by the values joined with \"/\" in `axisKeys` order. Must cover exactly the declared values"}},"required":["type","productId","axisKeys","variantIdByAxisValue"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","enum":["pool"],"description":"The buyer chooses the variants from a pool: `quantity` units, up to `maxQuantity`, any mix of the pool's variants; the cart gets one line per distinct variant"},"poolKey":{"type":"string","maxLength":64,"pattern":"^[a-z0-9][a-z0-9_-]*$","description":"The `pools[].key` the buyer chooses from"}},"required":["type","poolKey"],"additionalProperties":false}],"description":"Where the line's variant comes from"},"purchase":{"type":"object","properties":{"type":{"type":"string","enum":["one_time","subscription"],"description":"Bought once, or on a selling plan"},"sellingPlanId":{"type":"string","pattern":"^gid:\\/\\/shopify\\/SellingPlan\\/\\d+$","description":"The selling plan a subscription line is bought on; required when `type` is `subscription`"},"intervalDays":{"type":"integer","exclusiveMinimum":0,"description":"Days between a subscription's charges, as shown to the buyer"},"plans":{"type":"array","items":{"type":"object","properties":{"fromUnits":{"type":"integer","exclusiveMinimum":0,"description":"The fewest units of the group this plan's tier applies to; the first tier is 1"},"intervalDays":{"type":"integer","exclusiveMinimum":0,"description":"The cadence this plan renews on, one of the option's `cadence` intervals"},"sellingPlanId":{"type":"string","pattern":"^gid:\\/\\/shopify\\/SellingPlan\\/\\d+$","description":"The selling plan the group's lines go on at this tier and cadence"}},"required":["fromUnits","intervalDays","sellingPlanId"],"additionalProperties":false},"minItems":1,"description":"A subscription group's plan for each tier and cadence a cart can reach; `sellingPlanId` is one of them"}},"required":["type"],"additionalProperties":false,"description":"How the line is bought: once, or on a selling plan"},"bundleComponents":{"type":"array","items":{"type":"object","properties":{"variantId":{"type":"string","pattern":"^gid:\\/\\/shopify\\/ProductVariant\\/\\d+$","description":"A component variant of the fixed bundle"},"quantity":{"type":"integer","exclusiveMinimum":0,"description":"Units of that component in one bundle"}},"required":["variantId","quantity"],"additionalProperties":false},"minItems":1,"description":"What one unit holds, when the variant is a Shopify fixed bundle"},"catalogPrice":{"type":"object","properties":{"amountCents":{"type":"integer","minimum":0,"description":"The variant's catalog price when the document was written; line pricing starts from it"},"compareAtAmountCents":{"type":["integer","null"],"minimum":0,"description":"The variant's catalog compare-at price then, or null"},"capturedAt":{"type":"string","format":"date-time","description":"When the price was read from the catalog"}},"required":["amountCents","compareAtAmountCents","capturedAt"],"additionalProperties":false,"description":"The catalog price line pricing starts from"},"claimedValueCents":{"type":"integer","minimum":0,"description":"The value the page shows for the gift (struck through); never charged: the function zeroes the line, and its cost comes from the ledger"}},"required":["role","quantity","required","variantSource","purchase","catalogPrice","claimedValueCents"],"additionalProperties":false}]},"minItems":1,"description":"What the option puts in the cart"},"maxUnits":{"type":"integer","exclusiveMinimum":0,"description":"A category builder: the most units the option's non-gift lines may hold in all"},"cadence":{"type":"object","properties":{"tiers":{"type":"array","items":{"type":"object","properties":{"fromUnits":{"type":"integer","exclusiveMinimum":0,"description":"The fewest units of the largest subscription group this interval applies to; the first tier is 1"},"intervalDays":{"type":"integer","exclusiveMinimum":0,"description":"Days between charges of every subscription line"}},"required":["fromUnits","intervalDays"],"additionalProperties":false},"minItems":1,"description":"The tiers, ascending from 1; above the last tier the last interval holds"}},"required":["tiers"],"additionalProperties":false,"description":"A category builder: the one interval every subscription line renews on, by the units of the largest subscription group in the cart; required when a line has `purchase.plans`"},"pricing":{"type":"object","properties":{"promise":{"type":"object","properties":{"firstChargeCents":{"type":["integer","null"],"minimum":0,"description":"What the buyer is charged on the first order, before shipping and tax; required on a visible option. Publish checks a real cart charges it"},"renewalChargeCents":{"type":["integer","null"],"minimum":0,"description":"What each renewal charges, before shipping and tax; required when the option has a subscription line"}},"required":["firstChargeCents","renewalChargeCents"],"additionalProperties":false,"description":"What the option promises the buyer is charged"},"compareAtPrice":{"type":"object","properties":{"amountCents":{"type":"integer","minimum":0,"description":"The struck-through amount, in cents"},"source":{"type":"string","enum":["variant","selling_plan","unit_price_times_quantity","metafield","page_copy"],"description":"Where it comes from: the variant's compare-at price, the selling plan's compare-at price, the unit price times the quantity, a metafield, or page copy"}},"required":["amountCents","source"],"additionalProperties":false,"description":"The struck-through price the page shows beside the promise"},"shipping":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","enum":["free"],"description":"The discount function makes the named rates free for carts carrying this option"},"rates":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","enum":["cheapest"],"description":"The cheapest shipping rate in each delivery group"}},"required":["type"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","enum":["all"],"description":"Every shipping rate, express included"}},"required":["type"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","enum":["titles"],"description":"The rates whose title is one of `titles`, ignoring case"},"titles":{"type":"array","items":{"type":"string","minLength":1},"minItems":1,"description":"Rate titles as checkout shows them"}},"required":["type","titles"],"additionalProperties":false}],"description":"Which rates are free"},"charges":{"type":"string","enum":["first","every"],"description":"Which shipments are free: `every` charge (a subscription's renewals too) or the `first` only"},"claimedValueCents":{"type":"integer","minimum":0,"description":"The shipping value the page claims for the free shipment (\"a $6.99 value\"); never charged"},"renewalChargeCents":{"type":"integer","minimum":0,"description":"On a subscription option free on the first charge only: what each renewal's shipping charges. Required there, refused elsewhere"}},"required":["type","rates","charges"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","enum":["charged"],"description":"Shipping is charged at checkout's rates"},"expectedChargeCents":{"type":"integer","minimum":0,"description":"What the forecast assumes a shipment charges, in cents; 0 for none"}},"required":["type","expectedChargeCents"],"additionalProperties":false}],"description":"What the option promises about shipping"},"mechanisms":{"type":"array","items":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","enum":["managed_discount"],"description":"Our app discount prices the lines, from the option map publish writes; works on subscription lines"},"lineRoles":{"type":"array","items":{"type":"string","enum":["main","add_on","gift"],"description":"What a line is in its option: `main` is what the buyer pays for, `add_on` an extra the buyer opts into or is always added, `gift` a real product the discount function prices to zero"},"minItems":1,"description":"The roles of the option's lines this mechanism prices"},"discount":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","enum":["percent"],"description":"A percentage off"},"percent":{"type":"number","minimum":0,"maximum":100,"description":"The percentage off, 0 to 100"}},"required":["type","percent"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","enum":["fixed_amount"],"description":"A fixed amount off"},"amountCents":{"type":"integer","minimum":0,"description":"The amount off, in cents"},"per":{"type":"string","enum":["line","unit"],"description":"Off each line, or off each unit of the line"}},"required":["type","amountCents","per"],"additionalProperties":false}],"description":"How much comes off"},"charges":{"type":"string","enum":["first","every"],"description":"Which charges it prices: `first` the first order only; `every` the first order and every renewal of a subscription line"}},"required":["type","lineRoles","discount","charges"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","enum":["discount_code"],"description":"A Shopify discount code publish creates, applied to the cart the API builds"},"code":{"type":"string","minLength":1,"description":"The code the brand chose; absent, publish mints one"},"purchaseType":{"type":"string","enum":["one_time","subscription","subscription_first_payment_only"],"description":"Which purchases the code prices: one-time lines once, every charge of a subscription line, or a subscription's first order only"},"discount":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","enum":["percent"],"description":"A percentage off"},"percent":{"type":"number","minimum":0,"maximum":100,"description":"The percentage off, 0 to 100"}},"required":["type","percent"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","enum":["fixed_amount"],"description":"A fixed amount off"},"amountCents":{"type":"integer","minimum":0,"description":"The amount off, in cents"}},"required":["type","amountCents"],"additionalProperties":false}],"description":"How much comes off"},"lineRoles":{"type":"array","items":{"type":"string","enum":["main","add_on","gift"],"description":"What a line is in its option: `main` is what the buyer pays for, `add_on` an extra the buyer opts into or is always added, `gift` a real product the discount function prices to zero"},"minItems":1,"description":"The roles of the option's lines this mechanism prices"},"shopify":{"type":"object","properties":{"discountId":{"type":"string","pattern":"^gid:\\/\\/shopify\\/DiscountCodeNode\\/\\d+$","description":"The discount publish created on Shopify"},"code":{"type":"string","minLength":1,"description":"The code live on Shopify: the authored one, or the one publish minted"}},"required":["discountId","code"],"additionalProperties":false,"description":"What publish created on Shopify for the code; absent until publish runs. Server state, never authored"}},"required":["type","purchaseType","discount","lineRoles"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","enum":["selling_plan_adjustment"],"description":"The selling plan's own price adjustments price the subscription lines on that plan"},"sellingPlanId":{"type":"string","pattern":"^gid:\\/\\/shopify\\/SellingPlan\\/\\d+$","description":"The selling plan, carried by a subscription line of the option"},"adjustments":{"type":"array","items":{"type":"object","properties":{"fromOrder":{"anyOf":[{"type":"integer","exclusiveMinimum":0},{"type":"string","enum":["after_last"]}],"description":"The order from which the adjustment is in effect: N from the Nth order on, until a later one takes over; \"after_last\" after every numbered one (alone, from the first order). Before the first, the catalog price"},"discount":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","enum":["percent"],"description":"A percentage off"},"percent":{"type":"number","minimum":0,"maximum":100,"description":"The percentage off, 0 to 100"}},"required":["type","percent"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","enum":["fixed_amount"],"description":"A fixed amount off"},"amountCents":{"type":"integer","minimum":0,"description":"The amount off, in cents"}},"required":["type","amountCents"],"additionalProperties":false}],"description":"How much the plan takes off the variant's price, per unit"}},"required":["fromOrder","discount"],"additionalProperties":false},"minItems":1,"description":"The plan's price adjustments as Shopify holds them, at most two"}},"required":["type","sellingPlanId","adjustments"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","enum":["catalog_price"],"description":"The variant's catalog price is already the offer price; nothing is discounted"}},"required":["type"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","enum":["existing_automatic_discount"],"description":"An automatic discount the store already runs; we only describe it"},"lineRoles":{"type":"array","items":{"type":"string","enum":["main","add_on","gift"],"description":"What a line is in its option: `main` is what the buyer pays for, `add_on` an extra the buyer opts into or is always added, `gift` a real product the discount function prices to zero"},"minItems":1,"description":"The roles of the option's lines this mechanism prices"},"discount":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","enum":["percent"],"description":"A percentage off"},"percent":{"type":"number","minimum":0,"maximum":100,"description":"The percentage off, 0 to 100"}},"required":["type","percent"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","enum":["fixed_amount"],"description":"A fixed amount off"},"amountCents":{"type":"integer","minimum":0,"description":"The amount off, in cents"}},"required":["type","amountCents"],"additionalProperties":false}],"description":"How much comes off"},"charges":{"type":"string","enum":["first","every"],"description":"Which charges it prices: `first` the first order only; `every` the first order and every renewal of a subscription line"}},"required":["type","lineRoles","discount","charges"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","enum":["unit_price_tiers"],"description":"A category group's first-order unit price by how many units of it the cart holds; our app discount charges it, and the group's selling plans price the renewals"},"lineKey":{"type":"string","maxLength":64,"pattern":"^[a-z0-9][a-z0-9_-]*$","description":"The group: an optional, non-gift line bound to a pool, which a cart opts into by this key"},"tiers":{"type":"array","items":{"type":"object","properties":{"fromUnits":{"type":"integer","exclusiveMinimum":0,"description":"The fewest units of the group this tier's price applies to; the first tier is 1"},"unitCents":{"type":"integer","minimum":0,"description":"What each unit of the group charges on the first order at this tier, in cents"}},"required":["fromUnits","unitCents"],"additionalProperties":false},"minItems":1,"description":"The tiers, ascending from 1; above the last tier the last price holds"}},"required":["type","lineKey","tiers"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","enum":["line_price"],"description":"Our cart transform sets the lines' unit price as their own price, at or below each line's catalog price (never above: a raise is refused): shown as the product's price, with no saving at checkout. One-time lines only, on any store with our cart transform registered: `lineUpdate` on Shopify Plus, the line expanded into itself on every other plan"},"lineKeys":{"type":"array","items":{"type":"string","maxLength":64,"pattern":"^[a-z0-9][a-z0-9_-]*$","description":"A key the brand authors: lower-case letters, digits, `_` and `-`"},"minItems":1,"description":"The one-time lines priced, by key"},"unitCents":{"type":"integer","minimum":0,"description":"What each unit of those lines charges on the first order, in cents"}},"required":["type","lineKeys","unitCents"],"additionalProperties":false}]},"description":"How the promise is made real on Shopify; at most one product discount per line and charge"}},"required":["promise","compareAtPrice","shipping","mechanisms"],"additionalProperties":false,"description":"What the option promises and how Shopify charges it"},"presentations":{"type":"array","items":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","enum":["line_override"],"description":"One line shown with another title or image. It exists only on the cart line: the order keeps the product's real title. Shopify Plus only, except on a line with a line price, where it rides in the line expanded into itself on any plan"},"lineKey":{"type":"string","maxLength":64,"pattern":"^[a-z0-9][a-z0-9_-]*$","description":"The one-time line shown differently"},"title":{"type":"string","minLength":1,"maxLength":255,"description":"What the cart and checkout show as the line's title; the order keeps the product's own title"},"imageUrl":{"type":"string","pattern":"^https:\\/\\/cdn\\.shopify\\.com\\/\\S+$","description":"What the cart and checkout show as the line's image; never kept on the order"}},"required":["type","lineKey"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","enum":["merged_bundle"],"description":"Several lines merged into one titled parent line in the cart and at checkout; on the order, the lines are a bundle group under the parent's title. A merged bundle has no stock of its own"},"lineKeys":{"type":"array","items":{"type":"string","maxLength":64,"pattern":"^[a-z0-9][a-z0-9_-]*$","description":"A key the brand authors: lower-case letters, digits, `_` and `-`"},"minItems":1,"description":"The required one-time lines merged into the parent, each at its own quantity"},"parentVariantId":{"type":"string","pattern":"^gid:\\/\\/shopify\\/ProductVariant\\/\\d+$","description":"The variant the parent line shows as: a bundle product whose variant requires components, so it can never be bought on its own"},"title":{"type":"string","minLength":1,"maxLength":255,"description":"What the cart and checkout show as the line's title; the order keeps the product's own title"},"imageUrl":{"type":"string","pattern":"^https:\\/\\/cdn\\.shopify\\.com\\/\\S+$","description":"What the cart and checkout show as the line's image; never kept on the order"},"attributes":{"type":"array","items":{"type":"object","properties":{"key":{"type":"string","minLength":1,"description":"The attribute's key"},"value":{"type":"string","description":"The attribute's value"}},"required":["key","value"],"additionalProperties":false},"description":"Attributes Shopify puts on the order's bundle group (not in the order webhook)"},"price":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","enum":["percent_off"],"description":"The bundle costs its lines' catalog price less a percentage, shown as the bundle's own price with no saving at checkout"},"percent":{"type":"number","minimum":0,"maximum":100,"description":"The percentage off, 0 to 100"}},"required":["type","percent"],"additionalProperties":false}],"description":"The bundle's price from our cart transform; absent, each line keeps its own price and our discount prices the parent"}},"required":["type","lineKeys","parentVariantId"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","enum":["expanded_bundle"],"description":"One line expanded into components in the cart and at checkout; on the order, the components are a bundle group under the line's title. The line's variant is the parent"},"lineKey":{"type":"string","maxLength":64,"pattern":"^[a-z0-9][a-z0-9_-]*$","description":"The one-time line expanded"},"components":{"type":"array","items":{"type":"object","properties":{"variantId":{"type":"string","pattern":"^gid:\\/\\/shopify\\/ProductVariant\\/\\d+$","description":"A variant that ships inside each unit of the line"},"quantity":{"type":"integer","exclusiveMinimum":0,"description":"Units of the component in each unit of the line"},"unitCents":{"type":"integer","minimum":0,"description":"The component's own price per unit, in cents; set on every component or on none. A gift that ships inside the bundle is a component at 0"},"role":{"type":"string","enum":["main","add_on","gift"],"description":"What the component is on the order, for costing: `main`, `add_on` or `gift`; the expanded line's own role when absent"}},"required":["variantId","quantity"],"additionalProperties":false},"minItems":1,"maxItems":150,"description":"What each unit of the line ships as, at most 150 components (Shopify's limit)"},"title":{"type":"string","minLength":1,"maxLength":255,"description":"What the cart and checkout show as the line's title; the order keeps the product's own title"},"imageUrl":{"type":"string","pattern":"^https:\\/\\/cdn\\.shopify\\.com\\/\\S+$","description":"What the cart and checkout show as the line's image; never kept on the order"},"price":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","enum":["percent_off"],"description":"The bundle costs its lines' catalog price less a percentage, shown as the bundle's own price with no saving at checkout"},"percent":{"type":"number","minimum":0,"maximum":100,"description":"The percentage off, 0 to 100"}},"required":["type","percent"],"additionalProperties":false}],"description":"A percentage off the line's catalog price; refused beside component prices. Absent with no component prices, the line keeps its price and our discount can price it"}},"required":["type","lineKey","components"],"additionalProperties":false}]},"description":"How our cart transform presents the option's one-time lines in the cart and at checkout: line overrides, merged bundles and expanded bundles. Each needs the store's capability for it (`GET /stores/{id}` `capability`); a line appears in one presentation at most"},"checkoutMode":{"type":"string","enum":["cart_page","cart_drawer","direct_to_checkout","landing_cart","external"],"description":"Where the brand's page sends the buyer after the choice: the cart page, a cart drawer, straight to checkout, a cart on the landing page, or an external flow"},"landingPageUrl":{"type":"string","minLength":1,"description":"The page that renders this option; publish checks the page shows it (`page_bind`)"},"verification":{"type":"object","properties":{"status":{"type":"string","enum":["matched","mismatched","unverifiable","unverified"],"description":"Whether a real cart charges what the option promises: `matched`; `mismatched` when a check failed or Shopify refused the cart; `unverifiable` when a check of the promise could not run; `unverified` when never checked (a hidden option). An option goes live only when `matched`"},"evidenceSource":{"type":"string","enum":["none","cart_response","cart_rejection","commerce_api","page_copy"],"description":"What the verdict rests on: nothing yet, a real cart Shopify built, Shopify refusing the cart, the Commerce API, or page copy"},"checkedAt":{"type":["string","null"],"format":"date-time","description":"When the verifier last ran on this option, or null"},"validForSeconds":{"type":"integer","exclusiveMinimum":0,"description":"Seconds the verdict is trusted after `checkedAt`"},"checks":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string","minLength":1,"description":"What was checked (`promised_first_charge`, `line_net:0`, `free_shipping:0:Standard`…); a check that does not apply to the option is not listed"},"covers":{"type":"string","enum":["option","add_on","shipping","renewal","page","presentation"],"description":"What part of the promise the check proves: `option` the option's first-order cart, `add_on` a line of an opt-in add-on, `shipping` the free shipping, `renewal` what renewals charge, `page` the landing page, `presentation` a title or image our cart transform shows (no Storefront cart field carries it, so it never holds an option back)"},"result":{"type":"string","enum":["passed","failed","skipped"],"description":"`passed`, `failed`, or `skipped` when the check could not run"},"detail":{"type":["string","null"],"description":"What was expected and found, or null"}},"required":["name","covers","result","detail"],"additionalProperties":false},"description":"Every check the verifier ran on the option"}},"required":["status","evidenceSource","checkedAt","validForSeconds","checks"],"additionalProperties":false,"description":"What the verifier found; written by publish and re-verification, never authored"}},"required":["key","display","visible","axisValues","unitCount","cardKey","lines","pricing","checkoutMode","verification"],"additionalProperties":false},"minItems":1,"description":"Everything a buyer can choose, one resolved option per combination"},"valueClaims":{"type":"array","items":{"type":"object","properties":{"title":{"type":"string","minLength":1,"description":"The claim as the page words it"},"claimedValueCents":{"type":"integer","minimum":0,"description":"The value claimed, in cents; absent when the page states none"}},"required":["title"],"additionalProperties":false},"description":"Value claims the page makes (bonuses, prizes); never enter a cart"},"terms":{"type":"object","properties":{"guaranteeDays":{"type":"integer","exclusiveMinimum":0,"description":"The money-back guarantee the page states, in days"}},"additionalProperties":false,"description":"Terms the page states"},"costProfile":{"type":"string","minLength":1,"description":"The cost profile the forecast and the realized cost basis use: which cost kinds apply to this offer's orders"}},"required":["schemaVersion","id","version","status","code","tracking","store","axes","pools","defaultOptionKey","options","valueClaims","terms","costProfile"],"additionalProperties":false}},"required":["id","code","experienceName","defaultOptionKey","status","currentVersion","liveVersion","createdAt","updatedAt","version","options","verification","orderCount","document"]}}}},"400":{"description":"The document failed validation, or `code` differs from the offer's code","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}},"401":{"description":"Missing, unknown or revoked API key","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}},"403":{"description":"The key is public; this route needs a secret key","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}},"404":{"description":"No such offer for this tenant","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}}}}},"/offers/{id}/versions/{version}":{"get":{"operationId":"getOfferVersion","summary":"Get one version of an offer","description":"Versions are immutable once published; earlier versions stay readable.","tags":["Offers"],"security":[{"apiKey":[]}],"parameters":[{"schema":{"type":"string","format":"uuid","description":"The offer id"},"required":true,"description":"The offer id","name":"id","in":"path"},{"schema":{"type":"integer","exclusiveMinimum":0,"description":"The version number"},"required":true,"description":"The version number","name":"version","in":"path"}],"responses":{"200":{"description":"The offer at that version","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"code":{"type":"string","description":"The offer's code; unique per tenant, immutable"},"experienceName":{"type":"string","description":"`tracking.experienceName` of the summarized version: the human handle for the offer"},"defaultOptionKey":{"type":"string","description":"The option a renderer preselects, in the summarized version"},"status":{"type":"string","enum":["draft","verified","live","retired"],"description":"The live version's status when one exists, else the current version's"},"currentVersion":{"type":"integer","exclusiveMinimum":0},"liveVersion":{"type":["integer","null"],"exclusiveMinimum":0},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"},"version":{"type":"object","properties":{"number":{"type":"integer","exclusiveMinimum":0},"status":{"type":"string","enum":["draft","verified","live","retired"]},"createdAt":{"type":"string","format":"date-time"}},"required":["number","status","createdAt"]},"options":{"type":"array","items":{"type":"object","properties":{"key":{"type":"string","description":"The option key"},"title":{"type":"string","description":"The option's `display.title`"},"visible":{"type":"boolean","description":"Whether a renderer may show the option; only visible options are verified"},"promise":{"type":"object","properties":{"firstChargeCents":{"type":["integer","null"],"minimum":0,"description":"What the buyer is charged on the first order, before shipping and tax; required on a visible option. Publish checks a real cart charges it"},"renewalChargeCents":{"type":["integer","null"],"minimum":0,"description":"What each renewal charges, before shipping and tax; required when the option has a subscription line"}},"required":["firstChargeCents","renewalChargeCents"],"additionalProperties":false,"description":"What the option promises the buyer is charged"},"mechanisms":{"type":"array","items":{"type":"string"},"description":"The option's pricing mechanism types, in document order"},"verificationStatus":{"type":"string","enum":["matched","mismatched","unverifiable","unverified"],"description":"Whether a real cart charges what the option promises: `matched`; `mismatched` when a check failed or Shopify refused the cart; `unverifiable` when a check of the promise could not run; `unverified` when never checked (a hidden option). An option goes live only when `matched`"}},"required":["key","title","visible","promise","mechanisms","verificationStatus"]}},"verification":{"type":"object","properties":{"options":{"type":"integer","minimum":0,"description":"Every option of the version, visible or not"},"matched":{"type":"integer","minimum":0,"description":"Options a real cart charges exactly as promised"},"mismatched":{"type":"integer","minimum":0,"description":"Options a check failed on, or whose cart Shopify refused"},"unverifiable":{"type":"integer","minimum":0,"description":"Options a check of the promise could not run on"},"unverified":{"type":"integer","minimum":0,"description":"Options never checked: every hidden option, and every option of a version never published"},"lastCheckedAt":{"type":["string","null"],"format":"date-time","description":"When the verifier last ran on any option of the version"}},"required":["options","matched","mismatched","unverifiable","unverified","lastCheckedAt"],"description":"Verification status counts across the version's options"},"orderCount":{"type":"integer","minimum":0,"description":"Ingested orders attributed to this offer, across versions"},"document":{"type":"object","properties":{"schemaVersion":{"type":"string","enum":["offer/1"],"description":"The document format: `offer/1`"},"id":{"type":"string","minLength":1,"description":"The offer id; assigned by the server"},"version":{"type":"integer","exclusiveMinimum":0,"description":"The offer's version number; assigned by the server on every write"},"status":{"type":"string","enum":["draft","verified","live","retired"],"description":"`draft` until published, `live` while served, `retired` once replaced; assigned by the server"},"code":{"type":"string","maxLength":31,"pattern":"^[^,\\s](?:[^,]*[^,\\s])?$","description":"The offer's code: unique per tenant, immutable once created, and how an agent, `lookup_offer` and the order tag `os_offer:<code>` name the offer"},"tracking":{"type":"object","properties":{"experienceName":{"type":"string","minLength":1,"description":"A label for the page or funnel this offer runs in; the offers list shows it"},"campaignName":{"type":"string","minLength":1,"description":"A label for the marketing campaign this offer belongs to"},"presellPageName":{"type":["string","null"],"minLength":1,"description":"A label for the presell page in front of the offer, or null"},"preservedCartAttributes":{"type":"array","items":{"type":"string","minLength":1},"description":"The brand's own cart attribute names a cart request may set and the API keeps on the cart (`preservedCartAttributes` on the cart request)"}},"required":["experienceName","campaignName","presellPageName","preservedCartAttributes"],"additionalProperties":false,"description":"The labels reports group by, and the brand's own cart attributes a cart keeps"},"store":{"type":"object","properties":{"myshopifyDomain":{"type":"string","minLength":1,"description":"The connected store's myshopify domain (`brand.myshopify.com`); publish and serving use this store"},"market":{"type":"object","properties":{"countryCode":{"type":"string","pattern":"^[A-Z]{2}$","description":"The buyer's country, ISO 3166-1 alpha-2; carts are priced in its market"},"currencyCode":{"type":"string","pattern":"^[A-Z]{3}$","description":"The market's currency, ISO 4217; every amount in the document is in it"}},"required":["countryCode","currencyCode"],"additionalProperties":false,"description":"The one market the offer is priced in"}},"required":["myshopifyDomain","market"],"additionalProperties":false,"description":"The connected store and the market the offer is priced in"},"axes":{"type":"array","items":{"type":"object","properties":{"key":{"type":"string","maxLength":64,"pattern":"^[a-z0-9][a-z0-9_-]*$","description":"Names the axis; options and axis-mapped lines refer to it"},"values":{"type":"array","items":{"type":"string","minLength":1},"minItems":1,"description":"Every value the axis takes"}},"required":["key","values"],"additionalProperties":false},"description":"Dimensions the options vary along (flavour, size); they name and enumerate options, never patch one"},"pools":{"type":"array","items":{"type":"object","properties":{"key":{"type":"string","maxLength":64,"pattern":"^[a-z0-9][a-z0-9_-]*$","description":"Names the pool; a pool-bound line refers to it"},"variantIds":{"type":"array","items":{"type":"string","pattern":"^gid:\\/\\/shopify\\/ProductVariant\\/\\d+$","description":"A Shopify ProductVariant gid (`gid://shopify/ProductVariant/<id>`)"},"minItems":1,"description":"The pool's variants"},"allowRepeats":{"type":"boolean","description":"Whether one variant may be chosen more than once"}},"required":["key","variantIds","allowRepeats"],"additionalProperties":false},"description":"Pools a buyer chooses variants from, through a line bound to the pool"},"defaultOptionKey":{"type":"string","maxLength":64,"pattern":"^[a-z0-9][a-z0-9_-]*$","description":"The option a renderer preselects; must name a visible option"},"options":{"type":"array","items":{"type":"object","properties":{"key":{"type":"string","maxLength":30,"pattern":"^[a-z0-9][a-z0-9_-]*$","description":"Names the option: unique in the document, carried in the cart pointer, the order tag `os_option:<key>` (so at most 30 characters) and the economics. Keep it stable"},"display":{"type":"object","properties":{"title":{"type":"string","minLength":1,"description":"The option's name as a buyer reads it"}},"required":["title"],"additionalProperties":false,"description":"What a renderer shows for the option"},"visible":{"type":"boolean","description":"Whether a renderer may show the option and publish verifies it; a hidden option still resolves and builds carts"},"axisValues":{"type":"object","additionalProperties":{"type":"string"},"description":"The option's value on each document axis, by axis key"},"unitCount":{"type":"integer","exclusiveMinimum":0,"description":"The quantity the buyer perceives (\"4 units\"); not the sum of line quantities"},"cardKey":{"type":"string","maxLength":64,"pattern":"^[a-z0-9][a-z0-9_-]*$","description":"Options sharing a card key are drawn as one card (a subscribe and one-time pair of one product)"},"lines":{"type":"array","items":{"oneOf":[{"type":"object","properties":{"role":{"type":"string","enum":["main","add_on"],"description":"`main` is what the buyer pays for; `add_on` an extra"},"key":{"type":"string","maxLength":64,"pattern":"^[a-z0-9][a-z0-9_-]*$","description":"Names the line inside its option; required on an optional non-gift line, which a cart opts into by this key (`addOnLineKeys`)"},"quantity":{"type":"integer","exclusiveMinimum":0,"description":"Units of the variant in the cart; on a pool-bound line, the fewest the buyer may choose"},"maxQuantity":{"type":"integer","exclusiveMinimum":0,"description":"A pool-bound line only: the most units the buyer may choose"},"required":{"type":"boolean","description":"Whether every cart for the option holds the line; an optional line is added only when the cart request names its key"},"variantSource":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","enum":["fixed"],"description":"The line is one named variant"},"productId":{"type":"string","pattern":"^gid:\\/\\/shopify\\/Product\\/\\d+$","description":"The variant's product"},"variantId":{"type":"string","pattern":"^gid:\\/\\/shopify\\/ProductVariant\\/\\d+$","description":"The variant the line puts in the cart"}},"required":["type","productId","variantId"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","enum":["axis_map"],"description":"The variant follows the option's axis values, through `variantIdByAxisValue`"},"productId":{"type":"string","pattern":"^gid:\\/\\/shopify\\/Product\\/\\d+$","description":"The product every mapped variant belongs to"},"axisKeys":{"type":"array","items":{"type":"string","maxLength":64,"pattern":"^[a-z0-9][a-z0-9_-]*$","description":"A key the brand authors: lower-case letters, digits, `_` and `-`"},"minItems":1,"description":"The document axes whose values choose the variant, in `variantIdByAxisValue`'s key order"},"variantIdByAxisValue":{"type":"object","additionalProperties":{"type":"string","pattern":"^gid:\\/\\/shopify\\/ProductVariant\\/\\d+$","description":"A Shopify ProductVariant gid (`gid://shopify/ProductVariant/<id>`)"},"description":"Variant id by axis value; for several `axisKeys`, keyed by the values joined with \"/\" in `axisKeys` order. Must cover exactly the declared values"}},"required":["type","productId","axisKeys","variantIdByAxisValue"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","enum":["pool"],"description":"The buyer chooses the variants from a pool: `quantity` units, up to `maxQuantity`, any mix of the pool's variants; the cart gets one line per distinct variant"},"poolKey":{"type":"string","maxLength":64,"pattern":"^[a-z0-9][a-z0-9_-]*$","description":"The `pools[].key` the buyer chooses from"}},"required":["type","poolKey"],"additionalProperties":false}],"description":"Where the line's variant comes from"},"purchase":{"type":"object","properties":{"type":{"type":"string","enum":["one_time","subscription"],"description":"Bought once, or on a selling plan"},"sellingPlanId":{"type":"string","pattern":"^gid:\\/\\/shopify\\/SellingPlan\\/\\d+$","description":"The selling plan a subscription line is bought on; required when `type` is `subscription`"},"intervalDays":{"type":"integer","exclusiveMinimum":0,"description":"Days between a subscription's charges, as shown to the buyer"},"plans":{"type":"array","items":{"type":"object","properties":{"fromUnits":{"type":"integer","exclusiveMinimum":0,"description":"The fewest units of the group this plan's tier applies to; the first tier is 1"},"intervalDays":{"type":"integer","exclusiveMinimum":0,"description":"The cadence this plan renews on, one of the option's `cadence` intervals"},"sellingPlanId":{"type":"string","pattern":"^gid:\\/\\/shopify\\/SellingPlan\\/\\d+$","description":"The selling plan the group's lines go on at this tier and cadence"}},"required":["fromUnits","intervalDays","sellingPlanId"],"additionalProperties":false},"minItems":1,"description":"A subscription group's plan for each tier and cadence a cart can reach; `sellingPlanId` is one of them"}},"required":["type"],"additionalProperties":false,"description":"How the line is bought: once, or on a selling plan"},"bundleComponents":{"type":"array","items":{"type":"object","properties":{"variantId":{"type":"string","pattern":"^gid:\\/\\/shopify\\/ProductVariant\\/\\d+$","description":"A component variant of the fixed bundle"},"quantity":{"type":"integer","exclusiveMinimum":0,"description":"Units of that component in one bundle"}},"required":["variantId","quantity"],"additionalProperties":false},"minItems":1,"description":"What one unit holds, when the variant is a Shopify fixed bundle"},"catalogPrice":{"type":"object","properties":{"amountCents":{"type":"integer","minimum":0,"description":"The variant's catalog price when the document was written; line pricing starts from it"},"compareAtAmountCents":{"type":["integer","null"],"minimum":0,"description":"The variant's catalog compare-at price then, or null"},"capturedAt":{"type":"string","format":"date-time","description":"When the price was read from the catalog"}},"required":["amountCents","compareAtAmountCents","capturedAt"],"additionalProperties":false,"description":"The catalog price line pricing starts from"}},"required":["role","quantity","required","variantSource","purchase","catalogPrice"],"additionalProperties":false},{"type":"object","properties":{"role":{"type":"string","enum":["gift"],"description":"A real product the discount function prices to zero"},"key":{"type":"string","maxLength":64,"pattern":"^[a-z0-9][a-z0-9_-]*$","description":"Names the line inside its option; required on an optional non-gift line, which a cart opts into by this key (`addOnLineKeys`)"},"quantity":{"type":"integer","exclusiveMinimum":0,"description":"Units of the variant in the cart; on a pool-bound line, the fewest the buyer may choose"},"maxQuantity":{"type":"integer","exclusiveMinimum":0,"description":"A pool-bound line only: the most units the buyer may choose"},"required":{"type":"boolean","description":"Whether every cart for the option holds the line; an optional line is added only when the cart request names its key"},"variantSource":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","enum":["fixed"],"description":"The line is one named variant"},"productId":{"type":"string","pattern":"^gid:\\/\\/shopify\\/Product\\/\\d+$","description":"The variant's product"},"variantId":{"type":"string","pattern":"^gid:\\/\\/shopify\\/ProductVariant\\/\\d+$","description":"The variant the line puts in the cart"}},"required":["type","productId","variantId"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","enum":["axis_map"],"description":"The variant follows the option's axis values, through `variantIdByAxisValue`"},"productId":{"type":"string","pattern":"^gid:\\/\\/shopify\\/Product\\/\\d+$","description":"The product every mapped variant belongs to"},"axisKeys":{"type":"array","items":{"type":"string","maxLength":64,"pattern":"^[a-z0-9][a-z0-9_-]*$","description":"A key the brand authors: lower-case letters, digits, `_` and `-`"},"minItems":1,"description":"The document axes whose values choose the variant, in `variantIdByAxisValue`'s key order"},"variantIdByAxisValue":{"type":"object","additionalProperties":{"type":"string","pattern":"^gid:\\/\\/shopify\\/ProductVariant\\/\\d+$","description":"A Shopify ProductVariant gid (`gid://shopify/ProductVariant/<id>`)"},"description":"Variant id by axis value; for several `axisKeys`, keyed by the values joined with \"/\" in `axisKeys` order. Must cover exactly the declared values"}},"required":["type","productId","axisKeys","variantIdByAxisValue"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","enum":["pool"],"description":"The buyer chooses the variants from a pool: `quantity` units, up to `maxQuantity`, any mix of the pool's variants; the cart gets one line per distinct variant"},"poolKey":{"type":"string","maxLength":64,"pattern":"^[a-z0-9][a-z0-9_-]*$","description":"The `pools[].key` the buyer chooses from"}},"required":["type","poolKey"],"additionalProperties":false}],"description":"Where the line's variant comes from"},"purchase":{"type":"object","properties":{"type":{"type":"string","enum":["one_time","subscription"],"description":"Bought once, or on a selling plan"},"sellingPlanId":{"type":"string","pattern":"^gid:\\/\\/shopify\\/SellingPlan\\/\\d+$","description":"The selling plan a subscription line is bought on; required when `type` is `subscription`"},"intervalDays":{"type":"integer","exclusiveMinimum":0,"description":"Days between a subscription's charges, as shown to the buyer"},"plans":{"type":"array","items":{"type":"object","properties":{"fromUnits":{"type":"integer","exclusiveMinimum":0,"description":"The fewest units of the group this plan's tier applies to; the first tier is 1"},"intervalDays":{"type":"integer","exclusiveMinimum":0,"description":"The cadence this plan renews on, one of the option's `cadence` intervals"},"sellingPlanId":{"type":"string","pattern":"^gid:\\/\\/shopify\\/SellingPlan\\/\\d+$","description":"The selling plan the group's lines go on at this tier and cadence"}},"required":["fromUnits","intervalDays","sellingPlanId"],"additionalProperties":false},"minItems":1,"description":"A subscription group's plan for each tier and cadence a cart can reach; `sellingPlanId` is one of them"}},"required":["type"],"additionalProperties":false,"description":"How the line is bought: once, or on a selling plan"},"bundleComponents":{"type":"array","items":{"type":"object","properties":{"variantId":{"type":"string","pattern":"^gid:\\/\\/shopify\\/ProductVariant\\/\\d+$","description":"A component variant of the fixed bundle"},"quantity":{"type":"integer","exclusiveMinimum":0,"description":"Units of that component in one bundle"}},"required":["variantId","quantity"],"additionalProperties":false},"minItems":1,"description":"What one unit holds, when the variant is a Shopify fixed bundle"},"catalogPrice":{"type":"object","properties":{"amountCents":{"type":"integer","minimum":0,"description":"The variant's catalog price when the document was written; line pricing starts from it"},"compareAtAmountCents":{"type":["integer","null"],"minimum":0,"description":"The variant's catalog compare-at price then, or null"},"capturedAt":{"type":"string","format":"date-time","description":"When the price was read from the catalog"}},"required":["amountCents","compareAtAmountCents","capturedAt"],"additionalProperties":false,"description":"The catalog price line pricing starts from"},"claimedValueCents":{"type":"integer","minimum":0,"description":"The value the page shows for the gift (struck through); never charged: the function zeroes the line, and its cost comes from the ledger"}},"required":["role","quantity","required","variantSource","purchase","catalogPrice","claimedValueCents"],"additionalProperties":false}]},"minItems":1,"description":"What the option puts in the cart"},"maxUnits":{"type":"integer","exclusiveMinimum":0,"description":"A category builder: the most units the option's non-gift lines may hold in all"},"cadence":{"type":"object","properties":{"tiers":{"type":"array","items":{"type":"object","properties":{"fromUnits":{"type":"integer","exclusiveMinimum":0,"description":"The fewest units of the largest subscription group this interval applies to; the first tier is 1"},"intervalDays":{"type":"integer","exclusiveMinimum":0,"description":"Days between charges of every subscription line"}},"required":["fromUnits","intervalDays"],"additionalProperties":false},"minItems":1,"description":"The tiers, ascending from 1; above the last tier the last interval holds"}},"required":["tiers"],"additionalProperties":false,"description":"A category builder: the one interval every subscription line renews on, by the units of the largest subscription group in the cart; required when a line has `purchase.plans`"},"pricing":{"type":"object","properties":{"promise":{"type":"object","properties":{"firstChargeCents":{"type":["integer","null"],"minimum":0,"description":"What the buyer is charged on the first order, before shipping and tax; required on a visible option. Publish checks a real cart charges it"},"renewalChargeCents":{"type":["integer","null"],"minimum":0,"description":"What each renewal charges, before shipping and tax; required when the option has a subscription line"}},"required":["firstChargeCents","renewalChargeCents"],"additionalProperties":false,"description":"What the option promises the buyer is charged"},"compareAtPrice":{"type":"object","properties":{"amountCents":{"type":"integer","minimum":0,"description":"The struck-through amount, in cents"},"source":{"type":"string","enum":["variant","selling_plan","unit_price_times_quantity","metafield","page_copy"],"description":"Where it comes from: the variant's compare-at price, the selling plan's compare-at price, the unit price times the quantity, a metafield, or page copy"}},"required":["amountCents","source"],"additionalProperties":false,"description":"The struck-through price the page shows beside the promise"},"shipping":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","enum":["free"],"description":"The discount function makes the named rates free for carts carrying this option"},"rates":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","enum":["cheapest"],"description":"The cheapest shipping rate in each delivery group"}},"required":["type"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","enum":["all"],"description":"Every shipping rate, express included"}},"required":["type"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","enum":["titles"],"description":"The rates whose title is one of `titles`, ignoring case"},"titles":{"type":"array","items":{"type":"string","minLength":1},"minItems":1,"description":"Rate titles as checkout shows them"}},"required":["type","titles"],"additionalProperties":false}],"description":"Which rates are free"},"charges":{"type":"string","enum":["first","every"],"description":"Which shipments are free: `every` charge (a subscription's renewals too) or the `first` only"},"claimedValueCents":{"type":"integer","minimum":0,"description":"The shipping value the page claims for the free shipment (\"a $6.99 value\"); never charged"},"renewalChargeCents":{"type":"integer","minimum":0,"description":"On a subscription option free on the first charge only: what each renewal's shipping charges. Required there, refused elsewhere"}},"required":["type","rates","charges"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","enum":["charged"],"description":"Shipping is charged at checkout's rates"},"expectedChargeCents":{"type":"integer","minimum":0,"description":"What the forecast assumes a shipment charges, in cents; 0 for none"}},"required":["type","expectedChargeCents"],"additionalProperties":false}],"description":"What the option promises about shipping"},"mechanisms":{"type":"array","items":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","enum":["managed_discount"],"description":"Our app discount prices the lines, from the option map publish writes; works on subscription lines"},"lineRoles":{"type":"array","items":{"type":"string","enum":["main","add_on","gift"],"description":"What a line is in its option: `main` is what the buyer pays for, `add_on` an extra the buyer opts into or is always added, `gift` a real product the discount function prices to zero"},"minItems":1,"description":"The roles of the option's lines this mechanism prices"},"discount":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","enum":["percent"],"description":"A percentage off"},"percent":{"type":"number","minimum":0,"maximum":100,"description":"The percentage off, 0 to 100"}},"required":["type","percent"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","enum":["fixed_amount"],"description":"A fixed amount off"},"amountCents":{"type":"integer","minimum":0,"description":"The amount off, in cents"},"per":{"type":"string","enum":["line","unit"],"description":"Off each line, or off each unit of the line"}},"required":["type","amountCents","per"],"additionalProperties":false}],"description":"How much comes off"},"charges":{"type":"string","enum":["first","every"],"description":"Which charges it prices: `first` the first order only; `every` the first order and every renewal of a subscription line"}},"required":["type","lineRoles","discount","charges"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","enum":["discount_code"],"description":"A Shopify discount code publish creates, applied to the cart the API builds"},"code":{"type":"string","minLength":1,"description":"The code the brand chose; absent, publish mints one"},"purchaseType":{"type":"string","enum":["one_time","subscription","subscription_first_payment_only"],"description":"Which purchases the code prices: one-time lines once, every charge of a subscription line, or a subscription's first order only"},"discount":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","enum":["percent"],"description":"A percentage off"},"percent":{"type":"number","minimum":0,"maximum":100,"description":"The percentage off, 0 to 100"}},"required":["type","percent"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","enum":["fixed_amount"],"description":"A fixed amount off"},"amountCents":{"type":"integer","minimum":0,"description":"The amount off, in cents"}},"required":["type","amountCents"],"additionalProperties":false}],"description":"How much comes off"},"lineRoles":{"type":"array","items":{"type":"string","enum":["main","add_on","gift"],"description":"What a line is in its option: `main` is what the buyer pays for, `add_on` an extra the buyer opts into or is always added, `gift` a real product the discount function prices to zero"},"minItems":1,"description":"The roles of the option's lines this mechanism prices"},"shopify":{"type":"object","properties":{"discountId":{"type":"string","pattern":"^gid:\\/\\/shopify\\/DiscountCodeNode\\/\\d+$","description":"The discount publish created on Shopify"},"code":{"type":"string","minLength":1,"description":"The code live on Shopify: the authored one, or the one publish minted"}},"required":["discountId","code"],"additionalProperties":false,"description":"What publish created on Shopify for the code; absent until publish runs. Server state, never authored"}},"required":["type","purchaseType","discount","lineRoles"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","enum":["selling_plan_adjustment"],"description":"The selling plan's own price adjustments price the subscription lines on that plan"},"sellingPlanId":{"type":"string","pattern":"^gid:\\/\\/shopify\\/SellingPlan\\/\\d+$","description":"The selling plan, carried by a subscription line of the option"},"adjustments":{"type":"array","items":{"type":"object","properties":{"fromOrder":{"anyOf":[{"type":"integer","exclusiveMinimum":0},{"type":"string","enum":["after_last"]}],"description":"The order from which the adjustment is in effect: N from the Nth order on, until a later one takes over; \"after_last\" after every numbered one (alone, from the first order). Before the first, the catalog price"},"discount":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","enum":["percent"],"description":"A percentage off"},"percent":{"type":"number","minimum":0,"maximum":100,"description":"The percentage off, 0 to 100"}},"required":["type","percent"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","enum":["fixed_amount"],"description":"A fixed amount off"},"amountCents":{"type":"integer","minimum":0,"description":"The amount off, in cents"}},"required":["type","amountCents"],"additionalProperties":false}],"description":"How much the plan takes off the variant's price, per unit"}},"required":["fromOrder","discount"],"additionalProperties":false},"minItems":1,"description":"The plan's price adjustments as Shopify holds them, at most two"}},"required":["type","sellingPlanId","adjustments"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","enum":["catalog_price"],"description":"The variant's catalog price is already the offer price; nothing is discounted"}},"required":["type"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","enum":["existing_automatic_discount"],"description":"An automatic discount the store already runs; we only describe it"},"lineRoles":{"type":"array","items":{"type":"string","enum":["main","add_on","gift"],"description":"What a line is in its option: `main` is what the buyer pays for, `add_on` an extra the buyer opts into or is always added, `gift` a real product the discount function prices to zero"},"minItems":1,"description":"The roles of the option's lines this mechanism prices"},"discount":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","enum":["percent"],"description":"A percentage off"},"percent":{"type":"number","minimum":0,"maximum":100,"description":"The percentage off, 0 to 100"}},"required":["type","percent"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","enum":["fixed_amount"],"description":"A fixed amount off"},"amountCents":{"type":"integer","minimum":0,"description":"The amount off, in cents"}},"required":["type","amountCents"],"additionalProperties":false}],"description":"How much comes off"},"charges":{"type":"string","enum":["first","every"],"description":"Which charges it prices: `first` the first order only; `every` the first order and every renewal of a subscription line"}},"required":["type","lineRoles","discount","charges"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","enum":["unit_price_tiers"],"description":"A category group's first-order unit price by how many units of it the cart holds; our app discount charges it, and the group's selling plans price the renewals"},"lineKey":{"type":"string","maxLength":64,"pattern":"^[a-z0-9][a-z0-9_-]*$","description":"The group: an optional, non-gift line bound to a pool, which a cart opts into by this key"},"tiers":{"type":"array","items":{"type":"object","properties":{"fromUnits":{"type":"integer","exclusiveMinimum":0,"description":"The fewest units of the group this tier's price applies to; the first tier is 1"},"unitCents":{"type":"integer","minimum":0,"description":"What each unit of the group charges on the first order at this tier, in cents"}},"required":["fromUnits","unitCents"],"additionalProperties":false},"minItems":1,"description":"The tiers, ascending from 1; above the last tier the last price holds"}},"required":["type","lineKey","tiers"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","enum":["line_price"],"description":"Our cart transform sets the lines' unit price as their own price, at or below each line's catalog price (never above: a raise is refused): shown as the product's price, with no saving at checkout. One-time lines only, on any store with our cart transform registered: `lineUpdate` on Shopify Plus, the line expanded into itself on every other plan"},"lineKeys":{"type":"array","items":{"type":"string","maxLength":64,"pattern":"^[a-z0-9][a-z0-9_-]*$","description":"A key the brand authors: lower-case letters, digits, `_` and `-`"},"minItems":1,"description":"The one-time lines priced, by key"},"unitCents":{"type":"integer","minimum":0,"description":"What each unit of those lines charges on the first order, in cents"}},"required":["type","lineKeys","unitCents"],"additionalProperties":false}]},"description":"How the promise is made real on Shopify; at most one product discount per line and charge"}},"required":["promise","compareAtPrice","shipping","mechanisms"],"additionalProperties":false,"description":"What the option promises and how Shopify charges it"},"presentations":{"type":"array","items":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","enum":["line_override"],"description":"One line shown with another title or image. It exists only on the cart line: the order keeps the product's real title. Shopify Plus only, except on a line with a line price, where it rides in the line expanded into itself on any plan"},"lineKey":{"type":"string","maxLength":64,"pattern":"^[a-z0-9][a-z0-9_-]*$","description":"The one-time line shown differently"},"title":{"type":"string","minLength":1,"maxLength":255,"description":"What the cart and checkout show as the line's title; the order keeps the product's own title"},"imageUrl":{"type":"string","pattern":"^https:\\/\\/cdn\\.shopify\\.com\\/\\S+$","description":"What the cart and checkout show as the line's image; never kept on the order"}},"required":["type","lineKey"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","enum":["merged_bundle"],"description":"Several lines merged into one titled parent line in the cart and at checkout; on the order, the lines are a bundle group under the parent's title. A merged bundle has no stock of its own"},"lineKeys":{"type":"array","items":{"type":"string","maxLength":64,"pattern":"^[a-z0-9][a-z0-9_-]*$","description":"A key the brand authors: lower-case letters, digits, `_` and `-`"},"minItems":1,"description":"The required one-time lines merged into the parent, each at its own quantity"},"parentVariantId":{"type":"string","pattern":"^gid:\\/\\/shopify\\/ProductVariant\\/\\d+$","description":"The variant the parent line shows as: a bundle product whose variant requires components, so it can never be bought on its own"},"title":{"type":"string","minLength":1,"maxLength":255,"description":"What the cart and checkout show as the line's title; the order keeps the product's own title"},"imageUrl":{"type":"string","pattern":"^https:\\/\\/cdn\\.shopify\\.com\\/\\S+$","description":"What the cart and checkout show as the line's image; never kept on the order"},"attributes":{"type":"array","items":{"type":"object","properties":{"key":{"type":"string","minLength":1,"description":"The attribute's key"},"value":{"type":"string","description":"The attribute's value"}},"required":["key","value"],"additionalProperties":false},"description":"Attributes Shopify puts on the order's bundle group (not in the order webhook)"},"price":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","enum":["percent_off"],"description":"The bundle costs its lines' catalog price less a percentage, shown as the bundle's own price with no saving at checkout"},"percent":{"type":"number","minimum":0,"maximum":100,"description":"The percentage off, 0 to 100"}},"required":["type","percent"],"additionalProperties":false}],"description":"The bundle's price from our cart transform; absent, each line keeps its own price and our discount prices the parent"}},"required":["type","lineKeys","parentVariantId"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","enum":["expanded_bundle"],"description":"One line expanded into components in the cart and at checkout; on the order, the components are a bundle group under the line's title. The line's variant is the parent"},"lineKey":{"type":"string","maxLength":64,"pattern":"^[a-z0-9][a-z0-9_-]*$","description":"The one-time line expanded"},"components":{"type":"array","items":{"type":"object","properties":{"variantId":{"type":"string","pattern":"^gid:\\/\\/shopify\\/ProductVariant\\/\\d+$","description":"A variant that ships inside each unit of the line"},"quantity":{"type":"integer","exclusiveMinimum":0,"description":"Units of the component in each unit of the line"},"unitCents":{"type":"integer","minimum":0,"description":"The component's own price per unit, in cents; set on every component or on none. A gift that ships inside the bundle is a component at 0"},"role":{"type":"string","enum":["main","add_on","gift"],"description":"What the component is on the order, for costing: `main`, `add_on` or `gift`; the expanded line's own role when absent"}},"required":["variantId","quantity"],"additionalProperties":false},"minItems":1,"maxItems":150,"description":"What each unit of the line ships as, at most 150 components (Shopify's limit)"},"title":{"type":"string","minLength":1,"maxLength":255,"description":"What the cart and checkout show as the line's title; the order keeps the product's own title"},"imageUrl":{"type":"string","pattern":"^https:\\/\\/cdn\\.shopify\\.com\\/\\S+$","description":"What the cart and checkout show as the line's image; never kept on the order"},"price":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","enum":["percent_off"],"description":"The bundle costs its lines' catalog price less a percentage, shown as the bundle's own price with no saving at checkout"},"percent":{"type":"number","minimum":0,"maximum":100,"description":"The percentage off, 0 to 100"}},"required":["type","percent"],"additionalProperties":false}],"description":"A percentage off the line's catalog price; refused beside component prices. Absent with no component prices, the line keeps its price and our discount can price it"}},"required":["type","lineKey","components"],"additionalProperties":false}]},"description":"How our cart transform presents the option's one-time lines in the cart and at checkout: line overrides, merged bundles and expanded bundles. Each needs the store's capability for it (`GET /stores/{id}` `capability`); a line appears in one presentation at most"},"checkoutMode":{"type":"string","enum":["cart_page","cart_drawer","direct_to_checkout","landing_cart","external"],"description":"Where the brand's page sends the buyer after the choice: the cart page, a cart drawer, straight to checkout, a cart on the landing page, or an external flow"},"landingPageUrl":{"type":"string","minLength":1,"description":"The page that renders this option; publish checks the page shows it (`page_bind`)"},"verification":{"type":"object","properties":{"status":{"type":"string","enum":["matched","mismatched","unverifiable","unverified"],"description":"Whether a real cart charges what the option promises: `matched`; `mismatched` when a check failed or Shopify refused the cart; `unverifiable` when a check of the promise could not run; `unverified` when never checked (a hidden option). An option goes live only when `matched`"},"evidenceSource":{"type":"string","enum":["none","cart_response","cart_rejection","commerce_api","page_copy"],"description":"What the verdict rests on: nothing yet, a real cart Shopify built, Shopify refusing the cart, the Commerce API, or page copy"},"checkedAt":{"type":["string","null"],"format":"date-time","description":"When the verifier last ran on this option, or null"},"validForSeconds":{"type":"integer","exclusiveMinimum":0,"description":"Seconds the verdict is trusted after `checkedAt`"},"checks":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string","minLength":1,"description":"What was checked (`promised_first_charge`, `line_net:0`, `free_shipping:0:Standard`…); a check that does not apply to the option is not listed"},"covers":{"type":"string","enum":["option","add_on","shipping","renewal","page","presentation"],"description":"What part of the promise the check proves: `option` the option's first-order cart, `add_on` a line of an opt-in add-on, `shipping` the free shipping, `renewal` what renewals charge, `page` the landing page, `presentation` a title or image our cart transform shows (no Storefront cart field carries it, so it never holds an option back)"},"result":{"type":"string","enum":["passed","failed","skipped"],"description":"`passed`, `failed`, or `skipped` when the check could not run"},"detail":{"type":["string","null"],"description":"What was expected and found, or null"}},"required":["name","covers","result","detail"],"additionalProperties":false},"description":"Every check the verifier ran on the option"}},"required":["status","evidenceSource","checkedAt","validForSeconds","checks"],"additionalProperties":false,"description":"What the verifier found; written by publish and re-verification, never authored"}},"required":["key","display","visible","axisValues","unitCount","cardKey","lines","pricing","checkoutMode","verification"],"additionalProperties":false},"minItems":1,"description":"Everything a buyer can choose, one resolved option per combination"},"valueClaims":{"type":"array","items":{"type":"object","properties":{"title":{"type":"string","minLength":1,"description":"The claim as the page words it"},"claimedValueCents":{"type":"integer","minimum":0,"description":"The value claimed, in cents; absent when the page states none"}},"required":["title"],"additionalProperties":false},"description":"Value claims the page makes (bonuses, prizes); never enter a cart"},"terms":{"type":"object","properties":{"guaranteeDays":{"type":"integer","exclusiveMinimum":0,"description":"The money-back guarantee the page states, in days"}},"additionalProperties":false,"description":"Terms the page states"},"costProfile":{"type":"string","minLength":1,"description":"The cost profile the forecast and the realized cost basis use: which cost kinds apply to this offer's orders"}},"required":["schemaVersion","id","version","status","code","tracking","store","axes","pools","defaultOptionKey","options","valueClaims","terms","costProfile"],"additionalProperties":false}},"required":["id","code","experienceName","defaultOptionKey","status","currentVersion","liveVersion","createdAt","updatedAt","version","options","verification","orderCount","document"]}}}},"400":{"description":"Invalid id or version","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}},"401":{"description":"Missing, unknown or revoked API key","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}},"403":{"description":"The key is public; this route needs a secret key","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}},"404":{"description":"No such offer for this tenant","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}}}}},"/offers/{id}/resolve":{"get":{"operationId":"resolveOffer","summary":"Resolve an offer for rendering","description":"The rendering contract for the brand's dev team and the SDK: the live version's axes, options, lines with variant and selling plan ids, promised prices, compare-at, gifts, tracking labels and checkout mode. No economics, cost references or verification internals. Public keys may call it. A draft or retired offer is 404 unless a secret key passes `preview=1`, which resolves the current version. Pass the visitor's id as `visitorId` (the SDK does): while the offer runs an experiment, each visitor is assigned an arm deterministically and gets that version, with the experiment id in `X-Offer-Experiment`; render whatever version comes back. Send the returned `version` with the cart (`shownVersion` in `POST /offers/{id}/cart` and `cart-input`): if the visitor is served another version by then (an experiment started, paused or stopped, a new version went live), the cart answers `409 offer_changed` with the current document to render instead. Live responses carry an ETag that changes with the version and its content, honour `If-None-Match`, and may be kept by the browser for 60 seconds.","tags":["Offers"],"security":[{"apiKey":[]}],"parameters":[{"schema":{"type":"string","format":"uuid","description":"The offer id"},"required":true,"description":"The offer id","name":"id","in":"path"},{"schema":{"type":"string","enum":["1"]},"required":false,"name":"preview","in":"query"},{"schema":{"type":"string","minLength":1,"maxLength":128,"description":"The visitor id, for experiment assignment"},"required":false,"description":"The visitor id, for experiment assignment","name":"visitorId","in":"query"}],"responses":{"200":{"description":"The resolved offer","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","format":"uuid","description":"The offer id"},"code":{"type":"string","maxLength":31,"pattern":"^[^,\\s](?:[^,]*[^,\\s])?$","description":"The offer's code: unique per tenant, immutable once created, and how an agent, `lookup_offer` and the order tag `os_offer:<code>` name the offer"},"version":{"type":"integer","exclusiveMinimum":0,"description":"The version served; send it back as the cart request's `shownVersion`"},"status":{"type":"string","enum":["draft","verified","live","retired"],"description":"`live`, or under `preview` the current version's status"},"store":{"type":"object","properties":{"myshopifyDomain":{"type":"string","minLength":1,"description":"The connected store's myshopify domain (`brand.myshopify.com`); publish and serving use this store"},"market":{"type":"object","properties":{"countryCode":{"type":"string","pattern":"^[A-Z]{2}$","description":"The buyer's country, ISO 3166-1 alpha-2; carts are priced in its market"},"currencyCode":{"type":"string","pattern":"^[A-Z]{3}$","description":"The market's currency, ISO 4217; every amount in the document is in it"}},"required":["countryCode","currencyCode"],"additionalProperties":false,"description":"The one market the offer is priced in"}},"required":["myshopifyDomain","market"],"additionalProperties":false,"description":"The connected store and the market the offer is priced in"},"tracking":{"type":"object","properties":{"experienceName":{"type":"string","minLength":1,"description":"A label for the page or funnel this offer runs in; the offers list shows it"},"campaignName":{"type":"string","minLength":1,"description":"A label for the marketing campaign this offer belongs to"},"presellPageName":{"type":["string","null"],"minLength":1,"description":"A label for the presell page in front of the offer, or null"},"preservedCartAttributes":{"type":"array","items":{"type":"string","minLength":1},"description":"The brand's own cart attribute names a cart request may set and the API keeps on the cart (`preservedCartAttributes` on the cart request)"}},"required":["experienceName","campaignName","presellPageName","preservedCartAttributes"],"additionalProperties":false,"description":"The labels reports group by, and the brand's own cart attributes a cart keeps"},"axes":{"type":"array","items":{"type":"object","properties":{"key":{"type":"string","maxLength":64,"pattern":"^[a-z0-9][a-z0-9_-]*$","description":"Names the axis; options and axis-mapped lines refer to it"},"values":{"type":"array","items":{"type":"string","minLength":1},"minItems":1,"description":"Every value the axis takes"}},"required":["key","values"],"additionalProperties":false},"description":"Dimensions the options vary along (flavour, size); they name and enumerate options, never patch one"},"pools":{"type":"array","items":{"type":"object","properties":{"key":{"type":"string","maxLength":64,"pattern":"^[a-z0-9][a-z0-9_-]*$","description":"Names the pool; a pool-bound line refers to it"},"variantIds":{"type":"array","items":{"type":"string","pattern":"^gid:\\/\\/shopify\\/ProductVariant\\/\\d+$","description":"A Shopify ProductVariant gid (`gid://shopify/ProductVariant/<id>`)"},"minItems":1,"description":"The pool's variants"},"allowRepeats":{"type":"boolean","description":"Whether one variant may be chosen more than once"}},"required":["key","variantIds","allowRepeats"],"additionalProperties":false},"description":"Pools a buyer chooses variants from, through a line bound to the pool"},"defaultOptionKey":{"type":"string","maxLength":64,"pattern":"^[a-z0-9][a-z0-9_-]*$","description":"The option a renderer preselects; must name a visible option"},"options":{"type":"array","items":{"type":"object","properties":{"key":{"type":"string","maxLength":30,"pattern":"^[a-z0-9][a-z0-9_-]*$","description":"Names the option: unique in the document, carried in the cart pointer, the order tag `os_option:<key>` (so at most 30 characters) and the economics. Keep it stable"},"display":{"type":"object","properties":{"title":{"type":"string","minLength":1,"description":"The option's name as a buyer reads it"}},"required":["title"],"additionalProperties":false,"description":"What a renderer shows for the option"},"visible":{"type":"boolean","description":"Whether a renderer may show the option and publish verifies it; a hidden option still resolves and builds carts"},"axisValues":{"type":"object","additionalProperties":{"type":"string"},"description":"The option's value on each document axis, by axis key"},"unitCount":{"type":"integer","exclusiveMinimum":0,"description":"The quantity the buyer perceives (\"4 units\"); not the sum of line quantities"},"cardKey":{"type":"string","maxLength":64,"pattern":"^[a-z0-9][a-z0-9_-]*$","description":"Options sharing a card key are drawn as one card (a subscribe and one-time pair of one product)"},"lines":{"type":"array","items":{"type":"object","properties":{"key":{"type":"string","maxLength":64,"pattern":"^[a-z0-9][a-z0-9_-]*$","description":"Names the line inside its option; required on an optional non-gift line, which a cart opts into by this key (`addOnLineKeys`)"},"role":{"type":"string","enum":["main","add_on","gift"],"description":"What a line is in its option: `main` is what the buyer pays for, `add_on` an extra the buyer opts into or is always added, `gift` a real product the discount function prices to zero"},"quantity":{"type":"integer","exclusiveMinimum":0,"description":"Units of the variant in the cart; on a pool-bound line, the fewest the buyer may choose"},"maxQuantity":{"type":"integer","exclusiveMinimum":0,"description":"A pool-bound line only: the most units the buyer may choose"},"required":{"type":"boolean","description":"Whether every cart for the option holds the line; an optional line is added only when the cart request names its key"},"variantSource":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","enum":["fixed"],"description":"The line is one named variant"},"productId":{"type":"string","pattern":"^gid:\\/\\/shopify\\/Product\\/\\d+$","description":"The variant's product"},"variantId":{"type":"string","pattern":"^gid:\\/\\/shopify\\/ProductVariant\\/\\d+$","description":"The variant the line puts in the cart"}},"required":["type","productId","variantId"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","enum":["axis_map"],"description":"The variant follows the option's axis values, through `variantIdByAxisValue`"},"productId":{"type":"string","pattern":"^gid:\\/\\/shopify\\/Product\\/\\d+$","description":"The product every mapped variant belongs to"},"axisKeys":{"type":"array","items":{"type":"string","maxLength":64,"pattern":"^[a-z0-9][a-z0-9_-]*$","description":"A key the brand authors: lower-case letters, digits, `_` and `-`"},"minItems":1,"description":"The document axes whose values choose the variant, in `variantIdByAxisValue`'s key order"},"variantIdByAxisValue":{"type":"object","additionalProperties":{"type":"string","pattern":"^gid:\\/\\/shopify\\/ProductVariant\\/\\d+$","description":"A Shopify ProductVariant gid (`gid://shopify/ProductVariant/<id>`)"},"description":"Variant id by axis value; for several `axisKeys`, keyed by the values joined with \"/\" in `axisKeys` order. Must cover exactly the declared values"}},"required":["type","productId","axisKeys","variantIdByAxisValue"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","enum":["pool"],"description":"The buyer chooses the variants from a pool: `quantity` units, up to `maxQuantity`, any mix of the pool's variants; the cart gets one line per distinct variant"},"poolKey":{"type":"string","maxLength":64,"pattern":"^[a-z0-9][a-z0-9_-]*$","description":"The `pools[].key` the buyer chooses from"}},"required":["type","poolKey"],"additionalProperties":false}],"description":"Where the line's variant comes from"},"purchase":{"type":"object","properties":{"type":{"type":"string","enum":["one_time","subscription"],"description":"Bought once, or on a selling plan"},"sellingPlanId":{"type":"string","pattern":"^gid:\\/\\/shopify\\/SellingPlan\\/\\d+$","description":"The selling plan a subscription line is bought on; required when `type` is `subscription`"},"intervalDays":{"type":"integer","exclusiveMinimum":0,"description":"Days between a subscription's charges, as shown to the buyer"},"plans":{"type":"array","items":{"type":"object","properties":{"fromUnits":{"type":"integer","exclusiveMinimum":0,"description":"The fewest units of the group this plan's tier applies to; the first tier is 1"},"intervalDays":{"type":"integer","exclusiveMinimum":0,"description":"The cadence this plan renews on, one of the option's `cadence` intervals"},"sellingPlanId":{"type":"string","pattern":"^gid:\\/\\/shopify\\/SellingPlan\\/\\d+$","description":"The selling plan the group's lines go on at this tier and cadence"}},"required":["fromUnits","intervalDays","sellingPlanId"],"additionalProperties":false},"minItems":1,"description":"A subscription group's plan for each tier and cadence a cart can reach; `sellingPlanId` is one of them"}},"required":["type"],"additionalProperties":false,"description":"How the line is bought: once, or on a selling plan"},"bundleComponents":{"type":"array","items":{"type":"object","properties":{"variantId":{"type":"string","pattern":"^gid:\\/\\/shopify\\/ProductVariant\\/\\d+$","description":"A component variant of the fixed bundle"},"quantity":{"type":"integer","exclusiveMinimum":0,"description":"Units of that component in one bundle"}},"required":["variantId","quantity"],"additionalProperties":false},"minItems":1,"description":"What one unit holds, when the variant is a Shopify fixed bundle"},"catalogPrice":{"type":"object","properties":{"amountCents":{"type":"integer","minimum":0,"description":"The variant's catalog price when the document was written; line pricing starts from it"},"compareAtAmountCents":{"type":["integer","null"],"minimum":0,"description":"The variant's catalog compare-at price then, or null"},"capturedAt":{"type":"string","format":"date-time","description":"When the price was read from the catalog"}},"required":["amountCents","compareAtAmountCents","capturedAt"],"additionalProperties":false,"description":"The catalog price line pricing starts from"},"claimedValueCents":{"type":"integer","minimum":0,"description":"On a gift line: the value the page shows for it, in cents; never charged"}},"required":["role","quantity","required","variantSource","purchase","catalogPrice"],"additionalProperties":false},"minItems":1,"description":"What the option puts in the cart"},"maxUnits":{"type":"integer","exclusiveMinimum":0,"description":"A category builder: the most units the option's non-gift lines may hold in all"},"cadence":{"type":"object","properties":{"tiers":{"type":"array","items":{"type":"object","properties":{"fromUnits":{"type":"integer","exclusiveMinimum":0,"description":"The fewest units of the largest subscription group this interval applies to; the first tier is 1"},"intervalDays":{"type":"integer","exclusiveMinimum":0,"description":"Days between charges of every subscription line"}},"required":["fromUnits","intervalDays"],"additionalProperties":false},"minItems":1,"description":"The tiers, ascending from 1; above the last tier the last interval holds"}},"required":["tiers"],"additionalProperties":false,"description":"A category builder: the one interval every subscription line renews on, by the units of the largest subscription group in the cart; required when a line has `purchase.plans`"},"pricing":{"type":"object","properties":{"promise":{"type":"object","properties":{"firstChargeCents":{"type":["integer","null"],"minimum":0,"description":"What the buyer is charged on the first order, before shipping and tax; required on a visible option. Publish checks a real cart charges it"},"renewalChargeCents":{"type":["integer","null"],"minimum":0,"description":"What each renewal charges, before shipping and tax; required when the option has a subscription line"}},"required":["firstChargeCents","renewalChargeCents"],"additionalProperties":false,"description":"What the option promises the buyer is charged"},"compareAtPrice":{"type":"object","properties":{"amountCents":{"type":"integer","minimum":0,"description":"The struck-through amount, in cents"},"source":{"type":"string","enum":["variant","selling_plan","unit_price_times_quantity","metafield","page_copy"],"description":"Where it comes from: the variant's compare-at price, the selling plan's compare-at price, the unit price times the quantity, a metafield, or page copy"}},"required":["amountCents","source"],"additionalProperties":false,"description":"The struck-through price the page shows beside the promise"},"shipping":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","enum":["free"],"description":"The discount function makes the named rates free for carts carrying this option"},"rates":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","enum":["cheapest"],"description":"The cheapest shipping rate in each delivery group"}},"required":["type"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","enum":["all"],"description":"Every shipping rate, express included"}},"required":["type"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","enum":["titles"],"description":"The rates whose title is one of `titles`, ignoring case"},"titles":{"type":"array","items":{"type":"string","minLength":1},"minItems":1,"description":"Rate titles as checkout shows them"}},"required":["type","titles"],"additionalProperties":false}],"description":"Which rates are free"},"charges":{"type":"string","enum":["first","every"],"description":"Which shipments are free: `every` charge (a subscription's renewals too) or the `first` only"},"claimedValueCents":{"type":"integer","minimum":0,"description":"The shipping value the page claims for the free shipment (\"a $6.99 value\"); never charged"},"renewalChargeCents":{"type":"integer","minimum":0,"description":"On a subscription option free on the first charge only: what each renewal's shipping charges. Required there, refused elsewhere"}},"required":["type","rates","charges"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","enum":["charged"],"description":"Shipping is charged at checkout's rates"},"expectedChargeCents":{"type":"integer","minimum":0,"description":"What the forecast assumes a shipment charges, in cents; 0 for none"}},"required":["type","expectedChargeCents"],"additionalProperties":false}],"description":"What the option promises about shipping"},"mechanisms":{"type":"array","items":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","enum":["managed_discount"],"description":"Our app discount prices the lines, from the option map publish writes; works on subscription lines"},"lineRoles":{"type":"array","items":{"type":"string","enum":["main","add_on","gift"],"description":"What a line is in its option: `main` is what the buyer pays for, `add_on` an extra the buyer opts into or is always added, `gift` a real product the discount function prices to zero"},"minItems":1,"description":"The roles of the option's lines this mechanism prices"},"discount":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","enum":["percent"],"description":"A percentage off"},"percent":{"type":"number","minimum":0,"maximum":100,"description":"The percentage off, 0 to 100"}},"required":["type","percent"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","enum":["fixed_amount"],"description":"A fixed amount off"},"amountCents":{"type":"integer","minimum":0,"description":"The amount off, in cents"},"per":{"type":"string","enum":["line","unit"],"description":"Off each line, or off each unit of the line"}},"required":["type","amountCents","per"],"additionalProperties":false}],"description":"How much comes off"},"charges":{"type":"string","enum":["first","every"],"description":"Which charges it prices: `first` the first order only; `every` the first order and every renewal of a subscription line"}},"required":["type","lineRoles","discount","charges"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","enum":["discount_code"],"description":"A Shopify discount code publish creates, applied to the cart the API builds"},"code":{"type":"string","minLength":1,"description":"The code live on Shopify, once publish created it; the cart the API builds applies it"},"purchaseType":{"type":"string","enum":["one_time","subscription","subscription_first_payment_only"],"description":"Which purchases the code prices: one-time lines once, every charge of a subscription line, or a subscription's first order only"},"discount":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","enum":["percent"],"description":"A percentage off"},"percent":{"type":"number","minimum":0,"maximum":100,"description":"The percentage off, 0 to 100"}},"required":["type","percent"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","enum":["fixed_amount"],"description":"A fixed amount off"},"amountCents":{"type":"integer","minimum":0,"description":"The amount off, in cents"}},"required":["type","amountCents"],"additionalProperties":false}],"description":"How much comes off"},"lineRoles":{"type":"array","items":{"type":"string","enum":["main","add_on","gift"],"description":"What a line is in its option: `main` is what the buyer pays for, `add_on` an extra the buyer opts into or is always added, `gift` a real product the discount function prices to zero"},"minItems":1,"description":"The roles of the option's lines this mechanism prices"}},"required":["type","purchaseType","discount","lineRoles"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","enum":["selling_plan_adjustment"],"description":"The selling plan's own price adjustments price the subscription lines on that plan"},"sellingPlanId":{"type":"string","pattern":"^gid:\\/\\/shopify\\/SellingPlan\\/\\d+$","description":"The selling plan, carried by a subscription line of the option"},"adjustments":{"type":"array","items":{"type":"object","properties":{"fromOrder":{"anyOf":[{"type":"integer","exclusiveMinimum":0},{"type":"string","enum":["after_last"]}],"description":"The order from which the adjustment is in effect: N from the Nth order on, until a later one takes over; \"after_last\" after every numbered one (alone, from the first order). Before the first, the catalog price"},"discount":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","enum":["percent"],"description":"A percentage off"},"percent":{"type":"number","minimum":0,"maximum":100,"description":"The percentage off, 0 to 100"}},"required":["type","percent"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","enum":["fixed_amount"],"description":"A fixed amount off"},"amountCents":{"type":"integer","minimum":0,"description":"The amount off, in cents"}},"required":["type","amountCents"],"additionalProperties":false}],"description":"How much the plan takes off the variant's price, per unit"}},"required":["fromOrder","discount"],"additionalProperties":false},"minItems":1,"description":"The plan's price adjustments as Shopify holds them, at most two"}},"required":["type","sellingPlanId","adjustments"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","enum":["catalog_price"],"description":"The variant's catalog price is already the offer price; nothing is discounted"}},"required":["type"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","enum":["existing_automatic_discount"],"description":"An automatic discount the store already runs; we only describe it"},"lineRoles":{"type":"array","items":{"type":"string","enum":["main","add_on","gift"],"description":"What a line is in its option: `main` is what the buyer pays for, `add_on` an extra the buyer opts into or is always added, `gift` a real product the discount function prices to zero"},"minItems":1,"description":"The roles of the option's lines this mechanism prices"},"discount":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","enum":["percent"],"description":"A percentage off"},"percent":{"type":"number","minimum":0,"maximum":100,"description":"The percentage off, 0 to 100"}},"required":["type","percent"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","enum":["fixed_amount"],"description":"A fixed amount off"},"amountCents":{"type":"integer","minimum":0,"description":"The amount off, in cents"}},"required":["type","amountCents"],"additionalProperties":false}],"description":"How much comes off"},"charges":{"type":"string","enum":["first","every"],"description":"Which charges it prices: `first` the first order only; `every` the first order and every renewal of a subscription line"}},"required":["type","lineRoles","discount","charges"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","enum":["unit_price_tiers"],"description":"A category group's first-order unit price by how many units of it the cart holds; our app discount charges it, and the group's selling plans price the renewals"},"lineKey":{"type":"string","maxLength":64,"pattern":"^[a-z0-9][a-z0-9_-]*$","description":"The group: an optional, non-gift line bound to a pool, which a cart opts into by this key"},"tiers":{"type":"array","items":{"type":"object","properties":{"fromUnits":{"type":"integer","exclusiveMinimum":0,"description":"The fewest units of the group this tier's price applies to; the first tier is 1"},"unitCents":{"type":"integer","minimum":0,"description":"What each unit of the group charges on the first order at this tier, in cents"}},"required":["fromUnits","unitCents"],"additionalProperties":false},"minItems":1,"description":"The tiers, ascending from 1; above the last tier the last price holds"}},"required":["type","lineKey","tiers"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","enum":["line_price"],"description":"Our cart transform sets the lines' unit price as their own price, at or below each line's catalog price (never above: a raise is refused): shown as the product's price, with no saving at checkout. One-time lines only, on any store with our cart transform registered: `lineUpdate` on Shopify Plus, the line expanded into itself on every other plan"},"lineKeys":{"type":"array","items":{"type":"string","maxLength":64,"pattern":"^[a-z0-9][a-z0-9_-]*$","description":"A key the brand authors: lower-case letters, digits, `_` and `-`"},"minItems":1,"description":"The one-time lines priced, by key"},"unitCents":{"type":"integer","minimum":0,"description":"What each unit of those lines charges on the first order, in cents"}},"required":["type","lineKeys","unitCents"],"additionalProperties":false}]},"description":"How the promise is made real on Shopify; at most one product discount per line and charge"}},"required":["promise","compareAtPrice","shipping","mechanisms"],"additionalProperties":false,"description":"What the option promises and how Shopify charges it"},"prices":{"type":"object","properties":{"first":{"type":"object","properties":{"totalCents":{"type":"integer","minimum":0,"description":"What these lines charge on this charge, before shipping and tax: the sum of the lines' `netCents`"},"lines":{"type":"array","items":{"type":"object","properties":{"lineIndex":{"type":"integer","minimum":0,"description":"The line's index in the option's `lines`"},"key":{"type":"string","maxLength":64,"pattern":"^[a-z0-9][a-z0-9_-]*$","description":"Names the line inside its option; required on an optional non-gift line, which a cart opts into by this key (`addOnLineKeys`)"},"role":{"type":"string","enum":["main","add_on","gift"],"description":"What a line is in its option: `main` is what the buyer pays for, `add_on` an extra the buyer opts into or is always added, `gift` a real product the discount function prices to zero"},"variantId":{"type":"string","pattern":"^gid:\\/\\/shopify\\/ProductVariant\\/\\d+$","description":"The variant this cart line holds; a pool-bound line becomes one cart line per distinct variant chosen"},"quantity":{"type":"integer","exclusiveMinimum":0,"description":"Units on this cart line"},"sellingPlanId":{"type":"string","pattern":"^gid:\\/\\/shopify\\/SellingPlan\\/\\d+$","description":"The selling plan the cart line is bought on, for a subscription line"},"unitCents":{"type":"integer","minimum":0,"description":"One unit before any product discount: the catalog price with the selling plan's adjustment in effect on this charge"},"grossCents":{"type":"integer","minimum":0,"description":"`unitCents` × `quantity`"},"discountCents":{"type":"integer","minimum":0,"description":"What the one product discount takes off the line on this charge (all of it on a gift); 0 when nothing does"},"discountBy":{"type":["string","null"],"enum":["managed_discount","discount_code","existing_automatic_discount","unit_price_tiers","bundle_price","gift",null],"description":"The mechanism that takes `discountCents` off (`unit_price_tiers`: a category group's first-charge price for its units; `bundle_price`: a bundle's percentage off from our cart transform, which checkout shows as the bundle's price, not as a saving), `gift` when the discount function zeroes a gift, null when nothing does"},"netCents":{"type":"integer","minimum":0,"description":"What the line charges on this charge: `grossCents` less `discountCents`. Show this; never compute it"}},"required":["lineIndex","role","variantId","quantity","unitCents","grossCents","discountCents","discountBy","netCents"],"additionalProperties":false},"description":"Each cart line with its price on this charge"}},"required":["totalCents","lines"],"additionalProperties":false,"description":"The first order"},"renewal":{"type":["object","null"],"properties":{"totalCents":{"type":"integer","minimum":0,"description":"What these lines charge on this charge, before shipping and tax: the sum of the lines' `netCents`"},"lines":{"type":"array","items":{"type":"object","properties":{"lineIndex":{"type":"integer","minimum":0,"description":"The line's index in the option's `lines`"},"key":{"type":"string","maxLength":64,"pattern":"^[a-z0-9][a-z0-9_-]*$","description":"Names the line inside its option; required on an optional non-gift line, which a cart opts into by this key (`addOnLineKeys`)"},"role":{"type":"string","enum":["main","add_on","gift"],"description":"What a line is in its option: `main` is what the buyer pays for, `add_on` an extra the buyer opts into or is always added, `gift` a real product the discount function prices to zero"},"variantId":{"type":"string","pattern":"^gid:\\/\\/shopify\\/ProductVariant\\/\\d+$","description":"The variant this cart line holds; a pool-bound line becomes one cart line per distinct variant chosen"},"quantity":{"type":"integer","exclusiveMinimum":0,"description":"Units on this cart line"},"sellingPlanId":{"type":"string","pattern":"^gid:\\/\\/shopify\\/SellingPlan\\/\\d+$","description":"The selling plan the cart line is bought on, for a subscription line"},"unitCents":{"type":"integer","minimum":0,"description":"One unit before any product discount: the catalog price with the selling plan's adjustment in effect on this charge"},"grossCents":{"type":"integer","minimum":0,"description":"`unitCents` × `quantity`"},"discountCents":{"type":"integer","minimum":0,"description":"What the one product discount takes off the line on this charge (all of it on a gift); 0 when nothing does"},"discountBy":{"type":["string","null"],"enum":["managed_discount","discount_code","existing_automatic_discount","unit_price_tiers","bundle_price","gift",null],"description":"The mechanism that takes `discountCents` off (`unit_price_tiers`: a category group's first-charge price for its units; `bundle_price`: a bundle's percentage off from our cart transform, which checkout shows as the bundle's price, not as a saving), `gift` when the discount function zeroes a gift, null when nothing does"},"netCents":{"type":"integer","minimum":0,"description":"What the line charges on this charge: `grossCents` less `discountCents`. Show this; never compute it"}},"required":["lineIndex","role","variantId","quantity","unitCents","grossCents","discountCents","discountBy","netCents"],"additionalProperties":false},"description":"Each cart line with its price on this charge"}},"required":["totalCents","lines"],"additionalProperties":false,"description":"Every renewal, once the selling plan's last adjustment is in effect: only the lines that renew; null when none does"},"addOns":{"type":"array","items":{"type":"object","properties":{"first":{"type":"object","properties":{"totalCents":{"type":"integer","minimum":0,"description":"What these lines charge on this charge, before shipping and tax: the sum of the lines' `netCents`"},"lines":{"type":"array","items":{"type":"object","properties":{"lineIndex":{"type":"integer","minimum":0,"description":"The line's index in the option's `lines`"},"key":{"type":"string","maxLength":64,"pattern":"^[a-z0-9][a-z0-9_-]*$","description":"Names the line inside its option; required on an optional non-gift line, which a cart opts into by this key (`addOnLineKeys`)"},"role":{"type":"string","enum":["main","add_on","gift"],"description":"What a line is in its option: `main` is what the buyer pays for, `add_on` an extra the buyer opts into or is always added, `gift` a real product the discount function prices to zero"},"variantId":{"type":"string","pattern":"^gid:\\/\\/shopify\\/ProductVariant\\/\\d+$","description":"The variant this cart line holds; a pool-bound line becomes one cart line per distinct variant chosen"},"quantity":{"type":"integer","exclusiveMinimum":0,"description":"Units on this cart line"},"sellingPlanId":{"type":"string","pattern":"^gid:\\/\\/shopify\\/SellingPlan\\/\\d+$","description":"The selling plan the cart line is bought on, for a subscription line"},"unitCents":{"type":"integer","minimum":0,"description":"One unit before any product discount: the catalog price with the selling plan's adjustment in effect on this charge"},"grossCents":{"type":"integer","minimum":0,"description":"`unitCents` × `quantity`"},"discountCents":{"type":"integer","minimum":0,"description":"What the one product discount takes off the line on this charge (all of it on a gift); 0 when nothing does"},"discountBy":{"type":["string","null"],"enum":["managed_discount","discount_code","existing_automatic_discount","unit_price_tiers","bundle_price","gift",null],"description":"The mechanism that takes `discountCents` off (`unit_price_tiers`: a category group's first-charge price for its units; `bundle_price`: a bundle's percentage off from our cart transform, which checkout shows as the bundle's price, not as a saving), `gift` when the discount function zeroes a gift, null when nothing does"},"netCents":{"type":"integer","minimum":0,"description":"What the line charges on this charge: `grossCents` less `discountCents`. Show this; never compute it"}},"required":["lineIndex","role","variantId","quantity","unitCents","grossCents","discountCents","discountBy","netCents"],"additionalProperties":false},"description":"Each cart line with its price on this charge"}},"required":["totalCents","lines"],"additionalProperties":false,"description":"The first order"},"renewal":{"type":["object","null"],"properties":{"totalCents":{"type":"integer","minimum":0,"description":"What these lines charge on this charge, before shipping and tax: the sum of the lines' `netCents`"},"lines":{"type":"array","items":{"type":"object","properties":{"lineIndex":{"type":"integer","minimum":0,"description":"The line's index in the option's `lines`"},"key":{"type":"string","maxLength":64,"pattern":"^[a-z0-9][a-z0-9_-]*$","description":"Names the line inside its option; required on an optional non-gift line, which a cart opts into by this key (`addOnLineKeys`)"},"role":{"type":"string","enum":["main","add_on","gift"],"description":"What a line is in its option: `main` is what the buyer pays for, `add_on` an extra the buyer opts into or is always added, `gift` a real product the discount function prices to zero"},"variantId":{"type":"string","pattern":"^gid:\\/\\/shopify\\/ProductVariant\\/\\d+$","description":"The variant this cart line holds; a pool-bound line becomes one cart line per distinct variant chosen"},"quantity":{"type":"integer","exclusiveMinimum":0,"description":"Units on this cart line"},"sellingPlanId":{"type":"string","pattern":"^gid:\\/\\/shopify\\/SellingPlan\\/\\d+$","description":"The selling plan the cart line is bought on, for a subscription line"},"unitCents":{"type":"integer","minimum":0,"description":"One unit before any product discount: the catalog price with the selling plan's adjustment in effect on this charge"},"grossCents":{"type":"integer","minimum":0,"description":"`unitCents` × `quantity`"},"discountCents":{"type":"integer","minimum":0,"description":"What the one product discount takes off the line on this charge (all of it on a gift); 0 when nothing does"},"discountBy":{"type":["string","null"],"enum":["managed_discount","discount_code","existing_automatic_discount","unit_price_tiers","bundle_price","gift",null],"description":"The mechanism that takes `discountCents` off (`unit_price_tiers`: a category group's first-charge price for its units; `bundle_price`: a bundle's percentage off from our cart transform, which checkout shows as the bundle's price, not as a saving), `gift` when the discount function zeroes a gift, null when nothing does"},"netCents":{"type":"integer","minimum":0,"description":"What the line charges on this charge: `grossCents` less `discountCents`. Show this; never compute it"}},"required":["lineIndex","role","variantId","quantity","unitCents","grossCents","discountCents","discountBy","netCents"],"additionalProperties":false},"description":"Each cart line with its price on this charge"}},"required":["totalCents","lines"],"additionalProperties":false,"description":"Every renewal, once the selling plan's last adjustment is in effect: only the lines that renew; null when none does"},"lineKey":{"type":"string","maxLength":64,"pattern":"^[a-z0-9][a-z0-9_-]*$","description":"The add-on's line key, as `Selection.addOnLineKeys` names it"}},"required":["first","renewal","lineKey"],"additionalProperties":false},"description":"Each optional add-on's cart lines priced on their own. Cart lines are priced one by one, so an option with add-ons opted into charges `first.totalCents` plus each add-on's `first.totalCents` (and the same for renewals)"}},"required":["first","renewal","addOns"],"additionalProperties":false,"description":"What this option charges, computed by the line pricing the verifier proves on real carts (OS-303): the cart the option builds with nothing chosen (each pool at its first variants, no add-on), and each add-on. A buy box renders these numbers and never prices a line itself; for other pool picks, ask `POST /offers/{id}/price`"},"presentations":{"type":"array","items":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","enum":["line_override"],"description":"One line shown with another title or image. It exists only on the cart line: the order keeps the product's real title. Shopify Plus only, except on a line with a line price, where it rides in the line expanded into itself on any plan"},"lineKey":{"type":"string","maxLength":64,"pattern":"^[a-z0-9][a-z0-9_-]*$","description":"The one-time line shown differently"},"title":{"type":"string","minLength":1,"maxLength":255,"description":"What the cart and checkout show as the line's title; the order keeps the product's own title"},"imageUrl":{"type":"string","pattern":"^https:\\/\\/cdn\\.shopify\\.com\\/\\S+$","description":"What the cart and checkout show as the line's image; never kept on the order"}},"required":["type","lineKey"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","enum":["merged_bundle"],"description":"Several lines merged into one titled parent line in the cart and at checkout; on the order, the lines are a bundle group under the parent's title. A merged bundle has no stock of its own"},"lineKeys":{"type":"array","items":{"type":"string","maxLength":64,"pattern":"^[a-z0-9][a-z0-9_-]*$","description":"A key the brand authors: lower-case letters, digits, `_` and `-`"},"minItems":1,"description":"The required one-time lines merged into the parent, each at its own quantity"},"parentVariantId":{"type":"string","pattern":"^gid:\\/\\/shopify\\/ProductVariant\\/\\d+$","description":"The variant the parent line shows as: a bundle product whose variant requires components, so it can never be bought on its own"},"title":{"type":"string","minLength":1,"maxLength":255,"description":"What the cart and checkout show as the line's title; the order keeps the product's own title"},"imageUrl":{"type":"string","pattern":"^https:\\/\\/cdn\\.shopify\\.com\\/\\S+$","description":"What the cart and checkout show as the line's image; never kept on the order"},"attributes":{"type":"array","items":{"type":"object","properties":{"key":{"type":"string","minLength":1,"description":"The attribute's key"},"value":{"type":"string","description":"The attribute's value"}},"required":["key","value"],"additionalProperties":false},"description":"Attributes Shopify puts on the order's bundle group (not in the order webhook)"},"price":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","enum":["percent_off"],"description":"The bundle costs its lines' catalog price less a percentage, shown as the bundle's own price with no saving at checkout"},"percent":{"type":"number","minimum":0,"maximum":100,"description":"The percentage off, 0 to 100"}},"required":["type","percent"],"additionalProperties":false}],"description":"The bundle's price from our cart transform; absent, each line keeps its own price and our discount prices the parent"}},"required":["type","lineKeys","parentVariantId"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","enum":["expanded_bundle"],"description":"One line expanded into components in the cart and at checkout; on the order, the components are a bundle group under the line's title. The line's variant is the parent"},"lineKey":{"type":"string","maxLength":64,"pattern":"^[a-z0-9][a-z0-9_-]*$","description":"The one-time line expanded"},"components":{"type":"array","items":{"type":"object","properties":{"variantId":{"type":"string","pattern":"^gid:\\/\\/shopify\\/ProductVariant\\/\\d+$","description":"A variant that ships inside each unit of the line"},"quantity":{"type":"integer","exclusiveMinimum":0,"description":"Units of the component in each unit of the line"},"unitCents":{"type":"integer","minimum":0,"description":"The component's own price per unit, in cents; set on every component or on none. A gift that ships inside the bundle is a component at 0"},"role":{"type":"string","enum":["main","add_on","gift"],"description":"What the component is on the order, for costing: `main`, `add_on` or `gift`; the expanded line's own role when absent"}},"required":["variantId","quantity"],"additionalProperties":false},"minItems":1,"maxItems":150,"description":"What each unit of the line ships as, at most 150 components (Shopify's limit)"},"title":{"type":"string","minLength":1,"maxLength":255,"description":"What the cart and checkout show as the line's title; the order keeps the product's own title"},"imageUrl":{"type":"string","pattern":"^https:\\/\\/cdn\\.shopify\\.com\\/\\S+$","description":"What the cart and checkout show as the line's image; never kept on the order"},"price":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","enum":["percent_off"],"description":"The bundle costs its lines' catalog price less a percentage, shown as the bundle's own price with no saving at checkout"},"percent":{"type":"number","minimum":0,"maximum":100,"description":"The percentage off, 0 to 100"}},"required":["type","percent"],"additionalProperties":false}],"description":"A percentage off the line's catalog price; refused beside component prices. Absent with no component prices, the line keeps its price and our discount can price it"}},"required":["type","lineKey","components"],"additionalProperties":false}]},"description":"How our cart transform presents the option's one-time lines in the cart and at checkout: line overrides, merged bundles and expanded bundles. Each needs the store's capability for it (`GET /stores/{id}` `capability`); a line appears in one presentation at most"},"checkoutMode":{"type":"string","enum":["cart_page","cart_drawer","direct_to_checkout","landing_cart","external"],"description":"Where the brand's page sends the buyer after the choice: the cart page, a cart drawer, straight to checkout, a cart on the landing page, or an external flow"},"landingPageUrl":{"type":"string","minLength":1,"description":"The page that renders this option; publish checks the page shows it (`page_bind`)"},"verification":{"type":"object","properties":{"status":{"type":"string","enum":["matched","mismatched","unverifiable","unverified"],"description":"Whether a real cart charges what the option promises: `matched`; `mismatched` when a check failed or Shopify refused the cart; `unverifiable` when a check of the promise could not run; `unverified` when never checked (a hidden option). An option goes live only when `matched`"},"checkedAt":{"type":["string","null"],"format":"date-time","description":"When the verifier last ran on this option, or null"}},"required":["status","checkedAt"],"additionalProperties":false,"description":"Whether publish found a real cart charges the promise, and when"}},"required":["key","display","visible","axisValues","unitCount","cardKey","lines","pricing","prices","checkoutMode","verification"],"additionalProperties":false},"minItems":1,"description":"Everything a buyer can choose, one resolved option per combination"},"valueClaims":{"type":"array","items":{"type":"object","properties":{"title":{"type":"string","minLength":1,"description":"The claim as the page words it"},"claimedValueCents":{"type":"integer","minimum":0,"description":"The value claimed, in cents; absent when the page states none"}},"required":["title"],"additionalProperties":false},"description":"Value claims the page makes (bonuses, prizes); never enter a cart"},"terms":{"type":"object","properties":{"guaranteeDays":{"type":"integer","exclusiveMinimum":0,"description":"The money-back guarantee the page states, in days"}},"additionalProperties":false,"description":"Terms the page states"},"catalog":{"type":"object","additionalProperties":{"type":"object","properties":{"productId":{"type":["string","null"],"pattern":"^gid:\\/\\/shopify\\/Product\\/\\d+$","description":"The product's gid; null when Shopify no longer has the variant"},"productTitle":{"type":["string","null"],"description":"The product's title in Shopify"},"variantTitle":{"type":["string","null"],"description":"The variant's title in Shopify (`Default Title` on a product with one variant)"},"image":{"type":["object","null"],"properties":{"url":{"type":"string","format":"uri","description":"Shopify's CDN URL of the image"},"altText":{"type":["string","null"],"description":"The image's alt text in Shopify"},"width":{"type":["integer","null"],"description":"Width in pixels"},"height":{"type":["integer","null"],"description":"Height in pixels"}},"required":["url","altText","width","height"],"additionalProperties":false,"description":"The variant's own first image, else the product's featured image; null when neither exists"},"description":{"type":["string","null"],"description":"A plain-text excerpt of the product's description (at most 300 characters, cut at a word)"},"status":{"type":"string","enum":["active","draft","archived","deleted"],"description":"`active` is for sale; `draft` or `archived` is a product taken off sale in Shopify; `deleted` is a variant Shopify no longer has. Show a line whose variant is not `active` as unavailable"}},"required":["productId","productTitle","variantTitle","image","description","status"],"additionalProperties":false,"description":"What Shopify says about one variant"},"description":"What Shopify says about every variant the offer can put in a cart, keyed by variant gid (the ids in `lines[].variantSource` and `pools`): titles, image, a description excerpt and whether it is still for sale. Read from Shopify at publish, on every product change Shopify sends, and daily, and served as soon as it changes; a variant not read yet is absent. Render product content from here, with no Storefront call of your own"}},"required":["id","code","version","status","store","tracking","axes","pools","defaultOptionKey","options","valueClaims","terms","catalog"],"additionalProperties":false}}}},"304":{"description":"Unchanged since the version in If-None-Match"},"400":{"description":"Invalid id or query","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}},"401":{"description":"Missing, unknown or revoked API key","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}},"404":{"description":"No live version, or preview without a secret key","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}}}}},"/offers/{id}/economics":{"get":{"operationId":"getOfferEconomics","summary":"Forecast and realized economics per option","description":"Forecast: the engine run per option on `version`, or when it is omitted on the live version (what visitors are served), else the current draft of an offer never published, with the costs effective now (or at `at`) (item → product → tenant default) and the document's cost profile: revenue, the cost waterfall by kind, first-order and renewal gross margin, and `missingCosts`, the required cost kinds still without an amount on a line (the margin is overstated until they are entered). Realized: order count, revenue, refunds, cost and profit per option and version, in the cost view `view`: `current` (default) costs every order with the cost ledger as it stands now at the order's date, so a backdated cost moves it; `as_recorded` uses the costs frozen when each order arrived and never changes. `incompleteOrders` counts orders missing a required cost kind; a cancelled order is not a sale and appears only in `cancelledOrders`. Forecast versus actual is for this response's version only, margin before refunds and refunds apart. Computed on request, never stored. Shipping weights and carrier tables are not modelled yet, so freight and packaging-box entries are 0.","tags":["Offers"],"security":[{"apiKey":[]}],"parameters":[{"schema":{"type":"string","format":"uuid","description":"The offer id"},"required":true,"description":"The offer id","name":"id","in":"path"},{"schema":{"type":"integer","exclusiveMinimum":0},"required":false,"name":"version","in":"query"},{"schema":{"type":"string","enum":["current","as_recorded"],"default":"current","description":"Cost view of the realized figures"},"required":false,"description":"Cost view of the realized figures","name":"view","in":"query"},{"schema":{"type":"string","format":"date-time","description":"Resolve the forecast's costs at this date (default now): a future date previews a scheduled cost"},"required":false,"description":"Resolve the forecast's costs at this date (default now): a future date previews a scheduled cost","name":"at","in":"query"}],"responses":{"200":{"description":"The economics","content":{"application/json":{"schema":{"type":"object","properties":{"offerId":{"type":"string","format":"uuid"},"version":{"type":"integer","exclusiveMinimum":0},"view":{"type":"string","enum":["current","as_recorded"],"description":"The cost view of the realized figures"},"currencyCode":{"type":"string","description":"The document's market currency (ISO 4217): the forecast's currency"},"realizedCurrencyCodes":{"type":"array","items":{"type":"string"},"description":"The shop currencies the offer's orders were placed in, sorted. Realized figures are shop money and never converted or added across currencies (decision 41)"},"realizedCurrencyCode":{"type":["string","null"],"description":"The currency of every option's `realized` and `realizedRenewals`: the market currency when any order was placed in it, else the offer's only currency. Null without orders, or when the orders span several currencies none of which is the market's; every currency's figures are in `realizedByCurrency` either way"},"comparable":{"type":"boolean","description":"True when `realizedCurrencyCode` is the market currency (or nothing was realized): forecast versus actual is then computed from `realized`; otherwise it is null"},"costProfile":{"type":"string","description":"The document's cost profile: which cost kinds and rate estimates the forecast applies"},"rates":{"type":"object","properties":{"refundPercent":{"type":"number","description":"The refund estimate, a percent of revenue (0 to 100)"},"processingPercent":{"type":"number","description":"A payment processing rate on top of the costs, a percent of revenue (0 to 100). 0 for every profile: payment processing is a cost, the `payment_processing` and `payment_processing_fixed` kinds in the waterfall, replaced in realized by the order's actual fee once Shopify reports it"}},"required":["refundPercent","processingPercent"],"description":"The cost profile's rate estimates, which the forecast applies on top of the waterfall's own kinds"},"computedAt":{"type":"string","format":"date-time"},"options":{"type":"array","items":{"type":"object","properties":{"optionKey":{"type":"string"},"visible":{"type":"boolean"},"forecast":{"type":"object","properties":{"firstOrder":{"type":"object","properties":{"revenueCents":{"type":"integer","description":"What the customer is charged: the promised charge plus the shipping charged on this order"},"waterfall":{"type":"array","items":{"type":"object","properties":{"kindKey":{"type":"string","description":"The cost kind"},"grain":{"type":"string","enum":["per_unit","per_parcel","per_order","percent"],"description":"How the kind is charged"},"cents":{"type":"integer","description":"What the kind costs on this order"}},"required":["kindKey","grain","cents"]},"description":"Every cost of the order, in the profile's order, then gift fulfilment, the refund estimate and processing"},"totalCostCents":{"type":"integer","description":"The waterfall's sum"},"grossMarginCents":{"type":"integer","description":"revenueCents − totalCostCents"},"grossMarginPercent":{"type":"number","description":"grossMarginCents ÷ revenueCents, 0 to 100 (59.71 is 59.71%); 0 when revenue is 0"}},"required":["revenueCents","waterfall","totalCostCents","grossMarginCents","grossMarginPercent"]},"renewal":{"type":["object","null"],"properties":{"revenueCents":{"type":"integer","description":"What the customer is charged: the promised charge plus the shipping charged on this order"},"waterfall":{"type":"array","items":{"type":"object","properties":{"kindKey":{"type":"string","description":"The cost kind"},"grain":{"type":"string","enum":["per_unit","per_parcel","per_order","percent"],"description":"How the kind is charged"},"cents":{"type":"integer","description":"What the kind costs on this order"}},"required":["kindKey","grain","cents"]},"description":"Every cost of the order, in the profile's order, then gift fulfilment, the refund estimate and processing"},"totalCostCents":{"type":"integer","description":"The waterfall's sum"},"grossMarginCents":{"type":"integer","description":"revenueCents − totalCostCents"},"grossMarginPercent":{"type":"number","description":"grossMarginCents ÷ revenueCents, 0 to 100 (59.71 is 59.71%); 0 when revenue is 0"}},"required":["revenueCents","waterfall","totalCostCents","grossMarginCents","grossMarginPercent"]},"missingCosts":{"type":"array","items":{"type":"string"},"description":"Required cost kinds with no amount on at least one line of this option at the forecast's date, sorted. The forecast counts each as nothing, so its cost is understated and its margin overstated until the cost is entered (POST /costs); empty when every required kind has an amount"}},"required":["firstOrder","renewal","missingCosts"]},"realized":{"type":["object","null"],"properties":{"orders":{"type":"integer","minimum":0},"incompleteOrders":{"type":"integer","minimum":0,"description":"Orders with a line missing a required cost kind in this view; their cost is understated until the cost is entered (decision 57)"},"cancelledOrders":{"type":"integer","minimum":0,"description":"Orders cancelled in Shopify: not sales, so counted in no other figure (their revenue, refunds and cost are left out)"},"revenueCents":{"type":"integer","description":"Gross: lines plus shipping as charged, frozen at creation, in the shop currency"},"refundedCents":{"type":"integer","description":"Money returned after the sale against revenue the offer counted, tax excluded (decisions 47 and 58)"},"refundedExcludedCents":{"type":"integer","description":"Refunds of units a paid edit added or of lines without a variant: revenue the offer never counted, so shown and not subtracted"},"netRevenueCents":{"type":"integer","description":"revenueCents − refundedCents; what contribution is computed from"},"editAdjustmentsCents":{"type":"integer","description":"What paid order edits changed against the frozen gross revenue; shown, not in contribution"},"costCents":{"type":"integer","description":"The engine's cost in this view (current: the ledger now; as_recorded: frozen at ingest); refunds do not reduce it"},"profitCents":{"type":"integer","description":"Contribution: netRevenueCents − costCents, the revenue plus shipping charged less refunds and every cost; the profit of an offer or option"},"byVersion":{"type":"array","items":{"type":"object","properties":{"version":{"type":"integer"},"orders":{"type":"integer","minimum":0},"incompleteOrders":{"type":"integer","minimum":0,"description":"Orders with a line missing a required cost kind in this view; their cost is understated until the cost is entered (decision 57)"},"cancelledOrders":{"type":"integer","minimum":0,"description":"Orders cancelled in Shopify: not sales, so counted in no other figure (their revenue, refunds and cost are left out)"},"revenueCents":{"type":"integer","description":"Gross: lines plus shipping as charged, frozen at creation, in the shop currency"},"refundedCents":{"type":"integer","description":"Money returned after the sale against revenue the offer counted, tax excluded (decisions 47 and 58)"},"refundedExcludedCents":{"type":"integer","description":"Refunds of units a paid edit added or of lines without a variant: revenue the offer never counted, so shown and not subtracted"},"netRevenueCents":{"type":"integer","description":"revenueCents − refundedCents; what contribution is computed from"},"editAdjustmentsCents":{"type":"integer","description":"What paid order edits changed against the frozen gross revenue; shown, not in contribution"},"costCents":{"type":"integer","description":"The engine's cost in this view (current: the ledger now; as_recorded: frozen at ingest); refunds do not reduce it"},"profitCents":{"type":"integer","description":"Contribution: netRevenueCents − costCents, the revenue plus shipping charged less refunds and every cost; the profit of an offer or option"}},"required":["version","orders","incompleteOrders","cancelledOrders","revenueCents","refundedCents","refundedExcludedCents","netRevenueCents","editAdjustmentsCents","costCents","profitCents"]}}},"required":["orders","incompleteOrders","cancelledOrders","revenueCents","refundedCents","refundedExcludedCents","netRevenueCents","editAdjustmentsCents","costCents","profitCents","byVersion"],"description":"First orders of every version in `realizedCurrencyCode`. Null until such an order exists; revenue less cost in the chosen view, no rate estimates"},"realizedRenewals":{"type":["object","null"],"properties":{"orders":{"type":"integer","minimum":0},"incompleteOrders":{"type":"integer","minimum":0,"description":"Orders with a line missing a required cost kind in this view; their cost is understated until the cost is entered (decision 57)"},"cancelledOrders":{"type":"integer","minimum":0,"description":"Orders cancelled in Shopify: not sales, so counted in no other figure (their revenue, refunds and cost are left out)"},"revenueCents":{"type":"integer","description":"Gross: lines plus shipping as charged, frozen at creation, in the shop currency"},"refundedCents":{"type":"integer","description":"Money returned after the sale against revenue the offer counted, tax excluded (decisions 47 and 58)"},"refundedExcludedCents":{"type":"integer","description":"Refunds of units a paid edit added or of lines without a variant: revenue the offer never counted, so shown and not subtracted"},"netRevenueCents":{"type":"integer","description":"revenueCents − refundedCents; what contribution is computed from"},"editAdjustmentsCents":{"type":"integer","description":"What paid order edits changed against the frozen gross revenue; shown, not in contribution"},"costCents":{"type":"integer","description":"The engine's cost in this view (current: the ledger now; as_recorded: frozen at ingest); refunds do not reduce it"},"profitCents":{"type":"integer","description":"Contribution: netRevenueCents − costCents, the revenue plus shipping charged less refunds and every cost; the profit of an offer or option"},"byVersion":{"type":"array","items":{"type":"object","properties":{"version":{"type":"integer"},"orders":{"type":"integer","minimum":0},"incompleteOrders":{"type":"integer","minimum":0,"description":"Orders with a line missing a required cost kind in this view; their cost is understated until the cost is entered (decision 57)"},"cancelledOrders":{"type":"integer","minimum":0,"description":"Orders cancelled in Shopify: not sales, so counted in no other figure (their revenue, refunds and cost are left out)"},"revenueCents":{"type":"integer","description":"Gross: lines plus shipping as charged, frozen at creation, in the shop currency"},"refundedCents":{"type":"integer","description":"Money returned after the sale against revenue the offer counted, tax excluded (decisions 47 and 58)"},"refundedExcludedCents":{"type":"integer","description":"Refunds of units a paid edit added or of lines without a variant: revenue the offer never counted, so shown and not subtracted"},"netRevenueCents":{"type":"integer","description":"revenueCents − refundedCents; what contribution is computed from"},"editAdjustmentsCents":{"type":"integer","description":"What paid order edits changed against the frozen gross revenue; shown, not in contribution"},"costCents":{"type":"integer","description":"The engine's cost in this view (current: the ledger now; as_recorded: frozen at ingest); refunds do not reduce it"},"profitCents":{"type":"integer","description":"Contribution: netRevenueCents − costCents, the revenue plus shipping charged less refunds and every cost; the profit of an offer or option"}},"required":["version","orders","incompleteOrders","cancelledOrders","revenueCents","refundedCents","refundedExcludedCents","netRevenueCents","editAdjustmentsCents","costCents","profitCents"]}}},"required":["orders","incompleteOrders","cancelledOrders","revenueCents","refundedCents","refundedExcludedCents","netRevenueCents","editAdjustmentsCents","costCents","profitCents","byVersion"],"description":"Renewal orders (a subscription billing attempt created them) in `realizedCurrencyCode`, each kind charged only on the orders its scope names (a renewal never pays a first-order kind). Null until one exists"},"realizedByCurrency":{"type":"array","items":{"type":"object","properties":{"currencyCode":{"type":"string","description":"The shop currency (ISO 4217)"},"realized":{"type":["object","null"],"properties":{"orders":{"type":"integer","minimum":0},"incompleteOrders":{"type":"integer","minimum":0,"description":"Orders with a line missing a required cost kind in this view; their cost is understated until the cost is entered (decision 57)"},"cancelledOrders":{"type":"integer","minimum":0,"description":"Orders cancelled in Shopify: not sales, so counted in no other figure (their revenue, refunds and cost are left out)"},"revenueCents":{"type":"integer","description":"Gross: lines plus shipping as charged, frozen at creation, in the shop currency"},"refundedCents":{"type":"integer","description":"Money returned after the sale against revenue the offer counted, tax excluded (decisions 47 and 58)"},"refundedExcludedCents":{"type":"integer","description":"Refunds of units a paid edit added or of lines without a variant: revenue the offer never counted, so shown and not subtracted"},"netRevenueCents":{"type":"integer","description":"revenueCents − refundedCents; what contribution is computed from"},"editAdjustmentsCents":{"type":"integer","description":"What paid order edits changed against the frozen gross revenue; shown, not in contribution"},"costCents":{"type":"integer","description":"The engine's cost in this view (current: the ledger now; as_recorded: frozen at ingest); refunds do not reduce it"},"profitCents":{"type":"integer","description":"Contribution: netRevenueCents − costCents, the revenue plus shipping charged less refunds and every cost; the profit of an offer or option"},"byVersion":{"type":"array","items":{"type":"object","properties":{"version":{"type":"integer"},"orders":{"type":"integer","minimum":0},"incompleteOrders":{"type":"integer","minimum":0,"description":"Orders with a line missing a required cost kind in this view; their cost is understated until the cost is entered (decision 57)"},"cancelledOrders":{"type":"integer","minimum":0,"description":"Orders cancelled in Shopify: not sales, so counted in no other figure (their revenue, refunds and cost are left out)"},"revenueCents":{"type":"integer","description":"Gross: lines plus shipping as charged, frozen at creation, in the shop currency"},"refundedCents":{"type":"integer","description":"Money returned after the sale against revenue the offer counted, tax excluded (decisions 47 and 58)"},"refundedExcludedCents":{"type":"integer","description":"Refunds of units a paid edit added or of lines without a variant: revenue the offer never counted, so shown and not subtracted"},"netRevenueCents":{"type":"integer","description":"revenueCents − refundedCents; what contribution is computed from"},"editAdjustmentsCents":{"type":"integer","description":"What paid order edits changed against the frozen gross revenue; shown, not in contribution"},"costCents":{"type":"integer","description":"The engine's cost in this view (current: the ledger now; as_recorded: frozen at ingest); refunds do not reduce it"},"profitCents":{"type":"integer","description":"Contribution: netRevenueCents − costCents, the revenue plus shipping charged less refunds and every cost; the profit of an offer or option"}},"required":["version","orders","incompleteOrders","cancelledOrders","revenueCents","refundedCents","refundedExcludedCents","netRevenueCents","editAdjustmentsCents","costCents","profitCents"]}}},"required":["orders","incompleteOrders","cancelledOrders","revenueCents","refundedCents","refundedExcludedCents","netRevenueCents","editAdjustmentsCents","costCents","profitCents","byVersion"]},"realizedRenewals":{"type":["object","null"],"properties":{"orders":{"type":"integer","minimum":0},"incompleteOrders":{"type":"integer","minimum":0,"description":"Orders with a line missing a required cost kind in this view; their cost is understated until the cost is entered (decision 57)"},"cancelledOrders":{"type":"integer","minimum":0,"description":"Orders cancelled in Shopify: not sales, so counted in no other figure (their revenue, refunds and cost are left out)"},"revenueCents":{"type":"integer","description":"Gross: lines plus shipping as charged, frozen at creation, in the shop currency"},"refundedCents":{"type":"integer","description":"Money returned after the sale against revenue the offer counted, tax excluded (decisions 47 and 58)"},"refundedExcludedCents":{"type":"integer","description":"Refunds of units a paid edit added or of lines without a variant: revenue the offer never counted, so shown and not subtracted"},"netRevenueCents":{"type":"integer","description":"revenueCents − refundedCents; what contribution is computed from"},"editAdjustmentsCents":{"type":"integer","description":"What paid order edits changed against the frozen gross revenue; shown, not in contribution"},"costCents":{"type":"integer","description":"The engine's cost in this view (current: the ledger now; as_recorded: frozen at ingest); refunds do not reduce it"},"profitCents":{"type":"integer","description":"Contribution: netRevenueCents − costCents, the revenue plus shipping charged less refunds and every cost; the profit of an offer or option"},"byVersion":{"type":"array","items":{"type":"object","properties":{"version":{"type":"integer"},"orders":{"type":"integer","minimum":0},"incompleteOrders":{"type":"integer","minimum":0,"description":"Orders with a line missing a required cost kind in this view; their cost is understated until the cost is entered (decision 57)"},"cancelledOrders":{"type":"integer","minimum":0,"description":"Orders cancelled in Shopify: not sales, so counted in no other figure (their revenue, refunds and cost are left out)"},"revenueCents":{"type":"integer","description":"Gross: lines plus shipping as charged, frozen at creation, in the shop currency"},"refundedCents":{"type":"integer","description":"Money returned after the sale against revenue the offer counted, tax excluded (decisions 47 and 58)"},"refundedExcludedCents":{"type":"integer","description":"Refunds of units a paid edit added or of lines without a variant: revenue the offer never counted, so shown and not subtracted"},"netRevenueCents":{"type":"integer","description":"revenueCents − refundedCents; what contribution is computed from"},"editAdjustmentsCents":{"type":"integer","description":"What paid order edits changed against the frozen gross revenue; shown, not in contribution"},"costCents":{"type":"integer","description":"The engine's cost in this view (current: the ledger now; as_recorded: frozen at ingest); refunds do not reduce it"},"profitCents":{"type":"integer","description":"Contribution: netRevenueCents − costCents, the revenue plus shipping charged less refunds and every cost; the profit of an offer or option"}},"required":["version","orders","incompleteOrders","cancelledOrders","revenueCents","refundedCents","refundedExcludedCents","netRevenueCents","editAdjustmentsCents","costCents","profitCents"]}}},"required":["orders","incompleteOrders","cancelledOrders","revenueCents","refundedCents","refundedExcludedCents","netRevenueCents","editAdjustmentsCents","costCents","profitCents","byVersion"]}},"required":["currencyCode","realized","realizedRenewals"]},"description":"The same figures once per shop currency the option's orders were placed in, sorted by currency: an option sold in two currencies has two entries, never one sum"},"forecastVsActual":{"type":["object","null"],"properties":{"orders":{"type":"integer","exclusiveMinimum":0,"description":"Orders of the compared version"},"forecastMarginCents":{"type":"integer"},"forecastBeforeRatesCents":{"type":"integer","description":"Forecast margin before the refund estimate; payment processing is one of the costs, as it is in realized"},"realizedPerOrderMarginCents":{"type":"integer","description":"(revenue − cost) per order of the compared version, before refunds"},"deltaCents":{"type":"integer","description":"realizedPerOrder − forecastBeforeRates"},"forecastRefundsPerOrderCents":{"type":"integer","description":"The forecast's refund estimate per order"},"realizedRefundsPerOrderCents":{"type":"integer","description":"Refunded revenue per order of the compared version"},"refundsDeltaCents":{"type":"integer","description":"realizedRefundsPerOrder − forecastRefundsPerOrder"},"forecastFirstOrderMarginCents":{"type":"integer"}},"required":["orders","forecastMarginCents","forecastBeforeRatesCents","realizedPerOrderMarginCents","deltaCents","forecastRefundsPerOrderCents","realizedRefundsPerOrderCents","refundsDeltaCents","forecastFirstOrderMarginCents"],"description":"Per first order of this response's version in the market currency only; null without such orders"},"renewalForecastVsActual":{"type":["object","null"],"properties":{"orders":{"type":"integer","exclusiveMinimum":0,"description":"Orders of the compared version"},"forecastMarginCents":{"type":"integer"},"forecastBeforeRatesCents":{"type":"integer","description":"Forecast margin before the refund estimate; payment processing is one of the costs, as it is in realized"},"realizedPerOrderMarginCents":{"type":"integer","description":"(revenue − cost) per order of the compared version, before refunds"},"deltaCents":{"type":"integer","description":"realizedPerOrder − forecastBeforeRates"},"forecastRefundsPerOrderCents":{"type":"integer","description":"The forecast's refund estimate per order"},"realizedRefundsPerOrderCents":{"type":"integer","description":"Refunded revenue per order of the compared version"},"refundsDeltaCents":{"type":"integer","description":"realizedRefundsPerOrder − forecastRefundsPerOrder"}},"required":["orders","forecastMarginCents","forecastBeforeRatesCents","realizedPerOrderMarginCents","deltaCents","forecastRefundsPerOrderCents","realizedRefundsPerOrderCents","refundsDeltaCents"],"description":"Per renewal order of this response's version in the market currency against the renewal forecast; null without such renewals or a renewal forecast"}},"required":["optionKey","visible","forecast","realized","realizedRenewals","realizedByCurrency","forecastVsActual","renewalForecastVsActual"]}}},"required":["offerId","version","view","currencyCode","realizedCurrencyCodes","realizedCurrencyCode","comparable","costProfile","rates","computedAt","options"]}}}},"400":{"description":"Invalid id, or the document names an unknown cost profile","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}},"401":{"description":"Missing, unknown or revoked API key","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}},"403":{"description":"The key is public; this route needs a secret key","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}},"404":{"description":"No such offer or version","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}}}}},"/offers/{id}/purchase-comparison":{"get":{"operationId":"compareOfferPurchases","summary":"Browser-versus-server purchase comparison","description":"Purchases of the offer since `since`, or over the last `days` (default 7), as the browser reported them and as the order ingest recorded them, matched by the shared `purchase:<order gid>` event id. `browserOnly` is tracking without an order (or an order outside the window): a lost or late order webhook, or an event posted by anyone holding the store's public key, which is readable in its pages. These are unverified purchases, and the funnel, the simulator and experiments never count them (decision 212); `serverOnly` is an order the browser never reported: no pixel on the store, a buyer who declined analytics, a blocked request, or a cart the brand built without the pointer. Use `since` to compare two reads over the same purchases (before and after a launch, a campaign or a test run): a rolling `days` window drops the oldest purchases as time passes.","tags":["Offers"],"security":[{"apiKey":[]}],"parameters":[{"schema":{"type":"string","format":"uuid","description":"The offer id"},"required":true,"description":"The offer id","name":"id","in":"path"},{"schema":{"type":"integer","minimum":1,"maximum":90,"description":"A rolling window ending now (default 7)"},"required":false,"description":"A rolling window ending now (default 7)","name":"days","in":"query"},{"schema":{"type":"string","format":"date-time","description":"A fixed start (ISO 8601, UTC), at most 90 days ago; the window runs to now"},"required":false,"description":"A fixed start (ISO 8601, UTC), at most 90 days ago; the window runs to now","name":"since","in":"query"}],"responses":{"200":{"description":"The comparison","content":{"application/json":{"schema":{"type":"object","properties":{"offerId":{"type":"string","format":"uuid"},"windowDays":{"type":["integer","null"],"exclusiveMinimum":0,"description":"The rolling window in days, or null when the request gave `since`"},"since":{"type":"string","format":"date-time","description":"Where the window starts: `since` as given, or now minus `windowDays`"},"browser":{"type":"integer","minimum":0,"description":"Purchases the Web Pixel reported from the thank-you page"},"server":{"type":"integer","minimum":0,"description":"Purchases the order ingest recorded from webhooks"},"matched":{"type":"integer","minimum":0,"description":"Orders both sides reported, matched by `eventId`"},"browserOnly":{"type":"integer","minimum":0,"description":"Unverified purchases: the browser reported them and no order webhook confirms them (decision 212). No other report counts them"},"serverOnly":{"type":"integer","minimum":0},"variance":{"type":"integer","description":"browser − server"}},"required":["offerId","windowDays","since","browser","server","matched","browserOnly","serverOnly","variance"]}}}},"400":{"description":"Invalid id or query: both days and since, or since more than 90 days ago","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}},"401":{"description":"Missing, unknown or revoked API key","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}},"403":{"description":"The key is public; this route needs a secret key","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}},"404":{"description":"No such offer for this tenant","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}}}}},"/offers/{id}/funnel":{"get":{"operationId":"getOfferFunnel","summary":"The event ladder of an offer","description":"The five steps over the last `days` (default 7), each counted once per distinct `eventId`. Each step has one source of record (decision 45): `view_offer`, `select_option` and `add_to_cart` from the brand's page through the SDK; `checkout_started` from the Web Pixel, one per checkout token, so a reloaded checkout is one step and a cart the brand built without the SDK still counts; `purchase` from the order ingest, with the pixel's copy sharing its id. The pixel follows the store's cookie consent, so `checkout_started` can undercount where buyers decline analytics; `purchase` never does. `purchase` counts only orders the store's signed order webhook confirmed; a purchase only a browser reported is `unverifiedPurchases` (decision 212). The four earlier steps come from browsers holding the public key and cannot be confirmed the same way: read them as tracking, not as sales.","tags":["Offers"],"security":[{"apiKey":[]}],"parameters":[{"schema":{"type":"string","format":"uuid","description":"The offer id"},"required":true,"description":"The offer id","name":"id","in":"path"},{"schema":{"type":"integer","minimum":1,"maximum":90,"default":7},"required":false,"name":"days","in":"query"}],"responses":{"200":{"description":"The funnel","content":{"application/json":{"schema":{"type":"object","properties":{"offerId":{"type":"string","format":"uuid"},"windowDays":{"type":"integer","exclusiveMinimum":0},"steps":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string","enum":["view_offer","select_option","add_to_cart","checkout_started","purchase"]},"events":{"type":"integer","minimum":0,"description":"Distinct events of the step: one per checkout for checkout_started, one per order an order webhook confirmed for purchase"},"visitors":{"type":"integer","minimum":0,"description":"Distinct visitor ids that reached the step"}},"required":["name","events","visitors"]},"description":"The five steps in ladder order; a step nobody reached has 0"},"unverifiedPurchases":{"type":"integer","minimum":0,"description":"Purchases a browser reported in the window that no order webhook confirms: not counted in `purchase` (decision 212). A few are a late webhook; many are forged or lost orders"}},"required":["offerId","windowDays","steps","unverifiedPurchases"]}}}},"400":{"description":"Invalid id or query","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}},"401":{"description":"Missing, unknown or revoked API key","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}},"403":{"description":"The key is public; this route needs a secret key","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}},"404":{"description":"No such offer for this tenant","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}}}}},"/offers/{id}/publish":{"post":{"operationId":"publishOffer","x-destructive":true,"summary":"Publish a version: the one confirm verb","description":"Starts the publish Workflow for the offer's current draft version (or `version`): mints any discount codes, rewrites the store's option map on the app discount, proves every visible option with a real Storefront cart, and flips the version to live only when every assert passes. Poll the run with GET /offers/{id}/publish/{runId}. With `as: \"arm\"` the proven version becomes `verified` instead, an arm for an experiment, and the live version keeps serving. Publishing a new live version stops the offer's running experiment.","tags":["Offers"],"security":[{"apiKey":[]}],"parameters":[{"schema":{"type":"string","format":"uuid","description":"The offer id"},"required":true,"description":"The offer id","name":"id","in":"path"}],"requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"object","properties":{"version":{"type":"integer","exclusiveMinimum":0},"as":{"type":"string","enum":["live","arm"],"default":"live","description":"`arm`: prove the version for an experiment without making it live"}}}}}},"responses":{"202":{"description":"The Workflow run","content":{"application/json":{"schema":{"type":"object","properties":{"runId":{"type":"string"},"offerId":{"type":"string","format":"uuid"},"version":{"type":"integer","exclusiveMinimum":0},"status":{"type":"string","enum":["queued"]}},"required":["runId","offerId","version","status"]}}}},"400":{"description":"Invalid id","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}},"401":{"description":"Missing, unknown or revoked API key","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}},"403":{"description":"The key is public; this route needs a secret key","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}},"404":{"description":"No such offer for this tenant","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}},"409":{"description":"The version is already live, the document's store is not connected to this tenant, or an option presents what the store's cart transform cannot run (`store_capability_missing`)","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}}}}},"/offers/{id}/publish/{runId}":{"get":{"operationId":"getPublishRun","summary":"Status of a publish run","description":"The Workflow instance's status; `output` holds each step's summary once complete, `error` the final failure.","tags":["Offers"],"security":[{"apiKey":[]}],"parameters":[{"schema":{"type":"string","format":"uuid","description":"The offer id"},"required":true,"description":"The offer id","name":"id","in":"path"},{"schema":{"type":"string","minLength":1},"required":true,"name":"runId","in":"path"}],"responses":{"200":{"description":"The run","content":{"application/json":{"schema":{"type":"object","properties":{"runId":{"type":"string"},"status":{"type":"string"},"error":{"type":"object","properties":{"name":{"type":"string"},"message":{"type":"string"}},"required":["name","message"]},"output":{}},"required":["runId","status"]}}}},"400":{"description":"Invalid id","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}},"401":{"description":"Missing, unknown or revoked API key","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}},"403":{"description":"The key is public; this route needs a secret key","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}},"404":{"description":"No such offer for this tenant","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}}}}},"/offers/{id}/verify":{"post":{"operationId":"verifyOffer","summary":"Re-verify a version with real carts","description":"Runs the verifier now on the live version and rewrites its verification blocks: a real cart per visible option, the same cart without the pointer, and the landing page when declared. It records each option's status and never changes the version's status; a result other than `matched` on a live version is the signal the dashboard and the SDK act on (checkedAt and validForSeconds). Only the live version can be verified here (`not_live` otherwise): the discount function prices and ships free live versions only, so a draft or retired version would verify red for that reason alone. `publish_offer` verifies a draft as it publishes it.","tags":["Offers"],"security":[{"apiKey":[]}],"parameters":[{"schema":{"type":"string","format":"uuid","description":"The offer id"},"required":true,"description":"The offer id","name":"id","in":"path"}],"requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"object","properties":{"version":{"type":"integer","exclusiveMinimum":0}}}}}},"responses":{"200":{"description":"The verification summary; every check is on the version document","content":{"application/json":{"schema":{"type":"object","properties":{"offerId":{"type":"string","format":"uuid","description":"The offer"},"version":{"type":"integer","exclusiveMinimum":0,"description":"The version verified: the live one"},"status":{"type":"string","enum":["matched","mismatched","unverifiable"],"description":"`matched` only when every visible option is; else the worst option's status"},"options":{"type":"array","items":{"type":"object","properties":{"optionKey":{"type":"string","description":"The option"},"status":{"type":"string","enum":["matched","mismatched","unverifiable","unverified"],"description":"Whether a real cart charges what the option promises: `matched`; `mismatched` when a check failed or Shopify refused the cart; `unverifiable` when a check of the promise could not run; `unverified` when never checked (a hidden option). An option goes live only when `matched`"},"failedChecks":{"type":"array","items":{"type":"string"},"description":"Every check that did not pass, as `name (result): detail`"}},"required":["optionKey","status","failedChecks"]},"description":"One entry per visible option"}},"required":["offerId","version","status","options"]}}}},"400":{"description":"Invalid id","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}},"401":{"description":"Missing, unknown or revoked API key","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}},"403":{"description":"The key is public; this route needs a secret key","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}},"404":{"description":"No such offer for this tenant","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}},"409":{"description":"`not_live`: the offer has no live version, or `version` is not it; `store_not_connected`: the document's store is not connected","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}}}}},"/offers/{id}/price":{"post":{"operationId":"priceOfferSelection","summary":"Price a Selection without building a cart","description":"What the cart for this `Selection` would charge, per cart line and in total, on the first order and on a renewal, from the same line pricing the verifier proves on real carts and the same cart lines `POST /offers/{id}/cart` builds for it. Resolve already carries each option's prices with nothing chosen and each add-on's (`options[].prices`); call this when the shopper picks pool variants, so the page shows the price the cart will charge without pricing a line itself. Send `visitorId` and the rendered `shownVersion` like the cart: a visitor now served another version gets `409 offer_changed` with the document to render.","tags":["Offers"],"security":[{"apiKey":[]}],"parameters":[{"schema":{"type":"string","format":"uuid","description":"The offer id"},"required":true,"description":"The offer id","name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"optionKey":{"type":"string","maxLength":64,"pattern":"^[a-z0-9][a-z0-9_-]*$","description":"The option chosen"},"axisValues":{"type":"object","additionalProperties":{"type":"string","minLength":1},"default":{},"description":"Axis key → value, for an axis-mapped line whose variant follows the shopper's choice"},"poolSelections":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string","pattern":"^gid:\\/\\/shopify\\/ProductVariant\\/\\d+$","description":"A Shopify ProductVariant gid (`gid://shopify/ProductVariant/<id>`)"},"minItems":1},"default":{},"description":"Pool key → the variants chosen from it; a variant listed twice is two units"},"addOnLineKeys":{"type":"array","items":{"type":"string","maxLength":64,"pattern":"^[a-z0-9][a-z0-9_-]*$","description":"A key the brand authors: lower-case letters, digits, `_` and `-`"},"default":[],"description":"The optional add-on lines the shopper opted into, by line key"},"visitorId":{"type":"string","minLength":1,"maxLength":128,"description":"The visitor id (`v_…`): the cart is built from the version this visitor is served, and it rides on the cart as `_os_visitor`"},"shownVersion":{"type":"integer","exclusiveMinimum":0,"description":"The version the page rendered (`version` from resolve). If the visitor is served another version now, the cart is refused with `409 offer_changed` and the current document; without it the cart is built from whatever version the visitor is served"}},"required":["optionKey"],"additionalProperties":false}}}},"responses":{"200":{"description":"The price of the selection","content":{"application/json":{"schema":{"type":"object","properties":{"offerId":{"type":"string","format":"uuid"},"version":{"type":"integer","exclusiveMinimum":0,"description":"The version priced: the one this visitor is served, live or their experiment arm"},"optionKey":{"type":"string"},"currencyCode":{"type":"string","description":"The market currency every amount is in"},"first":{"type":"object","properties":{"totalCents":{"type":"integer","minimum":0,"description":"What these lines charge on this charge, before shipping and tax: the sum of the lines' `netCents`"},"lines":{"type":"array","items":{"type":"object","properties":{"lineIndex":{"type":"integer","minimum":0,"description":"The line's index in the option's `lines`"},"key":{"type":"string","maxLength":64,"pattern":"^[a-z0-9][a-z0-9_-]*$","description":"Names the line inside its option; required on an optional non-gift line, which a cart opts into by this key (`addOnLineKeys`)"},"role":{"type":"string","enum":["main","add_on","gift"],"description":"What a line is in its option: `main` is what the buyer pays for, `add_on` an extra the buyer opts into or is always added, `gift` a real product the discount function prices to zero"},"variantId":{"type":"string","pattern":"^gid:\\/\\/shopify\\/ProductVariant\\/\\d+$","description":"The variant this cart line holds; a pool-bound line becomes one cart line per distinct variant chosen"},"quantity":{"type":"integer","exclusiveMinimum":0,"description":"Units on this cart line"},"sellingPlanId":{"type":"string","pattern":"^gid:\\/\\/shopify\\/SellingPlan\\/\\d+$","description":"The selling plan the cart line is bought on, for a subscription line"},"unitCents":{"type":"integer","minimum":0,"description":"One unit before any product discount: the catalog price with the selling plan's adjustment in effect on this charge"},"grossCents":{"type":"integer","minimum":0,"description":"`unitCents` × `quantity`"},"discountCents":{"type":"integer","minimum":0,"description":"What the one product discount takes off the line on this charge (all of it on a gift); 0 when nothing does"},"discountBy":{"type":["string","null"],"enum":["managed_discount","discount_code","existing_automatic_discount","unit_price_tiers","bundle_price","gift",null],"description":"The mechanism that takes `discountCents` off (`unit_price_tiers`: a category group's first-charge price for its units; `bundle_price`: a bundle's percentage off from our cart transform, which checkout shows as the bundle's price, not as a saving), `gift` when the discount function zeroes a gift, null when nothing does"},"netCents":{"type":"integer","minimum":0,"description":"What the line charges on this charge: `grossCents` less `discountCents`. Show this; never compute it"}},"required":["lineIndex","role","variantId","quantity","unitCents","grossCents","discountCents","discountBy","netCents"],"additionalProperties":false},"description":"Each cart line with its price on this charge"}},"required":["totalCents","lines"],"additionalProperties":false,"description":"The first order"},"renewal":{"type":["object","null"],"properties":{"totalCents":{"type":"integer","minimum":0,"description":"What these lines charge on this charge, before shipping and tax: the sum of the lines' `netCents`"},"lines":{"type":"array","items":{"type":"object","properties":{"lineIndex":{"type":"integer","minimum":0,"description":"The line's index in the option's `lines`"},"key":{"type":"string","maxLength":64,"pattern":"^[a-z0-9][a-z0-9_-]*$","description":"Names the line inside its option; required on an optional non-gift line, which a cart opts into by this key (`addOnLineKeys`)"},"role":{"type":"string","enum":["main","add_on","gift"],"description":"What a line is in its option: `main` is what the buyer pays for, `add_on` an extra the buyer opts into or is always added, `gift` a real product the discount function prices to zero"},"variantId":{"type":"string","pattern":"^gid:\\/\\/shopify\\/ProductVariant\\/\\d+$","description":"The variant this cart line holds; a pool-bound line becomes one cart line per distinct variant chosen"},"quantity":{"type":"integer","exclusiveMinimum":0,"description":"Units on this cart line"},"sellingPlanId":{"type":"string","pattern":"^gid:\\/\\/shopify\\/SellingPlan\\/\\d+$","description":"The selling plan the cart line is bought on, for a subscription line"},"unitCents":{"type":"integer","minimum":0,"description":"One unit before any product discount: the catalog price with the selling plan's adjustment in effect on this charge"},"grossCents":{"type":"integer","minimum":0,"description":"`unitCents` × `quantity`"},"discountCents":{"type":"integer","minimum":0,"description":"What the one product discount takes off the line on this charge (all of it on a gift); 0 when nothing does"},"discountBy":{"type":["string","null"],"enum":["managed_discount","discount_code","existing_automatic_discount","unit_price_tiers","bundle_price","gift",null],"description":"The mechanism that takes `discountCents` off (`unit_price_tiers`: a category group's first-charge price for its units; `bundle_price`: a bundle's percentage off from our cart transform, which checkout shows as the bundle's price, not as a saving), `gift` when the discount function zeroes a gift, null when nothing does"},"netCents":{"type":"integer","minimum":0,"description":"What the line charges on this charge: `grossCents` less `discountCents`. Show this; never compute it"}},"required":["lineIndex","role","variantId","quantity","unitCents","grossCents","discountCents","discountBy","netCents"],"additionalProperties":false},"description":"Each cart line with its price on this charge"}},"required":["totalCents","lines"],"additionalProperties":false,"description":"Every renewal: only the lines that renew; null when none does"}},"required":["offerId","version","optionKey","currencyCode","first","renewal"]}}}},"400":{"description":"Unknown option, an invalid pool selection (`pool_selection_count_out_of_range`, `variant_not_in_pool`, `pool_selection_repeated`), an unknown add-on (`unknown_add_on`) or axis value","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}},"401":{"description":"Missing, unknown or revoked API key","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}},"404":{"description":"No live version","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}},"409":{"description":"`offer_changed`: `shownVersion` is not the version this visitor is served now; `offer` is the one to render","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]},"offer":{"type":"object","properties":{"id":{"type":"string","format":"uuid","description":"The offer id"},"code":{"type":"string","maxLength":31,"pattern":"^[^,\\s](?:[^,]*[^,\\s])?$","description":"The offer's code: unique per tenant, immutable once created, and how an agent, `lookup_offer` and the order tag `os_offer:<code>` name the offer"},"version":{"type":"integer","exclusiveMinimum":0,"description":"The version served; send it back as the cart request's `shownVersion`"},"status":{"type":"string","enum":["draft","verified","live","retired"],"description":"`live`, or under `preview` the current version's status"},"store":{"type":"object","properties":{"myshopifyDomain":{"type":"string","minLength":1,"description":"The connected store's myshopify domain (`brand.myshopify.com`); publish and serving use this store"},"market":{"type":"object","properties":{"countryCode":{"type":"string","pattern":"^[A-Z]{2}$","description":"The buyer's country, ISO 3166-1 alpha-2; carts are priced in its market"},"currencyCode":{"type":"string","pattern":"^[A-Z]{3}$","description":"The market's currency, ISO 4217; every amount in the document is in it"}},"required":["countryCode","currencyCode"],"additionalProperties":false,"description":"The one market the offer is priced in"}},"required":["myshopifyDomain","market"],"additionalProperties":false,"description":"The connected store and the market the offer is priced in"},"tracking":{"type":"object","properties":{"experienceName":{"type":"string","minLength":1,"description":"A label for the page or funnel this offer runs in; the offers list shows it"},"campaignName":{"type":"string","minLength":1,"description":"A label for the marketing campaign this offer belongs to"},"presellPageName":{"type":["string","null"],"minLength":1,"description":"A label for the presell page in front of the offer, or null"},"preservedCartAttributes":{"type":"array","items":{"type":"string","minLength":1},"description":"The brand's own cart attribute names a cart request may set and the API keeps on the cart (`preservedCartAttributes` on the cart request)"}},"required":["experienceName","campaignName","presellPageName","preservedCartAttributes"],"additionalProperties":false,"description":"The labels reports group by, and the brand's own cart attributes a cart keeps"},"axes":{"type":"array","items":{"type":"object","properties":{"key":{"type":"string","maxLength":64,"pattern":"^[a-z0-9][a-z0-9_-]*$","description":"Names the axis; options and axis-mapped lines refer to it"},"values":{"type":"array","items":{"type":"string","minLength":1},"minItems":1,"description":"Every value the axis takes"}},"required":["key","values"],"additionalProperties":false},"description":"Dimensions the options vary along (flavour, size); they name and enumerate options, never patch one"},"pools":{"type":"array","items":{"type":"object","properties":{"key":{"type":"string","maxLength":64,"pattern":"^[a-z0-9][a-z0-9_-]*$","description":"Names the pool; a pool-bound line refers to it"},"variantIds":{"type":"array","items":{"type":"string","pattern":"^gid:\\/\\/shopify\\/ProductVariant\\/\\d+$","description":"A Shopify ProductVariant gid (`gid://shopify/ProductVariant/<id>`)"},"minItems":1,"description":"The pool's variants"},"allowRepeats":{"type":"boolean","description":"Whether one variant may be chosen more than once"}},"required":["key","variantIds","allowRepeats"],"additionalProperties":false},"description":"Pools a buyer chooses variants from, through a line bound to the pool"},"defaultOptionKey":{"type":"string","maxLength":64,"pattern":"^[a-z0-9][a-z0-9_-]*$","description":"The option a renderer preselects; must name a visible option"},"options":{"type":"array","items":{"type":"object","properties":{"key":{"type":"string","maxLength":30,"pattern":"^[a-z0-9][a-z0-9_-]*$","description":"Names the option: unique in the document, carried in the cart pointer, the order tag `os_option:<key>` (so at most 30 characters) and the economics. Keep it stable"},"display":{"type":"object","properties":{"title":{"type":"string","minLength":1,"description":"The option's name as a buyer reads it"}},"required":["title"],"additionalProperties":false,"description":"What a renderer shows for the option"},"visible":{"type":"boolean","description":"Whether a renderer may show the option and publish verifies it; a hidden option still resolves and builds carts"},"axisValues":{"type":"object","additionalProperties":{"type":"string"},"description":"The option's value on each document axis, by axis key"},"unitCount":{"type":"integer","exclusiveMinimum":0,"description":"The quantity the buyer perceives (\"4 units\"); not the sum of line quantities"},"cardKey":{"type":"string","maxLength":64,"pattern":"^[a-z0-9][a-z0-9_-]*$","description":"Options sharing a card key are drawn as one card (a subscribe and one-time pair of one product)"},"lines":{"type":"array","items":{"type":"object","properties":{"key":{"type":"string","maxLength":64,"pattern":"^[a-z0-9][a-z0-9_-]*$","description":"Names the line inside its option; required on an optional non-gift line, which a cart opts into by this key (`addOnLineKeys`)"},"role":{"type":"string","enum":["main","add_on","gift"],"description":"What a line is in its option: `main` is what the buyer pays for, `add_on` an extra the buyer opts into or is always added, `gift` a real product the discount function prices to zero"},"quantity":{"type":"integer","exclusiveMinimum":0,"description":"Units of the variant in the cart; on a pool-bound line, the fewest the buyer may choose"},"maxQuantity":{"type":"integer","exclusiveMinimum":0,"description":"A pool-bound line only: the most units the buyer may choose"},"required":{"type":"boolean","description":"Whether every cart for the option holds the line; an optional line is added only when the cart request names its key"},"variantSource":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","enum":["fixed"],"description":"The line is one named variant"},"productId":{"type":"string","pattern":"^gid:\\/\\/shopify\\/Product\\/\\d+$","description":"The variant's product"},"variantId":{"type":"string","pattern":"^gid:\\/\\/shopify\\/ProductVariant\\/\\d+$","description":"The variant the line puts in the cart"}},"required":["type","productId","variantId"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","enum":["axis_map"],"description":"The variant follows the option's axis values, through `variantIdByAxisValue`"},"productId":{"type":"string","pattern":"^gid:\\/\\/shopify\\/Product\\/\\d+$","description":"The product every mapped variant belongs to"},"axisKeys":{"type":"array","items":{"type":"string","maxLength":64,"pattern":"^[a-z0-9][a-z0-9_-]*$","description":"A key the brand authors: lower-case letters, digits, `_` and `-`"},"minItems":1,"description":"The document axes whose values choose the variant, in `variantIdByAxisValue`'s key order"},"variantIdByAxisValue":{"type":"object","additionalProperties":{"type":"string","pattern":"^gid:\\/\\/shopify\\/ProductVariant\\/\\d+$","description":"A Shopify ProductVariant gid (`gid://shopify/ProductVariant/<id>`)"},"description":"Variant id by axis value; for several `axisKeys`, keyed by the values joined with \"/\" in `axisKeys` order. Must cover exactly the declared values"}},"required":["type","productId","axisKeys","variantIdByAxisValue"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","enum":["pool"],"description":"The buyer chooses the variants from a pool: `quantity` units, up to `maxQuantity`, any mix of the pool's variants; the cart gets one line per distinct variant"},"poolKey":{"type":"string","maxLength":64,"pattern":"^[a-z0-9][a-z0-9_-]*$","description":"The `pools[].key` the buyer chooses from"}},"required":["type","poolKey"],"additionalProperties":false}],"description":"Where the line's variant comes from"},"purchase":{"type":"object","properties":{"type":{"type":"string","enum":["one_time","subscription"],"description":"Bought once, or on a selling plan"},"sellingPlanId":{"type":"string","pattern":"^gid:\\/\\/shopify\\/SellingPlan\\/\\d+$","description":"The selling plan a subscription line is bought on; required when `type` is `subscription`"},"intervalDays":{"type":"integer","exclusiveMinimum":0,"description":"Days between a subscription's charges, as shown to the buyer"},"plans":{"type":"array","items":{"type":"object","properties":{"fromUnits":{"type":"integer","exclusiveMinimum":0,"description":"The fewest units of the group this plan's tier applies to; the first tier is 1"},"intervalDays":{"type":"integer","exclusiveMinimum":0,"description":"The cadence this plan renews on, one of the option's `cadence` intervals"},"sellingPlanId":{"type":"string","pattern":"^gid:\\/\\/shopify\\/SellingPlan\\/\\d+$","description":"The selling plan the group's lines go on at this tier and cadence"}},"required":["fromUnits","intervalDays","sellingPlanId"],"additionalProperties":false},"minItems":1,"description":"A subscription group's plan for each tier and cadence a cart can reach; `sellingPlanId` is one of them"}},"required":["type"],"additionalProperties":false,"description":"How the line is bought: once, or on a selling plan"},"bundleComponents":{"type":"array","items":{"type":"object","properties":{"variantId":{"type":"string","pattern":"^gid:\\/\\/shopify\\/ProductVariant\\/\\d+$","description":"A component variant of the fixed bundle"},"quantity":{"type":"integer","exclusiveMinimum":0,"description":"Units of that component in one bundle"}},"required":["variantId","quantity"],"additionalProperties":false},"minItems":1,"description":"What one unit holds, when the variant is a Shopify fixed bundle"},"catalogPrice":{"type":"object","properties":{"amountCents":{"type":"integer","minimum":0,"description":"The variant's catalog price when the document was written; line pricing starts from it"},"compareAtAmountCents":{"type":["integer","null"],"minimum":0,"description":"The variant's catalog compare-at price then, or null"},"capturedAt":{"type":"string","format":"date-time","description":"When the price was read from the catalog"}},"required":["amountCents","compareAtAmountCents","capturedAt"],"additionalProperties":false,"description":"The catalog price line pricing starts from"},"claimedValueCents":{"type":"integer","minimum":0,"description":"On a gift line: the value the page shows for it, in cents; never charged"}},"required":["role","quantity","required","variantSource","purchase","catalogPrice"],"additionalProperties":false},"minItems":1,"description":"What the option puts in the cart"},"maxUnits":{"type":"integer","exclusiveMinimum":0,"description":"A category builder: the most units the option's non-gift lines may hold in all"},"cadence":{"type":"object","properties":{"tiers":{"type":"array","items":{"type":"object","properties":{"fromUnits":{"type":"integer","exclusiveMinimum":0,"description":"The fewest units of the largest subscription group this interval applies to; the first tier is 1"},"intervalDays":{"type":"integer","exclusiveMinimum":0,"description":"Days between charges of every subscription line"}},"required":["fromUnits","intervalDays"],"additionalProperties":false},"minItems":1,"description":"The tiers, ascending from 1; above the last tier the last interval holds"}},"required":["tiers"],"additionalProperties":false,"description":"A category builder: the one interval every subscription line renews on, by the units of the largest subscription group in the cart; required when a line has `purchase.plans`"},"pricing":{"type":"object","properties":{"promise":{"type":"object","properties":{"firstChargeCents":{"type":["integer","null"],"minimum":0,"description":"What the buyer is charged on the first order, before shipping and tax; required on a visible option. Publish checks a real cart charges it"},"renewalChargeCents":{"type":["integer","null"],"minimum":0,"description":"What each renewal charges, before shipping and tax; required when the option has a subscription line"}},"required":["firstChargeCents","renewalChargeCents"],"additionalProperties":false,"description":"What the option promises the buyer is charged"},"compareAtPrice":{"type":"object","properties":{"amountCents":{"type":"integer","minimum":0,"description":"The struck-through amount, in cents"},"source":{"type":"string","enum":["variant","selling_plan","unit_price_times_quantity","metafield","page_copy"],"description":"Where it comes from: the variant's compare-at price, the selling plan's compare-at price, the unit price times the quantity, a metafield, or page copy"}},"required":["amountCents","source"],"additionalProperties":false,"description":"The struck-through price the page shows beside the promise"},"shipping":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","enum":["free"],"description":"The discount function makes the named rates free for carts carrying this option"},"rates":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","enum":["cheapest"],"description":"The cheapest shipping rate in each delivery group"}},"required":["type"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","enum":["all"],"description":"Every shipping rate, express included"}},"required":["type"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","enum":["titles"],"description":"The rates whose title is one of `titles`, ignoring case"},"titles":{"type":"array","items":{"type":"string","minLength":1},"minItems":1,"description":"Rate titles as checkout shows them"}},"required":["type","titles"],"additionalProperties":false}],"description":"Which rates are free"},"charges":{"type":"string","enum":["first","every"],"description":"Which shipments are free: `every` charge (a subscription's renewals too) or the `first` only"},"claimedValueCents":{"type":"integer","minimum":0,"description":"The shipping value the page claims for the free shipment (\"a $6.99 value\"); never charged"},"renewalChargeCents":{"type":"integer","minimum":0,"description":"On a subscription option free on the first charge only: what each renewal's shipping charges. Required there, refused elsewhere"}},"required":["type","rates","charges"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","enum":["charged"],"description":"Shipping is charged at checkout's rates"},"expectedChargeCents":{"type":"integer","minimum":0,"description":"What the forecast assumes a shipment charges, in cents; 0 for none"}},"required":["type","expectedChargeCents"],"additionalProperties":false}],"description":"What the option promises about shipping"},"mechanisms":{"type":"array","items":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","enum":["managed_discount"],"description":"Our app discount prices the lines, from the option map publish writes; works on subscription lines"},"lineRoles":{"type":"array","items":{"type":"string","enum":["main","add_on","gift"],"description":"What a line is in its option: `main` is what the buyer pays for, `add_on` an extra the buyer opts into or is always added, `gift` a real product the discount function prices to zero"},"minItems":1,"description":"The roles of the option's lines this mechanism prices"},"discount":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","enum":["percent"],"description":"A percentage off"},"percent":{"type":"number","minimum":0,"maximum":100,"description":"The percentage off, 0 to 100"}},"required":["type","percent"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","enum":["fixed_amount"],"description":"A fixed amount off"},"amountCents":{"type":"integer","minimum":0,"description":"The amount off, in cents"},"per":{"type":"string","enum":["line","unit"],"description":"Off each line, or off each unit of the line"}},"required":["type","amountCents","per"],"additionalProperties":false}],"description":"How much comes off"},"charges":{"type":"string","enum":["first","every"],"description":"Which charges it prices: `first` the first order only; `every` the first order and every renewal of a subscription line"}},"required":["type","lineRoles","discount","charges"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","enum":["discount_code"],"description":"A Shopify discount code publish creates, applied to the cart the API builds"},"code":{"type":"string","minLength":1,"description":"The code live on Shopify, once publish created it; the cart the API builds applies it"},"purchaseType":{"type":"string","enum":["one_time","subscription","subscription_first_payment_only"],"description":"Which purchases the code prices: one-time lines once, every charge of a subscription line, or a subscription's first order only"},"discount":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","enum":["percent"],"description":"A percentage off"},"percent":{"type":"number","minimum":0,"maximum":100,"description":"The percentage off, 0 to 100"}},"required":["type","percent"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","enum":["fixed_amount"],"description":"A fixed amount off"},"amountCents":{"type":"integer","minimum":0,"description":"The amount off, in cents"}},"required":["type","amountCents"],"additionalProperties":false}],"description":"How much comes off"},"lineRoles":{"type":"array","items":{"type":"string","enum":["main","add_on","gift"],"description":"What a line is in its option: `main` is what the buyer pays for, `add_on` an extra the buyer opts into or is always added, `gift` a real product the discount function prices to zero"},"minItems":1,"description":"The roles of the option's lines this mechanism prices"}},"required":["type","purchaseType","discount","lineRoles"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","enum":["selling_plan_adjustment"],"description":"The selling plan's own price adjustments price the subscription lines on that plan"},"sellingPlanId":{"type":"string","pattern":"^gid:\\/\\/shopify\\/SellingPlan\\/\\d+$","description":"The selling plan, carried by a subscription line of the option"},"adjustments":{"type":"array","items":{"type":"object","properties":{"fromOrder":{"anyOf":[{"type":"integer","exclusiveMinimum":0},{"type":"string","enum":["after_last"]}],"description":"The order from which the adjustment is in effect: N from the Nth order on, until a later one takes over; \"after_last\" after every numbered one (alone, from the first order). Before the first, the catalog price"},"discount":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","enum":["percent"],"description":"A percentage off"},"percent":{"type":"number","minimum":0,"maximum":100,"description":"The percentage off, 0 to 100"}},"required":["type","percent"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","enum":["fixed_amount"],"description":"A fixed amount off"},"amountCents":{"type":"integer","minimum":0,"description":"The amount off, in cents"}},"required":["type","amountCents"],"additionalProperties":false}],"description":"How much the plan takes off the variant's price, per unit"}},"required":["fromOrder","discount"],"additionalProperties":false},"minItems":1,"description":"The plan's price adjustments as Shopify holds them, at most two"}},"required":["type","sellingPlanId","adjustments"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","enum":["catalog_price"],"description":"The variant's catalog price is already the offer price; nothing is discounted"}},"required":["type"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","enum":["existing_automatic_discount"],"description":"An automatic discount the store already runs; we only describe it"},"lineRoles":{"type":"array","items":{"type":"string","enum":["main","add_on","gift"],"description":"What a line is in its option: `main` is what the buyer pays for, `add_on` an extra the buyer opts into or is always added, `gift` a real product the discount function prices to zero"},"minItems":1,"description":"The roles of the option's lines this mechanism prices"},"discount":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","enum":["percent"],"description":"A percentage off"},"percent":{"type":"number","minimum":0,"maximum":100,"description":"The percentage off, 0 to 100"}},"required":["type","percent"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","enum":["fixed_amount"],"description":"A fixed amount off"},"amountCents":{"type":"integer","minimum":0,"description":"The amount off, in cents"}},"required":["type","amountCents"],"additionalProperties":false}],"description":"How much comes off"},"charges":{"type":"string","enum":["first","every"],"description":"Which charges it prices: `first` the first order only; `every` the first order and every renewal of a subscription line"}},"required":["type","lineRoles","discount","charges"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","enum":["unit_price_tiers"],"description":"A category group's first-order unit price by how many units of it the cart holds; our app discount charges it, and the group's selling plans price the renewals"},"lineKey":{"type":"string","maxLength":64,"pattern":"^[a-z0-9][a-z0-9_-]*$","description":"The group: an optional, non-gift line bound to a pool, which a cart opts into by this key"},"tiers":{"type":"array","items":{"type":"object","properties":{"fromUnits":{"type":"integer","exclusiveMinimum":0,"description":"The fewest units of the group this tier's price applies to; the first tier is 1"},"unitCents":{"type":"integer","minimum":0,"description":"What each unit of the group charges on the first order at this tier, in cents"}},"required":["fromUnits","unitCents"],"additionalProperties":false},"minItems":1,"description":"The tiers, ascending from 1; above the last tier the last price holds"}},"required":["type","lineKey","tiers"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","enum":["line_price"],"description":"Our cart transform sets the lines' unit price as their own price, at or below each line's catalog price (never above: a raise is refused): shown as the product's price, with no saving at checkout. One-time lines only, on any store with our cart transform registered: `lineUpdate` on Shopify Plus, the line expanded into itself on every other plan"},"lineKeys":{"type":"array","items":{"type":"string","maxLength":64,"pattern":"^[a-z0-9][a-z0-9_-]*$","description":"A key the brand authors: lower-case letters, digits, `_` and `-`"},"minItems":1,"description":"The one-time lines priced, by key"},"unitCents":{"type":"integer","minimum":0,"description":"What each unit of those lines charges on the first order, in cents"}},"required":["type","lineKeys","unitCents"],"additionalProperties":false}]},"description":"How the promise is made real on Shopify; at most one product discount per line and charge"}},"required":["promise","compareAtPrice","shipping","mechanisms"],"additionalProperties":false,"description":"What the option promises and how Shopify charges it"},"prices":{"type":"object","properties":{"first":{"type":"object","properties":{"totalCents":{"type":"integer","minimum":0,"description":"What these lines charge on this charge, before shipping and tax: the sum of the lines' `netCents`"},"lines":{"type":"array","items":{"type":"object","properties":{"lineIndex":{"type":"integer","minimum":0,"description":"The line's index in the option's `lines`"},"key":{"type":"string","maxLength":64,"pattern":"^[a-z0-9][a-z0-9_-]*$","description":"Names the line inside its option; required on an optional non-gift line, which a cart opts into by this key (`addOnLineKeys`)"},"role":{"type":"string","enum":["main","add_on","gift"],"description":"What a line is in its option: `main` is what the buyer pays for, `add_on` an extra the buyer opts into or is always added, `gift` a real product the discount function prices to zero"},"variantId":{"type":"string","pattern":"^gid:\\/\\/shopify\\/ProductVariant\\/\\d+$","description":"The variant this cart line holds; a pool-bound line becomes one cart line per distinct variant chosen"},"quantity":{"type":"integer","exclusiveMinimum":0,"description":"Units on this cart line"},"sellingPlanId":{"type":"string","pattern":"^gid:\\/\\/shopify\\/SellingPlan\\/\\d+$","description":"The selling plan the cart line is bought on, for a subscription line"},"unitCents":{"type":"integer","minimum":0,"description":"One unit before any product discount: the catalog price with the selling plan's adjustment in effect on this charge"},"grossCents":{"type":"integer","minimum":0,"description":"`unitCents` × `quantity`"},"discountCents":{"type":"integer","minimum":0,"description":"What the one product discount takes off the line on this charge (all of it on a gift); 0 when nothing does"},"discountBy":{"type":["string","null"],"enum":["managed_discount","discount_code","existing_automatic_discount","unit_price_tiers","bundle_price","gift",null],"description":"The mechanism that takes `discountCents` off (`unit_price_tiers`: a category group's first-charge price for its units; `bundle_price`: a bundle's percentage off from our cart transform, which checkout shows as the bundle's price, not as a saving), `gift` when the discount function zeroes a gift, null when nothing does"},"netCents":{"type":"integer","minimum":0,"description":"What the line charges on this charge: `grossCents` less `discountCents`. Show this; never compute it"}},"required":["lineIndex","role","variantId","quantity","unitCents","grossCents","discountCents","discountBy","netCents"],"additionalProperties":false},"description":"Each cart line with its price on this charge"}},"required":["totalCents","lines"],"additionalProperties":false,"description":"The first order"},"renewal":{"type":["object","null"],"properties":{"totalCents":{"type":"integer","minimum":0,"description":"What these lines charge on this charge, before shipping and tax: the sum of the lines' `netCents`"},"lines":{"type":"array","items":{"type":"object","properties":{"lineIndex":{"type":"integer","minimum":0,"description":"The line's index in the option's `lines`"},"key":{"type":"string","maxLength":64,"pattern":"^[a-z0-9][a-z0-9_-]*$","description":"Names the line inside its option; required on an optional non-gift line, which a cart opts into by this key (`addOnLineKeys`)"},"role":{"type":"string","enum":["main","add_on","gift"],"description":"What a line is in its option: `main` is what the buyer pays for, `add_on` an extra the buyer opts into or is always added, `gift` a real product the discount function prices to zero"},"variantId":{"type":"string","pattern":"^gid:\\/\\/shopify\\/ProductVariant\\/\\d+$","description":"The variant this cart line holds; a pool-bound line becomes one cart line per distinct variant chosen"},"quantity":{"type":"integer","exclusiveMinimum":0,"description":"Units on this cart line"},"sellingPlanId":{"type":"string","pattern":"^gid:\\/\\/shopify\\/SellingPlan\\/\\d+$","description":"The selling plan the cart line is bought on, for a subscription line"},"unitCents":{"type":"integer","minimum":0,"description":"One unit before any product discount: the catalog price with the selling plan's adjustment in effect on this charge"},"grossCents":{"type":"integer","minimum":0,"description":"`unitCents` × `quantity`"},"discountCents":{"type":"integer","minimum":0,"description":"What the one product discount takes off the line on this charge (all of it on a gift); 0 when nothing does"},"discountBy":{"type":["string","null"],"enum":["managed_discount","discount_code","existing_automatic_discount","unit_price_tiers","bundle_price","gift",null],"description":"The mechanism that takes `discountCents` off (`unit_price_tiers`: a category group's first-charge price for its units; `bundle_price`: a bundle's percentage off from our cart transform, which checkout shows as the bundle's price, not as a saving), `gift` when the discount function zeroes a gift, null when nothing does"},"netCents":{"type":"integer","minimum":0,"description":"What the line charges on this charge: `grossCents` less `discountCents`. Show this; never compute it"}},"required":["lineIndex","role","variantId","quantity","unitCents","grossCents","discountCents","discountBy","netCents"],"additionalProperties":false},"description":"Each cart line with its price on this charge"}},"required":["totalCents","lines"],"additionalProperties":false,"description":"Every renewal, once the selling plan's last adjustment is in effect: only the lines that renew; null when none does"},"addOns":{"type":"array","items":{"type":"object","properties":{"first":{"type":"object","properties":{"totalCents":{"type":"integer","minimum":0,"description":"What these lines charge on this charge, before shipping and tax: the sum of the lines' `netCents`"},"lines":{"type":"array","items":{"type":"object","properties":{"lineIndex":{"type":"integer","minimum":0,"description":"The line's index in the option's `lines`"},"key":{"type":"string","maxLength":64,"pattern":"^[a-z0-9][a-z0-9_-]*$","description":"Names the line inside its option; required on an optional non-gift line, which a cart opts into by this key (`addOnLineKeys`)"},"role":{"type":"string","enum":["main","add_on","gift"],"description":"What a line is in its option: `main` is what the buyer pays for, `add_on` an extra the buyer opts into or is always added, `gift` a real product the discount function prices to zero"},"variantId":{"type":"string","pattern":"^gid:\\/\\/shopify\\/ProductVariant\\/\\d+$","description":"The variant this cart line holds; a pool-bound line becomes one cart line per distinct variant chosen"},"quantity":{"type":"integer","exclusiveMinimum":0,"description":"Units on this cart line"},"sellingPlanId":{"type":"string","pattern":"^gid:\\/\\/shopify\\/SellingPlan\\/\\d+$","description":"The selling plan the cart line is bought on, for a subscription line"},"unitCents":{"type":"integer","minimum":0,"description":"One unit before any product discount: the catalog price with the selling plan's adjustment in effect on this charge"},"grossCents":{"type":"integer","minimum":0,"description":"`unitCents` × `quantity`"},"discountCents":{"type":"integer","minimum":0,"description":"What the one product discount takes off the line on this charge (all of it on a gift); 0 when nothing does"},"discountBy":{"type":["string","null"],"enum":["managed_discount","discount_code","existing_automatic_discount","unit_price_tiers","bundle_price","gift",null],"description":"The mechanism that takes `discountCents` off (`unit_price_tiers`: a category group's first-charge price for its units; `bundle_price`: a bundle's percentage off from our cart transform, which checkout shows as the bundle's price, not as a saving), `gift` when the discount function zeroes a gift, null when nothing does"},"netCents":{"type":"integer","minimum":0,"description":"What the line charges on this charge: `grossCents` less `discountCents`. Show this; never compute it"}},"required":["lineIndex","role","variantId","quantity","unitCents","grossCents","discountCents","discountBy","netCents"],"additionalProperties":false},"description":"Each cart line with its price on this charge"}},"required":["totalCents","lines"],"additionalProperties":false,"description":"The first order"},"renewal":{"type":["object","null"],"properties":{"totalCents":{"type":"integer","minimum":0,"description":"What these lines charge on this charge, before shipping and tax: the sum of the lines' `netCents`"},"lines":{"type":"array","items":{"type":"object","properties":{"lineIndex":{"type":"integer","minimum":0,"description":"The line's index in the option's `lines`"},"key":{"type":"string","maxLength":64,"pattern":"^[a-z0-9][a-z0-9_-]*$","description":"Names the line inside its option; required on an optional non-gift line, which a cart opts into by this key (`addOnLineKeys`)"},"role":{"type":"string","enum":["main","add_on","gift"],"description":"What a line is in its option: `main` is what the buyer pays for, `add_on` an extra the buyer opts into or is always added, `gift` a real product the discount function prices to zero"},"variantId":{"type":"string","pattern":"^gid:\\/\\/shopify\\/ProductVariant\\/\\d+$","description":"The variant this cart line holds; a pool-bound line becomes one cart line per distinct variant chosen"},"quantity":{"type":"integer","exclusiveMinimum":0,"description":"Units on this cart line"},"sellingPlanId":{"type":"string","pattern":"^gid:\\/\\/shopify\\/SellingPlan\\/\\d+$","description":"The selling plan the cart line is bought on, for a subscription line"},"unitCents":{"type":"integer","minimum":0,"description":"One unit before any product discount: the catalog price with the selling plan's adjustment in effect on this charge"},"grossCents":{"type":"integer","minimum":0,"description":"`unitCents` × `quantity`"},"discountCents":{"type":"integer","minimum":0,"description":"What the one product discount takes off the line on this charge (all of it on a gift); 0 when nothing does"},"discountBy":{"type":["string","null"],"enum":["managed_discount","discount_code","existing_automatic_discount","unit_price_tiers","bundle_price","gift",null],"description":"The mechanism that takes `discountCents` off (`unit_price_tiers`: a category group's first-charge price for its units; `bundle_price`: a bundle's percentage off from our cart transform, which checkout shows as the bundle's price, not as a saving), `gift` when the discount function zeroes a gift, null when nothing does"},"netCents":{"type":"integer","minimum":0,"description":"What the line charges on this charge: `grossCents` less `discountCents`. Show this; never compute it"}},"required":["lineIndex","role","variantId","quantity","unitCents","grossCents","discountCents","discountBy","netCents"],"additionalProperties":false},"description":"Each cart line with its price on this charge"}},"required":["totalCents","lines"],"additionalProperties":false,"description":"Every renewal, once the selling plan's last adjustment is in effect: only the lines that renew; null when none does"},"lineKey":{"type":"string","maxLength":64,"pattern":"^[a-z0-9][a-z0-9_-]*$","description":"The add-on's line key, as `Selection.addOnLineKeys` names it"}},"required":["first","renewal","lineKey"],"additionalProperties":false},"description":"Each optional add-on's cart lines priced on their own. Cart lines are priced one by one, so an option with add-ons opted into charges `first.totalCents` plus each add-on's `first.totalCents` (and the same for renewals)"}},"required":["first","renewal","addOns"],"additionalProperties":false,"description":"What this option charges, computed by the line pricing the verifier proves on real carts (OS-303): the cart the option builds with nothing chosen (each pool at its first variants, no add-on), and each add-on. A buy box renders these numbers and never prices a line itself; for other pool picks, ask `POST /offers/{id}/price`"},"presentations":{"type":"array","items":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","enum":["line_override"],"description":"One line shown with another title or image. It exists only on the cart line: the order keeps the product's real title. Shopify Plus only, except on a line with a line price, where it rides in the line expanded into itself on any plan"},"lineKey":{"type":"string","maxLength":64,"pattern":"^[a-z0-9][a-z0-9_-]*$","description":"The one-time line shown differently"},"title":{"type":"string","minLength":1,"maxLength":255,"description":"What the cart and checkout show as the line's title; the order keeps the product's own title"},"imageUrl":{"type":"string","pattern":"^https:\\/\\/cdn\\.shopify\\.com\\/\\S+$","description":"What the cart and checkout show as the line's image; never kept on the order"}},"required":["type","lineKey"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","enum":["merged_bundle"],"description":"Several lines merged into one titled parent line in the cart and at checkout; on the order, the lines are a bundle group under the parent's title. A merged bundle has no stock of its own"},"lineKeys":{"type":"array","items":{"type":"string","maxLength":64,"pattern":"^[a-z0-9][a-z0-9_-]*$","description":"A key the brand authors: lower-case letters, digits, `_` and `-`"},"minItems":1,"description":"The required one-time lines merged into the parent, each at its own quantity"},"parentVariantId":{"type":"string","pattern":"^gid:\\/\\/shopify\\/ProductVariant\\/\\d+$","description":"The variant the parent line shows as: a bundle product whose variant requires components, so it can never be bought on its own"},"title":{"type":"string","minLength":1,"maxLength":255,"description":"What the cart and checkout show as the line's title; the order keeps the product's own title"},"imageUrl":{"type":"string","pattern":"^https:\\/\\/cdn\\.shopify\\.com\\/\\S+$","description":"What the cart and checkout show as the line's image; never kept on the order"},"attributes":{"type":"array","items":{"type":"object","properties":{"key":{"type":"string","minLength":1,"description":"The attribute's key"},"value":{"type":"string","description":"The attribute's value"}},"required":["key","value"],"additionalProperties":false},"description":"Attributes Shopify puts on the order's bundle group (not in the order webhook)"},"price":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","enum":["percent_off"],"description":"The bundle costs its lines' catalog price less a percentage, shown as the bundle's own price with no saving at checkout"},"percent":{"type":"number","minimum":0,"maximum":100,"description":"The percentage off, 0 to 100"}},"required":["type","percent"],"additionalProperties":false}],"description":"The bundle's price from our cart transform; absent, each line keeps its own price and our discount prices the parent"}},"required":["type","lineKeys","parentVariantId"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","enum":["expanded_bundle"],"description":"One line expanded into components in the cart and at checkout; on the order, the components are a bundle group under the line's title. The line's variant is the parent"},"lineKey":{"type":"string","maxLength":64,"pattern":"^[a-z0-9][a-z0-9_-]*$","description":"The one-time line expanded"},"components":{"type":"array","items":{"type":"object","properties":{"variantId":{"type":"string","pattern":"^gid:\\/\\/shopify\\/ProductVariant\\/\\d+$","description":"A variant that ships inside each unit of the line"},"quantity":{"type":"integer","exclusiveMinimum":0,"description":"Units of the component in each unit of the line"},"unitCents":{"type":"integer","minimum":0,"description":"The component's own price per unit, in cents; set on every component or on none. A gift that ships inside the bundle is a component at 0"},"role":{"type":"string","enum":["main","add_on","gift"],"description":"What the component is on the order, for costing: `main`, `add_on` or `gift`; the expanded line's own role when absent"}},"required":["variantId","quantity"],"additionalProperties":false},"minItems":1,"maxItems":150,"description":"What each unit of the line ships as, at most 150 components (Shopify's limit)"},"title":{"type":"string","minLength":1,"maxLength":255,"description":"What the cart and checkout show as the line's title; the order keeps the product's own title"},"imageUrl":{"type":"string","pattern":"^https:\\/\\/cdn\\.shopify\\.com\\/\\S+$","description":"What the cart and checkout show as the line's image; never kept on the order"},"price":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","enum":["percent_off"],"description":"The bundle costs its lines' catalog price less a percentage, shown as the bundle's own price with no saving at checkout"},"percent":{"type":"number","minimum":0,"maximum":100,"description":"The percentage off, 0 to 100"}},"required":["type","percent"],"additionalProperties":false}],"description":"A percentage off the line's catalog price; refused beside component prices. Absent with no component prices, the line keeps its price and our discount can price it"}},"required":["type","lineKey","components"],"additionalProperties":false}]},"description":"How our cart transform presents the option's one-time lines in the cart and at checkout: line overrides, merged bundles and expanded bundles. Each needs the store's capability for it (`GET /stores/{id}` `capability`); a line appears in one presentation at most"},"checkoutMode":{"type":"string","enum":["cart_page","cart_drawer","direct_to_checkout","landing_cart","external"],"description":"Where the brand's page sends the buyer after the choice: the cart page, a cart drawer, straight to checkout, a cart on the landing page, or an external flow"},"landingPageUrl":{"type":"string","minLength":1,"description":"The page that renders this option; publish checks the page shows it (`page_bind`)"},"verification":{"type":"object","properties":{"status":{"type":"string","enum":["matched","mismatched","unverifiable","unverified"],"description":"Whether a real cart charges what the option promises: `matched`; `mismatched` when a check failed or Shopify refused the cart; `unverifiable` when a check of the promise could not run; `unverified` when never checked (a hidden option). An option goes live only when `matched`"},"checkedAt":{"type":["string","null"],"format":"date-time","description":"When the verifier last ran on this option, or null"}},"required":["status","checkedAt"],"additionalProperties":false,"description":"Whether publish found a real cart charges the promise, and when"}},"required":["key","display","visible","axisValues","unitCount","cardKey","lines","pricing","prices","checkoutMode","verification"],"additionalProperties":false},"minItems":1,"description":"Everything a buyer can choose, one resolved option per combination"},"valueClaims":{"type":"array","items":{"type":"object","properties":{"title":{"type":"string","minLength":1,"description":"The claim as the page words it"},"claimedValueCents":{"type":"integer","minimum":0,"description":"The value claimed, in cents; absent when the page states none"}},"required":["title"],"additionalProperties":false},"description":"Value claims the page makes (bonuses, prizes); never enter a cart"},"terms":{"type":"object","properties":{"guaranteeDays":{"type":"integer","exclusiveMinimum":0,"description":"The money-back guarantee the page states, in days"}},"additionalProperties":false,"description":"Terms the page states"},"catalog":{"type":"object","additionalProperties":{"type":"object","properties":{"productId":{"type":["string","null"],"pattern":"^gid:\\/\\/shopify\\/Product\\/\\d+$","description":"The product's gid; null when Shopify no longer has the variant"},"productTitle":{"type":["string","null"],"description":"The product's title in Shopify"},"variantTitle":{"type":["string","null"],"description":"The variant's title in Shopify (`Default Title` on a product with one variant)"},"image":{"type":["object","null"],"properties":{"url":{"type":"string","format":"uri","description":"Shopify's CDN URL of the image"},"altText":{"type":["string","null"],"description":"The image's alt text in Shopify"},"width":{"type":["integer","null"],"description":"Width in pixels"},"height":{"type":["integer","null"],"description":"Height in pixels"}},"required":["url","altText","width","height"],"additionalProperties":false,"description":"The variant's own first image, else the product's featured image; null when neither exists"},"description":{"type":["string","null"],"description":"A plain-text excerpt of the product's description (at most 300 characters, cut at a word)"},"status":{"type":"string","enum":["active","draft","archived","deleted"],"description":"`active` is for sale; `draft` or `archived` is a product taken off sale in Shopify; `deleted` is a variant Shopify no longer has. Show a line whose variant is not `active` as unavailable"}},"required":["productId","productTitle","variantTitle","image","description","status"],"additionalProperties":false,"description":"What Shopify says about one variant"},"description":"What Shopify says about every variant the offer can put in a cart, keyed by variant gid (the ids in `lines[].variantSource` and `pools`): titles, image, a description excerpt and whether it is still for sale. Read from Shopify at publish, on every product change Shopify sends, and daily, and served as soon as it changes; a variant not read yet is absent. Render product content from here, with no Storefront call of your own"}},"required":["id","code","version","status","store","tracking","axes","pools","defaultOptionKey","options","valueClaims","terms","catalog"],"additionalProperties":false,"description":"What this visitor is served now: render it, then build the cart with its `version`"}},"required":["error","offer"]}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}}}}},"/offers/{id}/cart-input":{"get":{"operationId":"getOfferCartInput","summary":"The Storefront CartInput for an option, unexecuted","description":"The exact `CartInput` the cart endpoint executes and the verifier proved: lines with selling plan ids and line properties, the `_os` pointer, the `_os_visitor` attribute and each line's `_os_role`, discount codes when the option uses them. For brands whose code calls `cartCreate` itself (decision 2). The shopper's choice goes as JSON in `selection` (the same `Selection` the cart route takes). Send `visitorId`: while the offer runs an experiment, the input is built from that visitor's arm, the version resolve served them. Send the rendered version as `shownVersion` too: a visitor now served another version gets `409 offer_changed` with the document to render instead.","tags":["Offers"],"security":[{"apiKey":[]}],"parameters":[{"schema":{"type":"string","format":"uuid","description":"The offer id"},"required":true,"description":"The offer id","name":"id","in":"path"},{"schema":{"type":"string","minLength":1,"description":"JSON of a `Selection`: `{\"optionKey\":\"…\",\"axisValues\":{},\"poolSelections\":{},\"addOnLineKeys\":[]}`; only `optionKey` is required"},"required":true,"description":"JSON of a `Selection`: `{\"optionKey\":\"…\",\"axisValues\":{},\"poolSelections\":{},\"addOnLineKeys\":[]}`; only `optionKey` is required","name":"selection","in":"query"},{"schema":{"type":"string","minLength":1,"maxLength":128,"description":"The visitor id, for experiment assignment and the `_os_visitor` attribute"},"required":false,"description":"The visitor id, for experiment assignment and the `_os_visitor` attribute","name":"visitorId","in":"query"},{"schema":{"type":"integer","exclusiveMinimum":0,"description":"The version the page rendered"},"required":false,"description":"The version the page rendered","name":"shownVersion","in":"query"},{"schema":{"type":"string","description":"JSON object of the brand's own cart attributes to keep; only `tracking.preservedCartAttributes` survive"},"required":false,"description":"JSON object of the brand's own cart attributes to keep; only `tracking.preservedCartAttributes` survive","name":"preservedCartAttributes","in":"query"}],"responses":{"200":{"description":"The cart input","content":{"application/json":{"schema":{"type":"object","properties":{"lines":{"type":"array","items":{"type":"object","properties":{"merchandiseId":{"type":"string"},"quantity":{"type":"integer","exclusiveMinimum":0},"sellingPlanId":{"type":"string"},"attributes":{"type":"array","items":{"type":"object","properties":{"key":{"type":"string"},"value":{"type":"string"}},"required":["key","value"]}}},"required":["merchandiseId","quantity","attributes"]}},"attributes":{"type":"array","items":{"type":"object","properties":{"key":{"type":"string"},"value":{"type":"string"}},"required":["key","value"]}},"discountCodes":{"type":"array","items":{"type":"string"}}},"required":["lines","attributes"]}}}},"400":{"description":"Unknown option, an invalid pool selection (`pool_selection_count_out_of_range`, `variant_not_in_pool`, `pool_selection_repeated`), an unknown add-on (`unknown_add_on`) or axis value","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}},"401":{"description":"Missing, unknown or revoked API key","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}},"404":{"description":"No live version, or the offer's store is not connected","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}},"409":{"description":"`offer_changed`: `shownVersion` is not the version this visitor is served now; `offer` is the one to render","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]},"offer":{"type":"object","properties":{"id":{"type":"string","format":"uuid","description":"The offer id"},"code":{"type":"string","maxLength":31,"pattern":"^[^,\\s](?:[^,]*[^,\\s])?$","description":"The offer's code: unique per tenant, immutable once created, and how an agent, `lookup_offer` and the order tag `os_offer:<code>` name the offer"},"version":{"type":"integer","exclusiveMinimum":0,"description":"The version served; send it back as the cart request's `shownVersion`"},"status":{"type":"string","enum":["draft","verified","live","retired"],"description":"`live`, or under `preview` the current version's status"},"store":{"type":"object","properties":{"myshopifyDomain":{"type":"string","minLength":1,"description":"The connected store's myshopify domain (`brand.myshopify.com`); publish and serving use this store"},"market":{"type":"object","properties":{"countryCode":{"type":"string","pattern":"^[A-Z]{2}$","description":"The buyer's country, ISO 3166-1 alpha-2; carts are priced in its market"},"currencyCode":{"type":"string","pattern":"^[A-Z]{3}$","description":"The market's currency, ISO 4217; every amount in the document is in it"}},"required":["countryCode","currencyCode"],"additionalProperties":false,"description":"The one market the offer is priced in"}},"required":["myshopifyDomain","market"],"additionalProperties":false,"description":"The connected store and the market the offer is priced in"},"tracking":{"type":"object","properties":{"experienceName":{"type":"string","minLength":1,"description":"A label for the page or funnel this offer runs in; the offers list shows it"},"campaignName":{"type":"string","minLength":1,"description":"A label for the marketing campaign this offer belongs to"},"presellPageName":{"type":["string","null"],"minLength":1,"description":"A label for the presell page in front of the offer, or null"},"preservedCartAttributes":{"type":"array","items":{"type":"string","minLength":1},"description":"The brand's own cart attribute names a cart request may set and the API keeps on the cart (`preservedCartAttributes` on the cart request)"}},"required":["experienceName","campaignName","presellPageName","preservedCartAttributes"],"additionalProperties":false,"description":"The labels reports group by, and the brand's own cart attributes a cart keeps"},"axes":{"type":"array","items":{"type":"object","properties":{"key":{"type":"string","maxLength":64,"pattern":"^[a-z0-9][a-z0-9_-]*$","description":"Names the axis; options and axis-mapped lines refer to it"},"values":{"type":"array","items":{"type":"string","minLength":1},"minItems":1,"description":"Every value the axis takes"}},"required":["key","values"],"additionalProperties":false},"description":"Dimensions the options vary along (flavour, size); they name and enumerate options, never patch one"},"pools":{"type":"array","items":{"type":"object","properties":{"key":{"type":"string","maxLength":64,"pattern":"^[a-z0-9][a-z0-9_-]*$","description":"Names the pool; a pool-bound line refers to it"},"variantIds":{"type":"array","items":{"type":"string","pattern":"^gid:\\/\\/shopify\\/ProductVariant\\/\\d+$","description":"A Shopify ProductVariant gid (`gid://shopify/ProductVariant/<id>`)"},"minItems":1,"description":"The pool's variants"},"allowRepeats":{"type":"boolean","description":"Whether one variant may be chosen more than once"}},"required":["key","variantIds","allowRepeats"],"additionalProperties":false},"description":"Pools a buyer chooses variants from, through a line bound to the pool"},"defaultOptionKey":{"type":"string","maxLength":64,"pattern":"^[a-z0-9][a-z0-9_-]*$","description":"The option a renderer preselects; must name a visible option"},"options":{"type":"array","items":{"type":"object","properties":{"key":{"type":"string","maxLength":30,"pattern":"^[a-z0-9][a-z0-9_-]*$","description":"Names the option: unique in the document, carried in the cart pointer, the order tag `os_option:<key>` (so at most 30 characters) and the economics. Keep it stable"},"display":{"type":"object","properties":{"title":{"type":"string","minLength":1,"description":"The option's name as a buyer reads it"}},"required":["title"],"additionalProperties":false,"description":"What a renderer shows for the option"},"visible":{"type":"boolean","description":"Whether a renderer may show the option and publish verifies it; a hidden option still resolves and builds carts"},"axisValues":{"type":"object","additionalProperties":{"type":"string"},"description":"The option's value on each document axis, by axis key"},"unitCount":{"type":"integer","exclusiveMinimum":0,"description":"The quantity the buyer perceives (\"4 units\"); not the sum of line quantities"},"cardKey":{"type":"string","maxLength":64,"pattern":"^[a-z0-9][a-z0-9_-]*$","description":"Options sharing a card key are drawn as one card (a subscribe and one-time pair of one product)"},"lines":{"type":"array","items":{"type":"object","properties":{"key":{"type":"string","maxLength":64,"pattern":"^[a-z0-9][a-z0-9_-]*$","description":"Names the line inside its option; required on an optional non-gift line, which a cart opts into by this key (`addOnLineKeys`)"},"role":{"type":"string","enum":["main","add_on","gift"],"description":"What a line is in its option: `main` is what the buyer pays for, `add_on` an extra the buyer opts into or is always added, `gift` a real product the discount function prices to zero"},"quantity":{"type":"integer","exclusiveMinimum":0,"description":"Units of the variant in the cart; on a pool-bound line, the fewest the buyer may choose"},"maxQuantity":{"type":"integer","exclusiveMinimum":0,"description":"A pool-bound line only: the most units the buyer may choose"},"required":{"type":"boolean","description":"Whether every cart for the option holds the line; an optional line is added only when the cart request names its key"},"variantSource":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","enum":["fixed"],"description":"The line is one named variant"},"productId":{"type":"string","pattern":"^gid:\\/\\/shopify\\/Product\\/\\d+$","description":"The variant's product"},"variantId":{"type":"string","pattern":"^gid:\\/\\/shopify\\/ProductVariant\\/\\d+$","description":"The variant the line puts in the cart"}},"required":["type","productId","variantId"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","enum":["axis_map"],"description":"The variant follows the option's axis values, through `variantIdByAxisValue`"},"productId":{"type":"string","pattern":"^gid:\\/\\/shopify\\/Product\\/\\d+$","description":"The product every mapped variant belongs to"},"axisKeys":{"type":"array","items":{"type":"string","maxLength":64,"pattern":"^[a-z0-9][a-z0-9_-]*$","description":"A key the brand authors: lower-case letters, digits, `_` and `-`"},"minItems":1,"description":"The document axes whose values choose the variant, in `variantIdByAxisValue`'s key order"},"variantIdByAxisValue":{"type":"object","additionalProperties":{"type":"string","pattern":"^gid:\\/\\/shopify\\/ProductVariant\\/\\d+$","description":"A Shopify ProductVariant gid (`gid://shopify/ProductVariant/<id>`)"},"description":"Variant id by axis value; for several `axisKeys`, keyed by the values joined with \"/\" in `axisKeys` order. Must cover exactly the declared values"}},"required":["type","productId","axisKeys","variantIdByAxisValue"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","enum":["pool"],"description":"The buyer chooses the variants from a pool: `quantity` units, up to `maxQuantity`, any mix of the pool's variants; the cart gets one line per distinct variant"},"poolKey":{"type":"string","maxLength":64,"pattern":"^[a-z0-9][a-z0-9_-]*$","description":"The `pools[].key` the buyer chooses from"}},"required":["type","poolKey"],"additionalProperties":false}],"description":"Where the line's variant comes from"},"purchase":{"type":"object","properties":{"type":{"type":"string","enum":["one_time","subscription"],"description":"Bought once, or on a selling plan"},"sellingPlanId":{"type":"string","pattern":"^gid:\\/\\/shopify\\/SellingPlan\\/\\d+$","description":"The selling plan a subscription line is bought on; required when `type` is `subscription`"},"intervalDays":{"type":"integer","exclusiveMinimum":0,"description":"Days between a subscription's charges, as shown to the buyer"},"plans":{"type":"array","items":{"type":"object","properties":{"fromUnits":{"type":"integer","exclusiveMinimum":0,"description":"The fewest units of the group this plan's tier applies to; the first tier is 1"},"intervalDays":{"type":"integer","exclusiveMinimum":0,"description":"The cadence this plan renews on, one of the option's `cadence` intervals"},"sellingPlanId":{"type":"string","pattern":"^gid:\\/\\/shopify\\/SellingPlan\\/\\d+$","description":"The selling plan the group's lines go on at this tier and cadence"}},"required":["fromUnits","intervalDays","sellingPlanId"],"additionalProperties":false},"minItems":1,"description":"A subscription group's plan for each tier and cadence a cart can reach; `sellingPlanId` is one of them"}},"required":["type"],"additionalProperties":false,"description":"How the line is bought: once, or on a selling plan"},"bundleComponents":{"type":"array","items":{"type":"object","properties":{"variantId":{"type":"string","pattern":"^gid:\\/\\/shopify\\/ProductVariant\\/\\d+$","description":"A component variant of the fixed bundle"},"quantity":{"type":"integer","exclusiveMinimum":0,"description":"Units of that component in one bundle"}},"required":["variantId","quantity"],"additionalProperties":false},"minItems":1,"description":"What one unit holds, when the variant is a Shopify fixed bundle"},"catalogPrice":{"type":"object","properties":{"amountCents":{"type":"integer","minimum":0,"description":"The variant's catalog price when the document was written; line pricing starts from it"},"compareAtAmountCents":{"type":["integer","null"],"minimum":0,"description":"The variant's catalog compare-at price then, or null"},"capturedAt":{"type":"string","format":"date-time","description":"When the price was read from the catalog"}},"required":["amountCents","compareAtAmountCents","capturedAt"],"additionalProperties":false,"description":"The catalog price line pricing starts from"},"claimedValueCents":{"type":"integer","minimum":0,"description":"On a gift line: the value the page shows for it, in cents; never charged"}},"required":["role","quantity","required","variantSource","purchase","catalogPrice"],"additionalProperties":false},"minItems":1,"description":"What the option puts in the cart"},"maxUnits":{"type":"integer","exclusiveMinimum":0,"description":"A category builder: the most units the option's non-gift lines may hold in all"},"cadence":{"type":"object","properties":{"tiers":{"type":"array","items":{"type":"object","properties":{"fromUnits":{"type":"integer","exclusiveMinimum":0,"description":"The fewest units of the largest subscription group this interval applies to; the first tier is 1"},"intervalDays":{"type":"integer","exclusiveMinimum":0,"description":"Days between charges of every subscription line"}},"required":["fromUnits","intervalDays"],"additionalProperties":false},"minItems":1,"description":"The tiers, ascending from 1; above the last tier the last interval holds"}},"required":["tiers"],"additionalProperties":false,"description":"A category builder: the one interval every subscription line renews on, by the units of the largest subscription group in the cart; required when a line has `purchase.plans`"},"pricing":{"type":"object","properties":{"promise":{"type":"object","properties":{"firstChargeCents":{"type":["integer","null"],"minimum":0,"description":"What the buyer is charged on the first order, before shipping and tax; required on a visible option. Publish checks a real cart charges it"},"renewalChargeCents":{"type":["integer","null"],"minimum":0,"description":"What each renewal charges, before shipping and tax; required when the option has a subscription line"}},"required":["firstChargeCents","renewalChargeCents"],"additionalProperties":false,"description":"What the option promises the buyer is charged"},"compareAtPrice":{"type":"object","properties":{"amountCents":{"type":"integer","minimum":0,"description":"The struck-through amount, in cents"},"source":{"type":"string","enum":["variant","selling_plan","unit_price_times_quantity","metafield","page_copy"],"description":"Where it comes from: the variant's compare-at price, the selling plan's compare-at price, the unit price times the quantity, a metafield, or page copy"}},"required":["amountCents","source"],"additionalProperties":false,"description":"The struck-through price the page shows beside the promise"},"shipping":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","enum":["free"],"description":"The discount function makes the named rates free for carts carrying this option"},"rates":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","enum":["cheapest"],"description":"The cheapest shipping rate in each delivery group"}},"required":["type"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","enum":["all"],"description":"Every shipping rate, express included"}},"required":["type"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","enum":["titles"],"description":"The rates whose title is one of `titles`, ignoring case"},"titles":{"type":"array","items":{"type":"string","minLength":1},"minItems":1,"description":"Rate titles as checkout shows them"}},"required":["type","titles"],"additionalProperties":false}],"description":"Which rates are free"},"charges":{"type":"string","enum":["first","every"],"description":"Which shipments are free: `every` charge (a subscription's renewals too) or the `first` only"},"claimedValueCents":{"type":"integer","minimum":0,"description":"The shipping value the page claims for the free shipment (\"a $6.99 value\"); never charged"},"renewalChargeCents":{"type":"integer","minimum":0,"description":"On a subscription option free on the first charge only: what each renewal's shipping charges. Required there, refused elsewhere"}},"required":["type","rates","charges"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","enum":["charged"],"description":"Shipping is charged at checkout's rates"},"expectedChargeCents":{"type":"integer","minimum":0,"description":"What the forecast assumes a shipment charges, in cents; 0 for none"}},"required":["type","expectedChargeCents"],"additionalProperties":false}],"description":"What the option promises about shipping"},"mechanisms":{"type":"array","items":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","enum":["managed_discount"],"description":"Our app discount prices the lines, from the option map publish writes; works on subscription lines"},"lineRoles":{"type":"array","items":{"type":"string","enum":["main","add_on","gift"],"description":"What a line is in its option: `main` is what the buyer pays for, `add_on` an extra the buyer opts into or is always added, `gift` a real product the discount function prices to zero"},"minItems":1,"description":"The roles of the option's lines this mechanism prices"},"discount":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","enum":["percent"],"description":"A percentage off"},"percent":{"type":"number","minimum":0,"maximum":100,"description":"The percentage off, 0 to 100"}},"required":["type","percent"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","enum":["fixed_amount"],"description":"A fixed amount off"},"amountCents":{"type":"integer","minimum":0,"description":"The amount off, in cents"},"per":{"type":"string","enum":["line","unit"],"description":"Off each line, or off each unit of the line"}},"required":["type","amountCents","per"],"additionalProperties":false}],"description":"How much comes off"},"charges":{"type":"string","enum":["first","every"],"description":"Which charges it prices: `first` the first order only; `every` the first order and every renewal of a subscription line"}},"required":["type","lineRoles","discount","charges"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","enum":["discount_code"],"description":"A Shopify discount code publish creates, applied to the cart the API builds"},"code":{"type":"string","minLength":1,"description":"The code live on Shopify, once publish created it; the cart the API builds applies it"},"purchaseType":{"type":"string","enum":["one_time","subscription","subscription_first_payment_only"],"description":"Which purchases the code prices: one-time lines once, every charge of a subscription line, or a subscription's first order only"},"discount":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","enum":["percent"],"description":"A percentage off"},"percent":{"type":"number","minimum":0,"maximum":100,"description":"The percentage off, 0 to 100"}},"required":["type","percent"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","enum":["fixed_amount"],"description":"A fixed amount off"},"amountCents":{"type":"integer","minimum":0,"description":"The amount off, in cents"}},"required":["type","amountCents"],"additionalProperties":false}],"description":"How much comes off"},"lineRoles":{"type":"array","items":{"type":"string","enum":["main","add_on","gift"],"description":"What a line is in its option: `main` is what the buyer pays for, `add_on` an extra the buyer opts into or is always added, `gift` a real product the discount function prices to zero"},"minItems":1,"description":"The roles of the option's lines this mechanism prices"}},"required":["type","purchaseType","discount","lineRoles"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","enum":["selling_plan_adjustment"],"description":"The selling plan's own price adjustments price the subscription lines on that plan"},"sellingPlanId":{"type":"string","pattern":"^gid:\\/\\/shopify\\/SellingPlan\\/\\d+$","description":"The selling plan, carried by a subscription line of the option"},"adjustments":{"type":"array","items":{"type":"object","properties":{"fromOrder":{"anyOf":[{"type":"integer","exclusiveMinimum":0},{"type":"string","enum":["after_last"]}],"description":"The order from which the adjustment is in effect: N from the Nth order on, until a later one takes over; \"after_last\" after every numbered one (alone, from the first order). Before the first, the catalog price"},"discount":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","enum":["percent"],"description":"A percentage off"},"percent":{"type":"number","minimum":0,"maximum":100,"description":"The percentage off, 0 to 100"}},"required":["type","percent"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","enum":["fixed_amount"],"description":"A fixed amount off"},"amountCents":{"type":"integer","minimum":0,"description":"The amount off, in cents"}},"required":["type","amountCents"],"additionalProperties":false}],"description":"How much the plan takes off the variant's price, per unit"}},"required":["fromOrder","discount"],"additionalProperties":false},"minItems":1,"description":"The plan's price adjustments as Shopify holds them, at most two"}},"required":["type","sellingPlanId","adjustments"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","enum":["catalog_price"],"description":"The variant's catalog price is already the offer price; nothing is discounted"}},"required":["type"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","enum":["existing_automatic_discount"],"description":"An automatic discount the store already runs; we only describe it"},"lineRoles":{"type":"array","items":{"type":"string","enum":["main","add_on","gift"],"description":"What a line is in its option: `main` is what the buyer pays for, `add_on` an extra the buyer opts into or is always added, `gift` a real product the discount function prices to zero"},"minItems":1,"description":"The roles of the option's lines this mechanism prices"},"discount":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","enum":["percent"],"description":"A percentage off"},"percent":{"type":"number","minimum":0,"maximum":100,"description":"The percentage off, 0 to 100"}},"required":["type","percent"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","enum":["fixed_amount"],"description":"A fixed amount off"},"amountCents":{"type":"integer","minimum":0,"description":"The amount off, in cents"}},"required":["type","amountCents"],"additionalProperties":false}],"description":"How much comes off"},"charges":{"type":"string","enum":["first","every"],"description":"Which charges it prices: `first` the first order only; `every` the first order and every renewal of a subscription line"}},"required":["type","lineRoles","discount","charges"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","enum":["unit_price_tiers"],"description":"A category group's first-order unit price by how many units of it the cart holds; our app discount charges it, and the group's selling plans price the renewals"},"lineKey":{"type":"string","maxLength":64,"pattern":"^[a-z0-9][a-z0-9_-]*$","description":"The group: an optional, non-gift line bound to a pool, which a cart opts into by this key"},"tiers":{"type":"array","items":{"type":"object","properties":{"fromUnits":{"type":"integer","exclusiveMinimum":0,"description":"The fewest units of the group this tier's price applies to; the first tier is 1"},"unitCents":{"type":"integer","minimum":0,"description":"What each unit of the group charges on the first order at this tier, in cents"}},"required":["fromUnits","unitCents"],"additionalProperties":false},"minItems":1,"description":"The tiers, ascending from 1; above the last tier the last price holds"}},"required":["type","lineKey","tiers"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","enum":["line_price"],"description":"Our cart transform sets the lines' unit price as their own price, at or below each line's catalog price (never above: a raise is refused): shown as the product's price, with no saving at checkout. One-time lines only, on any store with our cart transform registered: `lineUpdate` on Shopify Plus, the line expanded into itself on every other plan"},"lineKeys":{"type":"array","items":{"type":"string","maxLength":64,"pattern":"^[a-z0-9][a-z0-9_-]*$","description":"A key the brand authors: lower-case letters, digits, `_` and `-`"},"minItems":1,"description":"The one-time lines priced, by key"},"unitCents":{"type":"integer","minimum":0,"description":"What each unit of those lines charges on the first order, in cents"}},"required":["type","lineKeys","unitCents"],"additionalProperties":false}]},"description":"How the promise is made real on Shopify; at most one product discount per line and charge"}},"required":["promise","compareAtPrice","shipping","mechanisms"],"additionalProperties":false,"description":"What the option promises and how Shopify charges it"},"prices":{"type":"object","properties":{"first":{"type":"object","properties":{"totalCents":{"type":"integer","minimum":0,"description":"What these lines charge on this charge, before shipping and tax: the sum of the lines' `netCents`"},"lines":{"type":"array","items":{"type":"object","properties":{"lineIndex":{"type":"integer","minimum":0,"description":"The line's index in the option's `lines`"},"key":{"type":"string","maxLength":64,"pattern":"^[a-z0-9][a-z0-9_-]*$","description":"Names the line inside its option; required on an optional non-gift line, which a cart opts into by this key (`addOnLineKeys`)"},"role":{"type":"string","enum":["main","add_on","gift"],"description":"What a line is in its option: `main` is what the buyer pays for, `add_on` an extra the buyer opts into or is always added, `gift` a real product the discount function prices to zero"},"variantId":{"type":"string","pattern":"^gid:\\/\\/shopify\\/ProductVariant\\/\\d+$","description":"The variant this cart line holds; a pool-bound line becomes one cart line per distinct variant chosen"},"quantity":{"type":"integer","exclusiveMinimum":0,"description":"Units on this cart line"},"sellingPlanId":{"type":"string","pattern":"^gid:\\/\\/shopify\\/SellingPlan\\/\\d+$","description":"The selling plan the cart line is bought on, for a subscription line"},"unitCents":{"type":"integer","minimum":0,"description":"One unit before any product discount: the catalog price with the selling plan's adjustment in effect on this charge"},"grossCents":{"type":"integer","minimum":0,"description":"`unitCents` × `quantity`"},"discountCents":{"type":"integer","minimum":0,"description":"What the one product discount takes off the line on this charge (all of it on a gift); 0 when nothing does"},"discountBy":{"type":["string","null"],"enum":["managed_discount","discount_code","existing_automatic_discount","unit_price_tiers","bundle_price","gift",null],"description":"The mechanism that takes `discountCents` off (`unit_price_tiers`: a category group's first-charge price for its units; `bundle_price`: a bundle's percentage off from our cart transform, which checkout shows as the bundle's price, not as a saving), `gift` when the discount function zeroes a gift, null when nothing does"},"netCents":{"type":"integer","minimum":0,"description":"What the line charges on this charge: `grossCents` less `discountCents`. Show this; never compute it"}},"required":["lineIndex","role","variantId","quantity","unitCents","grossCents","discountCents","discountBy","netCents"],"additionalProperties":false},"description":"Each cart line with its price on this charge"}},"required":["totalCents","lines"],"additionalProperties":false,"description":"The first order"},"renewal":{"type":["object","null"],"properties":{"totalCents":{"type":"integer","minimum":0,"description":"What these lines charge on this charge, before shipping and tax: the sum of the lines' `netCents`"},"lines":{"type":"array","items":{"type":"object","properties":{"lineIndex":{"type":"integer","minimum":0,"description":"The line's index in the option's `lines`"},"key":{"type":"string","maxLength":64,"pattern":"^[a-z0-9][a-z0-9_-]*$","description":"Names the line inside its option; required on an optional non-gift line, which a cart opts into by this key (`addOnLineKeys`)"},"role":{"type":"string","enum":["main","add_on","gift"],"description":"What a line is in its option: `main` is what the buyer pays for, `add_on` an extra the buyer opts into or is always added, `gift` a real product the discount function prices to zero"},"variantId":{"type":"string","pattern":"^gid:\\/\\/shopify\\/ProductVariant\\/\\d+$","description":"The variant this cart line holds; a pool-bound line becomes one cart line per distinct variant chosen"},"quantity":{"type":"integer","exclusiveMinimum":0,"description":"Units on this cart line"},"sellingPlanId":{"type":"string","pattern":"^gid:\\/\\/shopify\\/SellingPlan\\/\\d+$","description":"The selling plan the cart line is bought on, for a subscription line"},"unitCents":{"type":"integer","minimum":0,"description":"One unit before any product discount: the catalog price with the selling plan's adjustment in effect on this charge"},"grossCents":{"type":"integer","minimum":0,"description":"`unitCents` × `quantity`"},"discountCents":{"type":"integer","minimum":0,"description":"What the one product discount takes off the line on this charge (all of it on a gift); 0 when nothing does"},"discountBy":{"type":["string","null"],"enum":["managed_discount","discount_code","existing_automatic_discount","unit_price_tiers","bundle_price","gift",null],"description":"The mechanism that takes `discountCents` off (`unit_price_tiers`: a category group's first-charge price for its units; `bundle_price`: a bundle's percentage off from our cart transform, which checkout shows as the bundle's price, not as a saving), `gift` when the discount function zeroes a gift, null when nothing does"},"netCents":{"type":"integer","minimum":0,"description":"What the line charges on this charge: `grossCents` less `discountCents`. Show this; never compute it"}},"required":["lineIndex","role","variantId","quantity","unitCents","grossCents","discountCents","discountBy","netCents"],"additionalProperties":false},"description":"Each cart line with its price on this charge"}},"required":["totalCents","lines"],"additionalProperties":false,"description":"Every renewal, once the selling plan's last adjustment is in effect: only the lines that renew; null when none does"},"addOns":{"type":"array","items":{"type":"object","properties":{"first":{"type":"object","properties":{"totalCents":{"type":"integer","minimum":0,"description":"What these lines charge on this charge, before shipping and tax: the sum of the lines' `netCents`"},"lines":{"type":"array","items":{"type":"object","properties":{"lineIndex":{"type":"integer","minimum":0,"description":"The line's index in the option's `lines`"},"key":{"type":"string","maxLength":64,"pattern":"^[a-z0-9][a-z0-9_-]*$","description":"Names the line inside its option; required on an optional non-gift line, which a cart opts into by this key (`addOnLineKeys`)"},"role":{"type":"string","enum":["main","add_on","gift"],"description":"What a line is in its option: `main` is what the buyer pays for, `add_on` an extra the buyer opts into or is always added, `gift` a real product the discount function prices to zero"},"variantId":{"type":"string","pattern":"^gid:\\/\\/shopify\\/ProductVariant\\/\\d+$","description":"The variant this cart line holds; a pool-bound line becomes one cart line per distinct variant chosen"},"quantity":{"type":"integer","exclusiveMinimum":0,"description":"Units on this cart line"},"sellingPlanId":{"type":"string","pattern":"^gid:\\/\\/shopify\\/SellingPlan\\/\\d+$","description":"The selling plan the cart line is bought on, for a subscription line"},"unitCents":{"type":"integer","minimum":0,"description":"One unit before any product discount: the catalog price with the selling plan's adjustment in effect on this charge"},"grossCents":{"type":"integer","minimum":0,"description":"`unitCents` × `quantity`"},"discountCents":{"type":"integer","minimum":0,"description":"What the one product discount takes off the line on this charge (all of it on a gift); 0 when nothing does"},"discountBy":{"type":["string","null"],"enum":["managed_discount","discount_code","existing_automatic_discount","unit_price_tiers","bundle_price","gift",null],"description":"The mechanism that takes `discountCents` off (`unit_price_tiers`: a category group's first-charge price for its units; `bundle_price`: a bundle's percentage off from our cart transform, which checkout shows as the bundle's price, not as a saving), `gift` when the discount function zeroes a gift, null when nothing does"},"netCents":{"type":"integer","minimum":0,"description":"What the line charges on this charge: `grossCents` less `discountCents`. Show this; never compute it"}},"required":["lineIndex","role","variantId","quantity","unitCents","grossCents","discountCents","discountBy","netCents"],"additionalProperties":false},"description":"Each cart line with its price on this charge"}},"required":["totalCents","lines"],"additionalProperties":false,"description":"The first order"},"renewal":{"type":["object","null"],"properties":{"totalCents":{"type":"integer","minimum":0,"description":"What these lines charge on this charge, before shipping and tax: the sum of the lines' `netCents`"},"lines":{"type":"array","items":{"type":"object","properties":{"lineIndex":{"type":"integer","minimum":0,"description":"The line's index in the option's `lines`"},"key":{"type":"string","maxLength":64,"pattern":"^[a-z0-9][a-z0-9_-]*$","description":"Names the line inside its option; required on an optional non-gift line, which a cart opts into by this key (`addOnLineKeys`)"},"role":{"type":"string","enum":["main","add_on","gift"],"description":"What a line is in its option: `main` is what the buyer pays for, `add_on` an extra the buyer opts into or is always added, `gift` a real product the discount function prices to zero"},"variantId":{"type":"string","pattern":"^gid:\\/\\/shopify\\/ProductVariant\\/\\d+$","description":"The variant this cart line holds; a pool-bound line becomes one cart line per distinct variant chosen"},"quantity":{"type":"integer","exclusiveMinimum":0,"description":"Units on this cart line"},"sellingPlanId":{"type":"string","pattern":"^gid:\\/\\/shopify\\/SellingPlan\\/\\d+$","description":"The selling plan the cart line is bought on, for a subscription line"},"unitCents":{"type":"integer","minimum":0,"description":"One unit before any product discount: the catalog price with the selling plan's adjustment in effect on this charge"},"grossCents":{"type":"integer","minimum":0,"description":"`unitCents` × `quantity`"},"discountCents":{"type":"integer","minimum":0,"description":"What the one product discount takes off the line on this charge (all of it on a gift); 0 when nothing does"},"discountBy":{"type":["string","null"],"enum":["managed_discount","discount_code","existing_automatic_discount","unit_price_tiers","bundle_price","gift",null],"description":"The mechanism that takes `discountCents` off (`unit_price_tiers`: a category group's first-charge price for its units; `bundle_price`: a bundle's percentage off from our cart transform, which checkout shows as the bundle's price, not as a saving), `gift` when the discount function zeroes a gift, null when nothing does"},"netCents":{"type":"integer","minimum":0,"description":"What the line charges on this charge: `grossCents` less `discountCents`. Show this; never compute it"}},"required":["lineIndex","role","variantId","quantity","unitCents","grossCents","discountCents","discountBy","netCents"],"additionalProperties":false},"description":"Each cart line with its price on this charge"}},"required":["totalCents","lines"],"additionalProperties":false,"description":"Every renewal, once the selling plan's last adjustment is in effect: only the lines that renew; null when none does"},"lineKey":{"type":"string","maxLength":64,"pattern":"^[a-z0-9][a-z0-9_-]*$","description":"The add-on's line key, as `Selection.addOnLineKeys` names it"}},"required":["first","renewal","lineKey"],"additionalProperties":false},"description":"Each optional add-on's cart lines priced on their own. Cart lines are priced one by one, so an option with add-ons opted into charges `first.totalCents` plus each add-on's `first.totalCents` (and the same for renewals)"}},"required":["first","renewal","addOns"],"additionalProperties":false,"description":"What this option charges, computed by the line pricing the verifier proves on real carts (OS-303): the cart the option builds with nothing chosen (each pool at its first variants, no add-on), and each add-on. A buy box renders these numbers and never prices a line itself; for other pool picks, ask `POST /offers/{id}/price`"},"presentations":{"type":"array","items":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","enum":["line_override"],"description":"One line shown with another title or image. It exists only on the cart line: the order keeps the product's real title. Shopify Plus only, except on a line with a line price, where it rides in the line expanded into itself on any plan"},"lineKey":{"type":"string","maxLength":64,"pattern":"^[a-z0-9][a-z0-9_-]*$","description":"The one-time line shown differently"},"title":{"type":"string","minLength":1,"maxLength":255,"description":"What the cart and checkout show as the line's title; the order keeps the product's own title"},"imageUrl":{"type":"string","pattern":"^https:\\/\\/cdn\\.shopify\\.com\\/\\S+$","description":"What the cart and checkout show as the line's image; never kept on the order"}},"required":["type","lineKey"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","enum":["merged_bundle"],"description":"Several lines merged into one titled parent line in the cart and at checkout; on the order, the lines are a bundle group under the parent's title. A merged bundle has no stock of its own"},"lineKeys":{"type":"array","items":{"type":"string","maxLength":64,"pattern":"^[a-z0-9][a-z0-9_-]*$","description":"A key the brand authors: lower-case letters, digits, `_` and `-`"},"minItems":1,"description":"The required one-time lines merged into the parent, each at its own quantity"},"parentVariantId":{"type":"string","pattern":"^gid:\\/\\/shopify\\/ProductVariant\\/\\d+$","description":"The variant the parent line shows as: a bundle product whose variant requires components, so it can never be bought on its own"},"title":{"type":"string","minLength":1,"maxLength":255,"description":"What the cart and checkout show as the line's title; the order keeps the product's own title"},"imageUrl":{"type":"string","pattern":"^https:\\/\\/cdn\\.shopify\\.com\\/\\S+$","description":"What the cart and checkout show as the line's image; never kept on the order"},"attributes":{"type":"array","items":{"type":"object","properties":{"key":{"type":"string","minLength":1,"description":"The attribute's key"},"value":{"type":"string","description":"The attribute's value"}},"required":["key","value"],"additionalProperties":false},"description":"Attributes Shopify puts on the order's bundle group (not in the order webhook)"},"price":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","enum":["percent_off"],"description":"The bundle costs its lines' catalog price less a percentage, shown as the bundle's own price with no saving at checkout"},"percent":{"type":"number","minimum":0,"maximum":100,"description":"The percentage off, 0 to 100"}},"required":["type","percent"],"additionalProperties":false}],"description":"The bundle's price from our cart transform; absent, each line keeps its own price and our discount prices the parent"}},"required":["type","lineKeys","parentVariantId"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","enum":["expanded_bundle"],"description":"One line expanded into components in the cart and at checkout; on the order, the components are a bundle group under the line's title. The line's variant is the parent"},"lineKey":{"type":"string","maxLength":64,"pattern":"^[a-z0-9][a-z0-9_-]*$","description":"The one-time line expanded"},"components":{"type":"array","items":{"type":"object","properties":{"variantId":{"type":"string","pattern":"^gid:\\/\\/shopify\\/ProductVariant\\/\\d+$","description":"A variant that ships inside each unit of the line"},"quantity":{"type":"integer","exclusiveMinimum":0,"description":"Units of the component in each unit of the line"},"unitCents":{"type":"integer","minimum":0,"description":"The component's own price per unit, in cents; set on every component or on none. A gift that ships inside the bundle is a component at 0"},"role":{"type":"string","enum":["main","add_on","gift"],"description":"What the component is on the order, for costing: `main`, `add_on` or `gift`; the expanded line's own role when absent"}},"required":["variantId","quantity"],"additionalProperties":false},"minItems":1,"maxItems":150,"description":"What each unit of the line ships as, at most 150 components (Shopify's limit)"},"title":{"type":"string","minLength":1,"maxLength":255,"description":"What the cart and checkout show as the line's title; the order keeps the product's own title"},"imageUrl":{"type":"string","pattern":"^https:\\/\\/cdn\\.shopify\\.com\\/\\S+$","description":"What the cart and checkout show as the line's image; never kept on the order"},"price":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","enum":["percent_off"],"description":"The bundle costs its lines' catalog price less a percentage, shown as the bundle's own price with no saving at checkout"},"percent":{"type":"number","minimum":0,"maximum":100,"description":"The percentage off, 0 to 100"}},"required":["type","percent"],"additionalProperties":false}],"description":"A percentage off the line's catalog price; refused beside component prices. Absent with no component prices, the line keeps its price and our discount can price it"}},"required":["type","lineKey","components"],"additionalProperties":false}]},"description":"How our cart transform presents the option's one-time lines in the cart and at checkout: line overrides, merged bundles and expanded bundles. Each needs the store's capability for it (`GET /stores/{id}` `capability`); a line appears in one presentation at most"},"checkoutMode":{"type":"string","enum":["cart_page","cart_drawer","direct_to_checkout","landing_cart","external"],"description":"Where the brand's page sends the buyer after the choice: the cart page, a cart drawer, straight to checkout, a cart on the landing page, or an external flow"},"landingPageUrl":{"type":"string","minLength":1,"description":"The page that renders this option; publish checks the page shows it (`page_bind`)"},"verification":{"type":"object","properties":{"status":{"type":"string","enum":["matched","mismatched","unverifiable","unverified"],"description":"Whether a real cart charges what the option promises: `matched`; `mismatched` when a check failed or Shopify refused the cart; `unverifiable` when a check of the promise could not run; `unverified` when never checked (a hidden option). An option goes live only when `matched`"},"checkedAt":{"type":["string","null"],"format":"date-time","description":"When the verifier last ran on this option, or null"}},"required":["status","checkedAt"],"additionalProperties":false,"description":"Whether publish found a real cart charges the promise, and when"}},"required":["key","display","visible","axisValues","unitCount","cardKey","lines","pricing","prices","checkoutMode","verification"],"additionalProperties":false},"minItems":1,"description":"Everything a buyer can choose, one resolved option per combination"},"valueClaims":{"type":"array","items":{"type":"object","properties":{"title":{"type":"string","minLength":1,"description":"The claim as the page words it"},"claimedValueCents":{"type":"integer","minimum":0,"description":"The value claimed, in cents; absent when the page states none"}},"required":["title"],"additionalProperties":false},"description":"Value claims the page makes (bonuses, prizes); never enter a cart"},"terms":{"type":"object","properties":{"guaranteeDays":{"type":"integer","exclusiveMinimum":0,"description":"The money-back guarantee the page states, in days"}},"additionalProperties":false,"description":"Terms the page states"},"catalog":{"type":"object","additionalProperties":{"type":"object","properties":{"productId":{"type":["string","null"],"pattern":"^gid:\\/\\/shopify\\/Product\\/\\d+$","description":"The product's gid; null when Shopify no longer has the variant"},"productTitle":{"type":["string","null"],"description":"The product's title in Shopify"},"variantTitle":{"type":["string","null"],"description":"The variant's title in Shopify (`Default Title` on a product with one variant)"},"image":{"type":["object","null"],"properties":{"url":{"type":"string","format":"uri","description":"Shopify's CDN URL of the image"},"altText":{"type":["string","null"],"description":"The image's alt text in Shopify"},"width":{"type":["integer","null"],"description":"Width in pixels"},"height":{"type":["integer","null"],"description":"Height in pixels"}},"required":["url","altText","width","height"],"additionalProperties":false,"description":"The variant's own first image, else the product's featured image; null when neither exists"},"description":{"type":["string","null"],"description":"A plain-text excerpt of the product's description (at most 300 characters, cut at a word)"},"status":{"type":"string","enum":["active","draft","archived","deleted"],"description":"`active` is for sale; `draft` or `archived` is a product taken off sale in Shopify; `deleted` is a variant Shopify no longer has. Show a line whose variant is not `active` as unavailable"}},"required":["productId","productTitle","variantTitle","image","description","status"],"additionalProperties":false,"description":"What Shopify says about one variant"},"description":"What Shopify says about every variant the offer can put in a cart, keyed by variant gid (the ids in `lines[].variantSource` and `pools`): titles, image, a description excerpt and whether it is still for sale. Read from Shopify at publish, on every product change Shopify sends, and daily, and served as soon as it changes; a variant not read yet is absent. Render product content from here, with no Storefront call of your own"}},"required":["id","code","version","status","store","tracking","axes","pools","defaultOptionKey","options","valueClaims","terms","catalog"],"additionalProperties":false,"description":"What this visitor is served now: render it, then build the cart with its `version`"}},"required":["error","offer"]}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}}}}},"/offers/{id}/cart":{"post":{"operationId":"createOfferCart","summary":"Build the Storefront cart for an option and return its checkout URL","description":"Executes the same `CartInput` the cart-input route returns against the store's Storefront API in the document's market and returns the cart id and `checkoutUrl`. The default cart path (decision 2). The body is the shopper's `Selection` plus `visitorId`, `shownVersion` and `preservedCartAttributes`. With `visitorId`, the cart is built from that visitor's experiment arm while one runs, so it checks out at the price they were shown. With `shownVersion` (the version resolve returned and the page rendered), a visitor now served another version gets `409 offer_changed` with the document to render, never a cart at a price they were not shown. Call it from the visitor's own request so Shopify sees their address (`CF-Connecting-IP`) and can tell buyers apart; a server calling for its visitor uses a secret key and sends the visitor's address in `Offer-Suite-Buyer-IP`. On `storefront_throttled` (429) Shopify refused the Storefront call: wait the seconds in `Retry-After` and send the same request again; a store under sustained traffic can instead build the cart in the browser from `GET /offers/{id}/cart-input`. `warnings` is Shopify's own report that it changed this cart instead of refusing it (a line out of stock, a code it would not honour). The cart is real and `checkoutUrl` works, but the buyer may not be getting the option as published: show the message or send the visitor back to the offer rather than to checkout, and re-verify the offer (`POST /offers/{id}/verify`) if it keeps happening.","tags":["Offers"],"security":[{"apiKey":[]}],"parameters":[{"schema":{"type":"string","format":"uuid","description":"The offer id"},"required":true,"description":"The offer id","name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"optionKey":{"type":"string","maxLength":64,"pattern":"^[a-z0-9][a-z0-9_-]*$","description":"The option chosen"},"axisValues":{"type":"object","additionalProperties":{"type":"string","minLength":1},"default":{},"description":"Axis key → value, for an axis-mapped line whose variant follows the shopper's choice"},"poolSelections":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string","pattern":"^gid:\\/\\/shopify\\/ProductVariant\\/\\d+$","description":"A Shopify ProductVariant gid (`gid://shopify/ProductVariant/<id>`)"},"minItems":1},"default":{},"description":"Pool key → the variants chosen from it; a variant listed twice is two units"},"addOnLineKeys":{"type":"array","items":{"type":"string","maxLength":64,"pattern":"^[a-z0-9][a-z0-9_-]*$","description":"A key the brand authors: lower-case letters, digits, `_` and `-`"},"default":[],"description":"The optional add-on lines the shopper opted into, by line key"},"preservedCartAttributes":{"type":"object","additionalProperties":{"type":"string"},"description":"The brand's own cart attributes to keep on the cart; only the document's `tracking.preservedCartAttributes` survive"},"visitorId":{"type":"string","minLength":1,"maxLength":128,"description":"The visitor id (`v_…`): the cart is built from the version this visitor is served, and it rides on the cart as `_os_visitor`"},"shownVersion":{"type":"integer","exclusiveMinimum":0,"description":"The version the page rendered (`version` from resolve). If the visitor is served another version now, the cart is refused with `409 offer_changed` and the current document; without it the cart is built from whatever version the visitor is served"}},"required":["optionKey"],"additionalProperties":false}}}},"responses":{"201":{"description":"The cart","content":{"application/json":{"schema":{"type":"object","properties":{"offerId":{"type":"string","format":"uuid"},"version":{"type":"integer","exclusiveMinimum":0,"description":"The version the cart was built from: the one this visitor is served, live or their experiment arm"},"optionKey":{"type":"string"},"cartId":{"type":"string"},"checkoutUrl":{"type":"string","format":"uri"},"totalAmount":{"type":"string"},"currencyCode":{"type":"string"},"warnings":{"type":"array","items":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"target":{"type":"string"}},"required":["code","message","target"]},"description":"Present only when Shopify changed the cart it built: its own `CartWarning`s, each with the id of the cart object it is about"}},"required":["offerId","version","optionKey","cartId","checkoutUrl","totalAmount","currencyCode"]}}}},"400":{"description":"Unknown option, an invalid pool selection (`pool_selection_count_out_of_range`, `variant_not_in_pool`, `pool_selection_repeated`), an unknown add-on (`unknown_add_on`) or axis value","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}},"401":{"description":"Missing, unknown or revoked API key","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}},"404":{"description":"No live version, or the offer's store is not connected","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}},"409":{"description":"`offer_changed`: `shownVersion` is not the version this visitor is served now; `offer` is the one to render","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]},"offer":{"type":"object","properties":{"id":{"type":"string","format":"uuid","description":"The offer id"},"code":{"type":"string","maxLength":31,"pattern":"^[^,\\s](?:[^,]*[^,\\s])?$","description":"The offer's code: unique per tenant, immutable once created, and how an agent, `lookup_offer` and the order tag `os_offer:<code>` name the offer"},"version":{"type":"integer","exclusiveMinimum":0,"description":"The version served; send it back as the cart request's `shownVersion`"},"status":{"type":"string","enum":["draft","verified","live","retired"],"description":"`live`, or under `preview` the current version's status"},"store":{"type":"object","properties":{"myshopifyDomain":{"type":"string","minLength":1,"description":"The connected store's myshopify domain (`brand.myshopify.com`); publish and serving use this store"},"market":{"type":"object","properties":{"countryCode":{"type":"string","pattern":"^[A-Z]{2}$","description":"The buyer's country, ISO 3166-1 alpha-2; carts are priced in its market"},"currencyCode":{"type":"string","pattern":"^[A-Z]{3}$","description":"The market's currency, ISO 4217; every amount in the document is in it"}},"required":["countryCode","currencyCode"],"additionalProperties":false,"description":"The one market the offer is priced in"}},"required":["myshopifyDomain","market"],"additionalProperties":false,"description":"The connected store and the market the offer is priced in"},"tracking":{"type":"object","properties":{"experienceName":{"type":"string","minLength":1,"description":"A label for the page or funnel this offer runs in; the offers list shows it"},"campaignName":{"type":"string","minLength":1,"description":"A label for the marketing campaign this offer belongs to"},"presellPageName":{"type":["string","null"],"minLength":1,"description":"A label for the presell page in front of the offer, or null"},"preservedCartAttributes":{"type":"array","items":{"type":"string","minLength":1},"description":"The brand's own cart attribute names a cart request may set and the API keeps on the cart (`preservedCartAttributes` on the cart request)"}},"required":["experienceName","campaignName","presellPageName","preservedCartAttributes"],"additionalProperties":false,"description":"The labels reports group by, and the brand's own cart attributes a cart keeps"},"axes":{"type":"array","items":{"type":"object","properties":{"key":{"type":"string","maxLength":64,"pattern":"^[a-z0-9][a-z0-9_-]*$","description":"Names the axis; options and axis-mapped lines refer to it"},"values":{"type":"array","items":{"type":"string","minLength":1},"minItems":1,"description":"Every value the axis takes"}},"required":["key","values"],"additionalProperties":false},"description":"Dimensions the options vary along (flavour, size); they name and enumerate options, never patch one"},"pools":{"type":"array","items":{"type":"object","properties":{"key":{"type":"string","maxLength":64,"pattern":"^[a-z0-9][a-z0-9_-]*$","description":"Names the pool; a pool-bound line refers to it"},"variantIds":{"type":"array","items":{"type":"string","pattern":"^gid:\\/\\/shopify\\/ProductVariant\\/\\d+$","description":"A Shopify ProductVariant gid (`gid://shopify/ProductVariant/<id>`)"},"minItems":1,"description":"The pool's variants"},"allowRepeats":{"type":"boolean","description":"Whether one variant may be chosen more than once"}},"required":["key","variantIds","allowRepeats"],"additionalProperties":false},"description":"Pools a buyer chooses variants from, through a line bound to the pool"},"defaultOptionKey":{"type":"string","maxLength":64,"pattern":"^[a-z0-9][a-z0-9_-]*$","description":"The option a renderer preselects; must name a visible option"},"options":{"type":"array","items":{"type":"object","properties":{"key":{"type":"string","maxLength":30,"pattern":"^[a-z0-9][a-z0-9_-]*$","description":"Names the option: unique in the document, carried in the cart pointer, the order tag `os_option:<key>` (so at most 30 characters) and the economics. Keep it stable"},"display":{"type":"object","properties":{"title":{"type":"string","minLength":1,"description":"The option's name as a buyer reads it"}},"required":["title"],"additionalProperties":false,"description":"What a renderer shows for the option"},"visible":{"type":"boolean","description":"Whether a renderer may show the option and publish verifies it; a hidden option still resolves and builds carts"},"axisValues":{"type":"object","additionalProperties":{"type":"string"},"description":"The option's value on each document axis, by axis key"},"unitCount":{"type":"integer","exclusiveMinimum":0,"description":"The quantity the buyer perceives (\"4 units\"); not the sum of line quantities"},"cardKey":{"type":"string","maxLength":64,"pattern":"^[a-z0-9][a-z0-9_-]*$","description":"Options sharing a card key are drawn as one card (a subscribe and one-time pair of one product)"},"lines":{"type":"array","items":{"type":"object","properties":{"key":{"type":"string","maxLength":64,"pattern":"^[a-z0-9][a-z0-9_-]*$","description":"Names the line inside its option; required on an optional non-gift line, which a cart opts into by this key (`addOnLineKeys`)"},"role":{"type":"string","enum":["main","add_on","gift"],"description":"What a line is in its option: `main` is what the buyer pays for, `add_on` an extra the buyer opts into or is always added, `gift` a real product the discount function prices to zero"},"quantity":{"type":"integer","exclusiveMinimum":0,"description":"Units of the variant in the cart; on a pool-bound line, the fewest the buyer may choose"},"maxQuantity":{"type":"integer","exclusiveMinimum":0,"description":"A pool-bound line only: the most units the buyer may choose"},"required":{"type":"boolean","description":"Whether every cart for the option holds the line; an optional line is added only when the cart request names its key"},"variantSource":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","enum":["fixed"],"description":"The line is one named variant"},"productId":{"type":"string","pattern":"^gid:\\/\\/shopify\\/Product\\/\\d+$","description":"The variant's product"},"variantId":{"type":"string","pattern":"^gid:\\/\\/shopify\\/ProductVariant\\/\\d+$","description":"The variant the line puts in the cart"}},"required":["type","productId","variantId"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","enum":["axis_map"],"description":"The variant follows the option's axis values, through `variantIdByAxisValue`"},"productId":{"type":"string","pattern":"^gid:\\/\\/shopify\\/Product\\/\\d+$","description":"The product every mapped variant belongs to"},"axisKeys":{"type":"array","items":{"type":"string","maxLength":64,"pattern":"^[a-z0-9][a-z0-9_-]*$","description":"A key the brand authors: lower-case letters, digits, `_` and `-`"},"minItems":1,"description":"The document axes whose values choose the variant, in `variantIdByAxisValue`'s key order"},"variantIdByAxisValue":{"type":"object","additionalProperties":{"type":"string","pattern":"^gid:\\/\\/shopify\\/ProductVariant\\/\\d+$","description":"A Shopify ProductVariant gid (`gid://shopify/ProductVariant/<id>`)"},"description":"Variant id by axis value; for several `axisKeys`, keyed by the values joined with \"/\" in `axisKeys` order. Must cover exactly the declared values"}},"required":["type","productId","axisKeys","variantIdByAxisValue"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","enum":["pool"],"description":"The buyer chooses the variants from a pool: `quantity` units, up to `maxQuantity`, any mix of the pool's variants; the cart gets one line per distinct variant"},"poolKey":{"type":"string","maxLength":64,"pattern":"^[a-z0-9][a-z0-9_-]*$","description":"The `pools[].key` the buyer chooses from"}},"required":["type","poolKey"],"additionalProperties":false}],"description":"Where the line's variant comes from"},"purchase":{"type":"object","properties":{"type":{"type":"string","enum":["one_time","subscription"],"description":"Bought once, or on a selling plan"},"sellingPlanId":{"type":"string","pattern":"^gid:\\/\\/shopify\\/SellingPlan\\/\\d+$","description":"The selling plan a subscription line is bought on; required when `type` is `subscription`"},"intervalDays":{"type":"integer","exclusiveMinimum":0,"description":"Days between a subscription's charges, as shown to the buyer"},"plans":{"type":"array","items":{"type":"object","properties":{"fromUnits":{"type":"integer","exclusiveMinimum":0,"description":"The fewest units of the group this plan's tier applies to; the first tier is 1"},"intervalDays":{"type":"integer","exclusiveMinimum":0,"description":"The cadence this plan renews on, one of the option's `cadence` intervals"},"sellingPlanId":{"type":"string","pattern":"^gid:\\/\\/shopify\\/SellingPlan\\/\\d+$","description":"The selling plan the group's lines go on at this tier and cadence"}},"required":["fromUnits","intervalDays","sellingPlanId"],"additionalProperties":false},"minItems":1,"description":"A subscription group's plan for each tier and cadence a cart can reach; `sellingPlanId` is one of them"}},"required":["type"],"additionalProperties":false,"description":"How the line is bought: once, or on a selling plan"},"bundleComponents":{"type":"array","items":{"type":"object","properties":{"variantId":{"type":"string","pattern":"^gid:\\/\\/shopify\\/ProductVariant\\/\\d+$","description":"A component variant of the fixed bundle"},"quantity":{"type":"integer","exclusiveMinimum":0,"description":"Units of that component in one bundle"}},"required":["variantId","quantity"],"additionalProperties":false},"minItems":1,"description":"What one unit holds, when the variant is a Shopify fixed bundle"},"catalogPrice":{"type":"object","properties":{"amountCents":{"type":"integer","minimum":0,"description":"The variant's catalog price when the document was written; line pricing starts from it"},"compareAtAmountCents":{"type":["integer","null"],"minimum":0,"description":"The variant's catalog compare-at price then, or null"},"capturedAt":{"type":"string","format":"date-time","description":"When the price was read from the catalog"}},"required":["amountCents","compareAtAmountCents","capturedAt"],"additionalProperties":false,"description":"The catalog price line pricing starts from"},"claimedValueCents":{"type":"integer","minimum":0,"description":"On a gift line: the value the page shows for it, in cents; never charged"}},"required":["role","quantity","required","variantSource","purchase","catalogPrice"],"additionalProperties":false},"minItems":1,"description":"What the option puts in the cart"},"maxUnits":{"type":"integer","exclusiveMinimum":0,"description":"A category builder: the most units the option's non-gift lines may hold in all"},"cadence":{"type":"object","properties":{"tiers":{"type":"array","items":{"type":"object","properties":{"fromUnits":{"type":"integer","exclusiveMinimum":0,"description":"The fewest units of the largest subscription group this interval applies to; the first tier is 1"},"intervalDays":{"type":"integer","exclusiveMinimum":0,"description":"Days between charges of every subscription line"}},"required":["fromUnits","intervalDays"],"additionalProperties":false},"minItems":1,"description":"The tiers, ascending from 1; above the last tier the last interval holds"}},"required":["tiers"],"additionalProperties":false,"description":"A category builder: the one interval every subscription line renews on, by the units of the largest subscription group in the cart; required when a line has `purchase.plans`"},"pricing":{"type":"object","properties":{"promise":{"type":"object","properties":{"firstChargeCents":{"type":["integer","null"],"minimum":0,"description":"What the buyer is charged on the first order, before shipping and tax; required on a visible option. Publish checks a real cart charges it"},"renewalChargeCents":{"type":["integer","null"],"minimum":0,"description":"What each renewal charges, before shipping and tax; required when the option has a subscription line"}},"required":["firstChargeCents","renewalChargeCents"],"additionalProperties":false,"description":"What the option promises the buyer is charged"},"compareAtPrice":{"type":"object","properties":{"amountCents":{"type":"integer","minimum":0,"description":"The struck-through amount, in cents"},"source":{"type":"string","enum":["variant","selling_plan","unit_price_times_quantity","metafield","page_copy"],"description":"Where it comes from: the variant's compare-at price, the selling plan's compare-at price, the unit price times the quantity, a metafield, or page copy"}},"required":["amountCents","source"],"additionalProperties":false,"description":"The struck-through price the page shows beside the promise"},"shipping":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","enum":["free"],"description":"The discount function makes the named rates free for carts carrying this option"},"rates":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","enum":["cheapest"],"description":"The cheapest shipping rate in each delivery group"}},"required":["type"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","enum":["all"],"description":"Every shipping rate, express included"}},"required":["type"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","enum":["titles"],"description":"The rates whose title is one of `titles`, ignoring case"},"titles":{"type":"array","items":{"type":"string","minLength":1},"minItems":1,"description":"Rate titles as checkout shows them"}},"required":["type","titles"],"additionalProperties":false}],"description":"Which rates are free"},"charges":{"type":"string","enum":["first","every"],"description":"Which shipments are free: `every` charge (a subscription's renewals too) or the `first` only"},"claimedValueCents":{"type":"integer","minimum":0,"description":"The shipping value the page claims for the free shipment (\"a $6.99 value\"); never charged"},"renewalChargeCents":{"type":"integer","minimum":0,"description":"On a subscription option free on the first charge only: what each renewal's shipping charges. Required there, refused elsewhere"}},"required":["type","rates","charges"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","enum":["charged"],"description":"Shipping is charged at checkout's rates"},"expectedChargeCents":{"type":"integer","minimum":0,"description":"What the forecast assumes a shipment charges, in cents; 0 for none"}},"required":["type","expectedChargeCents"],"additionalProperties":false}],"description":"What the option promises about shipping"},"mechanisms":{"type":"array","items":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","enum":["managed_discount"],"description":"Our app discount prices the lines, from the option map publish writes; works on subscription lines"},"lineRoles":{"type":"array","items":{"type":"string","enum":["main","add_on","gift"],"description":"What a line is in its option: `main` is what the buyer pays for, `add_on` an extra the buyer opts into or is always added, `gift` a real product the discount function prices to zero"},"minItems":1,"description":"The roles of the option's lines this mechanism prices"},"discount":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","enum":["percent"],"description":"A percentage off"},"percent":{"type":"number","minimum":0,"maximum":100,"description":"The percentage off, 0 to 100"}},"required":["type","percent"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","enum":["fixed_amount"],"description":"A fixed amount off"},"amountCents":{"type":"integer","minimum":0,"description":"The amount off, in cents"},"per":{"type":"string","enum":["line","unit"],"description":"Off each line, or off each unit of the line"}},"required":["type","amountCents","per"],"additionalProperties":false}],"description":"How much comes off"},"charges":{"type":"string","enum":["first","every"],"description":"Which charges it prices: `first` the first order only; `every` the first order and every renewal of a subscription line"}},"required":["type","lineRoles","discount","charges"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","enum":["discount_code"],"description":"A Shopify discount code publish creates, applied to the cart the API builds"},"code":{"type":"string","minLength":1,"description":"The code live on Shopify, once publish created it; the cart the API builds applies it"},"purchaseType":{"type":"string","enum":["one_time","subscription","subscription_first_payment_only"],"description":"Which purchases the code prices: one-time lines once, every charge of a subscription line, or a subscription's first order only"},"discount":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","enum":["percent"],"description":"A percentage off"},"percent":{"type":"number","minimum":0,"maximum":100,"description":"The percentage off, 0 to 100"}},"required":["type","percent"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","enum":["fixed_amount"],"description":"A fixed amount off"},"amountCents":{"type":"integer","minimum":0,"description":"The amount off, in cents"}},"required":["type","amountCents"],"additionalProperties":false}],"description":"How much comes off"},"lineRoles":{"type":"array","items":{"type":"string","enum":["main","add_on","gift"],"description":"What a line is in its option: `main` is what the buyer pays for, `add_on` an extra the buyer opts into or is always added, `gift` a real product the discount function prices to zero"},"minItems":1,"description":"The roles of the option's lines this mechanism prices"}},"required":["type","purchaseType","discount","lineRoles"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","enum":["selling_plan_adjustment"],"description":"The selling plan's own price adjustments price the subscription lines on that plan"},"sellingPlanId":{"type":"string","pattern":"^gid:\\/\\/shopify\\/SellingPlan\\/\\d+$","description":"The selling plan, carried by a subscription line of the option"},"adjustments":{"type":"array","items":{"type":"object","properties":{"fromOrder":{"anyOf":[{"type":"integer","exclusiveMinimum":0},{"type":"string","enum":["after_last"]}],"description":"The order from which the adjustment is in effect: N from the Nth order on, until a later one takes over; \"after_last\" after every numbered one (alone, from the first order). Before the first, the catalog price"},"discount":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","enum":["percent"],"description":"A percentage off"},"percent":{"type":"number","minimum":0,"maximum":100,"description":"The percentage off, 0 to 100"}},"required":["type","percent"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","enum":["fixed_amount"],"description":"A fixed amount off"},"amountCents":{"type":"integer","minimum":0,"description":"The amount off, in cents"}},"required":["type","amountCents"],"additionalProperties":false}],"description":"How much the plan takes off the variant's price, per unit"}},"required":["fromOrder","discount"],"additionalProperties":false},"minItems":1,"description":"The plan's price adjustments as Shopify holds them, at most two"}},"required":["type","sellingPlanId","adjustments"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","enum":["catalog_price"],"description":"The variant's catalog price is already the offer price; nothing is discounted"}},"required":["type"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","enum":["existing_automatic_discount"],"description":"An automatic discount the store already runs; we only describe it"},"lineRoles":{"type":"array","items":{"type":"string","enum":["main","add_on","gift"],"description":"What a line is in its option: `main` is what the buyer pays for, `add_on` an extra the buyer opts into or is always added, `gift` a real product the discount function prices to zero"},"minItems":1,"description":"The roles of the option's lines this mechanism prices"},"discount":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","enum":["percent"],"description":"A percentage off"},"percent":{"type":"number","minimum":0,"maximum":100,"description":"The percentage off, 0 to 100"}},"required":["type","percent"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","enum":["fixed_amount"],"description":"A fixed amount off"},"amountCents":{"type":"integer","minimum":0,"description":"The amount off, in cents"}},"required":["type","amountCents"],"additionalProperties":false}],"description":"How much comes off"},"charges":{"type":"string","enum":["first","every"],"description":"Which charges it prices: `first` the first order only; `every` the first order and every renewal of a subscription line"}},"required":["type","lineRoles","discount","charges"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","enum":["unit_price_tiers"],"description":"A category group's first-order unit price by how many units of it the cart holds; our app discount charges it, and the group's selling plans price the renewals"},"lineKey":{"type":"string","maxLength":64,"pattern":"^[a-z0-9][a-z0-9_-]*$","description":"The group: an optional, non-gift line bound to a pool, which a cart opts into by this key"},"tiers":{"type":"array","items":{"type":"object","properties":{"fromUnits":{"type":"integer","exclusiveMinimum":0,"description":"The fewest units of the group this tier's price applies to; the first tier is 1"},"unitCents":{"type":"integer","minimum":0,"description":"What each unit of the group charges on the first order at this tier, in cents"}},"required":["fromUnits","unitCents"],"additionalProperties":false},"minItems":1,"description":"The tiers, ascending from 1; above the last tier the last price holds"}},"required":["type","lineKey","tiers"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","enum":["line_price"],"description":"Our cart transform sets the lines' unit price as their own price, at or below each line's catalog price (never above: a raise is refused): shown as the product's price, with no saving at checkout. One-time lines only, on any store with our cart transform registered: `lineUpdate` on Shopify Plus, the line expanded into itself on every other plan"},"lineKeys":{"type":"array","items":{"type":"string","maxLength":64,"pattern":"^[a-z0-9][a-z0-9_-]*$","description":"A key the brand authors: lower-case letters, digits, `_` and `-`"},"minItems":1,"description":"The one-time lines priced, by key"},"unitCents":{"type":"integer","minimum":0,"description":"What each unit of those lines charges on the first order, in cents"}},"required":["type","lineKeys","unitCents"],"additionalProperties":false}]},"description":"How the promise is made real on Shopify; at most one product discount per line and charge"}},"required":["promise","compareAtPrice","shipping","mechanisms"],"additionalProperties":false,"description":"What the option promises and how Shopify charges it"},"prices":{"type":"object","properties":{"first":{"type":"object","properties":{"totalCents":{"type":"integer","minimum":0,"description":"What these lines charge on this charge, before shipping and tax: the sum of the lines' `netCents`"},"lines":{"type":"array","items":{"type":"object","properties":{"lineIndex":{"type":"integer","minimum":0,"description":"The line's index in the option's `lines`"},"key":{"type":"string","maxLength":64,"pattern":"^[a-z0-9][a-z0-9_-]*$","description":"Names the line inside its option; required on an optional non-gift line, which a cart opts into by this key (`addOnLineKeys`)"},"role":{"type":"string","enum":["main","add_on","gift"],"description":"What a line is in its option: `main` is what the buyer pays for, `add_on` an extra the buyer opts into or is always added, `gift` a real product the discount function prices to zero"},"variantId":{"type":"string","pattern":"^gid:\\/\\/shopify\\/ProductVariant\\/\\d+$","description":"The variant this cart line holds; a pool-bound line becomes one cart line per distinct variant chosen"},"quantity":{"type":"integer","exclusiveMinimum":0,"description":"Units on this cart line"},"sellingPlanId":{"type":"string","pattern":"^gid:\\/\\/shopify\\/SellingPlan\\/\\d+$","description":"The selling plan the cart line is bought on, for a subscription line"},"unitCents":{"type":"integer","minimum":0,"description":"One unit before any product discount: the catalog price with the selling plan's adjustment in effect on this charge"},"grossCents":{"type":"integer","minimum":0,"description":"`unitCents` × `quantity`"},"discountCents":{"type":"integer","minimum":0,"description":"What the one product discount takes off the line on this charge (all of it on a gift); 0 when nothing does"},"discountBy":{"type":["string","null"],"enum":["managed_discount","discount_code","existing_automatic_discount","unit_price_tiers","bundle_price","gift",null],"description":"The mechanism that takes `discountCents` off (`unit_price_tiers`: a category group's first-charge price for its units; `bundle_price`: a bundle's percentage off from our cart transform, which checkout shows as the bundle's price, not as a saving), `gift` when the discount function zeroes a gift, null when nothing does"},"netCents":{"type":"integer","minimum":0,"description":"What the line charges on this charge: `grossCents` less `discountCents`. Show this; never compute it"}},"required":["lineIndex","role","variantId","quantity","unitCents","grossCents","discountCents","discountBy","netCents"],"additionalProperties":false},"description":"Each cart line with its price on this charge"}},"required":["totalCents","lines"],"additionalProperties":false,"description":"The first order"},"renewal":{"type":["object","null"],"properties":{"totalCents":{"type":"integer","minimum":0,"description":"What these lines charge on this charge, before shipping and tax: the sum of the lines' `netCents`"},"lines":{"type":"array","items":{"type":"object","properties":{"lineIndex":{"type":"integer","minimum":0,"description":"The line's index in the option's `lines`"},"key":{"type":"string","maxLength":64,"pattern":"^[a-z0-9][a-z0-9_-]*$","description":"Names the line inside its option; required on an optional non-gift line, which a cart opts into by this key (`addOnLineKeys`)"},"role":{"type":"string","enum":["main","add_on","gift"],"description":"What a line is in its option: `main` is what the buyer pays for, `add_on` an extra the buyer opts into or is always added, `gift` a real product the discount function prices to zero"},"variantId":{"type":"string","pattern":"^gid:\\/\\/shopify\\/ProductVariant\\/\\d+$","description":"The variant this cart line holds; a pool-bound line becomes one cart line per distinct variant chosen"},"quantity":{"type":"integer","exclusiveMinimum":0,"description":"Units on this cart line"},"sellingPlanId":{"type":"string","pattern":"^gid:\\/\\/shopify\\/SellingPlan\\/\\d+$","description":"The selling plan the cart line is bought on, for a subscription line"},"unitCents":{"type":"integer","minimum":0,"description":"One unit before any product discount: the catalog price with the selling plan's adjustment in effect on this charge"},"grossCents":{"type":"integer","minimum":0,"description":"`unitCents` × `quantity`"},"discountCents":{"type":"integer","minimum":0,"description":"What the one product discount takes off the line on this charge (all of it on a gift); 0 when nothing does"},"discountBy":{"type":["string","null"],"enum":["managed_discount","discount_code","existing_automatic_discount","unit_price_tiers","bundle_price","gift",null],"description":"The mechanism that takes `discountCents` off (`unit_price_tiers`: a category group's first-charge price for its units; `bundle_price`: a bundle's percentage off from our cart transform, which checkout shows as the bundle's price, not as a saving), `gift` when the discount function zeroes a gift, null when nothing does"},"netCents":{"type":"integer","minimum":0,"description":"What the line charges on this charge: `grossCents` less `discountCents`. Show this; never compute it"}},"required":["lineIndex","role","variantId","quantity","unitCents","grossCents","discountCents","discountBy","netCents"],"additionalProperties":false},"description":"Each cart line with its price on this charge"}},"required":["totalCents","lines"],"additionalProperties":false,"description":"Every renewal, once the selling plan's last adjustment is in effect: only the lines that renew; null when none does"},"addOns":{"type":"array","items":{"type":"object","properties":{"first":{"type":"object","properties":{"totalCents":{"type":"integer","minimum":0,"description":"What these lines charge on this charge, before shipping and tax: the sum of the lines' `netCents`"},"lines":{"type":"array","items":{"type":"object","properties":{"lineIndex":{"type":"integer","minimum":0,"description":"The line's index in the option's `lines`"},"key":{"type":"string","maxLength":64,"pattern":"^[a-z0-9][a-z0-9_-]*$","description":"Names the line inside its option; required on an optional non-gift line, which a cart opts into by this key (`addOnLineKeys`)"},"role":{"type":"string","enum":["main","add_on","gift"],"description":"What a line is in its option: `main` is what the buyer pays for, `add_on` an extra the buyer opts into or is always added, `gift` a real product the discount function prices to zero"},"variantId":{"type":"string","pattern":"^gid:\\/\\/shopify\\/ProductVariant\\/\\d+$","description":"The variant this cart line holds; a pool-bound line becomes one cart line per distinct variant chosen"},"quantity":{"type":"integer","exclusiveMinimum":0,"description":"Units on this cart line"},"sellingPlanId":{"type":"string","pattern":"^gid:\\/\\/shopify\\/SellingPlan\\/\\d+$","description":"The selling plan the cart line is bought on, for a subscription line"},"unitCents":{"type":"integer","minimum":0,"description":"One unit before any product discount: the catalog price with the selling plan's adjustment in effect on this charge"},"grossCents":{"type":"integer","minimum":0,"description":"`unitCents` × `quantity`"},"discountCents":{"type":"integer","minimum":0,"description":"What the one product discount takes off the line on this charge (all of it on a gift); 0 when nothing does"},"discountBy":{"type":["string","null"],"enum":["managed_discount","discount_code","existing_automatic_discount","unit_price_tiers","bundle_price","gift",null],"description":"The mechanism that takes `discountCents` off (`unit_price_tiers`: a category group's first-charge price for its units; `bundle_price`: a bundle's percentage off from our cart transform, which checkout shows as the bundle's price, not as a saving), `gift` when the discount function zeroes a gift, null when nothing does"},"netCents":{"type":"integer","minimum":0,"description":"What the line charges on this charge: `grossCents` less `discountCents`. Show this; never compute it"}},"required":["lineIndex","role","variantId","quantity","unitCents","grossCents","discountCents","discountBy","netCents"],"additionalProperties":false},"description":"Each cart line with its price on this charge"}},"required":["totalCents","lines"],"additionalProperties":false,"description":"The first order"},"renewal":{"type":["object","null"],"properties":{"totalCents":{"type":"integer","minimum":0,"description":"What these lines charge on this charge, before shipping and tax: the sum of the lines' `netCents`"},"lines":{"type":"array","items":{"type":"object","properties":{"lineIndex":{"type":"integer","minimum":0,"description":"The line's index in the option's `lines`"},"key":{"type":"string","maxLength":64,"pattern":"^[a-z0-9][a-z0-9_-]*$","description":"Names the line inside its option; required on an optional non-gift line, which a cart opts into by this key (`addOnLineKeys`)"},"role":{"type":"string","enum":["main","add_on","gift"],"description":"What a line is in its option: `main` is what the buyer pays for, `add_on` an extra the buyer opts into or is always added, `gift` a real product the discount function prices to zero"},"variantId":{"type":"string","pattern":"^gid:\\/\\/shopify\\/ProductVariant\\/\\d+$","description":"The variant this cart line holds; a pool-bound line becomes one cart line per distinct variant chosen"},"quantity":{"type":"integer","exclusiveMinimum":0,"description":"Units on this cart line"},"sellingPlanId":{"type":"string","pattern":"^gid:\\/\\/shopify\\/SellingPlan\\/\\d+$","description":"The selling plan the cart line is bought on, for a subscription line"},"unitCents":{"type":"integer","minimum":0,"description":"One unit before any product discount: the catalog price with the selling plan's adjustment in effect on this charge"},"grossCents":{"type":"integer","minimum":0,"description":"`unitCents` × `quantity`"},"discountCents":{"type":"integer","minimum":0,"description":"What the one product discount takes off the line on this charge (all of it on a gift); 0 when nothing does"},"discountBy":{"type":["string","null"],"enum":["managed_discount","discount_code","existing_automatic_discount","unit_price_tiers","bundle_price","gift",null],"description":"The mechanism that takes `discountCents` off (`unit_price_tiers`: a category group's first-charge price for its units; `bundle_price`: a bundle's percentage off from our cart transform, which checkout shows as the bundle's price, not as a saving), `gift` when the discount function zeroes a gift, null when nothing does"},"netCents":{"type":"integer","minimum":0,"description":"What the line charges on this charge: `grossCents` less `discountCents`. Show this; never compute it"}},"required":["lineIndex","role","variantId","quantity","unitCents","grossCents","discountCents","discountBy","netCents"],"additionalProperties":false},"description":"Each cart line with its price on this charge"}},"required":["totalCents","lines"],"additionalProperties":false,"description":"Every renewal, once the selling plan's last adjustment is in effect: only the lines that renew; null when none does"},"lineKey":{"type":"string","maxLength":64,"pattern":"^[a-z0-9][a-z0-9_-]*$","description":"The add-on's line key, as `Selection.addOnLineKeys` names it"}},"required":["first","renewal","lineKey"],"additionalProperties":false},"description":"Each optional add-on's cart lines priced on their own. Cart lines are priced one by one, so an option with add-ons opted into charges `first.totalCents` plus each add-on's `first.totalCents` (and the same for renewals)"}},"required":["first","renewal","addOns"],"additionalProperties":false,"description":"What this option charges, computed by the line pricing the verifier proves on real carts (OS-303): the cart the option builds with nothing chosen (each pool at its first variants, no add-on), and each add-on. A buy box renders these numbers and never prices a line itself; for other pool picks, ask `POST /offers/{id}/price`"},"presentations":{"type":"array","items":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","enum":["line_override"],"description":"One line shown with another title or image. It exists only on the cart line: the order keeps the product's real title. Shopify Plus only, except on a line with a line price, where it rides in the line expanded into itself on any plan"},"lineKey":{"type":"string","maxLength":64,"pattern":"^[a-z0-9][a-z0-9_-]*$","description":"The one-time line shown differently"},"title":{"type":"string","minLength":1,"maxLength":255,"description":"What the cart and checkout show as the line's title; the order keeps the product's own title"},"imageUrl":{"type":"string","pattern":"^https:\\/\\/cdn\\.shopify\\.com\\/\\S+$","description":"What the cart and checkout show as the line's image; never kept on the order"}},"required":["type","lineKey"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","enum":["merged_bundle"],"description":"Several lines merged into one titled parent line in the cart and at checkout; on the order, the lines are a bundle group under the parent's title. A merged bundle has no stock of its own"},"lineKeys":{"type":"array","items":{"type":"string","maxLength":64,"pattern":"^[a-z0-9][a-z0-9_-]*$","description":"A key the brand authors: lower-case letters, digits, `_` and `-`"},"minItems":1,"description":"The required one-time lines merged into the parent, each at its own quantity"},"parentVariantId":{"type":"string","pattern":"^gid:\\/\\/shopify\\/ProductVariant\\/\\d+$","description":"The variant the parent line shows as: a bundle product whose variant requires components, so it can never be bought on its own"},"title":{"type":"string","minLength":1,"maxLength":255,"description":"What the cart and checkout show as the line's title; the order keeps the product's own title"},"imageUrl":{"type":"string","pattern":"^https:\\/\\/cdn\\.shopify\\.com\\/\\S+$","description":"What the cart and checkout show as the line's image; never kept on the order"},"attributes":{"type":"array","items":{"type":"object","properties":{"key":{"type":"string","minLength":1,"description":"The attribute's key"},"value":{"type":"string","description":"The attribute's value"}},"required":["key","value"],"additionalProperties":false},"description":"Attributes Shopify puts on the order's bundle group (not in the order webhook)"},"price":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","enum":["percent_off"],"description":"The bundle costs its lines' catalog price less a percentage, shown as the bundle's own price with no saving at checkout"},"percent":{"type":"number","minimum":0,"maximum":100,"description":"The percentage off, 0 to 100"}},"required":["type","percent"],"additionalProperties":false}],"description":"The bundle's price from our cart transform; absent, each line keeps its own price and our discount prices the parent"}},"required":["type","lineKeys","parentVariantId"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","enum":["expanded_bundle"],"description":"One line expanded into components in the cart and at checkout; on the order, the components are a bundle group under the line's title. The line's variant is the parent"},"lineKey":{"type":"string","maxLength":64,"pattern":"^[a-z0-9][a-z0-9_-]*$","description":"The one-time line expanded"},"components":{"type":"array","items":{"type":"object","properties":{"variantId":{"type":"string","pattern":"^gid:\\/\\/shopify\\/ProductVariant\\/\\d+$","description":"A variant that ships inside each unit of the line"},"quantity":{"type":"integer","exclusiveMinimum":0,"description":"Units of the component in each unit of the line"},"unitCents":{"type":"integer","minimum":0,"description":"The component's own price per unit, in cents; set on every component or on none. A gift that ships inside the bundle is a component at 0"},"role":{"type":"string","enum":["main","add_on","gift"],"description":"What the component is on the order, for costing: `main`, `add_on` or `gift`; the expanded line's own role when absent"}},"required":["variantId","quantity"],"additionalProperties":false},"minItems":1,"maxItems":150,"description":"What each unit of the line ships as, at most 150 components (Shopify's limit)"},"title":{"type":"string","minLength":1,"maxLength":255,"description":"What the cart and checkout show as the line's title; the order keeps the product's own title"},"imageUrl":{"type":"string","pattern":"^https:\\/\\/cdn\\.shopify\\.com\\/\\S+$","description":"What the cart and checkout show as the line's image; never kept on the order"},"price":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","enum":["percent_off"],"description":"The bundle costs its lines' catalog price less a percentage, shown as the bundle's own price with no saving at checkout"},"percent":{"type":"number","minimum":0,"maximum":100,"description":"The percentage off, 0 to 100"}},"required":["type","percent"],"additionalProperties":false}],"description":"A percentage off the line's catalog price; refused beside component prices. Absent with no component prices, the line keeps its price and our discount can price it"}},"required":["type","lineKey","components"],"additionalProperties":false}]},"description":"How our cart transform presents the option's one-time lines in the cart and at checkout: line overrides, merged bundles and expanded bundles. Each needs the store's capability for it (`GET /stores/{id}` `capability`); a line appears in one presentation at most"},"checkoutMode":{"type":"string","enum":["cart_page","cart_drawer","direct_to_checkout","landing_cart","external"],"description":"Where the brand's page sends the buyer after the choice: the cart page, a cart drawer, straight to checkout, a cart on the landing page, or an external flow"},"landingPageUrl":{"type":"string","minLength":1,"description":"The page that renders this option; publish checks the page shows it (`page_bind`)"},"verification":{"type":"object","properties":{"status":{"type":"string","enum":["matched","mismatched","unverifiable","unverified"],"description":"Whether a real cart charges what the option promises: `matched`; `mismatched` when a check failed or Shopify refused the cart; `unverifiable` when a check of the promise could not run; `unverified` when never checked (a hidden option). An option goes live only when `matched`"},"checkedAt":{"type":["string","null"],"format":"date-time","description":"When the verifier last ran on this option, or null"}},"required":["status","checkedAt"],"additionalProperties":false,"description":"Whether publish found a real cart charges the promise, and when"}},"required":["key","display","visible","axisValues","unitCount","cardKey","lines","pricing","prices","checkoutMode","verification"],"additionalProperties":false},"minItems":1,"description":"Everything a buyer can choose, one resolved option per combination"},"valueClaims":{"type":"array","items":{"type":"object","properties":{"title":{"type":"string","minLength":1,"description":"The claim as the page words it"},"claimedValueCents":{"type":"integer","minimum":0,"description":"The value claimed, in cents; absent when the page states none"}},"required":["title"],"additionalProperties":false},"description":"Value claims the page makes (bonuses, prizes); never enter a cart"},"terms":{"type":"object","properties":{"guaranteeDays":{"type":"integer","exclusiveMinimum":0,"description":"The money-back guarantee the page states, in days"}},"additionalProperties":false,"description":"Terms the page states"},"catalog":{"type":"object","additionalProperties":{"type":"object","properties":{"productId":{"type":["string","null"],"pattern":"^gid:\\/\\/shopify\\/Product\\/\\d+$","description":"The product's gid; null when Shopify no longer has the variant"},"productTitle":{"type":["string","null"],"description":"The product's title in Shopify"},"variantTitle":{"type":["string","null"],"description":"The variant's title in Shopify (`Default Title` on a product with one variant)"},"image":{"type":["object","null"],"properties":{"url":{"type":"string","format":"uri","description":"Shopify's CDN URL of the image"},"altText":{"type":["string","null"],"description":"The image's alt text in Shopify"},"width":{"type":["integer","null"],"description":"Width in pixels"},"height":{"type":["integer","null"],"description":"Height in pixels"}},"required":["url","altText","width","height"],"additionalProperties":false,"description":"The variant's own first image, else the product's featured image; null when neither exists"},"description":{"type":["string","null"],"description":"A plain-text excerpt of the product's description (at most 300 characters, cut at a word)"},"status":{"type":"string","enum":["active","draft","archived","deleted"],"description":"`active` is for sale; `draft` or `archived` is a product taken off sale in Shopify; `deleted` is a variant Shopify no longer has. Show a line whose variant is not `active` as unavailable"}},"required":["productId","productTitle","variantTitle","image","description","status"],"additionalProperties":false,"description":"What Shopify says about one variant"},"description":"What Shopify says about every variant the offer can put in a cart, keyed by variant gid (the ids in `lines[].variantSource` and `pools`): titles, image, a description excerpt and whether it is still for sale. Read from Shopify at publish, on every product change Shopify sends, and daily, and served as soon as it changes; a variant not read yet is absent. Render product content from here, with no Storefront call of your own"}},"required":["id","code","version","status","store","tracking","axes","pools","defaultOptionKey","options","valueClaims","terms","catalog"],"additionalProperties":false,"description":"What this visitor is served now: render it, then build the cart with its `version`"}},"required":["error","offer"]}}}},"422":{"description":"Shopify rejected the cart; `issues` carry its userErrors","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}},"429":{"description":"Over the key's rate limit (`rate_limited`), or Shopify throttled the Storefront call (`storefront_throttled`); `Retry-After` says how long","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}}}}},"/offers/{id}/simulate":{"post":{"operationId":"simulateOffer","summary":"Simulate a draft offer's profit per order and per visitor before publishing it","description":"Costs a draft document (or a stored version) and the offer's baseline (the live version, else the current draft) with the same costs: the ledger at `at`, plus any what-if `costs` rows. Per option: expected profit per first order, the observed purchases and conversion over `windowDays`, and profit per visitor; overall: the per-visitor difference and the conversion lift the candidate needs to break even. Conversion is today's, assumed unchanged: run an experiment to learn how buyers respond. `realized` recosts past orders under the same what-if. Nothing is stored. Use it to compare several drafts, then `replace_offer` and `publish_offer` the best.","tags":["Offers"],"security":[{"apiKey":[]}],"parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"document":{"type":"object","properties":{"schemaVersion":{"type":"string","enum":["offer/1"],"description":"The document format: `offer/1`"},"code":{"type":"string","maxLength":31,"pattern":"^[^,\\s](?:[^,]*[^,\\s])?$","description":"The offer's code: unique per tenant, immutable once created, and how an agent, `lookup_offer` and the order tag `os_offer:<code>` name the offer"},"tracking":{"type":"object","properties":{"experienceName":{"type":"string","minLength":1,"description":"A label for the page or funnel this offer runs in; the offers list shows it"},"campaignName":{"type":"string","minLength":1,"description":"A label for the marketing campaign this offer belongs to"},"presellPageName":{"type":["string","null"],"minLength":1,"description":"A label for the presell page in front of the offer, or null"},"preservedCartAttributes":{"type":"array","items":{"type":"string","minLength":1},"description":"The brand's own cart attribute names a cart request may set and the API keeps on the cart (`preservedCartAttributes` on the cart request)"}},"required":["experienceName","campaignName","presellPageName","preservedCartAttributes"],"additionalProperties":false,"description":"The labels reports group by, and the brand's own cart attributes a cart keeps"},"store":{"type":"object","properties":{"myshopifyDomain":{"type":"string","minLength":1,"description":"The connected store's myshopify domain (`brand.myshopify.com`); publish and serving use this store"},"market":{"type":"object","properties":{"countryCode":{"type":"string","pattern":"^[A-Z]{2}$","description":"The buyer's country, ISO 3166-1 alpha-2; carts are priced in its market"},"currencyCode":{"type":"string","pattern":"^[A-Z]{3}$","description":"The market's currency, ISO 4217; every amount in the document is in it"}},"required":["countryCode","currencyCode"],"additionalProperties":false,"description":"The one market the offer is priced in"}},"required":["myshopifyDomain","market"],"additionalProperties":false,"description":"The connected store and the market the offer is priced in"},"axes":{"type":"array","items":{"type":"object","properties":{"key":{"type":"string","maxLength":64,"pattern":"^[a-z0-9][a-z0-9_-]*$","description":"Names the axis; options and axis-mapped lines refer to it"},"values":{"type":"array","items":{"type":"string","minLength":1},"minItems":1,"description":"Every value the axis takes"}},"required":["key","values"],"additionalProperties":false},"description":"Dimensions the options vary along (flavour, size); they name and enumerate options, never patch one"},"pools":{"type":"array","items":{"type":"object","properties":{"key":{"type":"string","maxLength":64,"pattern":"^[a-z0-9][a-z0-9_-]*$","description":"Names the pool; a pool-bound line refers to it"},"variantIds":{"type":"array","items":{"type":"string","pattern":"^gid:\\/\\/shopify\\/ProductVariant\\/\\d+$","description":"A Shopify ProductVariant gid (`gid://shopify/ProductVariant/<id>`)"},"minItems":1,"description":"The pool's variants"},"allowRepeats":{"type":"boolean","description":"Whether one variant may be chosen more than once"}},"required":["key","variantIds","allowRepeats"],"additionalProperties":false},"description":"Pools a buyer chooses variants from, through a line bound to the pool"},"defaultOptionKey":{"type":"string","maxLength":64,"pattern":"^[a-z0-9][a-z0-9_-]*$","description":"The option a renderer preselects; must name a visible option"},"options":{"type":"array","items":{"type":"object","properties":{"key":{"type":"string","maxLength":30,"pattern":"^[a-z0-9][a-z0-9_-]*$","description":"Names the option: unique in the document, carried in the cart pointer, the order tag `os_option:<key>` (so at most 30 characters) and the economics. Keep it stable"},"display":{"type":"object","properties":{"title":{"type":"string","minLength":1,"description":"The option's name as a buyer reads it"}},"required":["title"],"additionalProperties":false,"description":"What a renderer shows for the option"},"visible":{"type":"boolean","description":"Whether a renderer may show the option and publish verifies it; a hidden option still resolves and builds carts"},"axisValues":{"type":"object","additionalProperties":{"type":"string"},"description":"The option's value on each document axis, by axis key"},"unitCount":{"type":"integer","exclusiveMinimum":0,"description":"The quantity the buyer perceives (\"4 units\"); not the sum of line quantities"},"cardKey":{"type":"string","maxLength":64,"pattern":"^[a-z0-9][a-z0-9_-]*$","description":"Options sharing a card key are drawn as one card (a subscribe and one-time pair of one product)"},"lines":{"type":"array","items":{"oneOf":[{"type":"object","properties":{"role":{"type":"string","enum":["main","add_on"],"description":"`main` is what the buyer pays for; `add_on` an extra"},"key":{"type":"string","maxLength":64,"pattern":"^[a-z0-9][a-z0-9_-]*$","description":"Names the line inside its option; required on an optional non-gift line, which a cart opts into by this key (`addOnLineKeys`)"},"quantity":{"type":"integer","exclusiveMinimum":0,"description":"Units of the variant in the cart; on a pool-bound line, the fewest the buyer may choose"},"maxQuantity":{"type":"integer","exclusiveMinimum":0,"description":"A pool-bound line only: the most units the buyer may choose"},"required":{"type":"boolean","description":"Whether every cart for the option holds the line; an optional line is added only when the cart request names its key"},"variantSource":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","enum":["fixed"],"description":"The line is one named variant"},"productId":{"type":"string","pattern":"^gid:\\/\\/shopify\\/Product\\/\\d+$","description":"The variant's product"},"variantId":{"type":"string","pattern":"^gid:\\/\\/shopify\\/ProductVariant\\/\\d+$","description":"The variant the line puts in the cart"}},"required":["type","productId","variantId"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","enum":["axis_map"],"description":"The variant follows the option's axis values, through `variantIdByAxisValue`"},"productId":{"type":"string","pattern":"^gid:\\/\\/shopify\\/Product\\/\\d+$","description":"The product every mapped variant belongs to"},"axisKeys":{"type":"array","items":{"type":"string","maxLength":64,"pattern":"^[a-z0-9][a-z0-9_-]*$","description":"A key the brand authors: lower-case letters, digits, `_` and `-`"},"minItems":1,"description":"The document axes whose values choose the variant, in `variantIdByAxisValue`'s key order"},"variantIdByAxisValue":{"type":"object","additionalProperties":{"type":"string","pattern":"^gid:\\/\\/shopify\\/ProductVariant\\/\\d+$","description":"A Shopify ProductVariant gid (`gid://shopify/ProductVariant/<id>`)"},"description":"Variant id by axis value; for several `axisKeys`, keyed by the values joined with \"/\" in `axisKeys` order. Must cover exactly the declared values"}},"required":["type","productId","axisKeys","variantIdByAxisValue"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","enum":["pool"],"description":"The buyer chooses the variants from a pool: `quantity` units, up to `maxQuantity`, any mix of the pool's variants; the cart gets one line per distinct variant"},"poolKey":{"type":"string","maxLength":64,"pattern":"^[a-z0-9][a-z0-9_-]*$","description":"The `pools[].key` the buyer chooses from"}},"required":["type","poolKey"],"additionalProperties":false}],"description":"Where the line's variant comes from"},"purchase":{"type":"object","properties":{"type":{"type":"string","enum":["one_time","subscription"],"description":"Bought once, or on a selling plan"},"sellingPlanId":{"type":"string","pattern":"^gid:\\/\\/shopify\\/SellingPlan\\/\\d+$","description":"The selling plan a subscription line is bought on; required when `type` is `subscription`"},"intervalDays":{"type":"integer","exclusiveMinimum":0,"description":"Days between a subscription's charges, as shown to the buyer"},"plans":{"type":"array","items":{"type":"object","properties":{"fromUnits":{"type":"integer","exclusiveMinimum":0,"description":"The fewest units of the group this plan's tier applies to; the first tier is 1"},"intervalDays":{"type":"integer","exclusiveMinimum":0,"description":"The cadence this plan renews on, one of the option's `cadence` intervals"},"sellingPlanId":{"type":"string","pattern":"^gid:\\/\\/shopify\\/SellingPlan\\/\\d+$","description":"The selling plan the group's lines go on at this tier and cadence"}},"required":["fromUnits","intervalDays","sellingPlanId"],"additionalProperties":false},"minItems":1,"description":"A subscription group's plan for each tier and cadence a cart can reach; `sellingPlanId` is one of them"}},"required":["type"],"additionalProperties":false,"description":"How the line is bought: once, or on a selling plan"},"bundleComponents":{"type":"array","items":{"type":"object","properties":{"variantId":{"type":"string","pattern":"^gid:\\/\\/shopify\\/ProductVariant\\/\\d+$","description":"A component variant of the fixed bundle"},"quantity":{"type":"integer","exclusiveMinimum":0,"description":"Units of that component in one bundle"}},"required":["variantId","quantity"],"additionalProperties":false},"minItems":1,"description":"What one unit holds, when the variant is a Shopify fixed bundle"},"catalogPrice":{"type":"object","properties":{"amountCents":{"type":"integer","minimum":0,"description":"The variant's catalog price when the document was written; line pricing starts from it"},"compareAtAmountCents":{"type":["integer","null"],"minimum":0,"description":"The variant's catalog compare-at price then, or null"},"capturedAt":{"type":"string","format":"date-time","description":"When the price was read from the catalog"}},"required":["amountCents","compareAtAmountCents","capturedAt"],"additionalProperties":false,"description":"The catalog price line pricing starts from"}},"required":["role","quantity","required","variantSource","purchase","catalogPrice"],"additionalProperties":false},{"type":"object","properties":{"role":{"type":"string","enum":["gift"],"description":"A real product the discount function prices to zero"},"key":{"type":"string","maxLength":64,"pattern":"^[a-z0-9][a-z0-9_-]*$","description":"Names the line inside its option; required on an optional non-gift line, which a cart opts into by this key (`addOnLineKeys`)"},"quantity":{"type":"integer","exclusiveMinimum":0,"description":"Units of the variant in the cart; on a pool-bound line, the fewest the buyer may choose"},"maxQuantity":{"type":"integer","exclusiveMinimum":0,"description":"A pool-bound line only: the most units the buyer may choose"},"required":{"type":"boolean","description":"Whether every cart for the option holds the line; an optional line is added only when the cart request names its key"},"variantSource":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","enum":["fixed"],"description":"The line is one named variant"},"productId":{"type":"string","pattern":"^gid:\\/\\/shopify\\/Product\\/\\d+$","description":"The variant's product"},"variantId":{"type":"string","pattern":"^gid:\\/\\/shopify\\/ProductVariant\\/\\d+$","description":"The variant the line puts in the cart"}},"required":["type","productId","variantId"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","enum":["axis_map"],"description":"The variant follows the option's axis values, through `variantIdByAxisValue`"},"productId":{"type":"string","pattern":"^gid:\\/\\/shopify\\/Product\\/\\d+$","description":"The product every mapped variant belongs to"},"axisKeys":{"type":"array","items":{"type":"string","maxLength":64,"pattern":"^[a-z0-9][a-z0-9_-]*$","description":"A key the brand authors: lower-case letters, digits, `_` and `-`"},"minItems":1,"description":"The document axes whose values choose the variant, in `variantIdByAxisValue`'s key order"},"variantIdByAxisValue":{"type":"object","additionalProperties":{"type":"string","pattern":"^gid:\\/\\/shopify\\/ProductVariant\\/\\d+$","description":"A Shopify ProductVariant gid (`gid://shopify/ProductVariant/<id>`)"},"description":"Variant id by axis value; for several `axisKeys`, keyed by the values joined with \"/\" in `axisKeys` order. Must cover exactly the declared values"}},"required":["type","productId","axisKeys","variantIdByAxisValue"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","enum":["pool"],"description":"The buyer chooses the variants from a pool: `quantity` units, up to `maxQuantity`, any mix of the pool's variants; the cart gets one line per distinct variant"},"poolKey":{"type":"string","maxLength":64,"pattern":"^[a-z0-9][a-z0-9_-]*$","description":"The `pools[].key` the buyer chooses from"}},"required":["type","poolKey"],"additionalProperties":false}],"description":"Where the line's variant comes from"},"purchase":{"type":"object","properties":{"type":{"type":"string","enum":["one_time","subscription"],"description":"Bought once, or on a selling plan"},"sellingPlanId":{"type":"string","pattern":"^gid:\\/\\/shopify\\/SellingPlan\\/\\d+$","description":"The selling plan a subscription line is bought on; required when `type` is `subscription`"},"intervalDays":{"type":"integer","exclusiveMinimum":0,"description":"Days between a subscription's charges, as shown to the buyer"},"plans":{"type":"array","items":{"type":"object","properties":{"fromUnits":{"type":"integer","exclusiveMinimum":0,"description":"The fewest units of the group this plan's tier applies to; the first tier is 1"},"intervalDays":{"type":"integer","exclusiveMinimum":0,"description":"The cadence this plan renews on, one of the option's `cadence` intervals"},"sellingPlanId":{"type":"string","pattern":"^gid:\\/\\/shopify\\/SellingPlan\\/\\d+$","description":"The selling plan the group's lines go on at this tier and cadence"}},"required":["fromUnits","intervalDays","sellingPlanId"],"additionalProperties":false},"minItems":1,"description":"A subscription group's plan for each tier and cadence a cart can reach; `sellingPlanId` is one of them"}},"required":["type"],"additionalProperties":false,"description":"How the line is bought: once, or on a selling plan"},"bundleComponents":{"type":"array","items":{"type":"object","properties":{"variantId":{"type":"string","pattern":"^gid:\\/\\/shopify\\/ProductVariant\\/\\d+$","description":"A component variant of the fixed bundle"},"quantity":{"type":"integer","exclusiveMinimum":0,"description":"Units of that component in one bundle"}},"required":["variantId","quantity"],"additionalProperties":false},"minItems":1,"description":"What one unit holds, when the variant is a Shopify fixed bundle"},"catalogPrice":{"type":"object","properties":{"amountCents":{"type":"integer","minimum":0,"description":"The variant's catalog price when the document was written; line pricing starts from it"},"compareAtAmountCents":{"type":["integer","null"],"minimum":0,"description":"The variant's catalog compare-at price then, or null"},"capturedAt":{"type":"string","format":"date-time","description":"When the price was read from the catalog"}},"required":["amountCents","compareAtAmountCents","capturedAt"],"additionalProperties":false,"description":"The catalog price line pricing starts from"},"claimedValueCents":{"type":"integer","minimum":0,"description":"The value the page shows for the gift (struck through); never charged: the function zeroes the line, and its cost comes from the ledger"}},"required":["role","quantity","required","variantSource","purchase","catalogPrice","claimedValueCents"],"additionalProperties":false}]},"minItems":1,"description":"What the option puts in the cart"},"maxUnits":{"type":"integer","exclusiveMinimum":0,"description":"A category builder: the most units the option's non-gift lines may hold in all"},"cadence":{"type":"object","properties":{"tiers":{"type":"array","items":{"type":"object","properties":{"fromUnits":{"type":"integer","exclusiveMinimum":0,"description":"The fewest units of the largest subscription group this interval applies to; the first tier is 1"},"intervalDays":{"type":"integer","exclusiveMinimum":0,"description":"Days between charges of every subscription line"}},"required":["fromUnits","intervalDays"],"additionalProperties":false},"minItems":1,"description":"The tiers, ascending from 1; above the last tier the last interval holds"}},"required":["tiers"],"additionalProperties":false,"description":"A category builder: the one interval every subscription line renews on, by the units of the largest subscription group in the cart; required when a line has `purchase.plans`"},"pricing":{"type":"object","properties":{"promise":{"type":"object","properties":{"firstChargeCents":{"type":["integer","null"],"minimum":0,"description":"What the buyer is charged on the first order, before shipping and tax; required on a visible option. Publish checks a real cart charges it"},"renewalChargeCents":{"type":["integer","null"],"minimum":0,"description":"What each renewal charges, before shipping and tax; required when the option has a subscription line"}},"required":["firstChargeCents","renewalChargeCents"],"additionalProperties":false,"description":"What the option promises the buyer is charged"},"compareAtPrice":{"type":"object","properties":{"amountCents":{"type":"integer","minimum":0,"description":"The struck-through amount, in cents"},"source":{"type":"string","enum":["variant","selling_plan","unit_price_times_quantity","metafield","page_copy"],"description":"Where it comes from: the variant's compare-at price, the selling plan's compare-at price, the unit price times the quantity, a metafield, or page copy"}},"required":["amountCents","source"],"additionalProperties":false,"description":"The struck-through price the page shows beside the promise"},"shipping":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","enum":["free"],"description":"The discount function makes the named rates free for carts carrying this option"},"rates":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","enum":["cheapest"],"description":"The cheapest shipping rate in each delivery group"}},"required":["type"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","enum":["all"],"description":"Every shipping rate, express included"}},"required":["type"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","enum":["titles"],"description":"The rates whose title is one of `titles`, ignoring case"},"titles":{"type":"array","items":{"type":"string","minLength":1},"minItems":1,"description":"Rate titles as checkout shows them"}},"required":["type","titles"],"additionalProperties":false}],"description":"Which rates are free"},"charges":{"type":"string","enum":["first","every"],"description":"Which shipments are free: `every` charge (a subscription's renewals too) or the `first` only"},"claimedValueCents":{"type":"integer","minimum":0,"description":"The shipping value the page claims for the free shipment (\"a $6.99 value\"); never charged"},"renewalChargeCents":{"type":"integer","minimum":0,"description":"On a subscription option free on the first charge only: what each renewal's shipping charges. Required there, refused elsewhere"}},"required":["type","rates","charges"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","enum":["charged"],"description":"Shipping is charged at checkout's rates"},"expectedChargeCents":{"type":"integer","minimum":0,"description":"What the forecast assumes a shipment charges, in cents; 0 for none"}},"required":["type","expectedChargeCents"],"additionalProperties":false}],"description":"What the option promises about shipping"},"mechanisms":{"type":"array","items":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","enum":["managed_discount"],"description":"Our app discount prices the lines, from the option map publish writes; works on subscription lines"},"lineRoles":{"type":"array","items":{"type":"string","enum":["main","add_on","gift"],"description":"What a line is in its option: `main` is what the buyer pays for, `add_on` an extra the buyer opts into or is always added, `gift` a real product the discount function prices to zero"},"minItems":1,"description":"The roles of the option's lines this mechanism prices"},"discount":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","enum":["percent"],"description":"A percentage off"},"percent":{"type":"number","minimum":0,"maximum":100,"description":"The percentage off, 0 to 100"}},"required":["type","percent"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","enum":["fixed_amount"],"description":"A fixed amount off"},"amountCents":{"type":"integer","minimum":0,"description":"The amount off, in cents"},"per":{"type":"string","enum":["line","unit"],"description":"Off each line, or off each unit of the line"}},"required":["type","amountCents","per"],"additionalProperties":false}],"description":"How much comes off"},"charges":{"type":"string","enum":["first","every"],"description":"Which charges it prices: `first` the first order only; `every` the first order and every renewal of a subscription line"}},"required":["type","lineRoles","discount","charges"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","enum":["discount_code"],"description":"A Shopify discount code publish creates, applied to the cart the API builds"},"code":{"type":"string","minLength":1,"description":"The code the brand chose; absent, publish mints one"},"purchaseType":{"type":"string","enum":["one_time","subscription","subscription_first_payment_only"],"description":"Which purchases the code prices: one-time lines once, every charge of a subscription line, or a subscription's first order only"},"discount":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","enum":["percent"],"description":"A percentage off"},"percent":{"type":"number","minimum":0,"maximum":100,"description":"The percentage off, 0 to 100"}},"required":["type","percent"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","enum":["fixed_amount"],"description":"A fixed amount off"},"amountCents":{"type":"integer","minimum":0,"description":"The amount off, in cents"}},"required":["type","amountCents"],"additionalProperties":false}],"description":"How much comes off"},"lineRoles":{"type":"array","items":{"type":"string","enum":["main","add_on","gift"],"description":"What a line is in its option: `main` is what the buyer pays for, `add_on` an extra the buyer opts into or is always added, `gift` a real product the discount function prices to zero"},"minItems":1,"description":"The roles of the option's lines this mechanism prices"}},"required":["type","purchaseType","discount","lineRoles"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","enum":["selling_plan_adjustment"],"description":"The selling plan's own price adjustments price the subscription lines on that plan"},"sellingPlanId":{"type":"string","pattern":"^gid:\\/\\/shopify\\/SellingPlan\\/\\d+$","description":"The selling plan, carried by a subscription line of the option"},"adjustments":{"type":"array","items":{"type":"object","properties":{"fromOrder":{"anyOf":[{"type":"integer","exclusiveMinimum":0},{"type":"string","enum":["after_last"]}],"description":"The order from which the adjustment is in effect: N from the Nth order on, until a later one takes over; \"after_last\" after every numbered one (alone, from the first order). Before the first, the catalog price"},"discount":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","enum":["percent"],"description":"A percentage off"},"percent":{"type":"number","minimum":0,"maximum":100,"description":"The percentage off, 0 to 100"}},"required":["type","percent"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","enum":["fixed_amount"],"description":"A fixed amount off"},"amountCents":{"type":"integer","minimum":0,"description":"The amount off, in cents"}},"required":["type","amountCents"],"additionalProperties":false}],"description":"How much the plan takes off the variant's price, per unit"}},"required":["fromOrder","discount"],"additionalProperties":false},"minItems":1,"description":"The plan's price adjustments as Shopify holds them, at most two"}},"required":["type","sellingPlanId","adjustments"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","enum":["catalog_price"],"description":"The variant's catalog price is already the offer price; nothing is discounted"}},"required":["type"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","enum":["existing_automatic_discount"],"description":"An automatic discount the store already runs; we only describe it"},"lineRoles":{"type":"array","items":{"type":"string","enum":["main","add_on","gift"],"description":"What a line is in its option: `main` is what the buyer pays for, `add_on` an extra the buyer opts into or is always added, `gift` a real product the discount function prices to zero"},"minItems":1,"description":"The roles of the option's lines this mechanism prices"},"discount":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","enum":["percent"],"description":"A percentage off"},"percent":{"type":"number","minimum":0,"maximum":100,"description":"The percentage off, 0 to 100"}},"required":["type","percent"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","enum":["fixed_amount"],"description":"A fixed amount off"},"amountCents":{"type":"integer","minimum":0,"description":"The amount off, in cents"}},"required":["type","amountCents"],"additionalProperties":false}],"description":"How much comes off"},"charges":{"type":"string","enum":["first","every"],"description":"Which charges it prices: `first` the first order only; `every` the first order and every renewal of a subscription line"}},"required":["type","lineRoles","discount","charges"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","enum":["unit_price_tiers"],"description":"A category group's first-order unit price by how many units of it the cart holds; our app discount charges it, and the group's selling plans price the renewals"},"lineKey":{"type":"string","maxLength":64,"pattern":"^[a-z0-9][a-z0-9_-]*$","description":"The group: an optional, non-gift line bound to a pool, which a cart opts into by this key"},"tiers":{"type":"array","items":{"type":"object","properties":{"fromUnits":{"type":"integer","exclusiveMinimum":0,"description":"The fewest units of the group this tier's price applies to; the first tier is 1"},"unitCents":{"type":"integer","minimum":0,"description":"What each unit of the group charges on the first order at this tier, in cents"}},"required":["fromUnits","unitCents"],"additionalProperties":false},"minItems":1,"description":"The tiers, ascending from 1; above the last tier the last price holds"}},"required":["type","lineKey","tiers"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","enum":["line_price"],"description":"Our cart transform sets the lines' unit price as their own price, at or below each line's catalog price (never above: a raise is refused): shown as the product's price, with no saving at checkout. One-time lines only, on any store with our cart transform registered: `lineUpdate` on Shopify Plus, the line expanded into itself on every other plan"},"lineKeys":{"type":"array","items":{"type":"string","maxLength":64,"pattern":"^[a-z0-9][a-z0-9_-]*$","description":"A key the brand authors: lower-case letters, digits, `_` and `-`"},"minItems":1,"description":"The one-time lines priced, by key"},"unitCents":{"type":"integer","minimum":0,"description":"What each unit of those lines charges on the first order, in cents"}},"required":["type","lineKeys","unitCents"],"additionalProperties":false}]},"description":"How the promise is made real on Shopify; at most one product discount per line and charge"}},"required":["promise","compareAtPrice","shipping","mechanisms"],"additionalProperties":false,"description":"What the option promises and how Shopify charges it"},"presentations":{"type":"array","items":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","enum":["line_override"],"description":"One line shown with another title or image. It exists only on the cart line: the order keeps the product's real title. Shopify Plus only, except on a line with a line price, where it rides in the line expanded into itself on any plan"},"lineKey":{"type":"string","maxLength":64,"pattern":"^[a-z0-9][a-z0-9_-]*$","description":"The one-time line shown differently"},"title":{"type":"string","minLength":1,"maxLength":255,"description":"What the cart and checkout show as the line's title; the order keeps the product's own title"},"imageUrl":{"type":"string","pattern":"^https:\\/\\/cdn\\.shopify\\.com\\/\\S+$","description":"What the cart and checkout show as the line's image; never kept on the order"}},"required":["type","lineKey"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","enum":["merged_bundle"],"description":"Several lines merged into one titled parent line in the cart and at checkout; on the order, the lines are a bundle group under the parent's title. A merged bundle has no stock of its own"},"lineKeys":{"type":"array","items":{"type":"string","maxLength":64,"pattern":"^[a-z0-9][a-z0-9_-]*$","description":"A key the brand authors: lower-case letters, digits, `_` and `-`"},"minItems":1,"description":"The required one-time lines merged into the parent, each at its own quantity"},"parentVariantId":{"type":"string","pattern":"^gid:\\/\\/shopify\\/ProductVariant\\/\\d+$","description":"The variant the parent line shows as: a bundle product whose variant requires components, so it can never be bought on its own"},"title":{"type":"string","minLength":1,"maxLength":255,"description":"What the cart and checkout show as the line's title; the order keeps the product's own title"},"imageUrl":{"type":"string","pattern":"^https:\\/\\/cdn\\.shopify\\.com\\/\\S+$","description":"What the cart and checkout show as the line's image; never kept on the order"},"attributes":{"type":"array","items":{"type":"object","properties":{"key":{"type":"string","minLength":1,"description":"The attribute's key"},"value":{"type":"string","description":"The attribute's value"}},"required":["key","value"],"additionalProperties":false},"description":"Attributes Shopify puts on the order's bundle group (not in the order webhook)"},"price":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","enum":["percent_off"],"description":"The bundle costs its lines' catalog price less a percentage, shown as the bundle's own price with no saving at checkout"},"percent":{"type":"number","minimum":0,"maximum":100,"description":"The percentage off, 0 to 100"}},"required":["type","percent"],"additionalProperties":false}],"description":"The bundle's price from our cart transform; absent, each line keeps its own price and our discount prices the parent"}},"required":["type","lineKeys","parentVariantId"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","enum":["expanded_bundle"],"description":"One line expanded into components in the cart and at checkout; on the order, the components are a bundle group under the line's title. The line's variant is the parent"},"lineKey":{"type":"string","maxLength":64,"pattern":"^[a-z0-9][a-z0-9_-]*$","description":"The one-time line expanded"},"components":{"type":"array","items":{"type":"object","properties":{"variantId":{"type":"string","pattern":"^gid:\\/\\/shopify\\/ProductVariant\\/\\d+$","description":"A variant that ships inside each unit of the line"},"quantity":{"type":"integer","exclusiveMinimum":0,"description":"Units of the component in each unit of the line"},"unitCents":{"type":"integer","minimum":0,"description":"The component's own price per unit, in cents; set on every component or on none. A gift that ships inside the bundle is a component at 0"},"role":{"type":"string","enum":["main","add_on","gift"],"description":"What the component is on the order, for costing: `main`, `add_on` or `gift`; the expanded line's own role when absent"}},"required":["variantId","quantity"],"additionalProperties":false},"minItems":1,"maxItems":150,"description":"What each unit of the line ships as, at most 150 components (Shopify's limit)"},"title":{"type":"string","minLength":1,"maxLength":255,"description":"What the cart and checkout show as the line's title; the order keeps the product's own title"},"imageUrl":{"type":"string","pattern":"^https:\\/\\/cdn\\.shopify\\.com\\/\\S+$","description":"What the cart and checkout show as the line's image; never kept on the order"},"price":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","enum":["percent_off"],"description":"The bundle costs its lines' catalog price less a percentage, shown as the bundle's own price with no saving at checkout"},"percent":{"type":"number","minimum":0,"maximum":100,"description":"The percentage off, 0 to 100"}},"required":["type","percent"],"additionalProperties":false}],"description":"A percentage off the line's catalog price; refused beside component prices. Absent with no component prices, the line keeps its price and our discount can price it"}},"required":["type","lineKey","components"],"additionalProperties":false}]},"description":"How our cart transform presents the option's one-time lines in the cart and at checkout: line overrides, merged bundles and expanded bundles. Each needs the store's capability for it (`GET /stores/{id}` `capability`); a line appears in one presentation at most"},"checkoutMode":{"type":"string","enum":["cart_page","cart_drawer","direct_to_checkout","landing_cart","external"],"description":"Where the brand's page sends the buyer after the choice: the cart page, a cart drawer, straight to checkout, a cart on the landing page, or an external flow"},"landingPageUrl":{"type":"string","minLength":1,"description":"The page that renders this option; publish checks the page shows it (`page_bind`)"}},"required":["key","display","visible","axisValues","unitCount","cardKey","lines","pricing","checkoutMode"],"additionalProperties":false},"minItems":1,"description":"Everything a buyer can choose, one resolved option per combination"},"valueClaims":{"type":"array","items":{"type":"object","properties":{"title":{"type":"string","minLength":1,"description":"The claim as the page words it"},"claimedValueCents":{"type":"integer","minimum":0,"description":"The value claimed, in cents; absent when the page states none"}},"required":["title"],"additionalProperties":false},"description":"Value claims the page makes (bonuses, prizes); never enter a cart"},"terms":{"type":"object","properties":{"guaranteeDays":{"type":"integer","exclusiveMinimum":0,"description":"The money-back guarantee the page states, in days"}},"additionalProperties":false,"description":"Terms the page states"},"costProfile":{"type":"string","minLength":1,"description":"The cost profile the forecast and the realized cost basis use: which cost kinds apply to this offer's orders"}},"required":["schemaVersion","code","tracking","store","axes","pools","defaultOptionKey","options","valueClaims","terms","costProfile"],"additionalProperties":false,"description":"A draft to simulate, exactly as `replace_offer` would take it; nothing is stored. Its `code` must be the offer's"},"version":{"type":"integer","exclusiveMinimum":0,"description":"Simulate a stored version instead of a document"},"at":{"type":"string","format":"date-time","description":"Resolve costs at this date (default now), for the candidate and the baseline alike: a future date previews a scheduled cost"},"costs":{"type":"array","items":{"type":"object","properties":{"kindKey":{"type":"string","minLength":1},"targetType":{"type":"string","enum":["variant","item","product","offer","tenant"]},"targetId":{"type":"string","minLength":1,"description":"Variant: the variant gid; item: item id or SKU; product: the product gid; offer: the offer being simulated (a kind-level value for it alone); \"*\" for tenant"},"amount":{"type":"string","pattern":"^\\d+(\\.\\d{1,6})?$","description":"The amount assumed at this level, for a money kind (per_unit, per_parcel, per_order)"},"percent":{"type":"number","minimum":0,"maximum":100,"description":"The percent (0 to 100) assumed at this level, for a `percent` kind"}},"required":["kindKey","targetType","targetId"]},"maxItems":500,"default":[],"description":"What-if cost rows layered over the ledger for this simulation only; the ledger is never written"},"windowDays":{"type":"integer","minimum":1,"maximum":365,"default":30,"description":"The window over which visitors and purchases per option are observed"},"realized":{"type":"object","properties":{"from":{"type":"string","format":"date-time"},"to":{"type":"string","format":"date-time"},"costsAt":{"type":"string","format":"date-time","description":"Cost every order at this one date (for example today) instead of at its own date"}},"required":["from","to"],"description":"Also recost the offer's attributed orders placed in [from, to) under `costs` and `costsAt`, against their current costs"}}}}}},"responses":{"200":{"description":"The simulation","content":{"application/json":{"schema":{"type":"object","properties":{"offerId":{"type":"string","format":"uuid"},"currencyCode":{"type":"string","description":"The candidate's market currency (ISO 4217): every money figure is in it"},"costProfile":{"type":"string","description":"The candidate document's cost profile"},"at":{"type":"string","format":"date-time"},"overrides":{"type":"integer","minimum":0},"baseline":{"type":"object","properties":{"version":{"type":"integer","exclusiveMinimum":0},"status":{"type":"string","description":"live, or draft when the offer has never been published"}},"required":["version","status"]},"candidate":{"type":"object","properties":{"version":{"type":["integer","null"],"exclusiveMinimum":0,"description":"null for an unsaved document"}},"required":["version"]},"window":{"type":"object","properties":{"days":{"type":"integer"},"visitors":{"type":"integer","minimum":0,"description":"Distinct visitor ids that viewed the offer, as browsers reported them"},"purchases":{"type":"integer","minimum":0,"description":"Purchases the store's order webhook confirmed; a purchase only a browser reported is left out (decision 212)"},"thin":{"type":"boolean"}},"required":["days","visitors","purchases","thin"]},"assumptions":{"type":"array","items":{"type":"string"},"description":"What the figures assume; read them before acting on a per-visitor number"},"options":{"type":"array","items":{"type":"object","properties":{"optionKey":{"type":"string"},"candidate":{"type":["object","null"],"properties":{"firstOrder":{"type":"object","properties":{"revenueCents":{"type":"integer","description":"What the customer is charged: the promised charge plus the shipping charged on this order"},"waterfall":{"type":"array","items":{"type":"object","properties":{"kindKey":{"type":"string","description":"The cost kind"},"grain":{"type":"string","enum":["per_unit","per_parcel","per_order","percent"],"description":"How the kind is charged"},"cents":{"type":"integer","description":"What the kind costs on this order"}},"required":["kindKey","grain","cents"]},"description":"Every cost of the order, in the profile's order, then gift fulfilment, the refund estimate and processing"},"totalCostCents":{"type":"integer","description":"The waterfall's sum"},"grossMarginCents":{"type":"integer","description":"revenueCents − totalCostCents"},"grossMarginPercent":{"type":"number","description":"grossMarginCents ÷ revenueCents, 0 to 100 (59.71 is 59.71%); 0 when revenue is 0"}},"required":["revenueCents","waterfall","totalCostCents","grossMarginCents","grossMarginPercent"]},"renewal":{"type":["object","null"],"properties":{"revenueCents":{"type":"integer","description":"What the customer is charged: the promised charge plus the shipping charged on this order"},"waterfall":{"type":"array","items":{"type":"object","properties":{"kindKey":{"type":"string","description":"The cost kind"},"grain":{"type":"string","enum":["per_unit","per_parcel","per_order","percent"],"description":"How the kind is charged"},"cents":{"type":"integer","description":"What the kind costs on this order"}},"required":["kindKey","grain","cents"]},"description":"Every cost of the order, in the profile's order, then gift fulfilment, the refund estimate and processing"},"totalCostCents":{"type":"integer","description":"The waterfall's sum"},"grossMarginCents":{"type":"integer","description":"revenueCents − totalCostCents"},"grossMarginPercent":{"type":"number","description":"grossMarginCents ÷ revenueCents, 0 to 100 (59.71 is 59.71%); 0 when revenue is 0"}},"required":["revenueCents","waterfall","totalCostCents","grossMarginCents","grossMarginPercent"]},"profitPerOrderCents":{"type":"integer","description":"Expected profit per first order: gross margin after the refund estimate, with payment processing among the costs"},"missingCosts":{"type":"array","items":{"type":"string"},"description":"Required kinds with no amount on a line of this option: profit per order is overstated until they are entered"}},"required":["firstOrder","renewal","profitPerOrderCents","missingCosts"],"description":"null when the candidate has no such option"},"baseline":{"type":["object","null"],"properties":{"firstOrder":{"type":"object","properties":{"revenueCents":{"type":"integer","description":"What the customer is charged: the promised charge plus the shipping charged on this order"},"waterfall":{"type":"array","items":{"type":"object","properties":{"kindKey":{"type":"string","description":"The cost kind"},"grain":{"type":"string","enum":["per_unit","per_parcel","per_order","percent"],"description":"How the kind is charged"},"cents":{"type":"integer","description":"What the kind costs on this order"}},"required":["kindKey","grain","cents"]},"description":"Every cost of the order, in the profile's order, then gift fulfilment, the refund estimate and processing"},"totalCostCents":{"type":"integer","description":"The waterfall's sum"},"grossMarginCents":{"type":"integer","description":"revenueCents − totalCostCents"},"grossMarginPercent":{"type":"number","description":"grossMarginCents ÷ revenueCents, 0 to 100 (59.71 is 59.71%); 0 when revenue is 0"}},"required":["revenueCents","waterfall","totalCostCents","grossMarginCents","grossMarginPercent"]},"renewal":{"type":["object","null"],"properties":{"revenueCents":{"type":"integer","description":"What the customer is charged: the promised charge plus the shipping charged on this order"},"waterfall":{"type":"array","items":{"type":"object","properties":{"kindKey":{"type":"string","description":"The cost kind"},"grain":{"type":"string","enum":["per_unit","per_parcel","per_order","percent"],"description":"How the kind is charged"},"cents":{"type":"integer","description":"What the kind costs on this order"}},"required":["kindKey","grain","cents"]},"description":"Every cost of the order, in the profile's order, then gift fulfilment, the refund estimate and processing"},"totalCostCents":{"type":"integer","description":"The waterfall's sum"},"grossMarginCents":{"type":"integer","description":"revenueCents − totalCostCents"},"grossMarginPercent":{"type":"number","description":"grossMarginCents ÷ revenueCents, 0 to 100 (59.71 is 59.71%); 0 when revenue is 0"}},"required":["revenueCents","waterfall","totalCostCents","grossMarginCents","grossMarginPercent"]},"profitPerOrderCents":{"type":"integer","description":"Expected profit per first order: gross margin after the refund estimate, with payment processing among the costs"},"missingCosts":{"type":"array","items":{"type":"string"},"description":"Required kinds with no amount on a line of this option: profit per order is overstated until they are entered"},"realized":{"type":["object","null"],"properties":{"orders":{"type":"integer","exclusiveMinimum":0},"profitPerOrderCents":{"type":"integer"}},"required":["orders","profitPerOrderCents"],"description":"The baseline version's realized first orders in its market currency, current cost view, net of refunds; orders in any other shop currency are left out"}},"required":["firstOrder","renewal","profitPerOrderCents","missingCosts","realized"],"description":"null when the baseline has no such option"},"deltaPerOrderCents":{"type":["integer","null"]},"observed":{"type":"object","properties":{"purchases":{"type":"integer","minimum":0,"description":"Confirmed purchases of this option over the window"},"purchaseShare":{"type":"number","description":"This option's share of the offer's purchases, 0 to 1"},"conversion":{"type":"number","description":"purchases of this option ÷ the offer's visitors, 0 to 1"}},"required":["purchases","purchaseShare","conversion"]},"candidateProfitPerVisitorCents":{"type":["integer","null"]},"baselineProfitPerVisitorCents":{"type":["integer","null"]}},"required":["optionKey","candidate","baseline","deltaPerOrderCents","observed","candidateProfitPerVisitorCents","baselineProfitPerVisitorCents"]}},"perVisitor":{"type":"object","properties":{"candidateCents":{"type":["integer","null"]},"baselineCents":{"type":["integer","null"]},"deltaCents":{"type":["integer","null"]},"breakEvenConversionLift":{"type":["number","null"],"description":"How much conversion must rise (0.1 = 10%) for the candidate to earn the baseline's profit per visitor; 0 when it already does"}},"required":["candidateCents","baselineCents","deltaCents","breakEvenConversionLift"]},"realized":{"type":["object","null"],"properties":{"from":{"type":"string","format":"date-time"},"to":{"type":"string","format":"date-time"},"costsAt":{"type":["string","null"],"format":"date-time"},"orders":{"type":"integer","minimum":0},"netRevenueCents":{"type":"integer","description":"The offer's lines and shipping less the refunds it counted, as the realized current view holds them; the same in both costings"},"currentCostCents":{"type":"integer"},"scenarioCostCents":{"type":"integer"},"currentProfitCents":{"type":"integer"},"scenarioProfitCents":{"type":"integer"},"deltaCents":{"type":"integer","description":"scenarioProfit − currentProfit"},"currentIncompleteOrders":{"type":"integer","minimum":0},"scenarioIncompleteOrders":{"type":"integer","minimum":0},"byOption":{"type":"array","items":{"type":"object","properties":{"optionKey":{"type":"string"},"orders":{"type":"integer","minimum":0},"netRevenueCents":{"type":"integer","description":"The offer's lines and shipping less the refunds it counted, as the realized current view holds them; the same in both costings"},"currentCostCents":{"type":"integer"},"scenarioCostCents":{"type":"integer"},"currentProfitCents":{"type":"integer"},"scenarioProfitCents":{"type":"integer"},"deltaCents":{"type":"integer","description":"scenarioProfit − currentProfit"},"currentIncompleteOrders":{"type":"integer","minimum":0},"scenarioIncompleteOrders":{"type":"integer","minimum":0}},"required":["optionKey","orders","netRevenueCents","currentCostCents","scenarioCostCents","currentProfitCents","scenarioProfitCents","deltaCents","currentIncompleteOrders","scenarioIncompleteOrders"]}}},"required":["from","to","costsAt","orders","netRevenueCents","currentCostCents","scenarioCostCents","currentProfitCents","scenarioProfitCents","deltaCents","currentIncompleteOrders","scenarioIncompleteOrders","byOption"]}},"required":["offerId","currencyCode","costProfile","at","overrides","baseline","candidate","window","assumptions","options","perVisitor","realized"]}}}},"400":{"description":"Invalid request or document, an unknown cost kind in `costs`, an unknown cost profile, or a changed `code`","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}},"401":{"description":"Missing, unknown or revoked API key","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}},"403":{"description":"The key is public; this route needs a secret key","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}},"404":{"description":"No such offer or version","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}},"422":{"description":"`period_too_large`: the realized period holds more than 5,000 orders","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}}}}},"/offers/{id}/experiments/{experimentId}/check":{"post":{"operationId":"checkExperiment","summary":"Prove every arm of a running experiment again with real carts","description":"The guardrail the daily cron runs: each arm's visible options are verified with real Storefront carts. If any is no longer green, the experiment pauses (everyone sees the control; carts keep their prices) and `reason` names the failing versions and options. Fix the cause, publish the arm again with `as: \"arm\"`, then resume.","tags":["Experiments"],"security":[{"apiKey":[]}],"parameters":[{"schema":{"type":"string","format":"uuid","description":"The offer id"},"required":true,"description":"The offer id","name":"id","in":"path"},{"schema":{"type":"string","format":"uuid"},"required":true,"name":"experimentId","in":"path"}],"responses":{"200":{"description":"The check; `arms` is empty unless the experiment is running","content":{"application/json":{"schema":{"type":"object","properties":{"experimentId":{"type":"string","format":"uuid"},"arms":{"type":"array","items":{"type":"object","properties":{"version":{"type":"integer"},"verificationStatus":{"type":"string","enum":["matched","mismatched","unverifiable"],"description":"`matched` when every visible option of the arm matched a real cart; else the worst option's status"},"failedOptions":{"type":"array","items":{"type":"string"}}},"required":["version","verificationStatus","failedOptions"]}},"paused":{"type":"boolean"},"reason":{"type":["string","null"]}},"required":["experimentId","arms","paused","reason"]}}}},"400":{"description":"Invalid id","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}},"401":{"description":"Missing, unknown or revoked API key","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}},"403":{"description":"The key is public; this route needs a secret key","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}},"404":{"description":"No such experiment on this offer","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}}}}},"/offers/{id}/experiments":{"get":{"operationId":"listExperiments","summary":"An offer's experiments, newest first","tags":["Experiments"],"security":[{"apiKey":[]}],"parameters":[{"schema":{"type":"string","format":"uuid","description":"The offer id"},"required":true,"description":"The offer id","name":"id","in":"path"}],"responses":{"200":{"description":"The experiments","content":{"application/json":{"schema":{"type":"object","properties":{"experiments":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"offerId":{"type":"string","format":"uuid"},"status":{"type":"string","enum":["starting","running","paused","stopped"],"description":"`starting` while its arms are written into the store's option map (visitors see the control), `running`, `paused` (visitors see the control), `stopped`"},"controlVersion":{"type":"integer","exclusiveMinimum":0},"arms":{"type":"array","items":{"type":"object","properties":{"version":{"type":"integer","exclusiveMinimum":0},"weight":{"type":"number","exclusiveMinimum":0,"exclusiveMaximum":1}},"required":["version","weight"]}},"falsePositiveRate":{"type":"number"},"minimumDetectableEffect":{"type":"number"},"plannedVisitorsPerArm":{"type":["integer","null"],"description":"Visitors each arm needs to detect `minimumDetectableEffect` at 80% power, from the control's last 30 days; null without history"},"baseline":{"type":"object","properties":{"windowDays":{"type":"integer"},"visitors":{"type":"integer"},"meanCents":{"type":"number"},"varianceCentsSquared":{"type":"number"}},"required":["windowDays","visitors","meanCents","varianceCentsSquared"]},"startedAt":{"type":"string","format":"date-time"},"pausedAt":{"type":["string","null"],"format":"date-time"},"endedAt":{"type":["string","null"],"format":"date-time"},"stopReason":{"type":["string","null"]},"winnerVersion":{"type":["integer","null"]},"actor":{"type":"string"}},"required":["id","offerId","status","controlVersion","arms","falsePositiveRate","minimumDetectableEffect","plannedVisitorsPerArm","baseline","startedAt","pausedAt","endedAt","stopReason","winnerVersion","actor"]}}},"required":["experiments"]}}}},"400":{"description":"Invalid id","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}},"401":{"description":"Missing, unknown or revoked API key","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}},"403":{"description":"The key is public; this route needs a secret key","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}}}},"post":{"operationId":"createExperiment","summary":"Start a profit-per-visitor experiment on an offer","description":"Splits the offer's traffic between its live version (the control) and one to three versions published with `as: \"arm\"` (every option verified), by `weight`. Resolve assigns each visitor an arm deterministically from their visitor id, so the SDK renders it with no flicker and carts, events and orders carry the arm's version. The response states the visitors each arm needs (`plannedVisitorsPerArm`, from the control's last 30 days). Read `get_experiment` as often as you like: its interval stays valid. One active experiment per offer. The experiment answers `running` once the arms are priced on the store; until then it is `starting` and every visitor sees the control, and if the store refuses the prices it ends `stopped` and this call answers `shopify_refused`.","tags":["Experiments"],"security":[{"apiKey":[]}],"parameters":[{"schema":{"type":"string","format":"uuid","description":"The offer id"},"required":true,"description":"The offer id","name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"arms":{"type":"array","items":{"type":"object","properties":{"version":{"type":"integer","exclusiveMinimum":0},"weight":{"type":"number","exclusiveMinimum":0,"exclusiveMaximum":1}},"required":["version","weight"]},"minItems":2,"maxItems":4,"description":"The live version (the control) and one to three verified versions, with traffic weights summing to 1"},"falsePositiveRate":{"type":"number","minimum":0.001,"maximum":0.2,"default":0.05,"description":"The false-positive rate (alpha) across all comparisons, Bonferroni-split between challengers"},"minimumDetectableEffect":{"type":"number","minimum":0.01,"maximum":1,"default":0.1,"description":"The smallest relative lift in profit per visitor the plan is sized to detect (0.1 is 10%)"}},"required":["arms"]}}}},"responses":{"201":{"description":"Started","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"offerId":{"type":"string","format":"uuid"},"status":{"type":"string","enum":["starting","running","paused","stopped"],"description":"`starting` while its arms are written into the store's option map (visitors see the control), `running`, `paused` (visitors see the control), `stopped`"},"controlVersion":{"type":"integer","exclusiveMinimum":0},"arms":{"type":"array","items":{"type":"object","properties":{"version":{"type":"integer","exclusiveMinimum":0},"weight":{"type":"number","exclusiveMinimum":0,"exclusiveMaximum":1}},"required":["version","weight"]}},"falsePositiveRate":{"type":"number"},"minimumDetectableEffect":{"type":"number"},"plannedVisitorsPerArm":{"type":["integer","null"],"description":"Visitors each arm needs to detect `minimumDetectableEffect` at 80% power, from the control's last 30 days; null without history"},"baseline":{"type":"object","properties":{"windowDays":{"type":"integer"},"visitors":{"type":"integer"},"meanCents":{"type":"number"},"varianceCentsSquared":{"type":"number"}},"required":["windowDays","visitors","meanCents","varianceCentsSquared"]},"startedAt":{"type":"string","format":"date-time"},"pausedAt":{"type":["string","null"],"format":"date-time"},"endedAt":{"type":["string","null"],"format":"date-time"},"stopReason":{"type":["string","null"]},"winnerVersion":{"type":["integer","null"]},"actor":{"type":"string"}},"required":["id","offerId","status","controlVersion","arms","falsePositiveRate","minimumDetectableEffect","plannedVisitorsPerArm","baseline","startedAt","pausedAt","endedAt","stopReason","winnerVersion","actor"]}}}},"400":{"description":"`invalid_arms`: weights, duplicates, a missing control, a version from another store","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}},"401":{"description":"Missing, unknown or revoked API key","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}},"403":{"description":"The key is public; this route needs a secret key","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}},"404":{"description":"No such offer","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}},"409":{"description":"`no_live_version`, `arm_not_verified`, `experiment_active`, or `experiment_stopped` when it was stopped while starting","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}},"502":{"description":"`shopify_refused`: the option map could not be written; nothing started","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}}}}},"/offers/{id}/experiments/{experimentId}":{"get":{"operationId":"getExperiment","summary":"An experiment and its report: profit per visitor per arm, with the always-valid interval and a recommendation","description":"Per arm: visitors, buyers, conversion, orders, AOV, refund rate and profit per visitor (realized, current cost view, net of refunds). Per challenger: the difference from control with its confidence interval and `decision` (`challenger_wins`, `control_wins`, `no_difference`, `keep_running`). The decision is a recommendation: stop with `stop_experiment` and promote with `publish_offer`.","tags":["Experiments"],"security":[{"apiKey":[]}],"parameters":[{"schema":{"type":"string","format":"uuid","description":"The offer id"},"required":true,"description":"The offer id","name":"id","in":"path"},{"schema":{"type":"string","format":"uuid"},"required":true,"name":"experimentId","in":"path"}],"responses":{"200":{"description":"The experiment","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"offerId":{"type":"string","format":"uuid"},"status":{"type":"string","enum":["starting","running","paused","stopped"],"description":"`starting` while its arms are written into the store's option map (visitors see the control), `running`, `paused` (visitors see the control), `stopped`"},"controlVersion":{"type":"integer","exclusiveMinimum":0},"arms":{"type":"array","items":{"type":"object","properties":{"version":{"type":"integer","exclusiveMinimum":0},"weight":{"type":"number","exclusiveMinimum":0,"exclusiveMaximum":1}},"required":["version","weight"]}},"falsePositiveRate":{"type":"number"},"minimumDetectableEffect":{"type":"number"},"plannedVisitorsPerArm":{"type":["integer","null"],"description":"Visitors each arm needs to detect `minimumDetectableEffect` at 80% power, from the control's last 30 days; null without history"},"baseline":{"type":"object","properties":{"windowDays":{"type":"integer"},"visitors":{"type":"integer"},"meanCents":{"type":"number"},"varianceCentsSquared":{"type":"number"}},"required":["windowDays","visitors","meanCents","varianceCentsSquared"]},"startedAt":{"type":"string","format":"date-time"},"pausedAt":{"type":["string","null"],"format":"date-time"},"endedAt":{"type":["string","null"],"format":"date-time"},"stopReason":{"type":["string","null"]},"winnerVersion":{"type":["integer","null"]},"actor":{"type":"string"},"report":{"type":"object","properties":{"window":{"type":"object","properties":{"start":{"type":"string","format":"date-time"},"end":{"type":"string","format":"date-time"}},"required":["start","end"]},"currencyCode":{"type":["string","null"],"description":"The shop currency every money figure is in (ISO 4217): the one most of the window's first orders were placed in; null before the first order. Orders in any other currency are in no figure, and `assumptions` counts them"},"arms":{"type":"array","items":{"type":"object","properties":{"version":{"type":"integer","exclusiveMinimum":0},"control":{"type":"boolean"},"weight":{"type":"number"},"visitors":{"type":"integer","minimum":0,"description":"Distinct visitors who viewed this arm"},"buyers":{"type":"integer","minimum":0},"conversion":{"type":["number","null"],"description":"buyers ÷ visitors"},"profitPerVisitorCents":{"type":["number","null"],"description":"The metric: realized contribution (current cost view, net of refunds) of the arm's first orders per visitor"},"orders":{"type":"integer","minimum":0},"ordersWithoutVisitor":{"type":"integer","minimum":0,"description":"Orders whose cart carried no visitor id: in the order totals, not in profit per visitor"},"revenueCents":{"type":"integer"},"refundedCents":{"type":"integer"},"profitCents":{"type":"integer","description":"Contribution of the arm's first orders: revenue plus shipping charged, less refunds and every cost"},"averageOrderValueCents":{"type":["number","null"],"description":"revenueCents ÷ orders"},"refundPercent":{"type":["number","null"],"description":"refundedCents ÷ revenueCents, 0 to 100; null without revenue"},"plannedVisitors":{"type":["integer","null"]}},"required":["version","control","weight","visitors","buyers","conversion","profitPerVisitorCents","orders","ordersWithoutVisitor","revenueCents","refundedCents","profitCents","averageOrderValueCents","refundPercent","plannedVisitors"]}},"comparisons":{"type":"array","items":{"type":"object","properties":{"version":{"type":"integer","exclusiveMinimum":0},"falsePositiveRate":{"type":"number","description":"This comparison's share of the experiment's `falsePositiveRate`"},"differenceCents":{"type":"number","description":"Profit per visitor, challenger − control"},"lowerCents":{"type":["number","null"]},"upperCents":{"type":["number","null"]},"radiusCents":{"type":["number","null"],"description":"Half-width of the always-valid confidence interval: valid however often the report is read"},"relativeLift":{"type":["number","null"],"description":"differenceCents ÷ the control's profit per visitor"},"decision":{"type":"string","enum":["challenger_wins","control_wins","no_difference","keep_running"]}},"required":["version","falsePositiveRate","differenceCents","lowerCents","upperCents","radiusCents","relativeLift","decision"]}},"assumptions":{"type":"array","items":{"type":"string"}}},"required":["window","currencyCode","arms","comparisons","assumptions"]}},"required":["id","offerId","status","controlVersion","arms","falsePositiveRate","minimumDetectableEffect","plannedVisitorsPerArm","baseline","startedAt","pausedAt","endedAt","stopReason","winnerVersion","actor","report"]}}}},"400":{"description":"Invalid id","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}},"401":{"description":"Missing, unknown or revoked API key","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}},"403":{"description":"The key is public; this route needs a secret key","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}},"404":{"description":"No such experiment on this offer","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}}}}},"/offers/{id}/experiments/{experimentId}/pause":{"post":{"operationId":"pauseExperiment","summary":"Pause an experiment: everyone sees the control","description":"Takes effect with the next request of every visitor. Assignments are kept for a resume. Arms stay priced, so carts already built at an arm's price still check out at it.","tags":["Experiments"],"security":[{"apiKey":[]}],"parameters":[{"schema":{"type":"string","format":"uuid","description":"The offer id"},"required":true,"description":"The offer id","name":"id","in":"path"},{"schema":{"type":"string","format":"uuid"},"required":true,"name":"experimentId","in":"path"}],"requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"object","properties":{"reason":{"type":"string","minLength":1,"maxLength":500},"winnerVersion":{"type":"integer","exclusiveMinimum":0,"description":"stop only: the arm you are about to promote"}}}}}},"responses":{"200":{"description":"The experiment","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"offerId":{"type":"string","format":"uuid"},"status":{"type":"string","enum":["starting","running","paused","stopped"],"description":"`starting` while its arms are written into the store's option map (visitors see the control), `running`, `paused` (visitors see the control), `stopped`"},"controlVersion":{"type":"integer","exclusiveMinimum":0},"arms":{"type":"array","items":{"type":"object","properties":{"version":{"type":"integer","exclusiveMinimum":0},"weight":{"type":"number","exclusiveMinimum":0,"exclusiveMaximum":1}},"required":["version","weight"]}},"falsePositiveRate":{"type":"number"},"minimumDetectableEffect":{"type":"number"},"plannedVisitorsPerArm":{"type":["integer","null"],"description":"Visitors each arm needs to detect `minimumDetectableEffect` at 80% power, from the control's last 30 days; null without history"},"baseline":{"type":"object","properties":{"windowDays":{"type":"integer"},"visitors":{"type":"integer"},"meanCents":{"type":"number"},"varianceCentsSquared":{"type":"number"}},"required":["windowDays","visitors","meanCents","varianceCentsSquared"]},"startedAt":{"type":"string","format":"date-time"},"pausedAt":{"type":["string","null"],"format":"date-time"},"endedAt":{"type":["string","null"],"format":"date-time"},"stopReason":{"type":["string","null"]},"winnerVersion":{"type":["integer","null"]},"actor":{"type":"string"}},"required":["id","offerId","status","controlVersion","arms","falsePositiveRate","minimumDetectableEffect","plannedVisitorsPerArm","baseline","startedAt","pausedAt","endedAt","stopReason","winnerVersion","actor"]}}}},"400":{"description":"Invalid request, or a winner that is not an arm","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}},"401":{"description":"Missing, unknown or revoked API key","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}},"403":{"description":"The key is public; this route needs a secret key","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}},"404":{"description":"No such experiment on this offer","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}},"409":{"description":"`experiment_stopped`, or not in a state this action applies to","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}}}}},"/offers/{id}/experiments/{experimentId}/resume":{"post":{"operationId":"resumeExperiment","summary":"Resume a paused experiment","description":"Visitors get the arms they were assigned before the pause.","tags":["Experiments"],"security":[{"apiKey":[]}],"parameters":[{"schema":{"type":"string","format":"uuid","description":"The offer id"},"required":true,"description":"The offer id","name":"id","in":"path"},{"schema":{"type":"string","format":"uuid"},"required":true,"name":"experimentId","in":"path"}],"requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"object","properties":{"reason":{"type":"string","minLength":1,"maxLength":500},"winnerVersion":{"type":"integer","exclusiveMinimum":0,"description":"stop only: the arm you are about to promote"}}}}}},"responses":{"200":{"description":"The experiment","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"offerId":{"type":"string","format":"uuid"},"status":{"type":"string","enum":["starting","running","paused","stopped"],"description":"`starting` while its arms are written into the store's option map (visitors see the control), `running`, `paused` (visitors see the control), `stopped`"},"controlVersion":{"type":"integer","exclusiveMinimum":0},"arms":{"type":"array","items":{"type":"object","properties":{"version":{"type":"integer","exclusiveMinimum":0},"weight":{"type":"number","exclusiveMinimum":0,"exclusiveMaximum":1}},"required":["version","weight"]}},"falsePositiveRate":{"type":"number"},"minimumDetectableEffect":{"type":"number"},"plannedVisitorsPerArm":{"type":["integer","null"],"description":"Visitors each arm needs to detect `minimumDetectableEffect` at 80% power, from the control's last 30 days; null without history"},"baseline":{"type":"object","properties":{"windowDays":{"type":"integer"},"visitors":{"type":"integer"},"meanCents":{"type":"number"},"varianceCentsSquared":{"type":"number"}},"required":["windowDays","visitors","meanCents","varianceCentsSquared"]},"startedAt":{"type":"string","format":"date-time"},"pausedAt":{"type":["string","null"],"format":"date-time"},"endedAt":{"type":["string","null"],"format":"date-time"},"stopReason":{"type":["string","null"]},"winnerVersion":{"type":["integer","null"]},"actor":{"type":"string"}},"required":["id","offerId","status","controlVersion","arms","falsePositiveRate","minimumDetectableEffect","plannedVisitorsPerArm","baseline","startedAt","pausedAt","endedAt","stopReason","winnerVersion","actor"]}}}},"400":{"description":"Invalid request, or a winner that is not an arm","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}},"401":{"description":"Missing, unknown or revoked API key","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}},"403":{"description":"The key is public; this route needs a secret key","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}},"404":{"description":"No such experiment on this offer","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}},"409":{"description":"`experiment_stopped`, or not in a state this action applies to","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}}}}},"/offers/{id}/experiments/{experimentId}/stop":{"post":{"operationId":"stopExperiment","x-destructive":true,"summary":"Stop an experiment for good","description":"Everyone sees the control from the next request. Arms stay priced for 14 days. A `starting` experiment can be stopped too. Name `winnerVersion` to record the decision, then `publish_offer` that version to make it live.","tags":["Experiments"],"security":[{"apiKey":[]}],"parameters":[{"schema":{"type":"string","format":"uuid","description":"The offer id"},"required":true,"description":"The offer id","name":"id","in":"path"},{"schema":{"type":"string","format":"uuid"},"required":true,"name":"experimentId","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"reason":{"type":"string","minLength":1,"maxLength":500},"winnerVersion":{"type":"integer","exclusiveMinimum":0,"description":"stop only: the arm you are about to promote"}}}}}},"responses":{"200":{"description":"The experiment","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"offerId":{"type":"string","format":"uuid"},"status":{"type":"string","enum":["starting","running","paused","stopped"],"description":"`starting` while its arms are written into the store's option map (visitors see the control), `running`, `paused` (visitors see the control), `stopped`"},"controlVersion":{"type":"integer","exclusiveMinimum":0},"arms":{"type":"array","items":{"type":"object","properties":{"version":{"type":"integer","exclusiveMinimum":0},"weight":{"type":"number","exclusiveMinimum":0,"exclusiveMaximum":1}},"required":["version","weight"]}},"falsePositiveRate":{"type":"number"},"minimumDetectableEffect":{"type":"number"},"plannedVisitorsPerArm":{"type":["integer","null"],"description":"Visitors each arm needs to detect `minimumDetectableEffect` at 80% power, from the control's last 30 days; null without history"},"baseline":{"type":"object","properties":{"windowDays":{"type":"integer"},"visitors":{"type":"integer"},"meanCents":{"type":"number"},"varianceCentsSquared":{"type":"number"}},"required":["windowDays","visitors","meanCents","varianceCentsSquared"]},"startedAt":{"type":"string","format":"date-time"},"pausedAt":{"type":["string","null"],"format":"date-time"},"endedAt":{"type":["string","null"],"format":"date-time"},"stopReason":{"type":["string","null"]},"winnerVersion":{"type":["integer","null"]},"actor":{"type":"string"}},"required":["id","offerId","status","controlVersion","arms","falsePositiveRate","minimumDetectableEffect","plannedVisitorsPerArm","baseline","startedAt","pausedAt","endedAt","stopReason","winnerVersion","actor"]}}}},"400":{"description":"Invalid request, or a winner that is not an arm","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}},"401":{"description":"Missing, unknown or revoked API key","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}},"403":{"description":"The key is public; this route needs a secret key","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}},"404":{"description":"No such experiment on this offer","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}},"409":{"description":"`experiment_stopped`, or not in a state this action applies to","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}}}}},"/events":{"post":{"operationId":"recordEvents","summary":"Record a batch of funnel events","description":"The browser SDK and the Web Pixel post the event ladder here (view_offer, select_option, add_to_cart, checkout_started, purchase), up to 100 events per request. Every event carries a sender-generated `eventId`: a retried batch yields one row. Each step has one sender (decision 45): the SDK sends the three page steps; the Web Pixel sends `checkout_started` as `checkout_started:<checkout token>` and `purchase` as `purchase:<order gid>`, the id the server-side purchase the order ingest writes also uses, so the two sit beside each other for the purchase comparison. A public key is in every visitor's browser, so nothing posted here is trusted as a sale: a `purchase` counts in the funnel, the simulator's conversion and experiments only once the store's signed order webhook confirms the same order (decision 212); until then it is reported as unverified. Accepted batches are queued and land in ClickHouse within seconds; the response does not wait for the write. Public keys may call it. Each visitor id may post about one request a second per key; over that the whole batch is refused with `rate_limited` and nothing is queued.","tags":["Events"],"security":[{"apiKey":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"events":{"type":"array","items":{"type":"object","properties":{"eventId":{"type":"string","minLength":1,"maxLength":128,"description":"Generated by the sender; a retried event with the same id is stored once. A purchase uses `purchase:<order gid>`"},"name":{"type":"string","enum":["view_offer","select_option","add_to_cart","checkout_started","purchase"],"description":"Which step of the ladder: `view_offer`, `select_option`, `add_to_cart`, `checkout_started` or `purchase`"},"occurredAt":{"type":"string","format":"date-time","description":"When the event happened, ISO 8601"},"offerId":{"type":"string","format":"uuid","description":"The offer the visitor was shown"},"shownVersion":{"type":"integer","exclusiveMinimum":0,"description":"The offer version the visitor was shown"},"optionKey":{"type":"string","minLength":1,"maxLength":128,"description":"The option the event is about, when it is about one"},"visitorId":{"type":"string","minLength":1,"maxLength":128,"description":"The first-party visitor id (`v_…`); the same id travels as the `_os_visitor` cart attribute"},"cartId":{"type":"string","minLength":1,"maxLength":256,"description":"The Shopify cart id, once there is a cart"},"orderId":{"type":"string","maxLength":128,"pattern":"^gid:\\/\\/shopify\\/Order\\/\\d+$","description":"The Shopify order gid, on a purchase"},"amountCents":{"type":"integer","minimum":0,"description":"The amount the event is worth in cents, on an add to cart or a purchase"},"currencyCode":{"type":"string","pattern":"^[A-Z]{3}$","description":"The currency of `amountCents`, ISO 4217"}},"required":["eventId","name","occurredAt","offerId","shownVersion","visitorId"],"additionalProperties":false},"minItems":1,"maxItems":100,"description":"Up to 100 events, each with its own `eventId`"}},"required":["events"]}}}},"responses":{"202":{"description":"The number of events queued","content":{"application/json":{"schema":{"type":"object","properties":{"accepted":{"type":"integer","exclusiveMinimum":0}},"required":["accepted"]}}}},"400":{"description":"An event failed validation; `issues` lists each path","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}},"401":{"description":"Missing, unknown or revoked API key","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}},"429":{"description":"`rate_limited`: over the key's limit, or a visitor id in the batch over its own","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}}}}},"/orders/counts":{"get":{"operationId":"getOrderCounts","summary":"Count ingested orders by attribution","description":"Every order the webhook ingest stored for this tenant, split by how it was attributed. `none` is the number of orders that carried no usable `_os` attribute or `os_offer`/`os_option`/`os_version` tags; they are kept with `offer_id` null so nothing is lost.","tags":["Orders"],"security":[{"apiKey":[]}],"responses":{"200":{"description":"The counts","content":{"application/json":{"schema":{"type":"object","properties":{"total":{"type":"integer","minimum":0},"byAttribution":{"type":"object","properties":{"attribute":{"type":"integer","minimum":0,"description":"Attributed by the `_os` cart attribute"},"tag":{"type":"integer","minimum":0,"description":"Attributed by order tags"},"none":{"type":"integer","minimum":0,"description":"Stored unattributed: no pointer, or a pointer to an offer outside this tenant"}},"required":["attribute","tag","none"]}},"required":["total","byAttribution"]}}}},"401":{"description":"Missing, unknown or revoked API key","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}},"403":{"description":"The key is public; this route needs a secret key","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}}}}},"/orders/actual-costs":{"post":{"operationId":"recordActualCosts","summary":"Record what orders actually cost to ship and fulfil","description":"Records actual order-level costs, such as a 3PL's charge for an order's shipments or a carrier label, keyed by order, cost kind and `sourceRef`. Each replaces that kind's estimate for the order in both cost views, so realized profit becomes the real figure; the estimate is kept for the variance (`getOrderCosts`). An order's actual for a kind is the sum of its rows: send a credit as a negative amount under its own `sourceRef`. Sending the same order, kind, reference and amount again changes nothing; another amount under a reference already recorded is rejected, never overwritten. A split shipment is two rows (one per shipment) or their sum under one reference. Rows that cannot be placed (an unknown order, a product, percent or payment kind, an order stored without costs) come back in `rejected` with the reason, and the rest of the batch is recorded. Up to 500 rows a call.","tags":["Orders"],"security":[{"apiKey":[]}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"costs":{"type":"array","items":{"type":"object","properties":{"orderId":{"type":"string","pattern":"^gid:\\/\\/shopify\\/Order\\/\\d+$","description":"A Shopify Order gid (`gid://shopify/Order/<id>`)"},"kindKey":{"type":"string","minLength":1,"description":"An order-level cost kind of the tenant: per order (`3pl_base`, `3pl_label`), per parcel (`freight`) or the extra picks"},"amount":{"type":"string","pattern":"^-?\\d+(\\.\\d{1,2})?$","description":"Shop money; negative for a credit"},"sourceRef":{"type":"string","maxLength":200,"description":"Where it came from: the 3PL's shipment or charge id, the invoice line. Resending the same reference and amount changes nothing"}},"required":["orderId","kindKey","amount"]},"minItems":1,"maxItems":500}},"required":["costs"]}}}},"responses":{"200":{"description":"What was recorded, and every row that was not, with why","content":{"application/json":{"schema":{"type":"object","properties":{"recorded":{"type":"integer","minimum":0},"unchanged":{"type":"integer","minimum":0,"description":"Rows already recorded with the same amount under the same reference"},"rejected":{"type":"array","items":{"type":"object","properties":{"index":{"type":"integer","minimum":0},"orderId":{"type":"string","pattern":"^gid:\\/\\/shopify\\/Order\\/\\d+$","description":"A Shopify Order gid (`gid://shopify/Order/<id>`)"},"reason":{"type":"string"}},"required":["index","orderId","reason"]}}},"required":["recorded","unchanged","rejected"]}}}},"400":{"description":"`invalid_request`: a row is malformed","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}},"401":{"description":"Missing, unknown or revoked API key","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}},"403":{"description":"The key is public; this route needs a secret key","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}}}}},"/orders/costs":{"get":{"operationId":"getOrderCosts","summary":"One order's costs: estimate, actual and variance by kind, and its parcels","description":"The order's cost by kind in one view (`current` by default, or `as_recorded`), as realized profit counts it: for each kind the estimate, the actual recorded with `recordActualCosts` (null when none) and `varianceCents` (actual minus estimate), and `costCents`, what the order is charged. `parcels` are the order's fulfilments with the location each shipped from; per-parcel kinds are charged once per parcel not cancelled or failed, and once before the order ships.","tags":["Orders"],"security":[{"apiKey":[]}],"parameters":[{"schema":{"type":"string","pattern":"^gid:\\/\\/shopify\\/Order\\/\\d+$","description":"A Shopify Order gid (`gid://shopify/Order/<id>`)"},"required":true,"description":"A Shopify Order gid (`gid://shopify/Order/<id>`)","name":"orderId","in":"query"},{"schema":{"type":"string","enum":["current","as_recorded"]},"required":false,"name":"view","in":"query"}],"responses":{"200":{"description":"The order's costs","content":{"application/json":{"schema":{"type":"object","properties":{"orderId":{"type":"string","pattern":"^gid:\\/\\/shopify\\/Order\\/\\d+$","description":"A Shopify Order gid (`gid://shopify/Order/<id>`)"},"view":{"type":"string","enum":["current","as_recorded"]},"parcels":{"type":"object","properties":{"count":{"type":"integer","exclusiveMinimum":0},"shipments":{"type":"array","items":{"type":"object","properties":{"fulfillmentId":{"type":"string","pattern":"^gid:\\/\\/shopify\\/Fulfillment\\/\\d+$","description":"A Shopify Fulfillment gid (`gid://shopify/Fulfillment/<id>`)"},"locationId":{"type":["string","null"],"pattern":"^gid:\\/\\/shopify\\/Location\\/\\d+$","description":"null when the order was read from Admin, which does not show locations"},"status":{"type":"string"}},"required":["fulfillmentId","locationId","status"]}}},"required":["count","shipments"]},"kinds":{"type":"array","items":{"type":"object","properties":{"kindKey":{"type":"string"},"estimateCents":{"type":"integer"},"actualCents":{"type":["integer","null"]},"varianceCents":{"type":["integer","null"]},"costCents":{"type":"integer"}},"required":["kindKey","estimateCents","actualCents","varianceCents","costCents"]}},"actuals":{"type":"array","items":{"type":"object","properties":{"kindKey":{"type":"string"},"amount":{"type":"string"},"source":{"type":"string"},"sourceRef":{"type":"string"},"recordedBy":{"type":"string"},"recordedAt":{"type":"string","format":"date-time"}},"required":["kindKey","amount","source","sourceRef","recordedBy","recordedAt"]}}},"required":["orderId","view","parcels","kinds","actuals"]}}}},"400":{"description":"`invalid_request`","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}},"401":{"description":"Missing, unknown or revoked API key","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}},"403":{"description":"The key is public; this route needs a secret key","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}},"404":{"description":"No such order, or it is stored without costs","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}}}}},"/privacy/requests":{"get":{"operationId":"listPrivacyRequests","summary":"List compliance requests and their reports","description":"Every customers/data_request, customers/redact and shop/redact Shopify sent for this tenant's stores, newest first, with what was found and done. A data request's report is the data Offer Suite holds for the named orders, which the merchant passes to the customer. Nothing identifies a buyer: names, emails, phones and addresses are never stored.","tags":["Privacy"],"security":[{"apiKey":[]}],"parameters":[{"schema":{"type":"integer","minimum":1,"maximum":200,"default":50},"required":false,"name":"limit","in":"query"}],"responses":{"200":{"description":"The requests","content":{"application/json":{"schema":{"type":"object","properties":{"requests":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"topic":{"type":"string","enum":["customers/data_request","customers/redact","shop/redact"]},"myshopifyDomain":{"type":"string"},"dataRequestId":{"type":["string","null"],"description":"`data_request.id` on a customers/data_request"},"customerId":{"type":["string","null"],"description":"Shopify's numeric customer id; the email and phone Shopify sends are never stored"},"ordersRequested":{"type":"array","items":{"type":"string"},"description":"The order ids Shopify named"},"status":{"type":"string","enum":["completed","skipped"]},"report":{"type":"object","additionalProperties":{},"description":"What was found and done: for a data request, the data held per order, to hand to the customer"},"receivedAt":{"type":"string","format":"date-time"}},"required":["id","topic","myshopifyDomain","dataRequestId","customerId","ordersRequested","status","report","receivedAt"]}}},"required":["requests"]}}}},"400":{"description":"Invalid query","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}},"401":{"description":"Missing, unknown or revoked API key","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}},"403":{"description":"The key is public; this route needs a secret key","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}}}}},"/cost-kinds":{"get":{"operationId":"listCostKinds","summary":"List the tenant's cost kinds","description":"Every cost kind with its grain (the anti-double-count rule: a per_parcel kind counts once per order, a per_unit kind once per unit), whether it is required, and the tenant-wide value in effect now: `defaultAmount` for a money grain, `defaultPercent` (0 to 100) for `percent`.","tags":["Costs"],"security":[{"apiKey":[]}],"responses":{"200":{"description":"The kinds","content":{"application/json":{"schema":{"type":"object","properties":{"kinds":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"key":{"type":"string"},"grain":{"type":"string","enum":["per_unit","per_parcel","per_order","percent"]},"canonicalSource":{"type":"string"},"required":{"type":"boolean"},"defaultAmount":{"type":["string","null"],"description":"A money grain's tenant-wide amount in effect now, from the ledger; absent on a `percent` kind"},"defaultPercent":{"type":["number","null"],"description":"The `percent` grain's tenant-wide percent (0 to 100) in effect now, from the ledger; absent on a money kind"},"orderScope":{"type":["string","null"],"enum":["every","first","renewal","one_time","subscription",null],"description":"The tenant's own order scope; null keeps the profile's rule for a kind it names (`3pl_insert`: `first`), else `every`"},"percentBase":{"type":["string","null"],"enum":["revenue_with_shipping","product_revenue","unit_cost",null],"description":"The tenant's own base for a percent kind; null keeps the profile's, else `revenue_with_shipping`"},"unitCostMayInclude":{"type":["string","null"],"enum":["packaging","freight_in",null],"description":"The tenant's own label; null keeps the profile's (`packaging_box`, `packaging_plastic`: `packaging`)"},"createdAt":{"type":"string","format":"date-time"}},"required":["id","key","grain","canonicalSource","required","orderScope","percentBase","unitCostMayInclude","createdAt"]}}},"required":["kinds"]}}}},"401":{"description":"Missing, unknown or revoked API key","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}},"403":{"description":"The key is public; this route needs a secret key","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}}}},"post":{"operationId":"createCostKind","summary":"Create a cost kind","description":"Keys are unique per tenant and referenced by cost rows and order lines, so a kind cannot be renamed or deleted; create a new one instead. A `defaultAmount` (a money grain) or `defaultPercent` (0 to 100, the `percent` grain) is written as a tenant ledger row effective since the epoch; the other one is refused with 400. A kind with a default, or a required one, restates every attributed order (`restatement`). A key the cost profile already names (`3pl_base`, `payment_processing` at 2.9% of the order's revenue as charged, `payment_processing_fixed` at 0.30 per order, …) sets that kind's amount for this tenant, and must be created with the profile's grain; another grain is refused with 400. Payment processing is the order's actual Shopify Payments fee once Shopify reports it; these two kinds estimate it until then and for other gateways.","tags":["Costs"],"security":[{"apiKey":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"key":{"type":"string","minLength":1,"maxLength":64,"pattern":"^[a-z0-9_]+$"},"grain":{"type":"string","enum":["per_unit","per_parcel","per_order","percent"]},"canonicalSource":{"type":"string","minLength":1,"maxLength":64,"description":"Where the number comes from, for the operator (\"shopify\", \"3pl_contract\", \"stripe\")"},"required":{"type":"boolean","default":false,"description":"A required kind with no amount for a line leaves the order's costs incomplete, never zero"},"defaultAmount":{"type":["string","null"],"pattern":"^\\d+(\\.\\d{1,6})?$","description":"A money grain's tenant-wide amount, written as a `tenant` ledger row effective since the epoch; change it later with PATCH"},"defaultPercent":{"type":["number","null"],"minimum":0,"maximum":100,"description":"The `percent` grain's tenant-wide percent, 0 to 100, written as a `tenant` ledger row effective since the epoch"},"orderScope":{"type":"string","enum":["every","first","renewal","one_time","subscription"],"description":"Which orders the kind is charged on: `every` (the default); `first` first orders only (inserts, welcome gifts); `renewal` renewals only; `subscription` subscription orders, meaning every renewal and a first order holding a subscription line (a mixed cart counts, since a subscription app's fee applies to the whole checkout); `one_time` orders with no subscription line. Changing it restates every order"},"percentBase":{"type":"string","enum":["revenue_with_shipping","product_revenue","unit_cost"],"description":"A `percent` kind only: what it is a percent of. Every base is net of discounts and excludes tax. `revenue_with_shipping` (the default) is what the customer is charged, products plus shipping, as payment processors charge; `product_revenue` the products alone; `unit_cost` the order's `unit_cost` total (landed cost or scrap as a percent of COGS). Changing it restates every order"},"unitCostMayInclude":{"type":"string","enum":["packaging","freight_in"],"description":"The cost this kind counts that a brand's Shopify cost per item may already include. When the tenant's `unitCostIncludes` (PATCH /tenant) names it, the kind is not charged, so the cost is never counted twice"}},"required":["key","grain","canonicalSource"]}}}},"responses":{"201":{"description":"The kind","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"key":{"type":"string"},"grain":{"type":"string","enum":["per_unit","per_parcel","per_order","percent"]},"canonicalSource":{"type":"string"},"required":{"type":"boolean"},"defaultAmount":{"type":["string","null"],"description":"A money grain's tenant-wide amount in effect now, from the ledger; absent on a `percent` kind"},"defaultPercent":{"type":["number","null"],"description":"The `percent` grain's tenant-wide percent (0 to 100) in effect now, from the ledger; absent on a money kind"},"orderScope":{"type":["string","null"],"enum":["every","first","renewal","one_time","subscription",null],"description":"The tenant's own order scope; null keeps the profile's rule for a kind it names (`3pl_insert`: `first`), else `every`"},"percentBase":{"type":["string","null"],"enum":["revenue_with_shipping","product_revenue","unit_cost",null],"description":"The tenant's own base for a percent kind; null keeps the profile's, else `revenue_with_shipping`"},"unitCostMayInclude":{"type":["string","null"],"enum":["packaging","freight_in",null],"description":"The tenant's own label; null keeps the profile's (`packaging_box`, `packaging_plastic`: `packaging`)"},"createdAt":{"type":"string","format":"date-time"},"restatement":{"type":["object","null"],"properties":{"id":{"type":"string","format":"uuid"},"trigger":{"type":"string","enum":["cost_row","cost_void","cost_import","cost_seed","cost_kind","manual"]},"status":{"type":"string","enum":["queued","running","completed","failed"]},"actor":{"type":"string"},"reason":{"type":["string","null"]},"costRowIds":{"type":"array","items":{"type":"string","format":"uuid"},"description":"The ledger rows written or voided by the request"},"kindKeys":{"type":"array","items":{"type":"string"}},"targets":{"type":"array","items":{"type":"object","properties":{"targetType":{"type":"string","enum":["item","product","offer","tenant"]},"targetId":{"type":"string"}},"required":["targetType","targetId"]},"description":"Empty when tenant-wide"},"tenantWide":{"type":"boolean","description":"Every attributed order from `earliestEffectiveFrom` is restated"},"earliestEffectiveFrom":{"type":"string","format":"date-time","description":"Orders placed at or after this date are affected"},"ordersAffected":{"type":"integer","minimum":0,"description":"Counted when the request was recorded"},"ordersDone":{"type":"integer","minimum":0},"profitBeforeCents":{"type":["integer","null"],"description":"Realized profit (current view) of the tenant's orders from `earliestEffectiveFrom`, when the job started"},"profitAfterCents":{"type":["integer","null"],"description":"The same, when the job finished"},"profitDeltaCents":{"type":["integer","null"],"description":"profitAfterCents − profitBeforeCents"},"error":{"type":["string","null"]},"recordedAt":{"type":"string","format":"date-time"},"completedAt":{"type":["string","null"],"format":"date-time"}},"required":["id","trigger","status","actor","reason","costRowIds","kindKeys","targets","tenantWide","earliestEffectiveFrom","ordersAffected","ordersDone","profitBeforeCents","profitAfterCents","profitDeltaCents","error","recordedAt","completedAt"],"description":"The restatement this change recorded; null when it cannot change any order's cost"}},"required":["id","key","grain","canonicalSource","required","orderScope","percentBase","unitCostMayInclude","createdAt","restatement"]}}}},"400":{"description":"Invalid body, or a default of the wrong shape for the grain","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}},"401":{"description":"Missing, unknown or revoked API key","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}},"403":{"description":"The key is public; this route needs a secret key","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}},"409":{"description":"`cost_kind_exists`: a kind with this key exists","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}}}}},"/cost-kinds/{key}":{"patch":{"operationId":"updateCostKind","summary":"Change whether a kind is required, where it is sourced, or its tenant-wide amount from a date","description":"`required` changes at once. `defaultAmount` (a money grain) or `defaultPercent` (0 to 100, the `percent` grain) appends a tenant ledger row effective from `effectiveFrom` (default now, past allowed); null ends the tenant-wide amount from that date. Earlier amounts stay in the ledger. A new amount restates orders from `effectiveFrom`; changing `required` restates every order, since it decides which orders are incomplete (`restatement`). `canonicalSource` names the system the brand keeps this kind in and changes no amount, so it restates nothing; set `unit_cost` to `shopify` for a brand that keeps its COGS in Shopify, which is what lets `autoAcceptShopifyCosts` act on a cost proposal.","tags":["Costs"],"security":[{"apiKey":[]}],"parameters":[{"schema":{"type":"string","minLength":1},"required":true,"name":"key","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"required":{"type":"boolean"},"defaultAmount":{"type":["string","null"],"pattern":"^\\d+(\\.\\d{1,6})?$","description":"A money grain's new tenant-wide amount from `effectiveFrom`; null ends it from that date"},"defaultPercent":{"type":["number","null"],"minimum":0,"maximum":100,"description":"The `percent` grain's new tenant-wide percent (0 to 100) from `effectiveFrom`; null ends it from that date"},"effectiveFrom":{"type":"string","format":"date-time","description":"When the new default applies; any date, past included. Defaults to now"},"canonicalSource":{"type":"string","minLength":1,"description":"Where this kind's amounts come from (`shopify`, `erp`, `csv`, …). `autoAcceptShopifyCosts` acts only while the `unit_cost` kind is sourced `shopify`"},"orderScope":{"type":["string","null"],"enum":["every","first","renewal","one_time","subscription",null],"description":"Which orders the kind is charged on: `every` (the default); `first` first orders only (inserts, welcome gifts); `renewal` renewals only; `subscription` subscription orders, meaning every renewal and a first order holding a subscription line (a mixed cart counts, since a subscription app's fee applies to the whole checkout); `one_time` orders with no subscription line. Changing it restates every order Null returns the kind to its profile's rule (or `every`)"},"percentBase":{"type":["string","null"],"enum":["revenue_with_shipping","product_revenue","unit_cost",null],"description":"A `percent` kind only: what it is a percent of. Every base is net of discounts and excludes tax. `revenue_with_shipping` (the default) is what the customer is charged, products plus shipping, as payment processors charge; `product_revenue` the products alone; `unit_cost` the order's `unit_cost` total (landed cost or scrap as a percent of COGS). Changing it restates every order Null returns the kind to its profile's base (or `revenue_with_shipping`)"},"unitCostMayInclude":{"type":["string","null"],"enum":["packaging","freight_in",null],"description":"The cost this kind counts that a brand's Shopify cost per item may already include. When the tenant's `unitCostIncludes` (PATCH /tenant) names it, the kind is not charged, so the cost is never counted twice"}}}}}},"responses":{"200":{"description":"The kind","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"key":{"type":"string"},"grain":{"type":"string","enum":["per_unit","per_parcel","per_order","percent"]},"canonicalSource":{"type":"string"},"required":{"type":"boolean"},"defaultAmount":{"type":["string","null"],"description":"A money grain's tenant-wide amount in effect now, from the ledger; absent on a `percent` kind"},"defaultPercent":{"type":["number","null"],"description":"The `percent` grain's tenant-wide percent (0 to 100) in effect now, from the ledger; absent on a money kind"},"orderScope":{"type":["string","null"],"enum":["every","first","renewal","one_time","subscription",null],"description":"The tenant's own order scope; null keeps the profile's rule for a kind it names (`3pl_insert`: `first`), else `every`"},"percentBase":{"type":["string","null"],"enum":["revenue_with_shipping","product_revenue","unit_cost",null],"description":"The tenant's own base for a percent kind; null keeps the profile's, else `revenue_with_shipping`"},"unitCostMayInclude":{"type":["string","null"],"enum":["packaging","freight_in",null],"description":"The tenant's own label; null keeps the profile's (`packaging_box`, `packaging_plastic`: `packaging`)"},"createdAt":{"type":"string","format":"date-time"},"restatement":{"type":["object","null"],"properties":{"id":{"type":"string","format":"uuid"},"trigger":{"type":"string","enum":["cost_row","cost_void","cost_import","cost_seed","cost_kind","manual"]},"status":{"type":"string","enum":["queued","running","completed","failed"]},"actor":{"type":"string"},"reason":{"type":["string","null"]},"costRowIds":{"type":"array","items":{"type":"string","format":"uuid"},"description":"The ledger rows written or voided by the request"},"kindKeys":{"type":"array","items":{"type":"string"}},"targets":{"type":"array","items":{"type":"object","properties":{"targetType":{"type":"string","enum":["item","product","offer","tenant"]},"targetId":{"type":"string"}},"required":["targetType","targetId"]},"description":"Empty when tenant-wide"},"tenantWide":{"type":"boolean","description":"Every attributed order from `earliestEffectiveFrom` is restated"},"earliestEffectiveFrom":{"type":"string","format":"date-time","description":"Orders placed at or after this date are affected"},"ordersAffected":{"type":"integer","minimum":0,"description":"Counted when the request was recorded"},"ordersDone":{"type":"integer","minimum":0},"profitBeforeCents":{"type":["integer","null"],"description":"Realized profit (current view) of the tenant's orders from `earliestEffectiveFrom`, when the job started"},"profitAfterCents":{"type":["integer","null"],"description":"The same, when the job finished"},"profitDeltaCents":{"type":["integer","null"],"description":"profitAfterCents − profitBeforeCents"},"error":{"type":["string","null"]},"recordedAt":{"type":"string","format":"date-time"},"completedAt":{"type":["string","null"],"format":"date-time"}},"required":["id","trigger","status","actor","reason","costRowIds","kindKeys","targets","tenantWide","earliestEffectiveFrom","ordersAffected","ordersDone","profitBeforeCents","profitAfterCents","profitDeltaCents","error","recordedAt","completedAt"],"description":"The restatement this change recorded; null when it cannot change any order's cost"}},"required":["id","key","grain","canonicalSource","required","orderScope","percentBase","unitCostMayInclude","createdAt","restatement"]}}}},"400":{"description":"Invalid body, or a default of the wrong shape for the grain","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}},"401":{"description":"Missing, unknown or revoked API key","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}},"403":{"description":"The key is public; this route needs a secret key","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}},"404":{"description":"No such kind","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}}}}},"/costs":{"get":{"operationId":"listCosts","summary":"List cost ledger rows","description":"Rows newest effective first, then newest recorded, filterable by kind and target. A row carries `amount` (a decimal) for a money kind and `percent` (0 to 100) for a `percent` kind. With `asOf`, the ledger as it stood then: rows recorded later are left out, and `voided` shows only voids recorded by then. Nothing is ever edited: a later `effectiveFrom` supersedes, the same `effectiveFrom` recorded later corrects, and a void cancels.","tags":["Costs"],"security":[{"apiKey":[]}],"parameters":[{"schema":{"type":"string"},"required":false,"name":"kindKey","in":"query"},{"schema":{"type":"string","enum":["item","product","offer","tenant"],"description":"`item` is the physical SKU (decision 73); `product` a Shopify product; `offer` an offer's own costs; `tenant` the kind's tenant-wide amount, with `targetId` \"*\""},"required":false,"description":"`item` is the physical SKU (decision 73); `product` a Shopify product; `offer` an offer's own costs; `tenant` the kind's tenant-wide amount, with `targetId` \"*\"","name":"targetType","in":"query"},{"schema":{"type":"string","description":"An item id or SKU with `targetType=item`; an offer id or code with `targetType=offer`; the product gid (`gid://shopify/Product/<id>`) with `targetType=product`"},"required":false,"description":"An item id or SKU with `targetType=item`; an offer id or code with `targetType=offer`; the product gid (`gid://shopify/Product/<id>`) with `targetType=product`","name":"targetId","in":"query"},{"schema":{"type":"string","format":"uuid","description":"Only this offer's own rows"},"required":false,"description":"Only this offer's own rows","name":"offerId","in":"query"},{"schema":{"type":"string","format":"date-time","description":"Record time; defaults to now"},"required":false,"description":"Record time; defaults to now","name":"asOf","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":500,"default":100},"required":false,"name":"limit","in":"query"},{"schema":{"type":["integer","null"],"minimum":0,"default":0},"required":false,"name":"offset","in":"query"}],"responses":{"200":{"description":"The page of rows","content":{"application/json":{"schema":{"type":"object","properties":{"rows":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"kindKey":{"type":"string"},"targetType":{"type":"string","enum":["item","product","offer","tenant"],"description":"`item` is the physical SKU (decision 73); `product` a Shopify product; `offer` an offer's own costs; `tenant` the kind's tenant-wide amount, with `targetId` \"*\""},"targetId":{"type":"string","description":"The item id, the product gid, the offer id, or \"*\" for the tenant"},"sku":{"type":["string","null"],"description":"The item's SKU when the target is an item with one"},"offerCode":{"type":["string","null"],"description":"The offer's code when the target is an offer"},"amount":{"type":["string","null"],"description":"A money grain's decimal amount; absent on a `percent` row; null ends the kind"},"percent":{"type":["number","null"],"description":"A `percent` row's percent, 0 to 100; absent on a money row; null ends the kind"},"effectiveFrom":{"type":"string","format":"date-time","description":"Valid time: when the value applies"},"recordedAt":{"type":"string","format":"date-time","description":"Record time: when Offer Suite learned it"},"source":{"type":"string","enum":["shopify","csv","api","agent"]},"voided":{"type":["object","null"],"properties":{"reason":{"type":"string","minLength":1,"maxLength":500},"recordedAt":{"type":"string","format":"date-time"},"actor":{"type":"string"}},"required":["reason","recordedAt","actor"],"description":"Set when the row was voided at or before the listing's `asOf`"}},"required":["id","kindKey","targetType","targetId","sku","offerCode","effectiveFrom","recordedAt","source","voided"]}},"asOf":{"type":"string","format":"date-time"},"limit":{"type":"integer"},"offset":{"type":"integer"}},"required":["rows","asOf","limit","offset"]}}}},"400":{"description":"Invalid query","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}},"401":{"description":"Missing, unknown or revoked API key","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}},"403":{"description":"The key is public; this route needs a secret key","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}}}},"post":{"operationId":"createCost","summary":"Add a cost ledger row","description":"Appends a row for an item (by id or SKU; an unknown SKU creates the item), a product, an offer (by id or code: a per-order, per-parcel or percent amount this offer alone incurs, such as an insert or a kitting fee; never per unit) or the tenant (`targetId` \"*\"). Every variant mapped to the item is costed by it. The kind must exist. `effectiveFrom` defaults to now and may be in the past: the value then applies to orders from that date. A money kind takes `amount` (a decimal) and a `percent` kind takes `percent` (0 to 100 of the order's revenue); the other is refused with 400. A null value ends the kind for the target from that date. The response's `restatement` recomputes the current-view profit of the orders on or after `effectiveFrom` that carry the target; poll it.","tags":["Costs"],"security":[{"apiKey":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"kindKey":{"type":"string","minLength":1},"targetType":{"type":"string","enum":["item","product","offer","tenant"]},"targetId":{"type":"string","minLength":1,"description":"For `item`: the item id or its SKU (an unknown SKU creates the item); for `product`: the product gid (`gid://shopify/Product/<id>`); for `offer`: the offer id or its code; \"*\" for tenant"},"amount":{"type":["string","null"],"pattern":"^\\d+(\\.\\d{1,6})?$","description":"For a money grain (per_unit, per_parcel, per_order): a decimal. null ends the kind for this target from `effectiveFrom`, so the product or tenant amount applies again"},"percent":{"type":["number","null"],"minimum":0,"maximum":100,"description":"For the `percent` grain: 0 to 100 of the order's revenue. null ends the kind for this target from `effectiveFrom`"},"effectiveFrom":{"type":"string","format":"date-time","description":"When the value starts applying: any date, past included (restates later orders). Defaults to now"},"source":{"type":"string","enum":["api","agent"],"default":"api"}},"required":["kindKey","targetType","targetId"]}}}},"responses":{"201":{"description":"The row","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"kindKey":{"type":"string"},"targetType":{"type":"string","enum":["item","product","offer","tenant"],"description":"`item` is the physical SKU (decision 73); `product` a Shopify product; `offer` an offer's own costs; `tenant` the kind's tenant-wide amount, with `targetId` \"*\""},"targetId":{"type":"string","description":"The item id, the product gid, the offer id, or \"*\" for the tenant"},"sku":{"type":["string","null"],"description":"The item's SKU when the target is an item with one"},"offerCode":{"type":["string","null"],"description":"The offer's code when the target is an offer"},"amount":{"type":["string","null"],"description":"A money grain's decimal amount; absent on a `percent` row; null ends the kind"},"percent":{"type":["number","null"],"description":"A `percent` row's percent, 0 to 100; absent on a money row; null ends the kind"},"effectiveFrom":{"type":"string","format":"date-time","description":"Valid time: when the value applies"},"recordedAt":{"type":"string","format":"date-time","description":"Record time: when Offer Suite learned it"},"source":{"type":"string","enum":["shopify","csv","api","agent"]},"voided":{"type":["object","null"],"properties":{"reason":{"type":"string","minLength":1,"maxLength":500},"recordedAt":{"type":"string","format":"date-time"},"actor":{"type":"string"}},"required":["reason","recordedAt","actor"],"description":"Set when the row was voided at or before the listing's `asOf`"},"restatement":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"trigger":{"type":"string","enum":["cost_row","cost_void","cost_import","cost_seed","cost_kind","manual"]},"status":{"type":"string","enum":["queued","running","completed","failed"]},"actor":{"type":"string"},"reason":{"type":["string","null"]},"costRowIds":{"type":"array","items":{"type":"string","format":"uuid"},"description":"The ledger rows written or voided by the request"},"kindKeys":{"type":"array","items":{"type":"string"}},"targets":{"type":"array","items":{"type":"object","properties":{"targetType":{"type":"string","enum":["item","product","offer","tenant"]},"targetId":{"type":"string"}},"required":["targetType","targetId"]},"description":"Empty when tenant-wide"},"tenantWide":{"type":"boolean","description":"Every attributed order from `earliestEffectiveFrom` is restated"},"earliestEffectiveFrom":{"type":"string","format":"date-time","description":"Orders placed at or after this date are affected"},"ordersAffected":{"type":"integer","minimum":0,"description":"Counted when the request was recorded"},"ordersDone":{"type":"integer","minimum":0},"profitBeforeCents":{"type":["integer","null"],"description":"Realized profit (current view) of the tenant's orders from `earliestEffectiveFrom`, when the job started"},"profitAfterCents":{"type":["integer","null"],"description":"The same, when the job finished"},"profitDeltaCents":{"type":["integer","null"],"description":"profitAfterCents − profitBeforeCents"},"error":{"type":["string","null"]},"recordedAt":{"type":"string","format":"date-time"},"completedAt":{"type":["string","null"],"format":"date-time"}},"required":["id","trigger","status","actor","reason","costRowIds","kindKeys","targets","tenantWide","earliestEffectiveFrom","ordersAffected","ordersDone","profitBeforeCents","profitAfterCents","profitDeltaCents","error","recordedAt","completedAt"],"description":"The restatement of past orders this write recorded; `ordersAffected` 0 means none, completed at once"}},"required":["id","kindKey","targetType","targetId","sku","offerCode","effectiveFrom","recordedAt","source","voided","restatement"]}}}},"400":{"description":"Invalid body, a value of the wrong shape for the kind's grain, unknown kind, unknown item id or offer, or a per-unit offer row","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}},"401":{"description":"Missing, unknown or revoked API key","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}},"403":{"description":"The key is public; this route needs a secret key","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}}}}},"/costs/{id}/void":{"post":{"operationId":"voidCost","x-destructive":true,"summary":"Void a cost ledger row entered by mistake","description":"The row stops existing for every read with `asOf` at or after now; reads as of an earlier time still see it. The row itself is kept. To change an amount that was right until a date, add a row with that `effectiveFrom` instead. The response's `restatement` recomputes the orders the row applied to.","tags":["Costs"],"security":[{"apiKey":[]}],"parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"reason":{"type":"string","minLength":1,"maxLength":500}},"required":["reason"]}}}},"responses":{"201":{"description":"The voided row","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"kindKey":{"type":"string"},"targetType":{"type":"string","enum":["item","product","offer","tenant"],"description":"`item` is the physical SKU (decision 73); `product` a Shopify product; `offer` an offer's own costs; `tenant` the kind's tenant-wide amount, with `targetId` \"*\""},"targetId":{"type":"string","description":"The item id, the product gid, the offer id, or \"*\" for the tenant"},"sku":{"type":["string","null"],"description":"The item's SKU when the target is an item with one"},"offerCode":{"type":["string","null"],"description":"The offer's code when the target is an offer"},"amount":{"type":["string","null"],"description":"A money grain's decimal amount; absent on a `percent` row; null ends the kind"},"percent":{"type":["number","null"],"description":"A `percent` row's percent, 0 to 100; absent on a money row; null ends the kind"},"effectiveFrom":{"type":"string","format":"date-time","description":"Valid time: when the value applies"},"recordedAt":{"type":"string","format":"date-time","description":"Record time: when Offer Suite learned it"},"source":{"type":"string","enum":["shopify","csv","api","agent"]},"voided":{"type":["object","null"],"properties":{"reason":{"type":"string","minLength":1,"maxLength":500},"recordedAt":{"type":"string","format":"date-time"},"actor":{"type":"string"}},"required":["reason","recordedAt","actor"],"description":"Set when the row was voided at or before the listing's `asOf`"},"restatement":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"trigger":{"type":"string","enum":["cost_row","cost_void","cost_import","cost_seed","cost_kind","manual"]},"status":{"type":"string","enum":["queued","running","completed","failed"]},"actor":{"type":"string"},"reason":{"type":["string","null"]},"costRowIds":{"type":"array","items":{"type":"string","format":"uuid"},"description":"The ledger rows written or voided by the request"},"kindKeys":{"type":"array","items":{"type":"string"}},"targets":{"type":"array","items":{"type":"object","properties":{"targetType":{"type":"string","enum":["item","product","offer","tenant"]},"targetId":{"type":"string"}},"required":["targetType","targetId"]},"description":"Empty when tenant-wide"},"tenantWide":{"type":"boolean","description":"Every attributed order from `earliestEffectiveFrom` is restated"},"earliestEffectiveFrom":{"type":"string","format":"date-time","description":"Orders placed at or after this date are affected"},"ordersAffected":{"type":"integer","minimum":0,"description":"Counted when the request was recorded"},"ordersDone":{"type":"integer","minimum":0},"profitBeforeCents":{"type":["integer","null"],"description":"Realized profit (current view) of the tenant's orders from `earliestEffectiveFrom`, when the job started"},"profitAfterCents":{"type":["integer","null"],"description":"The same, when the job finished"},"profitDeltaCents":{"type":["integer","null"],"description":"profitAfterCents − profitBeforeCents"},"error":{"type":["string","null"]},"recordedAt":{"type":"string","format":"date-time"},"completedAt":{"type":["string","null"],"format":"date-time"}},"required":["id","trigger","status","actor","reason","costRowIds","kindKeys","targets","tenantWide","earliestEffectiveFrom","ordersAffected","ordersDone","profitBeforeCents","profitAfterCents","profitDeltaCents","error","recordedAt","completedAt"],"description":"The restatement of past orders this write recorded; `ordersAffected` 0 means none, completed at once"}},"required":["id","kindKey","targetType","targetId","sku","offerCode","effectiveFrom","recordedAt","source","voided","restatement"]}}}},"400":{"description":"Invalid body","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}},"401":{"description":"Missing, unknown or revoked API key","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}},"403":{"description":"The key is public; this route needs a secret key","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}},"404":{"description":"No such row","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}},"409":{"description":"The row is already voided","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}}}}},"/costs/import":{"post":{"operationId":"importCosts","summary":"Import cost rows from CSV","description":"Body is `text/csv` with the header `kindKey,targetType,targetId,amount,percent,effectiveFrom`: each row fills `amount` (a decimal) for a money kind or `percent` (0 to 100) for a `percent` kind and leaves the other empty; `effectiveFrom` is optional (empty = now, past dates allowed); `targetId` is an item id or SKU for `item` rows, the product gid for `product` rows, an offer id or code for `offer` rows, `*` for a tenant row. An unknown SKU becomes an item (`itemsCreated`). Every row is validated first. With any rejection the whole file is refused (422) and nothing is applied, unless `partial=1`, in which case the valid rows are applied and the rejected ones reported. Rows are stored with source `csv`. The applied rows record one restatement (`restatement`).","tags":["Costs"],"security":[{"apiKey":[]}],"parameters":[{"schema":{"type":"string","enum":["1"]},"required":false,"name":"partial","in":"query"}],"requestBody":{"required":true,"content":{"text/csv":{"schema":{"type":"string"}}}},"responses":{"200":{"description":"Applied; `rejected` is non-empty only with `partial=1`","content":{"application/json":{"schema":{"type":"object","properties":{"applied":{"type":"integer","minimum":0},"rejected":{"type":"array","items":{"type":"object","properties":{"row":{"type":"integer","minimum":0},"column":{"type":"string"},"message":{"type":"string"}},"required":["row","column","message"]}},"itemsCreated":{"type":"array","items":{"type":"string"},"description":"SKUs the file named that had no item yet; each is now an item (source manual)"},"restatement":{"type":["object","null"],"properties":{"id":{"type":"string","format":"uuid"},"trigger":{"type":"string","enum":["cost_row","cost_void","cost_import","cost_seed","cost_kind","manual"]},"status":{"type":"string","enum":["queued","running","completed","failed"]},"actor":{"type":"string"},"reason":{"type":["string","null"]},"costRowIds":{"type":"array","items":{"type":"string","format":"uuid"},"description":"The ledger rows written or voided by the request"},"kindKeys":{"type":"array","items":{"type":"string"}},"targets":{"type":"array","items":{"type":"object","properties":{"targetType":{"type":"string","enum":["item","product","offer","tenant"]},"targetId":{"type":"string"}},"required":["targetType","targetId"]},"description":"Empty when tenant-wide"},"tenantWide":{"type":"boolean","description":"Every attributed order from `earliestEffectiveFrom` is restated"},"earliestEffectiveFrom":{"type":"string","format":"date-time","description":"Orders placed at or after this date are affected"},"ordersAffected":{"type":"integer","minimum":0,"description":"Counted when the request was recorded"},"ordersDone":{"type":"integer","minimum":0},"profitBeforeCents":{"type":["integer","null"],"description":"Realized profit (current view) of the tenant's orders from `earliestEffectiveFrom`, when the job started"},"profitAfterCents":{"type":["integer","null"],"description":"The same, when the job finished"},"profitDeltaCents":{"type":["integer","null"],"description":"profitAfterCents − profitBeforeCents"},"error":{"type":["string","null"]},"recordedAt":{"type":"string","format":"date-time"},"completedAt":{"type":["string","null"],"format":"date-time"}},"required":["id","trigger","status","actor","reason","costRowIds","kindKeys","targets","tenantWide","earliestEffectiveFrom","ordersAffected","ordersDone","profitBeforeCents","profitAfterCents","profitDeltaCents","error","recordedAt","completedAt"],"description":"The restatement of past orders the applied rows record; null when nothing was applied"}},"required":["applied","rejected","itemsCreated","restatement"]}}}},"400":{"description":"Invalid query, an item id no item has, or an unknown offer","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}},"401":{"description":"Missing, unknown or revoked API key","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}},"403":{"description":"The key is public; this route needs a secret key","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}},"422":{"description":"Nothing applied: `rejected` names each row and column","content":{"application/json":{"schema":{"type":"object","properties":{"applied":{"type":"integer","minimum":0},"rejected":{"type":"array","items":{"type":"object","properties":{"row":{"type":"integer","minimum":0},"column":{"type":"string"},"message":{"type":"string"}},"required":["row","column","message"]}},"itemsCreated":{"type":"array","items":{"type":"string"},"description":"SKUs the file named that had no item yet; each is now an item (source manual)"},"restatement":{"type":["object","null"],"properties":{"id":{"type":"string","format":"uuid"},"trigger":{"type":"string","enum":["cost_row","cost_void","cost_import","cost_seed","cost_kind","manual"]},"status":{"type":"string","enum":["queued","running","completed","failed"]},"actor":{"type":"string"},"reason":{"type":["string","null"]},"costRowIds":{"type":"array","items":{"type":"string","format":"uuid"},"description":"The ledger rows written or voided by the request"},"kindKeys":{"type":"array","items":{"type":"string"}},"targets":{"type":"array","items":{"type":"object","properties":{"targetType":{"type":"string","enum":["item","product","offer","tenant"]},"targetId":{"type":"string"}},"required":["targetType","targetId"]},"description":"Empty when tenant-wide"},"tenantWide":{"type":"boolean","description":"Every attributed order from `earliestEffectiveFrom` is restated"},"earliestEffectiveFrom":{"type":"string","format":"date-time","description":"Orders placed at or after this date are affected"},"ordersAffected":{"type":"integer","minimum":0,"description":"Counted when the request was recorded"},"ordersDone":{"type":"integer","minimum":0},"profitBeforeCents":{"type":["integer","null"],"description":"Realized profit (current view) of the tenant's orders from `earliestEffectiveFrom`, when the job started"},"profitAfterCents":{"type":["integer","null"],"description":"The same, when the job finished"},"profitDeltaCents":{"type":["integer","null"],"description":"profitAfterCents − profitBeforeCents"},"error":{"type":["string","null"]},"recordedAt":{"type":"string","format":"date-time"},"completedAt":{"type":["string","null"],"format":"date-time"}},"required":["id","trigger","status","actor","reason","costRowIds","kindKeys","targets","tenantWide","earliestEffectiveFrom","ordersAffected","ordersDone","profitBeforeCents","profitAfterCents","profitDeltaCents","error","recordedAt","completedAt"],"description":"The restatement of past orders the applied rows record; null when nothing was applied"}},"required":["applied","rejected","itemsCreated","restatement"]}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}}}}},"/costs/seed-from-shopify":{"post":{"operationId":"seedCostsFromShopify","summary":"Seed unit costs from Shopify's inventory unit cost","description":"Reads every variant of the connected store with its SKU and `inventoryItem.unitCost`, maps each variant to its item (one item per SKU, shared by the variants that carry it; one per variant without a SKU) and writes a `unit_cost` row (source `shopify`, kind created and required if missing) per item whose amount differs from the one in effect at `effectiveFrom` (default now; a past date backdates the seed). Variants without a unit cost are skipped, not zeroed; variants sharing a SKU with different unit costs are reported as `conflicts` and left unwritten. `storeId` is required only when the tenant has more than one connected store. New rows and moved variants record one restatement (`restatement`).","tags":["Costs"],"security":[{"apiKey":[]}],"requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"object","properties":{"storeId":{"type":"string","format":"uuid"},"effectiveFrom":{"type":"string","format":"date-time","description":"When Shopify's amounts start applying; defaults to now"}}}}}},"responses":{"200":{"description":"What was read and written","content":{"application/json":{"schema":{"type":"object","properties":{"storeId":{"type":"string","format":"uuid"},"myshopifyDomain":{"type":"string"},"variants":{"type":"integer","minimum":0,"description":"Variants read from the store"},"written":{"type":"integer","minimum":0,"description":"New `unit_cost` rows on items, source shopify"},"unchanged":{"type":"integer","minimum":0,"description":"Items whose effective `unit_cost` row already carries Shopify's unit cost"},"withoutCost":{"type":"integer","minimum":0,"description":"Variants with no unit cost in Shopify"},"items":{"type":"object","properties":{"created":{"type":"integer","minimum":0,"description":"Items created: one per SKU, one per variant without a SKU"},"repointed":{"type":"integer","minimum":0,"description":"Variants moved to the item of their SKU; their orders are restated"}},"required":["created","repointed"]},"duplicates":{"type":"array","items":{"type":"object","properties":{"sku":{"type":"string"},"itemId":{"type":"string","format":"uuid"},"variantIds":{"type":"array","items":{"type":"string","pattern":"^gid:\\/\\/shopify\\/ProductVariant\\/\\d+$","description":"A Shopify ProductVariant gid (`gid://shopify/ProductVariant/<id>`)"}}},"required":["sku","itemId","variantIds"]},"description":"SKUs shared by more than one variant: one item, one cost"},"components":{"type":"object","properties":{"bundles":{"type":"integer","minimum":0,"description":"Shopify fixed-bundle variants read: their items are kits costed as their components, never seeded a `unit_cost` row"},"written":{"type":"integer","minimum":0,"description":"Kits whose component set was created or changed, from `effectiveFrom`"},"conflicts":{"type":"array","items":{"type":"object","properties":{"itemId":{"type":"string","format":"uuid"},"sku":{"type":["string","null"]},"variantIds":{"type":"array","items":{"type":"string","pattern":"^gid:\\/\\/shopify\\/ProductVariant\\/\\d+$","description":"A Shopify ProductVariant gid (`gid://shopify/ProductVariant/<id>`)"}}},"required":["itemId","sku","variantIds"]},"description":"Kits (one SKU) whose bundle variants list different components: no set is written for them; make the bundles agree in Shopify and reseed, or set the kit with `setItemComponents`"}},"required":["bundles","written","conflicts"]},"conflicts":{"type":"array","items":{"type":"object","properties":{"sku":{"type":"string"},"itemId":{"type":"string","format":"uuid"},"variants":{"type":"array","items":{"type":"object","properties":{"variantId":{"type":"string","pattern":"^gid:\\/\\/shopify\\/ProductVariant\\/\\d+$","description":"A Shopify ProductVariant gid (`gid://shopify/ProductVariant/<id>`)"},"unitCost":{"type":"string"}},"required":["variantId","unitCost"]}}},"required":["sku","itemId","variants"]},"description":"SKUs whose variants carry different Shopify unit costs: no `unit_cost` row is written for them (a missing cost is never a guess); fix Shopify and reseed, or write the SKU's cost directly"},"restatement":{"type":["object","null"],"properties":{"id":{"type":"string","format":"uuid"},"trigger":{"type":"string","enum":["cost_row","cost_void","cost_import","cost_seed","cost_kind","manual"]},"status":{"type":"string","enum":["queued","running","completed","failed"]},"actor":{"type":"string"},"reason":{"type":["string","null"]},"costRowIds":{"type":"array","items":{"type":"string","format":"uuid"},"description":"The ledger rows written or voided by the request"},"kindKeys":{"type":"array","items":{"type":"string"}},"targets":{"type":"array","items":{"type":"object","properties":{"targetType":{"type":"string","enum":["item","product","offer","tenant"]},"targetId":{"type":"string"}},"required":["targetType","targetId"]},"description":"Empty when tenant-wide"},"tenantWide":{"type":"boolean","description":"Every attributed order from `earliestEffectiveFrom` is restated"},"earliestEffectiveFrom":{"type":"string","format":"date-time","description":"Orders placed at or after this date are affected"},"ordersAffected":{"type":"integer","minimum":0,"description":"Counted when the request was recorded"},"ordersDone":{"type":"integer","minimum":0},"profitBeforeCents":{"type":["integer","null"],"description":"Realized profit (current view) of the tenant's orders from `earliestEffectiveFrom`, when the job started"},"profitAfterCents":{"type":["integer","null"],"description":"The same, when the job finished"},"profitDeltaCents":{"type":["integer","null"],"description":"profitAfterCents − profitBeforeCents"},"error":{"type":["string","null"]},"recordedAt":{"type":"string","format":"date-time"},"completedAt":{"type":["string","null"],"format":"date-time"}},"required":["id","trigger","status","actor","reason","costRowIds","kindKeys","targets","tenantWide","earliestEffectiveFrom","ordersAffected","ordersDone","profitBeforeCents","profitAfterCents","profitDeltaCents","error","recordedAt","completedAt"],"description":"The restatement of past orders the new rows record; null when nothing was written"}},"required":["storeId","myshopifyDomain","variants","written","unchanged","withoutCost","items","duplicates","components","conflicts","restatement"]}}}},"400":{"description":"Invalid body","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}},"401":{"description":"Missing, unknown or revoked API key","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}},"403":{"description":"The key is public; this route needs a secret key","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}},"404":{"description":"No such connected store","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}},"409":{"description":"More than one connected store; send `storeId`","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}},"502":{"description":"Shopify refused the read; the message says why","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}}}}},"/costs/effective":{"get":{"operationId":"getEffectiveCosts","summary":"The cost of a variant on a date, by kind","description":"Resolves each kind as the ingest and the economics do: the newest ledger row effective at `at` for the variant's item, else (for a kit) the sum of its components, else its product, else the tenant. `asOf` reads the ledger as it was recorded at that time (default now). `missing` lists required kinds an order of it would miss: no amount at any level and no kind-level default of the cost profile (decided as the realized mirror decides an order); a kit with a component missing a kind is missing that kind, never short.","tags":["Costs"],"security":[{"apiKey":[]}],"parameters":[{"schema":{"type":"string","pattern":"^gid:\\/\\/shopify\\/ProductVariant\\/\\d+$","description":"A Shopify ProductVariant gid (`gid://shopify/ProductVariant/<id>`)"},"required":true,"description":"A Shopify ProductVariant gid (`gid://shopify/ProductVariant/<id>`)","name":"variantId","in":"query"},{"schema":{"type":"string","pattern":"^gid:\\/\\/shopify\\/Product\\/\\d+$","description":"The variant's product gid; enables product-level inheritance"},"required":false,"description":"The variant's product gid; enables product-level inheritance","name":"productId","in":"query"},{"schema":{"type":"string","format":"date-time","description":"Valid time; defaults to now"},"required":false,"description":"Valid time; defaults to now","name":"at","in":"query"},{"schema":{"type":"string","format":"date-time","description":"Record time; defaults to now"},"required":false,"description":"Record time; defaults to now","name":"asOf","in":"query"}],"responses":{"200":{"description":"The effective costs","content":{"application/json":{"schema":{"type":"object","properties":{"at":{"type":"string","format":"date-time"},"asOf":{"type":"string","format":"date-time"},"variantId":{"type":"string","pattern":"^gid:\\/\\/shopify\\/ProductVariant\\/\\d+$","description":"A Shopify ProductVariant gid (`gid://shopify/ProductVariant/<id>`)"},"productId":{"type":["string","null"],"pattern":"^gid:\\/\\/shopify\\/Product\\/\\d+$","description":"A Shopify Product gid (`gid://shopify/Product/<id>`)"},"itemId":{"type":["string","null"],"description":"The item the variant maps to; null until it is seeded, ordered or mapped"},"sku":{"type":["string","null"]},"costs":{"type":"object","additionalProperties":{"type":"object","properties":{"amount":{"type":"number","description":"A money grain's amount; absent on a `percent` kind"},"percent":{"type":"number","description":"The `percent` grain's percent, 0 to 100; absent on a money kind"},"source":{"type":"string","enum":["item","components","product","default"]},"grain":{"type":"string","enum":["per_unit","per_parcel","per_order","percent"]}},"required":["source","grain"]}},"components":{"type":"array","items":{"type":"object","properties":{"itemId":{"type":"string","format":"uuid"},"sku":{"type":["string","null"]},"title":{"type":["string","null"]},"quantity":{"type":"integer","exclusiveMinimum":0},"costs":{"type":"object","additionalProperties":{"type":"object","properties":{"amount":{"type":"number","description":"A money grain's amount; absent on a `percent` kind"},"percent":{"type":"number","description":"The `percent` grain's percent, 0 to 100; absent on a money kind"},"source":{"type":"string","enum":["item","components","product","default"]},"grain":{"type":"string","enum":["per_unit","per_parcel","per_order","percent"]}},"required":["source","grain"]}}},"required":["itemId","sku","title","quantity","costs"]},"description":"When the variant's item is a kit: each component with its own effective costs; a per-unit kind the kit has no row for is their sum × quantity"},"missing":{"type":"array","items":{"type":"string"},"description":"Required kinds with no amount at any level and no kind-level default of the cost profile: the costs are incomplete, not zero"}},"required":["at","asOf","variantId","productId","itemId","sku","costs","components","missing"]}}}},"400":{"description":"Invalid query","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}},"401":{"description":"Missing, unknown or revoked API key","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}},"403":{"description":"The key is public; this route needs a secret key","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}}}}},"/cost-restatements":{"get":{"operationId":"listCostRestatements","summary":"List restatements of past orders, newest first","description":"Every cost write that can change what past orders cost records a restatement: which rows, which orders (from `earliestEffectiveFrom`, on the targets or tenant-wide), its status, and realized profit in the current view before and after. `failed` ones stay listed with the error; run `POST /cost-restatements` to try again.","tags":["Costs"],"security":[{"apiKey":[]}],"parameters":[{"schema":{"type":"integer","minimum":1,"maximum":200,"default":50},"required":false,"name":"limit","in":"query"},{"schema":{"type":["integer","null"],"minimum":0,"default":0},"required":false,"name":"offset","in":"query"}],"responses":{"200":{"description":"The page","content":{"application/json":{"schema":{"type":"object","properties":{"restatements":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"trigger":{"type":"string","enum":["cost_row","cost_void","cost_import","cost_seed","cost_kind","manual"]},"status":{"type":"string","enum":["queued","running","completed","failed"]},"actor":{"type":"string"},"reason":{"type":["string","null"]},"costRowIds":{"type":"array","items":{"type":"string","format":"uuid"},"description":"The ledger rows written or voided by the request"},"kindKeys":{"type":"array","items":{"type":"string"}},"targets":{"type":"array","items":{"type":"object","properties":{"targetType":{"type":"string","enum":["item","product","offer","tenant"]},"targetId":{"type":"string"}},"required":["targetType","targetId"]},"description":"Empty when tenant-wide"},"tenantWide":{"type":"boolean","description":"Every attributed order from `earliestEffectiveFrom` is restated"},"earliestEffectiveFrom":{"type":"string","format":"date-time","description":"Orders placed at or after this date are affected"},"ordersAffected":{"type":"integer","minimum":0,"description":"Counted when the request was recorded"},"ordersDone":{"type":"integer","minimum":0},"profitBeforeCents":{"type":["integer","null"],"description":"Realized profit (current view) of the tenant's orders from `earliestEffectiveFrom`, when the job started"},"profitAfterCents":{"type":["integer","null"],"description":"The same, when the job finished"},"profitDeltaCents":{"type":["integer","null"],"description":"profitAfterCents − profitBeforeCents"},"error":{"type":["string","null"]},"recordedAt":{"type":"string","format":"date-time"},"completedAt":{"type":["string","null"],"format":"date-time"}},"required":["id","trigger","status","actor","reason","costRowIds","kindKeys","targets","tenantWide","earliestEffectiveFrom","ordersAffected","ordersDone","profitBeforeCents","profitAfterCents","profitDeltaCents","error","recordedAt","completedAt"]}},"limit":{"type":"integer"},"offset":{"type":"integer"}},"required":["restatements","limit","offset"]}}}},"400":{"description":"Invalid query","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}},"401":{"description":"Missing, unknown or revoked API key","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}},"403":{"description":"The key is public; this route needs a secret key","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}}}},"post":{"operationId":"restateCosts","summary":"Recompute the current-view cost of every attributed order","description":"Cost writes restate the orders they touch on their own; use this after a failed restatement, or to recompute every order from `effectiveFrom` (default the epoch) with the ledger as it stands. The ledger and the as-recorded view never change.","tags":["Costs"],"security":[{"apiKey":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"reason":{"type":"string","minLength":1,"maxLength":500},"effectiveFrom":{"type":"string","format":"date-time","description":"Orders placed at or after this date; defaults to all"}},"required":["reason"]}}}},"responses":{"202":{"description":"Recorded and queued","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"trigger":{"type":"string","enum":["cost_row","cost_void","cost_import","cost_seed","cost_kind","manual"]},"status":{"type":"string","enum":["queued","running","completed","failed"]},"actor":{"type":"string"},"reason":{"type":["string","null"]},"costRowIds":{"type":"array","items":{"type":"string","format":"uuid"},"description":"The ledger rows written or voided by the request"},"kindKeys":{"type":"array","items":{"type":"string"}},"targets":{"type":"array","items":{"type":"object","properties":{"targetType":{"type":"string","enum":["item","product","offer","tenant"]},"targetId":{"type":"string"}},"required":["targetType","targetId"]},"description":"Empty when tenant-wide"},"tenantWide":{"type":"boolean","description":"Every attributed order from `earliestEffectiveFrom` is restated"},"earliestEffectiveFrom":{"type":"string","format":"date-time","description":"Orders placed at or after this date are affected"},"ordersAffected":{"type":"integer","minimum":0,"description":"Counted when the request was recorded"},"ordersDone":{"type":"integer","minimum":0},"profitBeforeCents":{"type":["integer","null"],"description":"Realized profit (current view) of the tenant's orders from `earliestEffectiveFrom`, when the job started"},"profitAfterCents":{"type":["integer","null"],"description":"The same, when the job finished"},"profitDeltaCents":{"type":["integer","null"],"description":"profitAfterCents − profitBeforeCents"},"error":{"type":["string","null"]},"recordedAt":{"type":"string","format":"date-time"},"completedAt":{"type":["string","null"],"format":"date-time"}},"required":["id","trigger","status","actor","reason","costRowIds","kindKeys","targets","tenantWide","earliestEffectiveFrom","ordersAffected","ordersDone","profitBeforeCents","profitAfterCents","profitDeltaCents","error","recordedAt","completedAt"]}}}},"400":{"description":"Invalid body","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}},"401":{"description":"Missing, unknown or revoked API key","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}},"403":{"description":"The key is public; this route needs a secret key","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}}}}},"/cost-restatements/{id}":{"get":{"operationId":"getCostRestatement","summary":"One restatement: poll it after a cost write until it is completed","description":"`ordersDone` counts up to `ordersAffected` while it runs; `profitDeltaCents` is set once it completes.","tags":["Costs"],"security":[{"apiKey":[]}],"parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"The restatement","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"trigger":{"type":"string","enum":["cost_row","cost_void","cost_import","cost_seed","cost_kind","manual"]},"status":{"type":"string","enum":["queued","running","completed","failed"]},"actor":{"type":"string"},"reason":{"type":["string","null"]},"costRowIds":{"type":"array","items":{"type":"string","format":"uuid"},"description":"The ledger rows written or voided by the request"},"kindKeys":{"type":"array","items":{"type":"string"}},"targets":{"type":"array","items":{"type":"object","properties":{"targetType":{"type":"string","enum":["item","product","offer","tenant"]},"targetId":{"type":"string"}},"required":["targetType","targetId"]},"description":"Empty when tenant-wide"},"tenantWide":{"type":"boolean","description":"Every attributed order from `earliestEffectiveFrom` is restated"},"earliestEffectiveFrom":{"type":"string","format":"date-time","description":"Orders placed at or after this date are affected"},"ordersAffected":{"type":"integer","minimum":0,"description":"Counted when the request was recorded"},"ordersDone":{"type":"integer","minimum":0},"profitBeforeCents":{"type":["integer","null"],"description":"Realized profit (current view) of the tenant's orders from `earliestEffectiveFrom`, when the job started"},"profitAfterCents":{"type":["integer","null"],"description":"The same, when the job finished"},"profitDeltaCents":{"type":["integer","null"],"description":"profitAfterCents − profitBeforeCents"},"error":{"type":["string","null"]},"recordedAt":{"type":"string","format":"date-time"},"completedAt":{"type":["string","null"],"format":"date-time"}},"required":["id","trigger","status","actor","reason","costRowIds","kindKeys","targets","tenantWide","earliestEffectiveFrom","ordersAffected","ordersDone","profitBeforeCents","profitAfterCents","profitDeltaCents","error","recordedAt","completedAt"]}}}},"400":{"description":"Invalid id","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}},"401":{"description":"Missing, unknown or revoked API key","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}},"403":{"description":"The key is public; this route needs a secret key","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}},"404":{"description":"No such restatement","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}}}}},"/cost-proposals":{"get":{"operationId":"listCostProposals","summary":"List Shopify cost and SKU changes waiting for a decision","description":"Newest first. Each row is something Shopify changed that we have not written to the ledger: a unit cost, a SKU, or a variant no item is mapped to. A unit cost or SKU the merchant cleared is a `unit_cost` or `sku_changed` row whose `newValue` is null: until you decide it, the ledger keeps costing the item at the old amount. `pending` is the total waiting and `autoAccepted` the total the tenant's own `autoAcceptShopifyCosts` setting has taken without anyone being asked; both are tenant totals that ignore this page and the filters, so you can report the backlog and what was decided for the brand without paging. On each row, `automatic` says which of the two decided it. Accept one with `POST /cost-proposals/{id}/accept`, dismiss it with `.../ignore`; ignoring the same value keeps it quiet, a different value raises a fresh proposal. A proposal is never a cost until it is accepted.","tags":["Costs"],"security":[{"apiKey":[]}],"parameters":[{"schema":{"type":"string","enum":["pending","accepted","ignored","superseded"],"default":"pending","description":"Pass any status to see what was decided"},"required":false,"description":"Pass any status to see what was decided","name":"status","in":"query"},{"schema":{"type":"string","enum":["unit_cost","sku_changed","new_variant"],"description":"Only proposals of this type"},"required":false,"description":"Only proposals of this type","name":"type","in":"query"},{"schema":{"type":"string","enum":["true","false"],"description":"`true` for only what the tenant's setting decided, `false` for only what a person decided; omit for both"},"required":false,"description":"`true` for only what the tenant's setting decided, `false` for only what a person decided; omit for both","name":"automatic","in":"query"},{"schema":{"type":"string","format":"uuid","description":"Only the proposals about this item. The dashboard's item page (OS-67) is what this is for; nothing links to it yet"},"required":false,"description":"Only the proposals about this item. The dashboard's item page (OS-67) is what this is for; nothing links to it yet","name":"itemId","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":200,"default":50},"required":false,"name":"limit","in":"query"},{"schema":{"type":["integer","null"],"minimum":0,"default":0},"required":false,"name":"offset","in":"query"}],"responses":{"200":{"description":"The page of proposals","content":{"application/json":{"schema":{"type":"object","properties":{"proposals":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"type":{"type":"string","enum":["unit_cost","sku_changed","new_variant"],"description":"`unit_cost`: Shopify's unit cost for this inventory item is a different number, or was cleared (`newValue` null). `sku_changed`: its SKU is a different string, or was cleared (`newValue` null). `new_variant`: Shopify has a variant no item is mapped to yet."},"status":{"type":"string","enum":["pending","accepted","ignored","superseded"],"description":"`superseded` means a later change for the same inventory item arrived while this one was still pending; act on the later one."},"storeId":{"type":"string","format":"uuid"},"inventoryItemId":{"type":"string","pattern":"^gid:\\/\\/shopify\\/InventoryItem\\/\\d+$","description":"The inventory item the change is about; the webhook payload names no variant, so this is the key everything maps on"},"variantId":{"type":["string","null"],"pattern":"^gid:\\/\\/shopify\\/ProductVariant\\/\\d+$","description":"A Shopify ProductVariant gid (`gid://shopify/ProductVariant/<id>`)"},"itemId":{"type":["string","null"],"format":"uuid","description":"The item an accepted `unit_cost` proposal costs. Null for a `new_variant`, which has no item until it is accepted"},"sku":{"type":["string","null"],"description":"The item's SKU today, for labelling"},"newValue":{"type":["string","null"],"description":"What Shopify now says: an amount for `unit_cost`, a SKU for `sku_changed` or `new_variant`. Null when Shopify now has none: a unit cost or SKU the merchant cleared, or a new variant without a SKU. Accepting a cleared `unit_cost` ends the item's cost from `sourceUpdatedAt`, so its orders from then on read as incomplete until a cost is written"},"oldValue":{"type":["string","null"],"description":"What we had observed before; null when we had never observed this inventory item"},"sourceUpdatedAt":{"type":"string","format":"date-time","description":"Shopify's `updated_at` for the change. Accepting a `unit_cost` proposal writes this as the ledger row's `effectiveFrom` unless you send another date"},"observed":{"type":"object","additionalProperties":{},"description":"The evidence. `via` is `webhook` or `reconciliation`; `costFromPayload` says whether the delivery itself carried the cost or the Admin API had to be asked. `conflict`, when present, is the OS-75 rule: other variants share this item and Shopify still prices them differently, so accepting picks one number for all of them."},"decidedBy":{"type":["string","null"]},"automatic":{"type":"boolean","description":"True when the tenant's own `autoAcceptShopifyCosts` setting accepted this, with nobody asked; false for a pending proposal and for one a person decided. Read this rather than matching `decidedBy` against an actor string: who counts as the system is this API's judgement, not a caller's."},"decidedAt":{"type":["string","null"],"format":"date-time"},"costRowId":{"type":["string","null"],"format":"uuid","description":"The ledger row an accepted `unit_cost` proposal wrote (for a cleared cost, the row with no amount that ends it)"},"createdAt":{"type":"string","format":"date-time"}},"required":["id","type","status","storeId","inventoryItemId","variantId","itemId","sku","newValue","oldValue","sourceUpdatedAt","observed","decidedBy","automatic","decidedAt","costRowId","createdAt"]}},"pending":{"type":"integer","description":"Every pending proposal of the tenant, not just this page"},"autoAccepted":{"type":"integer","description":"Every proposal the tenant's `autoAcceptShopifyCosts` setting has accepted, not just this page"},"limit":{"type":"integer"},"offset":{"type":"integer"}},"required":["proposals","pending","autoAccepted","limit","offset"]}}}},"400":{"description":"Invalid query","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}},"401":{"description":"Missing, unknown or revoked API key","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}},"403":{"description":"The key is public; this route needs a secret key","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}}}}},"/cost-proposals/{id}/accept":{"post":{"operationId":"acceptCostProposal","summary":"Accept a Shopify cost or SKU change","description":"A `unit_cost` proposal appends one `unit_cost` ledger row on the variant's **item** (so every variant of that item is costed by it, and a kit is still the sum of its parts), source `shopify`, `effectiveFrom` Shopify's `updated_at` unless you send another date, and records a restatement of the orders from that date: poll `restatement`. A cleared `unit_cost` (`newValue` null) appends the same row with no amount, which ends the item's cost from that date: its later orders restate as missing `unit_cost` and `GET /items/health` lists the item under `itemsWithoutCost` and those orders under `ordersIncomplete` until you write a cost (or send `amount` here to write yours instead). A `sku_changed` proposal renames the item when this variant was its only one, and otherwise re-points the variant to the item of the new SKU, creating it if needed; that restates both items from the beginning. A cleared SKU (`newValue` null) gives the variant an item of its own with no SKU the same way: its item drops the SKU when the variant was its only one (nothing restates), otherwise it moves to a new SKU-less item and both items restate. A `new_variant` proposal creates the item and the mapping the seed would have, and its unit cost follows as its own proposal. Only a pending proposal can be accepted.","tags":["Costs"],"security":[{"apiKey":[]}],"parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"object","properties":{"effectiveFrom":{"type":"string","format":"date-time","description":"Overrides Shopify's `updated_at` as the date the amount applies from. Past dates are allowed and restate past orders"},"amount":{"type":"string","pattern":"^\\d+(\\.\\d{1,6})?$","description":"Overrides Shopify's amount: accept the change but at your own number. It applies to a `unit_cost` proposal only (a cleared one included, where it is written instead of ending the cost) — a `sku_changed` or `new_variant` proposal writes no amount, so it is ignored there."}}}}}},"responses":{"200":{"description":"The decided proposal","content":{"application/json":{"schema":{"type":"object","properties":{"proposal":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"type":{"type":"string","enum":["unit_cost","sku_changed","new_variant"],"description":"`unit_cost`: Shopify's unit cost for this inventory item is a different number, or was cleared (`newValue` null). `sku_changed`: its SKU is a different string, or was cleared (`newValue` null). `new_variant`: Shopify has a variant no item is mapped to yet."},"status":{"type":"string","enum":["pending","accepted","ignored","superseded"],"description":"`superseded` means a later change for the same inventory item arrived while this one was still pending; act on the later one."},"storeId":{"type":"string","format":"uuid"},"inventoryItemId":{"type":"string","pattern":"^gid:\\/\\/shopify\\/InventoryItem\\/\\d+$","description":"The inventory item the change is about; the webhook payload names no variant, so this is the key everything maps on"},"variantId":{"type":["string","null"],"pattern":"^gid:\\/\\/shopify\\/ProductVariant\\/\\d+$","description":"A Shopify ProductVariant gid (`gid://shopify/ProductVariant/<id>`)"},"itemId":{"type":["string","null"],"format":"uuid","description":"The item an accepted `unit_cost` proposal costs. Null for a `new_variant`, which has no item until it is accepted"},"sku":{"type":["string","null"],"description":"The item's SKU today, for labelling"},"newValue":{"type":["string","null"],"description":"What Shopify now says: an amount for `unit_cost`, a SKU for `sku_changed` or `new_variant`. Null when Shopify now has none: a unit cost or SKU the merchant cleared, or a new variant without a SKU. Accepting a cleared `unit_cost` ends the item's cost from `sourceUpdatedAt`, so its orders from then on read as incomplete until a cost is written"},"oldValue":{"type":["string","null"],"description":"What we had observed before; null when we had never observed this inventory item"},"sourceUpdatedAt":{"type":"string","format":"date-time","description":"Shopify's `updated_at` for the change. Accepting a `unit_cost` proposal writes this as the ledger row's `effectiveFrom` unless you send another date"},"observed":{"type":"object","additionalProperties":{},"description":"The evidence. `via` is `webhook` or `reconciliation`; `costFromPayload` says whether the delivery itself carried the cost or the Admin API had to be asked. `conflict`, when present, is the OS-75 rule: other variants share this item and Shopify still prices them differently, so accepting picks one number for all of them."},"decidedBy":{"type":["string","null"]},"automatic":{"type":"boolean","description":"True when the tenant's own `autoAcceptShopifyCosts` setting accepted this, with nobody asked; false for a pending proposal and for one a person decided. Read this rather than matching `decidedBy` against an actor string: who counts as the system is this API's judgement, not a caller's."},"decidedAt":{"type":["string","null"],"format":"date-time"},"costRowId":{"type":["string","null"],"format":"uuid","description":"The ledger row an accepted `unit_cost` proposal wrote (for a cleared cost, the row with no amount that ends it)"},"createdAt":{"type":"string","format":"date-time"}},"required":["id","type","status","storeId","inventoryItemId","variantId","itemId","sku","newValue","oldValue","sourceUpdatedAt","observed","decidedBy","automatic","decidedAt","costRowId","createdAt"]},"restatement":{"type":["object","null"],"properties":{"id":{"type":"string","format":"uuid"},"trigger":{"type":"string","enum":["cost_row","cost_void","cost_import","cost_seed","cost_kind","manual"]},"status":{"type":"string","enum":["queued","running","completed","failed"]},"actor":{"type":"string"},"reason":{"type":["string","null"]},"costRowIds":{"type":"array","items":{"type":"string","format":"uuid"},"description":"The ledger rows written or voided by the request"},"kindKeys":{"type":"array","items":{"type":"string"}},"targets":{"type":"array","items":{"type":"object","properties":{"targetType":{"type":"string","enum":["item","product","offer","tenant"]},"targetId":{"type":"string"}},"required":["targetType","targetId"]},"description":"Empty when tenant-wide"},"tenantWide":{"type":"boolean","description":"Every attributed order from `earliestEffectiveFrom` is restated"},"earliestEffectiveFrom":{"type":"string","format":"date-time","description":"Orders placed at or after this date are affected"},"ordersAffected":{"type":"integer","minimum":0,"description":"Counted when the request was recorded"},"ordersDone":{"type":"integer","minimum":0},"profitBeforeCents":{"type":["integer","null"],"description":"Realized profit (current view) of the tenant's orders from `earliestEffectiveFrom`, when the job started"},"profitAfterCents":{"type":["integer","null"],"description":"The same, when the job finished"},"profitDeltaCents":{"type":["integer","null"],"description":"profitAfterCents − profitBeforeCents"},"error":{"type":["string","null"]},"recordedAt":{"type":"string","format":"date-time"},"completedAt":{"type":["string","null"],"format":"date-time"}},"required":["id","trigger","status","actor","reason","costRowIds","kindKeys","targets","tenantWide","earliestEffectiveFrom","ordersAffected","ordersDone","profitBeforeCents","profitAfterCents","profitDeltaCents","error","recordedAt","completedAt"]}},"required":["proposal","restatement"]}}}},"400":{"description":"Invalid body","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}},"401":{"description":"Missing, unknown or revoked API key","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}},"403":{"description":"The key is public; this route needs a secret key","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}},"404":{"description":"No such proposal","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}},"409":{"description":"`proposal_decided`: this proposal is not pending","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}}}}},"/cost-proposals/{id}/ignore":{"post":{"operationId":"ignoreCostProposal","summary":"Dismiss a Shopify cost or SKU change","description":"Nothing is written to the ledger and the mapping does not move: ignoring a cleared unit cost keeps the item costed at the amount it had. The same value never alerts again — a redelivery of the same change is the same fact — but a different value raises a fresh proposal, so ignoring is not muting. Only a pending proposal can be ignored.","tags":["Costs"],"security":[{"apiKey":[]}],"parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"The dismissed proposal","content":{"application/json":{"schema":{"type":"object","properties":{"proposal":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"type":{"type":"string","enum":["unit_cost","sku_changed","new_variant"],"description":"`unit_cost`: Shopify's unit cost for this inventory item is a different number, or was cleared (`newValue` null). `sku_changed`: its SKU is a different string, or was cleared (`newValue` null). `new_variant`: Shopify has a variant no item is mapped to yet."},"status":{"type":"string","enum":["pending","accepted","ignored","superseded"],"description":"`superseded` means a later change for the same inventory item arrived while this one was still pending; act on the later one."},"storeId":{"type":"string","format":"uuid"},"inventoryItemId":{"type":"string","pattern":"^gid:\\/\\/shopify\\/InventoryItem\\/\\d+$","description":"The inventory item the change is about; the webhook payload names no variant, so this is the key everything maps on"},"variantId":{"type":["string","null"],"pattern":"^gid:\\/\\/shopify\\/ProductVariant\\/\\d+$","description":"A Shopify ProductVariant gid (`gid://shopify/ProductVariant/<id>`)"},"itemId":{"type":["string","null"],"format":"uuid","description":"The item an accepted `unit_cost` proposal costs. Null for a `new_variant`, which has no item until it is accepted"},"sku":{"type":["string","null"],"description":"The item's SKU today, for labelling"},"newValue":{"type":["string","null"],"description":"What Shopify now says: an amount for `unit_cost`, a SKU for `sku_changed` or `new_variant`. Null when Shopify now has none: a unit cost or SKU the merchant cleared, or a new variant without a SKU. Accepting a cleared `unit_cost` ends the item's cost from `sourceUpdatedAt`, so its orders from then on read as incomplete until a cost is written"},"oldValue":{"type":["string","null"],"description":"What we had observed before; null when we had never observed this inventory item"},"sourceUpdatedAt":{"type":"string","format":"date-time","description":"Shopify's `updated_at` for the change. Accepting a `unit_cost` proposal writes this as the ledger row's `effectiveFrom` unless you send another date"},"observed":{"type":"object","additionalProperties":{},"description":"The evidence. `via` is `webhook` or `reconciliation`; `costFromPayload` says whether the delivery itself carried the cost or the Admin API had to be asked. `conflict`, when present, is the OS-75 rule: other variants share this item and Shopify still prices them differently, so accepting picks one number for all of them."},"decidedBy":{"type":["string","null"]},"automatic":{"type":"boolean","description":"True when the tenant's own `autoAcceptShopifyCosts` setting accepted this, with nobody asked; false for a pending proposal and for one a person decided. Read this rather than matching `decidedBy` against an actor string: who counts as the system is this API's judgement, not a caller's."},"decidedAt":{"type":["string","null"],"format":"date-time"},"costRowId":{"type":["string","null"],"format":"uuid","description":"The ledger row an accepted `unit_cost` proposal wrote (for a cleared cost, the row with no amount that ends it)"},"createdAt":{"type":"string","format":"date-time"}},"required":["id","type","status","storeId","inventoryItemId","variantId","itemId","sku","newValue","oldValue","sourceUpdatedAt","observed","decidedBy","automatic","decidedAt","costRowId","createdAt"]}},"required":["proposal"]}}}},"401":{"description":"Missing, unknown or revoked API key","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}},"403":{"description":"The key is public; this route needs a secret key","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}},"404":{"description":"No such proposal","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}},"409":{"description":"`proposal_decided`: this proposal is not pending","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}}}}},"/items/economics":{"get":{"operationId":"listItemEconomics","summary":"Realized profit per item (SKU) across every offer and every order","description":"What each item earned over [from, to): every line of every costed order, offer-attributed or not (orders no offer claims are costed once the tenant has a `defaultCostProfile`, see `updateTenant`), grouped by the item the line's variant mapped to at ingest, in one cost view. `byOffer` splits each item by offer, with `offerId` null for orders no offer claimed. Money is shop money and never converted or added across currencies: each entry is one item in one shop `currencyCode` (an item sold in two is two entries), sorted by currency and then largest revenue first, and `totals` holds one total per currency. Σ over one currency's items is the tenant's total in it to the cent: order-level money and costs sit on the first line of each order and land on that line's item; `unitCostCents` is the item's own cost. A kit sold as its own variant is reported as the item the buyer bought; its parts appear under it, not as themselves. A Shopify bundle's order carries its parts as lines instead: they appear as themselves with the revenue and cost, and the kit, found by matching the parts against the bills of materials of the order's date (`setItemComponents`), counts the order and the kits sold with zero revenue and cost. The total counts those units once, as parts. A bundle whose parts match no kit, or more than one, counts only as its parts.","tags":["Items"],"security":[{"apiKey":[]}],"parameters":[{"schema":{"type":"string","format":"date-time","description":"Orders placed at or after. A full ISO 8601 datetime in UTC, for example `2026-09-01T00:00:00Z`; a date on its own (`2026-09-01`) is refused"},"required":true,"description":"Orders placed at or after. A full ISO 8601 datetime in UTC, for example `2026-09-01T00:00:00Z`; a date on its own (`2026-09-01`) is refused","name":"from","in":"query"},{"schema":{"type":"string","format":"date-time","description":"Orders placed before. A full ISO 8601 datetime in UTC, for example `2026-10-01T00:00:00Z`; a date on its own (`2026-10-01`) is refused"},"required":true,"description":"Orders placed before. A full ISO 8601 datetime in UTC, for example `2026-10-01T00:00:00Z`; a date on its own (`2026-10-01`) is refused","name":"to","in":"query"},{"schema":{"type":"string","enum":["current","as_recorded"],"default":"current"},"required":false,"name":"view","in":"query"}],"responses":{"200":{"description":"Per item and currency, largest revenue first within a currency","content":{"application/json":{"schema":{"type":"object","properties":{"from":{"type":"string","format":"date-time"},"to":{"type":"string","format":"date-time"},"view":{"type":"string"},"items":{"type":"array","items":{"type":"object","properties":{"orders":{"type":"integer","minimum":0},"units":{"type":"integer","minimum":0},"revenueCents":{"type":"integer","description":"Line revenue as charged, tax excluded; shipping is order money and stays with the offer"},"refundedCents":{"type":"integer","description":"Refunds ride on an order's first line, so they land on that line's item"},"costCents":{"type":"integer","description":"Cents"},"costCentsByKind":{"type":"object","additionalProperties":{"type":"integer","description":"Cents"},"description":"Per-unit kinds are the item's own; order-level kinds ride on the first line of each order as the cost split's remainder"},"unitCostCents":{"type":"integer","description":"The per-unit kinds alone: what the item itself cost"},"profitCents":{"type":"integer","description":"Product profit: revenue − refunds − cost, without shipping charged (it cannot be split across items); the profit of an item"},"marginPercent":{"type":["number","null"],"description":"Product profit as a percent of revenue, 0 to 100 (negative on a loss); null when revenue is 0"},"incompleteOrders":{"type":"integer","minimum":0},"itemId":{"type":"string"},"sku":{"type":["string","null"]},"title":{"type":["string","null"]},"currencyCode":{"type":"string","description":"The shop currency of these orders (ISO 4217): every money figure here, and in `byOffer`, is in it. An item sold in several currencies has one entry per currency"},"byOffer":{"type":"array","items":{"type":"object","properties":{"orders":{"type":"integer","minimum":0},"units":{"type":"integer","minimum":0},"revenueCents":{"type":"integer","description":"Line revenue as charged, tax excluded; shipping is order money and stays with the offer"},"refundedCents":{"type":"integer","description":"Refunds ride on an order's first line, so they land on that line's item"},"costCents":{"type":"integer","description":"Cents"},"costCentsByKind":{"type":"object","additionalProperties":{"type":"integer","description":"Cents"},"description":"Per-unit kinds are the item's own; order-level kinds ride on the first line of each order as the cost split's remainder"},"unitCostCents":{"type":"integer","description":"The per-unit kinds alone: what the item itself cost"},"profitCents":{"type":"integer","description":"Product profit: revenue − refunds − cost, without shipping charged (it cannot be split across items); the profit of an item"},"marginPercent":{"type":["number","null"],"description":"Product profit as a percent of revenue, 0 to 100 (negative on a loss); null when revenue is 0"},"incompleteOrders":{"type":"integer","minimum":0},"offerId":{"type":["string","null"],"description":"null: orders no offer claimed"},"offerCode":{"type":["string","null"]}},"required":["orders","units","revenueCents","refundedCents","costCents","costCentsByKind","unitCostCents","profitCents","marginPercent","incompleteOrders","offerId","offerCode"]}}},"required":["orders","units","revenueCents","refundedCents","costCents","costCentsByKind","unitCostCents","profitCents","marginPercent","incompleteOrders","itemId","sku","title","currencyCode","byOffer"]}},"totals":{"type":"array","items":{"type":"object","properties":{"orders":{"type":"integer","minimum":0},"units":{"type":"integer","minimum":0},"revenueCents":{"type":"integer","description":"Line revenue as charged, tax excluded; shipping is order money and stays with the offer"},"refundedCents":{"type":"integer","description":"Refunds ride on an order's first line, so they land on that line's item"},"costCents":{"type":"integer","description":"Cents"},"costCentsByKind":{"type":"object","additionalProperties":{"type":"integer","description":"Cents"},"description":"Per-unit kinds are the item's own; order-level kinds ride on the first line of each order as the cost split's remainder"},"unitCostCents":{"type":"integer","description":"The per-unit kinds alone: what the item itself cost"},"profitCents":{"type":"integer","description":"Product profit: revenue − refunds − cost, without shipping charged (it cannot be split across items); the profit of an item"},"marginPercent":{"type":["number","null"],"description":"Product profit as a percent of revenue, 0 to 100 (negative on a loss); null when revenue is 0"},"incompleteOrders":{"type":"integer","minimum":0},"currencyCode":{"type":"string"}},"required":["orders","units","revenueCents","refundedCents","costCents","costCentsByKind","unitCostCents","profitCents","marginPercent","incompleteOrders","currencyCode"]},"description":"Every item of one shop currency summed, one entry per currency, sorted by currency; `orders` and `incompleteOrders` count distinct orders, since one order spans items"},"total":{"type":["object","null"],"properties":{"orders":{"type":"integer","minimum":0},"units":{"type":"integer","minimum":0},"revenueCents":{"type":"integer","description":"Line revenue as charged, tax excluded; shipping is order money and stays with the offer"},"refundedCents":{"type":"integer","description":"Refunds ride on an order's first line, so they land on that line's item"},"costCents":{"type":"integer","description":"Cents"},"costCentsByKind":{"type":"object","additionalProperties":{"type":"integer","description":"Cents"},"description":"Per-unit kinds are the item's own; order-level kinds ride on the first line of each order as the cost split's remainder"},"unitCostCents":{"type":"integer","description":"The per-unit kinds alone: what the item itself cost"},"profitCents":{"type":"integer","description":"Product profit: revenue − refunds − cost, without shipping charged (it cannot be split across items); the profit of an item"},"marginPercent":{"type":["number","null"],"description":"Product profit as a percent of revenue, 0 to 100 (negative on a loss); null when revenue is 0"},"incompleteOrders":{"type":"integer","minimum":0},"currencyCode":{"type":["string","null"]}},"required":["orders","units","revenueCents","refundedCents","costCents","costCentsByKind","unitCostCents","profitCents","marginPercent","incompleteOrders","currencyCode"],"description":"The one entry of `totals` when the window sold in at most one currency (zeros in no currency when it sold nothing); null when it sold in several, since no total adds two currencies"}},"required":["from","to","view","items","totals","total"]}}}},"400":{"description":"Invalid query","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}},"401":{"description":"Missing, unknown or revoked API key","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}},"403":{"description":"The key is public; this route needs a secret key","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}}}}},"/items/{id}/economics":{"get":{"operationId":"getItemEconomics","summary":"One item's realized profit over time","description":"The item's figures over [from, to) per `bucket` (day, week starting Monday, or month), in one cost view, plus the same split by offer as `listItemEconomics`. For a kit sold as a Shopify bundle, `orders` and `units` count the bundles sold while revenue and cost stay on its parts, as `listItemEconomics` explains. Every figure is in one shop `currencyCode`, never a sum across currencies: `currencyCodes` lists each the item sold in over the window, and the `currencyCode` query picks one (default: the one with the most orders, ties to the first by name).","tags":["Items"],"security":[{"apiKey":[]}],"parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string","format":"date-time","description":"Orders placed at or after. A full ISO 8601 datetime in UTC, for example `2026-09-01T00:00:00Z`; a date on its own (`2026-09-01`) is refused"},"required":true,"description":"Orders placed at or after. A full ISO 8601 datetime in UTC, for example `2026-09-01T00:00:00Z`; a date on its own (`2026-09-01`) is refused","name":"from","in":"query"},{"schema":{"type":"string","format":"date-time","description":"Orders placed before. A full ISO 8601 datetime in UTC, for example `2026-10-01T00:00:00Z`; a date on its own (`2026-10-01`) is refused"},"required":true,"description":"Orders placed before. A full ISO 8601 datetime in UTC, for example `2026-10-01T00:00:00Z`; a date on its own (`2026-10-01`) is refused","name":"to","in":"query"},{"schema":{"type":"string","enum":["current","as_recorded"],"default":"current"},"required":false,"name":"view","in":"query"},{"schema":{"type":"string","enum":["day","week","month"],"default":"week"},"required":false,"name":"bucket","in":"query"},{"schema":{"type":"string","pattern":"^[A-Z]{3}$","description":"The shop currency to report, as an ISO 4217 code (`USD`); one the item did not sell in answers zeros in it"},"required":false,"description":"The shop currency to report, as an ISO 4217 code (`USD`); one the item did not sell in answers zeros in it","name":"currencyCode","in":"query"}],"responses":{"200":{"description":"The item over time","content":{"application/json":{"schema":{"type":"object","properties":{"orders":{"type":"integer","minimum":0},"units":{"type":"integer","minimum":0},"revenueCents":{"type":"integer","description":"Line revenue as charged, tax excluded; shipping is order money and stays with the offer"},"refundedCents":{"type":"integer","description":"Refunds ride on an order's first line, so they land on that line's item"},"costCents":{"type":"integer","description":"Cents"},"costCentsByKind":{"type":"object","additionalProperties":{"type":"integer","description":"Cents"},"description":"Per-unit kinds are the item's own; order-level kinds ride on the first line of each order as the cost split's remainder"},"unitCostCents":{"type":"integer","description":"The per-unit kinds alone: what the item itself cost"},"profitCents":{"type":"integer","description":"Product profit: revenue − refunds − cost, without shipping charged (it cannot be split across items); the profit of an item"},"marginPercent":{"type":["number","null"],"description":"Product profit as a percent of revenue, 0 to 100 (negative on a loss); null when revenue is 0"},"incompleteOrders":{"type":"integer","minimum":0},"itemId":{"type":"string"},"sku":{"type":["string","null"]},"title":{"type":["string","null"]},"currencyCode":{"type":["string","null"],"description":"The shop currency every money figure, `byOffer` and `series` are in; null when the item sold nothing in the window and none was asked for"},"byOffer":{"type":"array","items":{"type":"object","properties":{"orders":{"type":"integer","minimum":0},"units":{"type":"integer","minimum":0},"revenueCents":{"type":"integer","description":"Line revenue as charged, tax excluded; shipping is order money and stays with the offer"},"refundedCents":{"type":"integer","description":"Refunds ride on an order's first line, so they land on that line's item"},"costCents":{"type":"integer","description":"Cents"},"costCentsByKind":{"type":"object","additionalProperties":{"type":"integer","description":"Cents"},"description":"Per-unit kinds are the item's own; order-level kinds ride on the first line of each order as the cost split's remainder"},"unitCostCents":{"type":"integer","description":"The per-unit kinds alone: what the item itself cost"},"profitCents":{"type":"integer","description":"Product profit: revenue − refunds − cost, without shipping charged (it cannot be split across items); the profit of an item"},"marginPercent":{"type":["number","null"],"description":"Product profit as a percent of revenue, 0 to 100 (negative on a loss); null when revenue is 0"},"incompleteOrders":{"type":"integer","minimum":0},"offerId":{"type":["string","null"],"description":"null: orders no offer claimed"},"offerCode":{"type":["string","null"]}},"required":["orders","units","revenueCents","refundedCents","costCents","costCentsByKind","unitCostCents","profitCents","marginPercent","incompleteOrders","offerId","offerCode"]}},"currencyCodes":{"type":"array","items":{"type":"string"},"description":"Every shop currency the item sold in over the window, sorted"},"from":{"type":"string","format":"date-time"},"to":{"type":"string","format":"date-time"},"view":{"type":"string"},"bucket":{"type":"string"},"series":{"type":"array","items":{"type":"object","properties":{"bucket":{"type":"string","description":"YYYY-MM-DD, the bucket's start"},"orders":{"type":"integer"},"units":{"type":"integer"},"revenueCents":{"type":"integer","description":"Cents"},"refundedCents":{"type":"integer","description":"Cents"},"costCents":{"type":"integer","description":"Cents"},"profitCents":{"type":"integer","description":"Product profit: revenue − refunds − cost, without shipping charged"}},"required":["bucket","orders","units","revenueCents","refundedCents","costCents","profitCents"]}}},"required":["orders","units","revenueCents","refundedCents","costCents","costCentsByKind","unitCostCents","profitCents","marginPercent","incompleteOrders","itemId","sku","title","currencyCode","byOffer","currencyCodes","from","to","view","bucket","series"]}}}},"400":{"description":"Invalid query","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}},"401":{"description":"Missing, unknown or revoked API key","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}},"403":{"description":"The key is public; this route needs a secret key","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}},"404":{"description":"No such item","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}}}}},"/items/health":{"get":{"operationId":"getItemsHealth","summary":"The audit of what stops this catalog from being costed","description":"Run this first after `seedCostsFromShopify`, fix what it names with `setVariantItem`, `createCost`, `importCosts` and `setItemComponents`, then run it again. Shopify enforces nothing about a SKU: it can be blank, shared by variants that disagree on cost, or reused for another product. Offer Suite says one SKU is one item, so each of those silently costs an order wrong. Every check is read-only and counts its finding with the first 100 offenders; `check` with `cursor` pages one check in full. `costableRevenuePercent` is the percent of the window's realized revenue on orders with no missing cost kind: the number to watch go to 100.","tags":["Items"],"security":[{"apiKey":[]}],"parameters":[{"schema":{"type":"integer","minimum":1,"maximum":365,"default":90,"description":"The order window the line, order and mapping checks cover, back from now"},"required":false,"description":"The order window the line, order and mapping checks cover, back from now","name":"days","in":"query"},{"schema":{"type":"string","enum":["variants_without_sku","sku_cost_conflict","sku_reused","items_without_cost","kits_with_uncosted_parts","lines_without_item","orders_incomplete","mappings_changed"],"description":"Report only this check, paged in full"},"required":false,"description":"Report only this check, paged in full","name":"check","in":"query"},{"schema":{"type":"string","maxLength":200,"description":"The `nextCursor` of the previous page; needs `check`. A cursor whose shape this check cannot read is `invalid_request`; a well-formed one it does not recognise simply positions the page, which then comes back empty"},"required":false,"description":"The `nextCursor` of the previous page; needs `check`. A cursor whose shape this check cannot read is `invalid_request`; a well-formed one it does not recognise simply positions the page, which then comes back empty","name":"cursor","in":"query"}],"responses":{"200":{"description":"The report","content":{"application/json":{"schema":{"type":"object","properties":{"at":{"type":"string","format":"date-time"},"window":{"type":"object","properties":{"from":{"type":"string","format":"date-time"},"to":{"type":"string","format":"date-time"},"days":{"type":"integer","exclusiveMinimum":0}},"required":["from","to","days"],"description":"The order window the last three checks and `costableRevenuePercent` cover"},"view":{"type":"string","description":"The cost view the order figures read: always `current`, the ledger as it stands now"},"revenueCents":{"type":"integer","description":"Line revenue of every costed order in the window, tax excluded: the same number `listItemEconomics` totals"},"costableRevenueCents":{"type":"integer","description":"That revenue on orders where every required kind resolved"},"costableRevenuePercent":{"type":"number","description":"costableRevenueCents as a percent of revenueCents, 0 to 100; 100 when the window has no revenue. The one number to watch go to 100"},"checks":{"type":"object","properties":{"variantsWithoutSku":{"type":"object","properties":{"count":{"type":"integer","minimum":0,"description":"Offenders this check found in total, whatever the page shows"},"offenders":{"type":"array","items":{"type":"object","properties":{"variantId":{"type":"string","pattern":"^gid:\\/\\/shopify\\/ProductVariant\\/\\d+$","description":"A Shopify ProductVariant gid (`gid://shopify/ProductVariant/<id>`)"},"itemId":{"type":"string","format":"uuid"},"title":{"type":["string","null"]}},"required":["variantId","itemId","title"]},"description":"At most 100; page the rest with `check` and `cursor`"},"nextCursor":{"type":["string","null"],"description":"Pass back as `cursor` with this `check` to read the next page; null when the list is complete"}},"required":["count","offenders","nextCursor"],"description":"Variants whose item has no SKU: each is its own item and matches no ERP, 3PL or cost file"},"skuCostConflict":{"type":"object","properties":{"count":{"type":"integer","minimum":0,"description":"Offenders this check found in total, whatever the page shows"},"offenders":{"type":"array","items":{"type":"object","properties":{"storeId":{"type":"string","format":"uuid"},"sku":{"type":"string"},"itemId":{"type":"string","format":"uuid"},"variants":{"type":"array","items":{"type":"object","properties":{"variantId":{"type":"string","pattern":"^gid:\\/\\/shopify\\/ProductVariant\\/\\d+$","description":"A Shopify ProductVariant gid (`gid://shopify/ProductVariant/<id>`)"},"unitCost":{"type":"string"}},"required":["variantId","unitCost"]}},"seededAt":{"type":"string","format":"date-time"}},"required":["storeId","sku","itemId","variants","seededAt"]},"description":"At most 100; page the rest with `check` and `cursor`"},"nextCursor":{"type":["string","null"],"description":"Pass back as `cursor` with this `check` to read the next page; null when the list is complete"}},"required":["count","offenders","nextCursor"],"description":"SKUs whose variants carry different Shopify unit costs, from each store's newest `seedCostsFromShopify`: one physical item cannot have two costs, so no row was written. Fix Shopify and seed again, or write the item's cost with `createCost`. `count` is what that seed found; a seed records at most 1000 of them, so a catalog that conflicts more widely than that has offenders no page can reach"},"skuReused":{"type":"object","properties":{"count":{"type":"integer","minimum":0,"description":"Offenders this check found in total, whatever the page shows"},"offenders":{"type":"array","items":{"type":"object","properties":{"itemId":{"type":"string","format":"uuid"},"sku":{"type":["string","null"]},"reasons":{"type":"array","items":{"type":"string"}},"variantIds":{"type":"array","items":{"type":"string","pattern":"^gid:\\/\\/shopify\\/ProductVariant\\/\\d+$","description":"A Shopify ProductVariant gid (`gid://shopify/ProductVariant/<id>`)"}},"productTitles":{"type":"array","items":{"type":"string"}},"skusOnOrders":{"type":"array","items":{"type":"string"}}},"required":["itemId","sku","reasons","variantIds","productTitles","skusOnOrders"]},"description":"At most 100; page the rest with `check` and `cursor`"},"nextCursor":{"type":["string","null"],"description":"Pass back as `cursor` with this `check` to read the next page; null when the list is complete"}},"required":["count","offenders","nextCursor"],"description":"One SKU that now names more than one thing: `titles_disagree` (its variants sit on products with different titles, as the store's newest `seedCostsFromShopify` saw them — titles are compared ignoring case and repeated whitespace, and several variants of one product title are a product duplicated to price it differently, which is how the model is meant to work, and never appear here; a seed records at most 1000 of them, so a catalog with more has offenders counted but unreachable) or `sku_changed_after_orders` (an order line carries a SKU snapshot that names no item today, so history is being costed as whatever the string means now). Fix either with `setVariantItem`, then seed again"},"itemsWithoutCost":{"type":"object","properties":{"count":{"type":"integer","minimum":0,"description":"Offenders this check found in total, whatever the page shows"},"offenders":{"type":"array","items":{"type":"object","properties":{"itemId":{"type":"string","format":"uuid"},"sku":{"type":["string","null"]},"title":{"type":["string","null"]},"missing":{"type":"array","items":{"type":"string"},"description":"Required cost kinds that resolve to no amount today"}},"required":["itemId","sku","title","missing"]},"description":"At most 100; page the rest with `check` and `cursor`"},"nextCursor":{"type":["string","null"],"description":"Pass back as `cursor` with this `check` to read the next page; null when the list is complete"}},"required":["count","offenders","nextCursor"],"description":"Items with a required cost kind unresolved today, so an order on them is incomplete. `missing` is the array `getItem` gives the same item, decided as the realized mirror decides an order: each variant under its product (its item's rows, a kit's parts, the product's rows, the tenant's), less the kinds the cost profile's kind-level defaults cover. An item sold under two products is listed when either leaves a kind unresolved"},"kitsWithUncostedParts":{"type":"object","properties":{"count":{"type":"integer","minimum":0,"description":"Offenders this check found in total, whatever the page shows"},"offenders":{"type":"array","items":{"type":"object","properties":{"itemId":{"type":"string","format":"uuid"},"sku":{"type":["string","null"]},"title":{"type":["string","null"]},"missing":{"type":"array","items":{"type":"string"},"description":"Required cost kinds that resolve to no amount today"},"parts":{"type":"array","items":{"type":"object","properties":{"itemId":{"type":"string","format":"uuid"},"sku":{"type":["string","null"]},"title":{"type":["string","null"]},"missing":{"type":"array","items":{"type":"string"},"description":"Required cost kinds that resolve to no amount today"}},"required":["itemId","sku","title","missing"]},"description":"The components that resolve no amount"}},"required":["itemId","sku","title","missing","parts"]},"description":"At most 100; page the rest with `check` and `cursor`"},"nextCursor":{"type":["string","null"],"description":"Pass back as `cursor` with this `check` to read the next page; null when the list is complete"}},"required":["count","offenders","nextCursor"],"description":"Kits a part leaves uncosted: a kit's kind is missing, never short, so the whole kit reads incomplete. Cost the parts, not the kit. The kit's `missing` is decided as for `itemsWithoutCost`; a part's is what it resolves on its own, as the kit sums it"},"linesWithoutItem":{"type":"object","properties":{"count":{"type":"integer","minimum":0,"description":"Offenders this check found in total, whatever the page shows"},"offenders":{"type":"array","items":{"type":"object","properties":{"orderId":{"type":"string","pattern":"^gid:\\/\\/shopify\\/Order\\/\\d+$","description":"A Shopify Order gid (`gid://shopify/Order/<id>`)"},"lineIndex":{"type":"integer"},"variantId":{"type":"string","pattern":"^gid:\\/\\/shopify\\/ProductVariant\\/\\d+$","description":"A Shopify ProductVariant gid (`gid://shopify/ProductVariant/<id>`)"},"sku":{"type":["string","null"]},"orderedAt":{"type":"string","format":"date-time"}},"required":["orderId","lineIndex","variantId","sku","orderedAt"]},"description":"At most 100; page the rest with `check` and `cursor`"},"nextCursor":{"type":["string","null"],"description":"Pass back as `cursor` with this `check` to read the next page; null when the list is complete"}},"required":["count","offenders","nextCursor"],"description":"Order lines in the window that map to no item: nothing can cost them"},"ordersIncomplete":{"type":"object","properties":{"count":{"type":"integer","minimum":0,"description":"Offenders this check found in total, whatever the page shows"},"offenders":{"type":"array","items":{"type":"object","properties":{"orderId":{"type":"string","pattern":"^gid:\\/\\/shopify\\/Order\\/\\d+$","description":"A Shopify Order gid (`gid://shopify/Order/<id>`)"},"revenueCents":{"type":"integer"},"kindKeys":{"type":"array","items":{"type":"string"},"description":"The required cost kinds the order misses"}},"required":["orderId","revenueCents","kindKeys"]},"description":"At most 100; page the rest with `check` and `cursor`"},"nextCursor":{"type":["string","null"],"description":"Pass back as `cursor` with this `check` to read the next page; null when the list is complete"},"byKind":{"type":"array","items":{"type":"object","properties":{"kindKey":{"type":"string"},"orders":{"type":"integer"},"revenueCents":{"type":"integer"}},"required":["kindKey","orders","revenueCents"]},"description":"The same orders by kind; an order missing two kinds counts under both"}},"required":["count","offenders","nextCursor","byKind"]},"mappingsChanged":{"type":"object","properties":{"count":{"type":"integer","minimum":0,"description":"Offenders this check found in total, whatever the page shows"},"offenders":{"type":"array","items":{"type":"object","properties":{"changeId":{"type":"string","format":"uuid","description":"The audit row's id; it is also this check's cursor"},"at":{"type":"string","format":"date-time"},"type":{"type":"string","enum":["variant_repointed","components_set","sku_renamed"],"description":"`variant_repointed`: a variant moved to another item; `components_set`: a kit's bill of materials changed; `sku_renamed`: an item's SKU was renamed"},"subjectId":{"type":"string","description":"The variant gid for a re-point, the item id for a component change or a SKU rename"},"fromItemId":{"type":["string","null"],"format":"uuid"},"toItemId":{"type":["string","null"],"format":"uuid"},"components":{"type":["array","null"],"items":{"type":"object","properties":{"itemId":{"type":"string","format":"uuid"},"quantity":{"type":"integer"}},"required":["itemId","quantity"]}}},"required":["changeId","at","type","subjectId","fromItemId","toItemId","components"]},"description":"At most 100; page the rest with `check` and `cursor`"},"nextCursor":{"type":["string","null"],"description":"Pass back as `cursor` with this `check` to read the next page; null when the list is complete"}},"required":["count","offenders","nextCursor"],"description":"Variant re-points and component changes in the window, newest first: what a SKU means changed"}},"description":"One entry per check, keyed by the camelCase of its `check` value (`variants_without_sku` is `variantsWithoutSku`); with `check` only that one is present"}},"required":["at","window","view","revenueCents","costableRevenueCents","costableRevenuePercent","checks"]}}}},"400":{"description":"Invalid query","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}},"401":{"description":"Missing, unknown or revoked API key","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}},"403":{"description":"The key is public; this route needs a secret key","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}}}}},"/items":{"get":{"operationId":"listItems","summary":"List the tenant's items (physical SKUs)","description":"An item is what a cost attaches to: one per SKU, shared by every variant that carries it, and one per variant without a SKU. Built by `seedCostsFromShopify` and by orders as they arrive; filter by `sku` for an exact match.","tags":["Items"],"security":[{"apiKey":[]}],"parameters":[{"schema":{"type":"string"},"required":false,"name":"sku","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":500,"default":100},"required":false,"name":"limit","in":"query"},{"schema":{"type":["integer","null"],"minimum":0,"default":0},"required":false,"name":"offset","in":"query"}],"responses":{"200":{"description":"The page","content":{"application/json":{"schema":{"type":"object","properties":{"items":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"sku":{"type":["string","null"]},"title":{"type":["string","null"]},"source":{"type":"string","enum":["shopify_sku","shopify_variant","manual"],"description":"shopify_sku: created from a SKU Shopify carries; shopify_variant: a variant without a SKU; manual: created by the brand or a CSV"},"variantCount":{"type":"integer","minimum":0},"createdAt":{"type":"string","format":"date-time"}},"required":["id","sku","title","source","variantCount","createdAt"]}},"limit":{"type":"integer"},"offset":{"type":"integer"}},"required":["items","limit","offset"]}}}},"400":{"description":"Invalid query","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}},"401":{"description":"Missing, unknown or revoked API key","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}},"403":{"description":"The key is public; this route needs a secret key","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}}}},"post":{"operationId":"createItem","summary":"Create an item ahead of its costs or its variants","description":"Needed only for an item no variant or CSV has named yet; `createCost` and `importCosts` create unknown SKUs themselves. SKUs are unique per tenant.","tags":["Items"],"security":[{"apiKey":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"sku":{"type":"string","minLength":1,"maxLength":255},"title":{"type":"string","minLength":1,"maxLength":255}}}}}},"responses":{"201":{"description":"The item","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"sku":{"type":["string","null"]},"title":{"type":["string","null"]},"source":{"type":"string","enum":["shopify_sku","shopify_variant","manual"],"description":"shopify_sku: created from a SKU Shopify carries; shopify_variant: a variant without a SKU; manual: created by the brand or a CSV"},"variantCount":{"type":"integer","minimum":0},"createdAt":{"type":"string","format":"date-time"}},"required":["id","sku","title","source","variantCount","createdAt"]}}}},"400":{"description":"Invalid body","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}},"401":{"description":"Missing, unknown or revoked API key","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}},"403":{"description":"The key is public; this route needs a secret key","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}},"409":{"description":"An item with this SKU exists","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}}}}},"/items/{id}":{"get":{"operationId":"getItem","summary":"One item: its variants, its bill of materials and its effective costs on a date","description":"`costs` resolves the item's own ledger rows, then (for a kit) its components, then the tenant's defaults, at `at` (default now), as recorded by `asOf` (default now); a variant's product-level rows are not part of an item on its own. `missing` is what an order of it would miss: each variant under its product, with the cost profile's defaults, as the realized mirror decides. `components` is the kit's bill of materials at `at`; `componentHistory` lists every version with the date it starts applying.","tags":["Items"],"security":[{"apiKey":[]}],"parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string","format":"date-time"},"required":false,"name":"at","in":"query"},{"schema":{"type":"string","format":"date-time"},"required":false,"name":"asOf","in":"query"}],"responses":{"200":{"description":"The item","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"sku":{"type":["string","null"]},"title":{"type":["string","null"]},"source":{"type":"string","enum":["shopify_sku","shopify_variant","manual"],"description":"shopify_sku: created from a SKU Shopify carries; shopify_variant: a variant without a SKU; manual: created by the brand or a CSV"},"variantCount":{"type":"integer","minimum":0},"createdAt":{"type":"string","format":"date-time"},"variants":{"type":"array","items":{"type":"object","properties":{"variantId":{"type":"string","pattern":"^gid:\\/\\/shopify\\/ProductVariant\\/\\d+$","description":"A Shopify ProductVariant gid (`gid://shopify/ProductVariant/<id>`)"},"itemId":{"type":"string","format":"uuid"},"sku":{"type":["string","null"]},"productId":{"type":["string","null"],"pattern":"^gid:\\/\\/shopify\\/Product\\/\\d+$","description":"A Shopify Product gid (`gid://shopify/Product/<id>`)"},"inventoryItemId":{"type":["string","null"],"pattern":"^gid:\\/\\/shopify\\/InventoryItem\\/\\d+$","description":"A Shopify InventoryItem gid (`gid://shopify/InventoryItem/<id>`)"},"title":{"type":["string","null"]}},"required":["variantId","itemId","sku","productId","inventoryItemId","title"]}},"at":{"type":"string","format":"date-time"},"costs":{"type":"object","additionalProperties":{"type":"object","properties":{"amount":{"type":"number","description":"A money grain's amount; absent on a `percent` kind"},"percent":{"type":"number","description":"The `percent` grain's percent, 0 to 100; absent on a money kind"},"source":{"type":"string","enum":["item","components","product","default"]},"grain":{"type":"string","enum":["per_unit","per_parcel","per_order","percent"]}},"required":["source","grain"]},"description":"The item's effective costs at `at`: its own rows, else (for a kit) the sum of its components, then the tenant's"},"components":{"type":"array","items":{"type":"object","properties":{"itemId":{"type":"string","format":"uuid"},"sku":{"type":["string","null"]},"title":{"type":["string","null"]},"quantity":{"type":"integer","exclusiveMinimum":0},"costs":{"type":"object","additionalProperties":{"type":"object","properties":{"amount":{"type":"number","description":"A money grain's amount; absent on a `percent` kind"},"percent":{"type":"number","description":"The `percent` grain's percent, 0 to 100; absent on a money kind"},"source":{"type":"string","enum":["item","components","product","default"]},"grain":{"type":"string","enum":["per_unit","per_parcel","per_order","percent"]}},"required":["source","grain"]}}},"required":["itemId","sku","title","quantity","costs"]},"description":"The kit's bill of materials with each part's own effective costs; empty for a plain item"},"usedIn":{"type":"array","items":{"type":"object","properties":{"itemId":{"type":"string","format":"uuid"},"sku":{"type":["string","null"]},"title":{"type":["string","null"]},"quantity":{"type":"integer","exclusiveMinimum":0}},"required":["itemId","sku","title","quantity"]},"description":"Kits this item is a component of at `at`"},"componentHistory":{"type":"array","items":{"type":"object","properties":{"effectiveFrom":{"type":"string","format":"date-time"},"components":{"type":"array","items":{"type":"object","properties":{"itemId":{"type":"string","format":"uuid"},"sku":{"type":["string","null"]},"title":{"type":["string","null"]},"quantity":{"type":"integer","exclusiveMinimum":0}},"required":["itemId","sku","title","quantity"]},"description":"The whole set in effect from `effectiveFrom`; empty once every component was ended"}},"required":["effectiveFrom","components"]},"description":"Every version of the kit's bill of materials as recorded by `asOf`, oldest first; empty for an item that was never a kit"},"missing":{"type":"array","items":{"type":"string"},"description":"Required cost kinds some order of this item would miss at `at`: judged per variant, with its product's rows and the cost profile's kind-level defaults, exactly as the realized mirror costs an order (on its own when no variant maps to it). Empty means every order on the item is complete"}},"required":["id","sku","title","source","variantCount","createdAt","variants","at","costs","components","usedIn","componentHistory","missing"]}}}},"400":{"description":"Invalid id","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}},"401":{"description":"Missing, unknown or revoked API key","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}},"403":{"description":"The key is public; this route needs a secret key","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}},"404":{"description":"No such item","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}}}}},"/variants":{"get":{"operationId":"listVariants","summary":"The variant-to-item map","description":"Every variant this tenant has seen (seeded or ordered) with the item it maps to. Filter by `itemId` to see the variants sharing one SKU, or by `productId`.","tags":["Items"],"security":[{"apiKey":[]}],"parameters":[{"schema":{"type":"string","format":"uuid"},"required":false,"name":"itemId","in":"query"},{"schema":{"type":"string","pattern":"^gid:\\/\\/shopify\\/Product\\/\\d+$","description":"A Shopify Product gid (`gid://shopify/Product/<id>`)"},"required":false,"description":"A Shopify Product gid (`gid://shopify/Product/<id>`)","name":"productId","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":500,"default":100},"required":false,"name":"limit","in":"query"},{"schema":{"type":["integer","null"],"minimum":0,"default":0},"required":false,"name":"offset","in":"query"}],"responses":{"200":{"description":"The page","content":{"application/json":{"schema":{"type":"object","properties":{"variants":{"type":"array","items":{"type":"object","properties":{"variantId":{"type":"string","pattern":"^gid:\\/\\/shopify\\/ProductVariant\\/\\d+$","description":"A Shopify ProductVariant gid (`gid://shopify/ProductVariant/<id>`)"},"itemId":{"type":"string","format":"uuid"},"sku":{"type":["string","null"]},"productId":{"type":["string","null"],"pattern":"^gid:\\/\\/shopify\\/Product\\/\\d+$","description":"A Shopify Product gid (`gid://shopify/Product/<id>`)"},"inventoryItemId":{"type":["string","null"],"pattern":"^gid:\\/\\/shopify\\/InventoryItem\\/\\d+$","description":"A Shopify InventoryItem gid (`gid://shopify/InventoryItem/<id>`)"},"title":{"type":["string","null"]}},"required":["variantId","itemId","sku","productId","inventoryItemId","title"]}},"limit":{"type":"integer"},"offset":{"type":"integer"}},"required":["variants","limit","offset"]}}}},"400":{"description":"Invalid query","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}},"401":{"description":"Missing, unknown or revoked API key","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}},"403":{"description":"The key is public; this route needs a secret key","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}}}}},"/variants/{variantId}/item":{"put":{"operationId":"setVariantItem","summary":"Map a variant to an item (move it when it is mapped already)","description":"Send the item's id or its SKU (an unknown SKU creates the item). From now on the variant is costed as that item, and its past orders are recomputed in the current view (`restatement`). Use it when Shopify's SKU is blank or wrong, or when a duplicated product should share its twin's cost.","tags":["Items"],"security":[{"apiKey":[]}],"parameters":[{"schema":{"type":"string","pattern":"^gid:\\/\\/shopify\\/ProductVariant\\/\\d+$","description":"The variant gid (`gid://shopify/ProductVariant/<id>`), percent-encoded in the path"},"required":true,"description":"The variant gid (`gid://shopify/ProductVariant/<id>`), percent-encoded in the path","name":"variantId","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"item":{"type":"string","minLength":1,"description":"Item id or SKU"},"productId":{"type":"string","pattern":"^gid:\\/\\/shopify\\/Product\\/\\d+$","description":"The variant's product gid; recorded on the mapping"}},"required":["item"]}}}},"responses":{"200":{"description":"The mapping","content":{"application/json":{"schema":{"type":"object","properties":{"variantId":{"type":"string","pattern":"^gid:\\/\\/shopify\\/ProductVariant\\/\\d+$","description":"A Shopify ProductVariant gid (`gid://shopify/ProductVariant/<id>`)"},"itemId":{"type":"string","format":"uuid"},"sku":{"type":["string","null"]},"productId":{"type":["string","null"],"pattern":"^gid:\\/\\/shopify\\/Product\\/\\d+$","description":"A Shopify Product gid (`gid://shopify/Product/<id>`)"},"inventoryItemId":{"type":["string","null"],"pattern":"^gid:\\/\\/shopify\\/InventoryItem\\/\\d+$","description":"A Shopify InventoryItem gid (`gid://shopify/InventoryItem/<id>`)"},"title":{"type":["string","null"]},"restatement":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"trigger":{"type":"string","enum":["cost_row","cost_void","cost_import","cost_seed","cost_kind","manual"]},"status":{"type":"string","enum":["queued","running","completed","failed"]},"actor":{"type":"string"},"reason":{"type":["string","null"]},"costRowIds":{"type":"array","items":{"type":"string","format":"uuid"},"description":"The ledger rows written or voided by the request"},"kindKeys":{"type":"array","items":{"type":"string"}},"targets":{"type":"array","items":{"type":"object","properties":{"targetType":{"type":"string","enum":["item","product","offer","tenant"]},"targetId":{"type":"string"}},"required":["targetType","targetId"]},"description":"Empty when tenant-wide"},"tenantWide":{"type":"boolean","description":"Every attributed order from `earliestEffectiveFrom` is restated"},"earliestEffectiveFrom":{"type":"string","format":"date-time","description":"Orders placed at or after this date are affected"},"ordersAffected":{"type":"integer","minimum":0,"description":"Counted when the request was recorded"},"ordersDone":{"type":"integer","minimum":0},"profitBeforeCents":{"type":["integer","null"],"description":"Realized profit (current view) of the tenant's orders from `earliestEffectiveFrom`, when the job started"},"profitAfterCents":{"type":["integer","null"],"description":"The same, when the job finished"},"profitDeltaCents":{"type":["integer","null"],"description":"profitAfterCents − profitBeforeCents"},"error":{"type":["string","null"]},"recordedAt":{"type":"string","format":"date-time"},"completedAt":{"type":["string","null"],"format":"date-time"}},"required":["id","trigger","status","actor","reason","costRowIds","kindKeys","targets","tenantWide","earliestEffectiveFrom","ordersAffected","ordersDone","profitBeforeCents","profitAfterCents","profitDeltaCents","error","recordedAt","completedAt"]}},"required":["variantId","itemId","sku","productId","inventoryItemId","title","restatement"]}}}},"400":{"description":"Invalid body or unknown item id","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}},"401":{"description":"Missing, unknown or revoked API key","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}},"403":{"description":"The key is public; this route needs a secret key","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}}}}},"/items/{id}/components":{"put":{"operationId":"setItemComponents","summary":"Set a kit's bill of materials from a date","description":"Makes the item a kit of these components with quantities from `effectiveFrom` (default now; a past date backdates it). An empty list makes it a plain item again from that date. History is kept: orders placed before `effectiveFrom` stay costed by the recipe of their own date, so changing a recipe never recosts them. The request is compared with the set in effect at `effectiveFrom` and only the differences are recorded (a changed quantity, a new component, a component ended); each recorded component applies until that component's next recorded change, so a backdated set does not end a component a later version still lists. `changed: false` when the set already applies. A per-unit kind the kit has no row of its own for is the sum of its components; a kit-only kind (kitting, its box) goes on the kit itself with `createCost`. Nesting is allowed up to 8 levels; a component that is or contains this item at any date is refused (`component_cycle`), and so is deeper nesting (`component_too_deep`). A change is a cost write: orders placed from `effectiveFrom` of this kit and of every kit containing it are recomputed in the current view (`restatement`).","tags":["Items"],"security":[{"apiKey":[]}],"parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"components":{"type":"array","items":{"type":"object","properties":{"item":{"type":"string","minLength":1,"description":"Item id or SKU; an unknown SKU creates the item"},"quantity":{"type":"integer","exclusiveMinimum":0}},"required":["item","quantity"]},"maxItems":100},"effectiveFrom":{"type":"string","format":"date-time","description":"When this set starts applying (valid time); defaults to now, past allowed. Orders placed before it keep the set of their own date"}},"required":["components"]}}}},"responses":{"200":{"description":"The kit's components","content":{"application/json":{"schema":{"type":"object","properties":{"itemId":{"type":"string","format":"uuid"},"effectiveFrom":{"type":"string","format":"date-time"},"components":{"type":"array","items":{"type":"object","properties":{"itemId":{"type":"string","format":"uuid"},"sku":{"type":["string","null"]},"title":{"type":["string","null"]},"quantity":{"type":"integer","exclusiveMinimum":0}},"required":["itemId","sku","title","quantity"]},"description":"The set in effect from `effectiveFrom`"},"changed":{"type":"boolean"},"restatement":{"type":["object","null"],"properties":{"id":{"type":"string","format":"uuid"},"trigger":{"type":"string","enum":["cost_row","cost_void","cost_import","cost_seed","cost_kind","manual"]},"status":{"type":"string","enum":["queued","running","completed","failed"]},"actor":{"type":"string"},"reason":{"type":["string","null"]},"costRowIds":{"type":"array","items":{"type":"string","format":"uuid"},"description":"The ledger rows written or voided by the request"},"kindKeys":{"type":"array","items":{"type":"string"}},"targets":{"type":"array","items":{"type":"object","properties":{"targetType":{"type":"string","enum":["item","product","offer","tenant"]},"targetId":{"type":"string"}},"required":["targetType","targetId"]},"description":"Empty when tenant-wide"},"tenantWide":{"type":"boolean","description":"Every attributed order from `earliestEffectiveFrom` is restated"},"earliestEffectiveFrom":{"type":"string","format":"date-time","description":"Orders placed at or after this date are affected"},"ordersAffected":{"type":"integer","minimum":0,"description":"Counted when the request was recorded"},"ordersDone":{"type":"integer","minimum":0},"profitBeforeCents":{"type":["integer","null"],"description":"Realized profit (current view) of the tenant's orders from `earliestEffectiveFrom`, when the job started"},"profitAfterCents":{"type":["integer","null"],"description":"The same, when the job finished"},"profitDeltaCents":{"type":["integer","null"],"description":"profitAfterCents − profitBeforeCents"},"error":{"type":["string","null"]},"recordedAt":{"type":"string","format":"date-time"},"completedAt":{"type":["string","null"],"format":"date-time"}},"required":["id","trigger","status","actor","reason","costRowIds","kindKeys","targets","tenantWide","earliestEffectiveFrom","ordersAffected","ordersDone","profitBeforeCents","profitAfterCents","profitDeltaCents","error","recordedAt","completedAt"]}},"required":["itemId","effectiveFrom","components","changed","restatement"]}}}},"400":{"description":"Invalid body, unknown item id, a cycle, or nesting deeper than 8","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}},"401":{"description":"Missing, unknown or revoked API key","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}},"403":{"description":"The key is public; this route needs a secret key","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}},"404":{"description":"No such item","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}}}}},"/items/components/import":{"post":{"operationId":"importItemComponents","summary":"Import bills of materials from CSV","description":"Body is `text/csv` with the header `sku,componentSku,quantity` and an optional `effectiveFrom` (ISO 8601; empty = now, past allowed): one row per component, grouped by `sku` and `effectiveFrom`; each group is the kit's whole set from that date, applied as `setItemComponents` applies one, oldest date first, so one file can load a kit's history. Unknown SKUs become items. Every row is validated first; with any rejection the file is refused (422) unless `partial=1`. The kits changed record one restatement, from the earliest date that changed.","tags":["Items"],"security":[{"apiKey":[]}],"parameters":[{"schema":{"type":"string","enum":["1"]},"required":false,"name":"partial","in":"query"}],"requestBody":{"required":true,"content":{"text/csv":{"schema":{"type":"string"}}}},"responses":{"200":{"description":"Applied","content":{"application/json":{"schema":{"type":"object","properties":{"kits":{"type":"integer","minimum":0},"changed":{"type":"integer","minimum":0},"itemsCreated":{"type":"array","items":{"type":"string"}},"rejected":{"type":"array","items":{"type":"object","properties":{"row":{"type":"integer"},"column":{"type":"string"},"message":{"type":"string"}},"required":["row","column","message"]}},"restatement":{"type":["object","null"],"properties":{"id":{"type":"string","format":"uuid"},"trigger":{"type":"string","enum":["cost_row","cost_void","cost_import","cost_seed","cost_kind","manual"]},"status":{"type":"string","enum":["queued","running","completed","failed"]},"actor":{"type":"string"},"reason":{"type":["string","null"]},"costRowIds":{"type":"array","items":{"type":"string","format":"uuid"},"description":"The ledger rows written or voided by the request"},"kindKeys":{"type":"array","items":{"type":"string"}},"targets":{"type":"array","items":{"type":"object","properties":{"targetType":{"type":"string","enum":["item","product","offer","tenant"]},"targetId":{"type":"string"}},"required":["targetType","targetId"]},"description":"Empty when tenant-wide"},"tenantWide":{"type":"boolean","description":"Every attributed order from `earliestEffectiveFrom` is restated"},"earliestEffectiveFrom":{"type":"string","format":"date-time","description":"Orders placed at or after this date are affected"},"ordersAffected":{"type":"integer","minimum":0,"description":"Counted when the request was recorded"},"ordersDone":{"type":"integer","minimum":0},"profitBeforeCents":{"type":["integer","null"],"description":"Realized profit (current view) of the tenant's orders from `earliestEffectiveFrom`, when the job started"},"profitAfterCents":{"type":["integer","null"],"description":"The same, when the job finished"},"profitDeltaCents":{"type":["integer","null"],"description":"profitAfterCents − profitBeforeCents"},"error":{"type":["string","null"]},"recordedAt":{"type":"string","format":"date-time"},"completedAt":{"type":["string","null"],"format":"date-time"}},"required":["id","trigger","status","actor","reason","costRowIds","kindKeys","targets","tenantWide","earliestEffectiveFrom","ordersAffected","ordersDone","profitBeforeCents","profitAfterCents","profitDeltaCents","error","recordedAt","completedAt"]}},"required":["kits","changed","itemsCreated","rejected","restatement"]}}}},"400":{"description":"A cycle, nesting deeper than 8, or an item id no item has","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}},"401":{"description":"Missing, unknown or revoked API key","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}},"403":{"description":"The key is public; this route needs a secret key","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}},"422":{"description":"Nothing applied","content":{"application/json":{"schema":{"type":"object","properties":{"kits":{"type":"integer"},"changed":{"type":"integer"},"itemsCreated":{"type":"array","items":{"type":"string"}},"rejected":{"type":"array","items":{"type":"object","properties":{"row":{"type":"integer"},"column":{"type":"string"},"message":{"type":"string"}},"required":["row","column","message"]}},"restatement":{"type":["object","null"],"properties":{"id":{"type":"string","format":"uuid"},"trigger":{"type":"string","enum":["cost_row","cost_void","cost_import","cost_seed","cost_kind","manual"]},"status":{"type":"string","enum":["queued","running","completed","failed"]},"actor":{"type":"string"},"reason":{"type":["string","null"]},"costRowIds":{"type":"array","items":{"type":"string","format":"uuid"},"description":"The ledger rows written or voided by the request"},"kindKeys":{"type":"array","items":{"type":"string"}},"targets":{"type":"array","items":{"type":"object","properties":{"targetType":{"type":"string","enum":["item","product","offer","tenant"]},"targetId":{"type":"string"}},"required":["targetType","targetId"]},"description":"Empty when tenant-wide"},"tenantWide":{"type":"boolean","description":"Every attributed order from `earliestEffectiveFrom` is restated"},"earliestEffectiveFrom":{"type":"string","format":"date-time","description":"Orders placed at or after this date are affected"},"ordersAffected":{"type":"integer","minimum":0,"description":"Counted when the request was recorded"},"ordersDone":{"type":"integer","minimum":0},"profitBeforeCents":{"type":["integer","null"],"description":"Realized profit (current view) of the tenant's orders from `earliestEffectiveFrom`, when the job started"},"profitAfterCents":{"type":["integer","null"],"description":"The same, when the job finished"},"profitDeltaCents":{"type":["integer","null"],"description":"profitAfterCents − profitBeforeCents"},"error":{"type":["string","null"]},"recordedAt":{"type":"string","format":"date-time"},"completedAt":{"type":["string","null"],"format":"date-time"}},"required":["id","trigger","status","actor","reason","costRowIds","kindKeys","targets","tenantWide","earliestEffectiveFrom","ordersAffected","ordersDone","profitBeforeCents","profitAfterCents","profitDeltaCents","error","recordedAt","completedAt"]}},"required":["kits","changed","itemsCreated","rejected","restatement"]}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}}}}},"/tenant":{"get":{"operationId":"getTenant","summary":"The tenant this key belongs to, with its settings","tags":["Tenant"],"security":[{"apiKey":[]}],"responses":{"200":{"description":"The tenant","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"slug":{"type":"string"},"defaultCostProfile":{"type":["string","null"],"description":"The cost profile for orders no offer claims (e.g. `dtc-us`); null leaves them uncosted"},"autoAcceptShopifyCosts":{"type":"boolean","description":"When true, a Shopify unit-cost proposal is accepted the moment it arrives instead of waiting for a person, and is shown as a notice rather than an alert. It only ever acts while the `unit_cost` kind’s `canonicalSource` is `shopify`, never on a proposal whose item other variants still price differently, and never on a unit cost the merchant cleared: ending a cost makes the item's later orders incomplete, so that one always waits for a person."},"unitCostIncludes":{"type":"array","items":{"type":"string","enum":["packaging","freight_in"]},"description":"The onboarding answer to \"does your Shopify cost per item already include freight/duties? packaging?\": `freight_in` when it is a landed cost (inbound freight and duties), `packaging` when it holds the box and liners. Every cost kind that counts the same cost separately (`unitCostMayInclude`: the `dtc-us` profile's `packaging_box` and `packaging_plastic` count packaging) is then not charged, in forecasts and realized profit alike, so nothing is counted twice. Empty (the default) means the Shopify cost is the product alone."}},"required":["id","name","slug","defaultCostProfile","autoAcceptShopifyCosts","unitCostIncludes"]}}}},"401":{"description":"Missing, unknown or revoked API key","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}},"403":{"description":"The key is public; this route needs a secret key","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}}}},"patch":{"operationId":"updateTenant","summary":"Change the tenant's settings","description":"`defaultCostProfile` names the cost profile (`dtc-us`) that costs orders no offer claims from the next delivery on, so profit per item covers the whole store; earlier such orders pick it up on their next delivery or restatement. Null stops costing them. Offer economics never change: they filter on the offer. `autoAcceptShopifyCosts` is the onboarding answer to \"is Shopify where you keep your COGS?\": with it on, a Shopify unit-cost proposal is written to the ledger as it arrives and shown as a notice (a cleared unit cost still waits for a person); with it off, every proposal waits in `GET /cost-proposals`. `unitCostIncludes` says what the Shopify cost per item already includes (OS-339); a change restates every order's `current` view, while `as_recorded` keeps what each order was costed with, and the response carries the restatement.","tags":["Tenant"],"security":[{"apiKey":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"defaultCostProfile":{"type":["string","null"],"minLength":1},"autoAcceptShopifyCosts":{"type":"boolean"},"unitCostIncludes":{"type":"array","items":{"type":"string","enum":["packaging","freight_in"]},"description":"The onboarding answer to \"does your Shopify cost per item already include freight/duties? packaging?\": `freight_in` when it is a landed cost (inbound freight and duties), `packaging` when it holds the box and liners. Every cost kind that counts the same cost separately (`unitCostMayInclude`: the `dtc-us` profile's `packaging_box` and `packaging_plastic` count packaging) is then not charged, in forecasts and realized profit alike, so nothing is counted twice. Empty (the default) means the Shopify cost is the product alone."}}}}}},"responses":{"200":{"description":"The tenant","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"slug":{"type":"string"},"defaultCostProfile":{"type":["string","null"],"description":"The cost profile for orders no offer claims (e.g. `dtc-us`); null leaves them uncosted"},"autoAcceptShopifyCosts":{"type":"boolean","description":"When true, a Shopify unit-cost proposal is accepted the moment it arrives instead of waiting for a person, and is shown as a notice rather than an alert. It only ever acts while the `unit_cost` kind’s `canonicalSource` is `shopify`, never on a proposal whose item other variants still price differently, and never on a unit cost the merchant cleared: ending a cost makes the item's later orders incomplete, so that one always waits for a person."},"unitCostIncludes":{"type":"array","items":{"type":"string","enum":["packaging","freight_in"]},"description":"The onboarding answer to \"does your Shopify cost per item already include freight/duties? packaging?\": `freight_in` when it is a landed cost (inbound freight and duties), `packaging` when it holds the box and liners. Every cost kind that counts the same cost separately (`unitCostMayInclude`: the `dtc-us` profile's `packaging_box` and `packaging_plastic` count packaging) is then not charged, in forecasts and realized profit alike, so nothing is counted twice. Empty (the default) means the Shopify cost is the product alone."},"restatement":{"type":["object","null"],"properties":{"id":{"type":"string","format":"uuid"},"status":{"type":"string"}},"required":["id","status"],"additionalProperties":{},"description":"The restatement a `unitCostIncludes` change started; null when the answer did not change"}},"required":["id","name","slug","defaultCostProfile","autoAcceptShopifyCosts","unitCostIncludes"]}}}},"400":{"description":"Invalid body or unknown cost profile","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}},"401":{"description":"Missing, unknown or revoked API key","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}},"403":{"description":"The key is public; this route needs a secret key","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}}}}},"/stores/{id}":{"get":{"operationId":"getStore","summary":"One connected store, with its webhook health","description":"The store as GET /stores lists it, plus what the daily health job last found: whether its webhook subscriptions are in place (Shopify deletes a subscription after 8 failed deliveries), when one was last re-created, and how many orders the last reconciliation run had to fetch because their delivery never arrived. A non-zero `reconciliation.repairedOrders` or a recent `webhooks.reregisteredAt` means deliveries were being lost; `webhooks.healthy: false` means they may be lost right now. `pricing.ok: false` means the store's live offers are being sold at list price, and `rebuildStorePricing` puts them back. `capability` says which cart transform operations the store's plan runs (a line price and line overrides need Shopify Plus or a development store). Like GET /stores this is read from the database and makes no call to Shopify.","tags":["Stores"],"security":[{"apiKey":[]}],"parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"The store","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"myshopifyDomain":{"type":"string"},"scopes":{"type":"array","items":{"type":"string"}},"installedAt":{"type":"string","format":"date-time"},"uninstalledAt":{"type":["string","null"],"format":"date-time"},"webhooks":{"type":"object","properties":{"healthy":{"type":"boolean","description":"False for either of two reasons. The last check failed, so deliveries may be lost until one succeeds; or the check succeeded but a window of orders older than Shopify's 60-day `read_orders` access went unreconciled and never can be. The second is permanent and is recorded once per window as a `webhooks.unreconcilable` audit entry, since this field is overwritten as soon as a later run is clean. An order that failed to ingest does NOT make this false — the subscriptions are fine and deliveries are arriving; read `reconciliation.failed` for that."},"lastCheckedAt":{"type":["string","null"],"format":"date-time"},"reregisteredAt":{"type":["string","null"],"format":"date-time","description":"When a subscription Shopify had deleted was last re-created. It stays set; `recentlyReregistered` is the one to act on, and is true for 7 days after it."},"recentlyReregistered":{"type":"boolean","description":"True while `reregisteredAt` is within the last 7 days: deliveries were being lost that recently"},"error":{"type":["string","null"]}},"required":["healthy","lastCheckedAt","reregisteredAt","recentlyReregistered","error"]},"reconciliation":{"type":"object","properties":{"lastRunAt":{"type":["string","null"],"format":"date-time","description":"When reconciliation last ran"},"reconciledThrough":{"type":["string","null"],"format":"date-time","description":"The Shopify `updated_at` reconciliation has reached; it lags `lastRunAt` while a backlog drains"},"repairedOrders":{"type":"integer","description":"Orders the last run re-fetched from Shopify, because their delivery never arrived or ours was older than Shopify's, and OFFERED to the ingest queue. Ingest is asynchronous, so this counts what was sent, not what was stored; an order that does not land is re-offered by every later run and appears in `failed`."},"failed":{"type":"integer","description":"How many DISTINCT orders were offered to the ingest queue at least an hour ago and are still not stored at the revision offered: their ingest is failing, so they are missing from realized profit and from `listItemEconomics`. Counted now, not taken from the last run, and counted in full: an order offered at two revisions counts once. Every reconciliation run re-offers up to 25 of them, least recently offered first, so a transient cause clears itself and no order waits for ever — but those 25 come out of the same 50 order fetches and the same Admin-call budget the run spends catching up on new orders, so a busy run may retry fewer of them, or none, and this number then stays put for a day. A number that stays above 0 for days with a quiet store is a payload the ingest cannot parse, and the API's logs name the reason (`order.ingest_failed`, for the order id in `failedOrderIds`). An order still failing when it passes Shopify's 60-day `read_orders` horizon can never be recovered: it is recorded once as a `webhooks.order_lost` audit entry and drops out of this count. That write-off also takes at most 25 orders a run, so an order can stay counted here for a few days after crossing the horizon."},"failedOrderIds":{"type":"array","items":{"type":"string"},"description":"The order gids behind `failed`, the ones failing longest first, at most 25 of them however large `failed` is. Empty when `failed` is 0."},"failedOrderIdsOmitted":{"type":"integer","minimum":0,"description":"How many of `failed` this response does not name: 0 whenever `failedOrderIds` holds every failing order, and `failed` minus the 25 it names beyond that. It is here so that a caller saying \"and N more\" out loud states a figure this API computed rather than subtracting a page from a total (decision 89). Never negative: the count and the names come from two statements, so a set that grows between them is reported as a full list and nothing more."},"backlog":{"type":"boolean","description":"True when the last run stopped at its cap: orders before `reconciledThrough` are handled, later ones are still queued for the next runs"}},"required":["lastRunAt","reconciledThrough","repairedOrders","failed","failedOrderIds","failedOrderIdsOmitted","backlog"]},"pricing":{"type":"object","properties":{"ok":{"type":["boolean","null"],"description":"True when both app discounts exist, are active on Shopify, and hold every entry a publish would write. False when they do not, which means every live offer on this store is selling at list price. Null when nothing has checked yet, or the last check could not reach Shopify; `error` says which, and `rebuildStorePricing` settles it."},"error":{"type":["string","null"],"description":"What is wrong and what to do about it, in a stable sentence; null when `ok` is true"},"checkedAt":{"type":["string","null"],"format":"date-time","description":"When the install, the daily job or `rebuildStorePricing` last asked Shopify"}},"required":["ok","error","checkedAt"]},"capability":{"type":"object","properties":{"plan":{"type":["object","null"],"properties":{"shopifyPlus":{"type":"boolean","description":"The shop is on Shopify Plus"},"partnerDevelopment":{"type":"boolean","description":"The shop is a partner development store, which runs every operation Plus runs"},"name":{"type":"string","description":"The plan's name as Shopify shows it, such as `Basic` or `Shopify Plus`"},"currencyCode":{"type":"string","description":"The shop's own currency. A fixed transform price in a document of this currency is converted to another market's currency at checkout; one in another currency applies only to carts in that currency"},"checkedAt":{"type":"string","format":"date-time","description":"When the plan was last read from Shopify"}},"required":["shopifyPlus","partnerDevelopment","name","currencyCode","checkedAt"],"description":"Null until the plan has been read since the store's last grant; the store then counts as the least capable plan"},"cartTransformRegistered":{"type":"boolean","description":"Offer Suite's cart transform is registered on the store; without it no presentation or line price can run"},"operations":{"type":"object","properties":{"lineUpdate":{"type":"boolean","description":"A line's own price, title or image (`line_price` and line overrides). Shopify Plus only; elsewhere a line price runs as the line expanded into itself"},"linesMerge":{"type":"boolean","description":"A virtual bundle by merge: several lines into a parent variant with a percentage off, a title, an image and attributes"},"lineExpand":{"type":"boolean","description":"A virtual bundle by expand: one line into components with a percentage off the parent and per-component attributes"},"lineExpandFixedPrices":{"type":"boolean","description":"An expand that sets a fixed price per component. Any plan with our cart transform registered (OS-366)"},"lineExpandTitleImage":{"type":"boolean","description":"An expand that sets the bundle's title or image. Any plan with our cart transform registered (OS-366)"}},"required":["lineUpdate","linesMerge","lineExpand","lineExpandFixedPrices","lineExpandTitleImage"],"description":"The cart transform operations this store can run. None of them ever runs on a line with a selling plan: Shopify drops those silently"},"error":{"type":["string","null"],"description":"Why the plan or the transform could not be read or registered last time, in a sentence; null when both were"}},"required":["plan","cartTransformRegistered","operations","error"],"description":"What the store can present and price through Offer Suite's cart transform"}},"required":["id","myshopifyDomain","scopes","installedAt","uninstalledAt","webhooks","reconciliation","pricing","capability"]}}}},"401":{"description":"Missing, unknown or revoked API key","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}},"403":{"description":"The key is public; this route needs a secret key","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}},"404":{"description":"No such store","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}}}}},"/stores/{id}/overview":{"get":{"operationId":"getStoreOverview","summary":"One store's setup, profit summary and notices","description":"What the store's setup still needs (an offer live, prices that work in Shopify, shoppers seeing an offer, orders arriving, a costed catalog, and optionally an agent), its realized contribution over the shop's last 30 days (current cost view, net of refunds, first orders and renewals) with first-order contribution per visitor, and ranked notices, most urgent first. The store's figures are those of the offer versions written for it, so another store's orders never count, even in the same workspace. The App Home shows the same object for the store it is opened in.","tags":["Stores"],"security":[{"apiKey":[]}],"parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"The overview","content":{"application/json":{"schema":{"type":"object","properties":{"storeId":{"type":"string","format":"uuid"},"myshopifyDomain":{"type":"string"},"ianaTimezone":{"type":["string","null"],"description":"The shop's time zone, read from Shopify with its plan; the summary's days are the shop's own. Null until read, when days are UTC"},"setup":{"type":"object","properties":{"dismissedAt":{"type":["string","null"],"format":"date-time"},"complete":{"type":"boolean","description":"Every step that is not optional is done"},"steps":{"type":"array","items":{"type":"object","properties":{"key":{"type":"string","enum":["offer_published","prices_work","storefront_shows_offer","orders_arrive","catalog_costed","agent_connected"]},"done":{"type":"boolean"},"optional":{"type":"boolean","description":"A step the store works without: a merchant may run offers without an agent"},"detail":{"type":"string","description":"What was found, or what to do next"}},"required":["key","done","optional","detail"]}}},"required":["dismissedAt","complete","steps"]},"summary":{"type":"object","properties":{"window":{"type":"object","properties":{"from":{"type":"string","format":"date-time"},"to":{"type":"string","format":"date-time"},"days":{"type":"integer","exclusiveMinimum":0}},"required":["from","to","days"]},"currencyCode":{"type":["string","null"],"description":"The shop currency every money figure is in; null before the first order"},"orders":{"type":"integer","minimum":0,"description":"Orders on this store's offers in the window, first orders and renewals, not cancelled"},"firstOrders":{"type":"integer","minimum":0},"contributionCents":{"type":"integer","description":"Realized contribution of those orders, current cost view, net of refunds"},"firstOrderContributionCents":{"type":"integer"},"visitors":{"type":"integer","minimum":0,"description":"Distinct visitors who saw one of this store's offers in the window"},"contributionPerVisitorCents":{"type":["number","null"],"description":"First-order contribution per visitor, the experiments' metric; null without visitors"},"otherCurrencyOrders":{"type":"integer","minimum":0,"description":"Orders in another currency: in no figure above"}},"required":["window","currencyCode","orders","firstOrders","contributionCents","firstOrderContributionCents","visitors","contributionPerVisitorCents","otherCurrencyOrders"]},"notices":{"type":"array","items":{"type":"object","properties":{"key":{"type":"string","description":"Stable per kind of notice, so a page can key and test it"},"tone":{"type":"string","enum":["critical","warning","info"]},"title":{"type":"string"},"body":{"type":"string"},"action":{"type":["string","null"],"enum":["open_dashboard","open_costs",null],"description":"Where the notice sends the merchant; each surface maps it to its own link"}},"required":["key","tone","title","body","action"]},"description":"Most urgent first"}},"required":["storeId","myshopifyDomain","ianaTimezone","setup","summary","notices"]}}}},"401":{"description":"Missing, unknown or revoked API key","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}},"403":{"description":"The key is public; this route needs a secret key","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}},"404":{"description":"No such connected store","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}}}}},"/stores":{"get":{"operationId":"listStores","summary":"List the tenant's connected stores","description":"Every store that completed the install flow, with its granted scopes and the health the daily job last found: its webhook subscriptions, its order reconciliation, and whether its app discounts still price what its live offers promise (`pricing.ok: false` means the store is selling at list price). Every field is read from the database, so this route makes no call to Shopify. An uninstalled store keeps its row with `uninstalledAt` set. `GET /stores/{id}` returns one store in the same shape.","tags":["Stores"],"security":[{"apiKey":[]}],"responses":{"200":{"description":"The stores","content":{"application/json":{"schema":{"type":"object","properties":{"stores":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"myshopifyDomain":{"type":"string"},"scopes":{"type":"array","items":{"type":"string"}},"installedAt":{"type":"string","format":"date-time"},"uninstalledAt":{"type":["string","null"],"format":"date-time"},"webhooks":{"type":"object","properties":{"healthy":{"type":"boolean","description":"False for either of two reasons. The last check failed, so deliveries may be lost until one succeeds; or the check succeeded but a window of orders older than Shopify's 60-day `read_orders` access went unreconciled and never can be. The second is permanent and is recorded once per window as a `webhooks.unreconcilable` audit entry, since this field is overwritten as soon as a later run is clean. An order that failed to ingest does NOT make this false — the subscriptions are fine and deliveries are arriving; read `reconciliation.failed` for that."},"lastCheckedAt":{"type":["string","null"],"format":"date-time"},"reregisteredAt":{"type":["string","null"],"format":"date-time","description":"When a subscription Shopify had deleted was last re-created. It stays set; `recentlyReregistered` is the one to act on, and is true for 7 days after it."},"recentlyReregistered":{"type":"boolean","description":"True while `reregisteredAt` is within the last 7 days: deliveries were being lost that recently"},"error":{"type":["string","null"]}},"required":["healthy","lastCheckedAt","reregisteredAt","recentlyReregistered","error"]},"reconciliation":{"type":"object","properties":{"lastRunAt":{"type":["string","null"],"format":"date-time","description":"When reconciliation last ran"},"reconciledThrough":{"type":["string","null"],"format":"date-time","description":"The Shopify `updated_at` reconciliation has reached; it lags `lastRunAt` while a backlog drains"},"repairedOrders":{"type":"integer","description":"Orders the last run re-fetched from Shopify, because their delivery never arrived or ours was older than Shopify's, and OFFERED to the ingest queue. Ingest is asynchronous, so this counts what was sent, not what was stored; an order that does not land is re-offered by every later run and appears in `failed`."},"failed":{"type":"integer","description":"How many DISTINCT orders were offered to the ingest queue at least an hour ago and are still not stored at the revision offered: their ingest is failing, so they are missing from realized profit and from `listItemEconomics`. Counted now, not taken from the last run, and counted in full: an order offered at two revisions counts once. Every reconciliation run re-offers up to 25 of them, least recently offered first, so a transient cause clears itself and no order waits for ever — but those 25 come out of the same 50 order fetches and the same Admin-call budget the run spends catching up on new orders, so a busy run may retry fewer of them, or none, and this number then stays put for a day. A number that stays above 0 for days with a quiet store is a payload the ingest cannot parse, and the API's logs name the reason (`order.ingest_failed`, for the order id in `failedOrderIds`). An order still failing when it passes Shopify's 60-day `read_orders` horizon can never be recovered: it is recorded once as a `webhooks.order_lost` audit entry and drops out of this count. That write-off also takes at most 25 orders a run, so an order can stay counted here for a few days after crossing the horizon."},"failedOrderIds":{"type":"array","items":{"type":"string"},"description":"The order gids behind `failed`, the ones failing longest first, at most 25 of them however large `failed` is. Empty when `failed` is 0."},"failedOrderIdsOmitted":{"type":"integer","minimum":0,"description":"How many of `failed` this response does not name: 0 whenever `failedOrderIds` holds every failing order, and `failed` minus the 25 it names beyond that. It is here so that a caller saying \"and N more\" out loud states a figure this API computed rather than subtracting a page from a total (decision 89). Never negative: the count and the names come from two statements, so a set that grows between them is reported as a full list and nothing more."},"backlog":{"type":"boolean","description":"True when the last run stopped at its cap: orders before `reconciledThrough` are handled, later ones are still queued for the next runs"}},"required":["lastRunAt","reconciledThrough","repairedOrders","failed","failedOrderIds","failedOrderIdsOmitted","backlog"]},"pricing":{"type":"object","properties":{"ok":{"type":["boolean","null"],"description":"True when both app discounts exist, are active on Shopify, and hold every entry a publish would write. False when they do not, which means every live offer on this store is selling at list price. Null when nothing has checked yet, or the last check could not reach Shopify; `error` says which, and `rebuildStorePricing` settles it."},"error":{"type":["string","null"],"description":"What is wrong and what to do about it, in a stable sentence; null when `ok` is true"},"checkedAt":{"type":["string","null"],"format":"date-time","description":"When the install, the daily job or `rebuildStorePricing` last asked Shopify"}},"required":["ok","error","checkedAt"]},"capability":{"type":"object","properties":{"plan":{"type":["object","null"],"properties":{"shopifyPlus":{"type":"boolean","description":"The shop is on Shopify Plus"},"partnerDevelopment":{"type":"boolean","description":"The shop is a partner development store, which runs every operation Plus runs"},"name":{"type":"string","description":"The plan's name as Shopify shows it, such as `Basic` or `Shopify Plus`"},"currencyCode":{"type":"string","description":"The shop's own currency. A fixed transform price in a document of this currency is converted to another market's currency at checkout; one in another currency applies only to carts in that currency"},"checkedAt":{"type":"string","format":"date-time","description":"When the plan was last read from Shopify"}},"required":["shopifyPlus","partnerDevelopment","name","currencyCode","checkedAt"],"description":"Null until the plan has been read since the store's last grant; the store then counts as the least capable plan"},"cartTransformRegistered":{"type":"boolean","description":"Offer Suite's cart transform is registered on the store; without it no presentation or line price can run"},"operations":{"type":"object","properties":{"lineUpdate":{"type":"boolean","description":"A line's own price, title or image (`line_price` and line overrides). Shopify Plus only; elsewhere a line price runs as the line expanded into itself"},"linesMerge":{"type":"boolean","description":"A virtual bundle by merge: several lines into a parent variant with a percentage off, a title, an image and attributes"},"lineExpand":{"type":"boolean","description":"A virtual bundle by expand: one line into components with a percentage off the parent and per-component attributes"},"lineExpandFixedPrices":{"type":"boolean","description":"An expand that sets a fixed price per component. Any plan with our cart transform registered (OS-366)"},"lineExpandTitleImage":{"type":"boolean","description":"An expand that sets the bundle's title or image. Any plan with our cart transform registered (OS-366)"}},"required":["lineUpdate","linesMerge","lineExpand","lineExpandFixedPrices","lineExpandTitleImage"],"description":"The cart transform operations this store can run. None of them ever runs on a line with a selling plan: Shopify drops those silently"},"error":{"type":["string","null"],"description":"Why the plan or the transform could not be read or registered last time, in a sentence; null when both were"}},"required":["plan","cartTransformRegistered","operations","error"],"description":"What the store can present and price through Offer Suite's cart transform"}},"required":["id","myshopifyDomain","scopes","installedAt","uninstalledAt","webhooks","reconciliation","pricing","capability"]}}},"required":["stores"]}}}},"401":{"description":"Missing, unknown or revoked API key","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}},"403":{"description":"The key is public; this route needs a secret key","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}}}}},"/stores/{id}/webhooks":{"post":{"operationId":"registerStoreWebhooks","summary":"Register (or re-register) the store's webhooks","description":"Creates any missing subscription (orders/create, orders/updated, app/uninstalled) pointing at this environment. Use it after the install page reported a refused topic, for example once protected customer data access is granted.","tags":["Stores"],"security":[{"apiKey":[]}],"parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"Every topic now subscribed","content":{"application/json":{"schema":{"type":"object","properties":{"registered":{"type":"array","items":{"type":"object","properties":{"topic":{"type":"string"},"id":{"type":"string"},"created":{"type":"boolean"}},"required":["topic","id","created"]}}},"required":["registered"]}}}},"401":{"description":"Missing, unknown or revoked API key","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}},"403":{"description":"The key is public; this route needs a secret key","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}},"404":{"description":"No such store, or it is uninstalled","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}},"502":{"description":"Shopify refused a subscription; the message says why","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}}}}},"/stores/{id}/pixel":{"post":{"operationId":"connectStorePixel","summary":"Connect (or reconnect) the store's web pixel","description":"Creates the Offer Suite web pixel on the store, or replaces its settings: a freshly minted public key and this environment's API origin, so checkout and purchase events reach `POST /events` (decision 44). The store's previous pixel key is revoked. Needs the `write_pixels` and `read_customer_events` scopes: on a store installed before they existed, the merchant opens Offer Suite from the Shopify admin first, where Shopify asks them to approve the scopes the app now declares.","tags":["Stores"],"security":[{"apiKey":[]}],"parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"The pixel is connected with a new public key","content":{"application/json":{"schema":{"type":"object","properties":{"pixelId":{"type":"string"},"created":{"type":"boolean"},"keyPrefix":{"type":"string"}},"required":["pixelId","created","keyPrefix"]}}}},"401":{"description":"Missing, unknown or revoked API key","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}},"403":{"description":"The key is public; this route needs a secret key","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}},"404":{"description":"No such store, or it is uninstalled","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}},"502":{"description":"`pixel_refused`: Shopify refused the pixel, usually for missing scopes; the message says why","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}}}}},"/stores/{id}/theme-block":{"post":{"operationId":"connectStoreThemeBlock","summary":"Give the store's theme app block its key","description":"The Offer Suite theme app block (\"Verified offer\" in the theme editor) renders an offer with the store's public key and this environment's API origin, which it reads from an app-data metafield on the app's installation, so a merchant never pastes a key. Installing or opening the app writes them; call this to repair a block that shows no offer after its key was revoked. When the key the store holds is live, nothing changes (`created: false`); otherwise a new public key is minted and written, and the store's older block key is revoked only once Shopify accepted the new one.","tags":["Stores"],"security":[{"apiKey":[]}],"parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"The block holds a live key","content":{"application/json":{"schema":{"type":"object","properties":{"connected":{"type":"boolean","enum":[true]},"created":{"type":"boolean","description":"A new key was minted and written"},"keyPrefix":{"type":"string"}},"required":["connected","created","keyPrefix"]}}}},"401":{"description":"Missing, unknown or revoked API key","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}},"403":{"description":"The key is public; this route needs a secret key","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}},"404":{"description":"No such store, or it is uninstalled","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}},"502":{"description":"`theme_block_refused`: Shopify refused the metafield write; the block keeps the key it had","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}}}}},"/stores/{id}/pricing":{"post":{"operationId":"rebuildStorePricing","summary":"Rebuild the store's app discounts and option maps","description":"Puts the store's prices back without republishing anything. Uninstalling the app deletes its automatic discounts and their metafields, and a merchant can delete one in the Shopify admin: every live offer then sells at list price while every version still reads `live`, and publishing the same version again is refused (`not_publishable`). This re-creates both app discounts and rewrites the option map of every version the store must price, exactly as a publish's map step does (decision 88). It changes no offer, mints no discount code and flips no status, so it is safe to call at any time; it writes to Shopify only when a discount is missing or an entry a publish would write is absent. A map holding MORE than the live versions is left alone: a version being published is legitimately there between its map step and going live, and pruning it would make that version sell at list price. A discount the merchant DEACTIVATED has its map repaired but its dates are never touched — only they can turn it back on, and `error` says so. **This is the only store route that calls Shopify** (about four Admin calls for a check, fourteen for a repair); `GET /stores` and `GET /stores/{id}` read the judgement this writes on the store row. The install flow and the daily health job call this by themselves — use it to repair a store sooner.","tags":["Stores"],"security":[{"apiKey":[]}],"parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"What the check found, after any repair it made","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","description":"The store prices what its live offers promise, after any repair this call made, and no live option's latest real-cart verification (the daily job's or `POST /offers/{id}/verify`) is mismatched"},"stale":{"type":"boolean","description":"A discount was missing, or an entry a publish would write was missing or different: what this call repairs. A map holding MORE than the live versions is not stale — a version being published is legitimately there"},"repaired":{"type":"boolean","description":"The discounts and every shard were written by this call"},"documents":{"type":"integer","description":"Offer versions these maps must price: live versions, versions retired inside the grace period, and running experiment arms"},"discounts":{"type":"array","items":{"type":"object","properties":{"title":{"type":"string"},"present":{"type":"boolean","description":"The store has this discount and our app owns it"},"current":{"type":"boolean","description":"Its option map holds every entry a publish would write; it may hold more"},"status":{"type":["string","null"],"description":"Shopify's own status; only an `ACTIVE` discount prices a cart"}},"required":["title","present","current","status"]}},"error":{"type":["string","null"],"description":"What is still wrong after this call, in a stable sentence; null when `ok`"}},"required":["ok","stale","repaired","documents","discounts","error"]}}}},"401":{"description":"Missing, unknown or revoked API key","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}},"403":{"description":"The key is public; this route needs a secret key","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}},"404":{"description":"No such store, or it is uninstalled","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}},"502":{"description":"`pricing_refused`: Shopify refused a discount or a metafield write. Check the app still has `write_discounts` on this store and retry; the raw reason is in the API logs","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}}}}},"/stores/{id}/order-imports":{"post":{"operationId":"startOrderImport","summary":"Import the store's past orders","description":"Stores the orders the store took before Offer Suite saw them, so SKU, product and store profit history starts before the install. Every order goes through the same ingest as a live one: frozen as placed, refunds and cancellations included, costed at the costs effective on its date as the ledger knows them now, and mirrored for realized profit. Past orders carry no Offer Suite pointer, so they count toward items and the store, never toward an offer. Runs in the background, about 100 orders a page; read its progress with `getOrderImport`. Orders already stored are skipped, so running it again only fills gaps. Without Shopify's `read_all_orders` grant only the last 60 days can be read (`window.limitedBy`). Past orders are costed with the tenant's `defaultCostProfile`, which must be set first. Adding costs later restates the imported orders' current view like any other.","tags":["Stores"],"security":[{"apiKey":[]}],"parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"object","properties":{"since":{"type":"string","format":"date-time","description":"Import orders created at or after this instant; a year back by default"}}}}}},"responses":{"202":{"description":"The import, started","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"storeId":{"type":"string","format":"uuid"},"status":{"type":"string","enum":["running","done","failed"],"description":"`running` until the last page is stored; `failed` says why in `error`"},"window":{"type":"object","properties":{"since":{"type":"string","format":"date-time","description":"Orders created at or after this instant are imported"},"until":{"type":"string","format":"date-time","description":"The moment the import started: later orders arrive through the webhooks, not the import"},"requestedSince":{"type":"string","format":"date-time","description":"What was asked for (a year back by default)"},"limitedBy":{"type":["string","null"],"enum":["read_orders",null],"description":"`read_orders` when `since` is later than asked: until Shopify grants the app `read_all_orders`, it serves only the last 60 days of orders"}},"required":["since","until","requestedSince","limitedBy"]},"counts":{"type":"object","properties":{"found":{"type":"integer","description":"Orders Shopify listed in the window so far"},"imported":{"type":"integer","description":"Stored or brought up to date by this import"},"alreadyStored":{"type":"integer","description":"Already stored at Shopify's current revision (a webhook or an earlier import got there), so not read again"},"failed":{"type":"integer","description":"Orders that could not be stored; the first 50 are in `failures` with the reason"}},"required":["found","imported","alreadyStored","failed"]},"failures":{"type":"array","items":{"type":"object","properties":{"orderId":{"type":"string","pattern":"^gid:\\/\\/shopify\\/Order\\/\\d+$","description":"A Shopify Order gid (`gid://shopify/Order/<id>`)"},"reason":{"type":"string"}},"required":["orderId","reason"]}},"error":{"type":["string","null"]},"requestedBy":{"type":"string"},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time","description":"Moves with every page: an import that stops moving for an hour is replaced by the next start"},"finishedAt":{"type":["string","null"],"format":"date-time"}},"required":["id","storeId","status","window","counts","failures","error","requestedBy","createdAt","updatedAt","finishedAt"]}}}},"400":{"description":"`invalid_request`: `since` is not an instant, or is in the future","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}},"401":{"description":"Missing, unknown or revoked API key","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}},"403":{"description":"The key is public; this route needs a secret key","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}},"404":{"description":"No such connected store","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}},"409":{"description":"`import_running`: the store already has an import running; the message names it. `default_cost_profile_required`: set the tenant's `defaultCostProfile` first","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}}}},"get":{"operationId":"listOrderImports","summary":"The store's past-order imports","description":"The store's last 20 imports, newest first, each as `getOrderImport` returns it.","tags":["Stores"],"security":[{"apiKey":[]}],"parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"The imports","content":{"application/json":{"schema":{"type":"object","properties":{"imports":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"storeId":{"type":"string","format":"uuid"},"status":{"type":"string","enum":["running","done","failed"],"description":"`running` until the last page is stored; `failed` says why in `error`"},"window":{"type":"object","properties":{"since":{"type":"string","format":"date-time","description":"Orders created at or after this instant are imported"},"until":{"type":"string","format":"date-time","description":"The moment the import started: later orders arrive through the webhooks, not the import"},"requestedSince":{"type":"string","format":"date-time","description":"What was asked for (a year back by default)"},"limitedBy":{"type":["string","null"],"enum":["read_orders",null],"description":"`read_orders` when `since` is later than asked: until Shopify grants the app `read_all_orders`, it serves only the last 60 days of orders"}},"required":["since","until","requestedSince","limitedBy"]},"counts":{"type":"object","properties":{"found":{"type":"integer","description":"Orders Shopify listed in the window so far"},"imported":{"type":"integer","description":"Stored or brought up to date by this import"},"alreadyStored":{"type":"integer","description":"Already stored at Shopify's current revision (a webhook or an earlier import got there), so not read again"},"failed":{"type":"integer","description":"Orders that could not be stored; the first 50 are in `failures` with the reason"}},"required":["found","imported","alreadyStored","failed"]},"failures":{"type":"array","items":{"type":"object","properties":{"orderId":{"type":"string","pattern":"^gid:\\/\\/shopify\\/Order\\/\\d+$","description":"A Shopify Order gid (`gid://shopify/Order/<id>`)"},"reason":{"type":"string"}},"required":["orderId","reason"]}},"error":{"type":["string","null"]},"requestedBy":{"type":"string"},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time","description":"Moves with every page: an import that stops moving for an hour is replaced by the next start"},"finishedAt":{"type":["string","null"],"format":"date-time"}},"required":["id","storeId","status","window","counts","failures","error","requestedBy","createdAt","updatedAt","finishedAt"]}}},"required":["imports"]}}}},"401":{"description":"Missing, unknown or revoked API key","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}},"403":{"description":"The key is public; this route needs a secret key","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}}}}},"/stores/{id}/order-imports/{importId}":{"get":{"operationId":"getOrderImport","summary":"One past-order import and its progress","description":"The import's window, how many orders it found, stored, skipped as already stored and could not store (with the first 50 reasons), and whether it is still running.","tags":["Stores"],"security":[{"apiKey":[]}],"parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string","format":"uuid"},"required":true,"name":"importId","in":"path"}],"responses":{"200":{"description":"The import","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"storeId":{"type":"string","format":"uuid"},"status":{"type":"string","enum":["running","done","failed"],"description":"`running` until the last page is stored; `failed` says why in `error`"},"window":{"type":"object","properties":{"since":{"type":"string","format":"date-time","description":"Orders created at or after this instant are imported"},"until":{"type":"string","format":"date-time","description":"The moment the import started: later orders arrive through the webhooks, not the import"},"requestedSince":{"type":"string","format":"date-time","description":"What was asked for (a year back by default)"},"limitedBy":{"type":["string","null"],"enum":["read_orders",null],"description":"`read_orders` when `since` is later than asked: until Shopify grants the app `read_all_orders`, it serves only the last 60 days of orders"}},"required":["since","until","requestedSince","limitedBy"]},"counts":{"type":"object","properties":{"found":{"type":"integer","description":"Orders Shopify listed in the window so far"},"imported":{"type":"integer","description":"Stored or brought up to date by this import"},"alreadyStored":{"type":"integer","description":"Already stored at Shopify's current revision (a webhook or an earlier import got there), so not read again"},"failed":{"type":"integer","description":"Orders that could not be stored; the first 50 are in `failures` with the reason"}},"required":["found","imported","alreadyStored","failed"]},"failures":{"type":"array","items":{"type":"object","properties":{"orderId":{"type":"string","pattern":"^gid:\\/\\/shopify\\/Order\\/\\d+$","description":"A Shopify Order gid (`gid://shopify/Order/<id>`)"},"reason":{"type":"string"}},"required":["orderId","reason"]}},"error":{"type":["string","null"]},"requestedBy":{"type":"string"},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time","description":"Moves with every page: an import that stops moving for an hour is replaced by the next start"},"finishedAt":{"type":["string","null"],"format":"date-time"}},"required":["id","storeId","status","window","counts","failures","error","requestedBy","createdAt","updatedAt","finishedAt"]}}}},"401":{"description":"Missing, unknown or revoked API key","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}},"403":{"description":"The key is public; this route needs a secret key","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}},"404":{"description":"No such import of this store","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}}}}},"/experiments":{"get":{"operationId":"listWorkspaceExperiments","summary":"Every experiment in the workspace, newest first","description":"The experiments of every offer of this workspace, active ones and stopped ones, newest first, each with the offer it runs on. `status` narrows it (`active` is starting, running or paused). Read one with `get_experiment` for its report.","tags":["Experiments"],"security":[{"apiKey":[]}],"parameters":[{"schema":{"type":"string","enum":["active","stopped"]},"required":false,"name":"status","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":100},"required":false,"name":"limit","in":"query"}],"responses":{"200":{"description":"The experiments","content":{"application/json":{"schema":{"type":"object","properties":{"experiments":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"offerId":{"type":"string","format":"uuid"},"status":{"type":"string","enum":["starting","running","paused","stopped"],"description":"`starting` while its arms are written into the store's option map (visitors see the control), `running`, `paused` (visitors see the control), `stopped`"},"controlVersion":{"type":"integer","exclusiveMinimum":0},"arms":{"type":"array","items":{"type":"object","properties":{"version":{"type":"integer","exclusiveMinimum":0},"weight":{"type":"number","exclusiveMinimum":0,"exclusiveMaximum":1}},"required":["version","weight"]}},"falsePositiveRate":{"type":"number"},"minimumDetectableEffect":{"type":"number"},"plannedVisitorsPerArm":{"type":["integer","null"],"description":"Visitors each arm needs to detect `minimumDetectableEffect` at 80% power, from the control's last 30 days; null without history"},"baseline":{"type":"object","properties":{"windowDays":{"type":"integer"},"visitors":{"type":"integer"},"meanCents":{"type":"number"},"varianceCentsSquared":{"type":"number"}},"required":["windowDays","visitors","meanCents","varianceCentsSquared"]},"startedAt":{"type":"string","format":"date-time"},"pausedAt":{"type":["string","null"],"format":"date-time"},"endedAt":{"type":["string","null"],"format":"date-time"},"stopReason":{"type":["string","null"]},"winnerVersion":{"type":["integer","null"]},"actor":{"type":"string"},"offer":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"code":{"type":"string"}},"required":["id","code"],"description":"The offer the experiment runs on"}},"required":["id","offerId","status","controlVersion","arms","falsePositiveRate","minimumDetectableEffect","plannedVisitorsPerArm","baseline","startedAt","pausedAt","endedAt","stopReason","winnerVersion","actor","offer"]}}},"required":["experiments"]}}}},"401":{"description":"Missing, unknown or revoked API key","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}},"403":{"description":"The key is public; this route needs a secret key","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"]}}},"required":["code","message"]}},"required":["error"]}}}}}}}},"webhooks":{}}