Coupons

Use the Coupons API to programmatically create, manage, and delete promotional coupons — whether targeting specific products, subscription tiers, or the entire order subtotal.

The API supports both item-level coupons (applied to specific products or all eligible items in a cart) and order-level coupons (a flat discount applied to the entire order subtotal). A single POST /coupons endpoint handles both creation and updates — the operation is determined automatically based on whether the coupon path identifier already exists. For base URL, authentication, technical standards, and observability, see the API overview.

🚧

Closed Beta — Order-Level Coupons. Order-level coupon functionality is currently in a closed, invite-only beta. Fields and examples marked Beta in the endpoint references below only behave as documented for enrolled accounts. The orderLevelDiscount request field, its response counterpart, and the constraints it enforces (flat-only discount type, single-period duration, forced combine: true and applyDiscountImmediately: true) are all beta-gated. Item-level coupon functionality is generally available.

API reference

The Coupons API is organized around two resources: coupons (discount configurations) and codes (the values customers enter at checkout). Each coupon can have many codes. Select an endpoint below to view its request parameters, path variables, and response schemas.

Coupon path identifier

Every coupon has a unique coupon path identifier (e.g., summer-sale-2026) that targets it across all endpoints as {coupon_id}. The identifier also drives the upsert pattern on POST /coupons — the API creates a new coupon if the identifier is unused and updates an existing one if it matches.

Identifier format and upsert behavior

The coupon identifier accepts alphanumeric characters, hyphens, and underscores only. On POST /coupons, an unused identifier triggers creation (action: coupon.create) and a matching identifier triggers an update (action: coupon.update). Validation errors return 200 OK with result: "error" — always inspect the action and result fields rather than relying on the HTTP status code alone.