Search Documentation
Search for a documentation page...
Subscription Cycles API
REST API endpoints for the curated boxes of a rolling subscription.
A rolling subscription ships a different box every cycle — "October: Ethiopia Guji + Colombia Huila". Each box is a subscription cycle: a title, a start date, and the list of items that ship in it. A cycle is the current one for exactly one step of its subscription plan's cadence (startsAt <= now < endsAt), and endsAt is derived from that cadence — it is returned but never accepted as input.
Cycles belong to a product whose subscriptionMode is rolling. Create the programme in the dashboard under Subscriptions → Rolling, then curate its calendar here. See Subscription Plans for the billing side, and Products for how the current and upcoming box appear on a product read.
Draft visibility
draft cycles are the merchant's unannounced boxes. They are returned only to a key that also holds the catalog:write scope (or to an unscoped key). A storefront:read key sees published cycles only — a draft is a 404 on the single read and is filtered out of the list, even when ?status=draft is requested.
List Subscription Cycles
Returns the boxes of one rolling subscription, or of every rolling subscription in the store, newest start date first.
Query Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
productId | string | — | Only the boxes of this rolling subscription (its product UUID). Omit for every rolling subscription in the store. |
status | string | — | draft or published. Omit for both. |
from | string | — | Only boxes starting on or after this ISO 8601 date |
to | string | — | Only boxes starting on or before this ISO 8601 date |
limit | number | 50 | Boxes per page (1-100) |
offset | number | 0 | Boxes to skip |
Response (200)
meta.count is how many boxes matched the filters, not the store total.
Items are returned as a denormalized snapshot — the same shape the packing list and order emails use. Prices, stock and other catalog fields are deliberately not exposed: a box may contain subscription-only products (status: "hidden") that are never listed on their own.
Get Subscription Cycle
Returns a single box by UUID. Same shape as one entry of the list data.
Errors
| Status | Meaning |
|---|---|
404 | No such box in this store — or the box is a draft and the key cannot see drafts |
Create Subscription Cycle
Adds a box to a rolling subscription's calendar.
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
productId | string | Yes | UUID of the rolling subscription's product (subscriptionMode must be rolling) |
title | string | Yes | What subscribers see this box called (1-120 chars), e.g. "October 2026" |
startsAt | string | Yes | ISO 8601 date or date-time the box starts shipping |
description | string | null | No | A few lines about the box, shown under the title |
image | string | null | No | Absolute URL of the box photo. Storefronts fall back to the item photos when unset. |
status | string | No | draft (default) or published |
items | object[] | No | What ships in the box (max 20 entries) |
Each entry of items:
| Field | Type | Required | Description |
|---|---|---|---|
productVariantId | string | Yes | Variant UUID of an item that ships in this box |
quantity | number | No | How many of this item ship in the box (1-99, default 1) |
A variant may appear only once — raise its quantity instead. Subscription-only items are ordinary products set to status: "hidden" (sellable but unlisted), so a box never needs a separate catalog.
endsAt is not accepted: it is derived from the subscription plan's cadence and moves with startsAt.
Response (201)
Returns the created cycle (same shape as Get Subscription Cycle).
Errors
| Status | Meaning |
|---|---|
400 | The product is not a rolling subscription, an item variant is not in this store, an item appears twice, or the box is published with no items — or with an item whose own product is still a draft |
404 | No such product in this store |
409 | Another box of this subscription already starts on that date, or the derived window overlaps another published box |
Error bodies carry error plus, where one applies, a hint describing the next step:
Update Subscription Cycle
Partially updates a box. Every field from Create is accepted and optional, except productId — a box cannot move between subscriptions.
Sending items replaces the whole list, so send the full box. Omitting it leaves the items untouched. Moving startsAt moves the derived endsAt with it.
The publish rules are evaluated against the resulting box: flipping an empty box to published without also sending its items is rejected with 400.
Response (200)
Returns the updated cycle.
Errors
Same as Create, plus 404 when the box does not exist in this store.
Delete Subscription Cycle
Removes a box from the calendar. Orders keep their own snapshot of what shipped, so deleting a box never erases a packing list.
Response (200)
Errors
| Status | Meaning |
|---|---|
404 | No such box in this store |