Skip to main content

Promotion Codes

The Promotion Codes API lets you manage redeemable discount codes for your store.

Overview

The Promotion Codes API provides endpoints to:

A promotion code is the redeemable string a customer enters at checkout, together with the discount it applies — a fixed amount or a percentage, with optional currency, duration, redemption cap, and expiry.

Stripe connection required

Promotion codes are synchronised with Stripe. A store that is not connected to Stripe cannot create promotion codes — Create returns 422 until the connection is in place. List, get, update, and archive work regardless.

Most fields are immutable after create

Once a promotion code has been created, only three fields can be changed: active, name, and price_uuids. The discount amount/percent, currency, duration, expiry, max redemptions, and the first_time_transaction / minimum_amount restrictions are frozen.

To change any frozen field, archive the code and create a new one.

Status

Every promotion code carries a derived status (also usable as a list filter):

StatusMeaning
activePublished, not hidden, and either has no expiry or the expiry is in the future
inactiveReversibly deactivated via PATCH {"active": false} — can be re-enabled
expiredThe expires_at date has passed
archivedIrreversibly archived via POST /promotion-codes/{id}/archive

An archived code with a past expiry reports archived — archive takes precedence over expiry.

Deactivate vs. archive

There are two ways to stop a code from being redeemed:

  • DeactivatePATCH /promotion-codes/{id} with {"active": false}. Reversible: call again with {"active": true} to re-enable.
  • ArchivePOST /promotion-codes/{id}/archive. Irreversible. The code is hidden from default listings and cannot be re-enabled.

Archived codes are excluded from the default list — pass ?status=archived to see them.

Scope

A promotion code is either global (valid for any product) or product-scoped, with an optional narrower list of variant UUIDs:

{ "type": "global" }
{
"type": "product",
"product_id": "550e8400-e29b-41d4-a716-446655440000",
"price_ids": [
"550e8400-e29b-41d4-a716-446655440001"
]
}

price_ids narrows a product-scoped code to specific variants of that product. An empty array means "all prices of the product".

The list endpoint's product_id filter is inclusive: it returns product-scoped codes for that product plus all global codes — the direct answer to "which promotion codes apply to product X?"