Bundle set endpoint and app proxy
What a headless storefront or mobile app can read from Luxe, and the storefront endpoints Shopify proxies.
Bundle set endpoint
Read-only JSON of a store's live sets and published rewards ladder, for clients without a storefront session. Off by default: the merchant turns it on in Settings > Data and integrations > Mobile apps, which shows the base address. Password-protected stores answer 404 unless the merchant allows testing.
curl https://<luxe app>/public/v1/shops/<store>.myshopify.com/kitsconst base = "https://<luxe app>/public/v1/shops/<store>.myshopify.com";
const res = await fetch(`${base}/kits/${kitId}`, {
headers: etag ? { "If-None-Match": etag } : {},
});
if (res.status === 304) return cached;
const { schemaVersion, kit, items, config, rewards } = await res.json();Requests
| Request | Answer |
|---|---|
GET …/kits | Every live set (at most 500), oldest first |
GET …/kits?product=<id> | The set whose product is that product |
GET …/kits?collection=<handle> | The collection set on that collection |
GET …/kits/:kitId | One live set |
GET …/rewards | Store-wide ladders and collection set rules |
Objects
KitSummary: {id, type: "SLOT" | "FIXED" | "COLLECTION", title, handle, productId, collectionId}. The list requests answer {schemaVersion, shop, kits: KitSummary[]} (an empty list when nothing matches). PublicKit is {schemaVersion, shop, currency, kit, shell, collection, config, tray, pricing, items, rewards}: kit is the KitSummary plus rev, and config is the set as checkout reads it. Amounts are minor units of the shop currency.
Caching, limits and errors
- CORS
*, GET and OPTIONS, no credentials Cache-Control: public, max-age=60, stale-while-revalidate=300,ETag- 300 requests a minute per IP, 60 per store and IP, 6,000 per store
| Status | Body |
|---|---|
| 400 | invalid_request or invalid_shop |
| 404 | not_found |
| 405 | method_not_allowed, with Allow: GET, OPTIONS |
| 429 | rate_limited, with Retry-After |
| 502 | unavailable |
App proxy endpoints
Shopify proxies /apps/luxe/* on the store's domain with a signed query, so these answer only requests that come through the store's domain. Listed for transparency; not for third-party use.
| Method and path | Purpose |
|---|---|
POST /apps/luxe/events | Consent-gated analytics beacon |
POST /apps/luxe/concierge | Complete my set: Smart picks or Luxe AI picks |
GET /apps/luxe/concierge | Complete my set status: whether Smart picks and Luxe AI picks are on |
GET /apps/luxe/upsells | Upsell items for an offer and product |