Skip to content

Coupons

Create discount codes and apply them to orders.

Coupons let you offer fixed-amount or percentage discounts to customers. Each coupon can have one or more codes that customers enter at checkout.

Concepts

A Coupon defines the discount rules — type, value, usage limit, validity window, and which items it applies to.

A Coupon Code is the string a customer enters (e.g. TEST50). Multiple codes can share the same coupon configuration.


Creating a Coupon

Percentage Discount

const { coupon } = await client.coupon.create({
  name: 'Early Bird 20%',
  kind: 'PERCENT',
  discount: 2000, // basis points — 2000 = 20%
  filter: 'EVENTS',
  events: [{ id: 'evt_01jps5cgsenjrazw6wswmyspa3' }],
  limit: 100,
  saleStartsAt: '2025-01-01T00:00:00',
  saleEndsAt: '2025-02-01T00:00:00',
  teamId: 'team_456',
});

Fixed Amount Discount

const { coupon } = await client.coupon.create({
  name: '$10 Off',
  kind: 'AMOUNT',
  discount: 1000, // cents — 1000 = $10.00
  currency: 'AUD',
  filter: 'TEAM',
  limit: -1, // unlimited
  saleStartsAt: '2025-01-01T00:00:00',
  teamId: 'team_456',
});

Coupon Fields

FieldTypeRequiredDescription
namestringYesInternal label
kindstringYesPERCENT (basis points) or AMOUNT (cents)
discountnumberYesDiscount value (see kind)
currencystringAMOUNT onlyISO 4217 currency code
filterstringYesScope: TEAM, PROMOTER, EVENTS, SECTIONS, or ADMISSIONS
limitnumberYesMax redemptions (-1 for unlimited)
saleStartsAtstringYesStart of validity window (ISO 8601, no timezone)
saleEndsAtstringNoEnd of validity window
teamIdstringYesOwning team
eventsarrayNoEvent IDs (when filter is EVENTS)
sectionsarrayNoSection IDs (when filter is SECTIONS)
admissionsarrayNoAdmission IDs (when filter is ADMISSIONS)
promotersarrayNoPromoter IDs (when filter is PROMOTER)

Filter Scopes

FilterApplies to
TEAMAll events in the team
PROMOTERAll events by the specified promoters
EVENTSOnly the specified events
SECTIONSOnly the specified sections
ADMISSIONSOnly the specified admissions

Managing Codes

Add one or more codes to a coupon:

const { couponCode } = await client.coupon.code.create({
  couponId: 'cpn_01jps5cgsfzs1ksqaet5hba8ac',
  name: 'TEST50',
  active: true,
  teamId: 'team_456',
});

Code names must be unique within a team.

List codes for a coupon:

const { couponCodes } = await client.coupon.code.list({
  couponId: 'cpn_01jps5cgsfzs1ksqaet5hba8ac',
});

Deactivate a code without deleting it:

await client.coupon.code.update({
  id: 'code_789',
  active: false,
});

Applying a Coupon to an Order

Pass the code string when creating an order or requesting a quote:

// Preview the discount
const { quote } = await client.order.quote({
  eventId: 'evt_01jps5cgsenjrazw6wswmyspa3',
  items: [{ admissionId: 'adm_01jps5cgsee0xvapbk92e8eb4g', quantity: 2 }],
  couponCode: 'TEST50',
});

console.log(quote.price.discount); // negative value in cents
console.log(quote.price.total); // total after discount
// Apply at order creation
const { order } = await client.order.create({
  eventId: 'evt_01jps5cgsenjrazw6wswmyspa3',
  items: [{ admissionId: 'adm_01jps5cgsee0xvapbk92e8eb4g', quantity: 2 }],
  couponCode: 'TEST50',
  returnUrl: 'https://yoursite.com/order/complete',
});

Validation Rules

The API validates the coupon when applied:

  • The code must be active
  • The parent coupon must be active
  • The current time must be within the validity window
  • The coupon must not have exceeded its usage limit
  • The coupon’s filter must match the items in the order

If validation fails, the API returns a 400 Bad Request with details.


Usage Tracking

Each coupon tracks how many times it has been redeemed:

const { coupon } = await client.coupon.get({ id: 'cpn_01jps5cgsfzs1ksqaet5hba8ac' });

console.log(coupon.uses); // current redemptions
console.log(coupon.limit); // max allowed (-1 = unlimited)

Usage is tracked at both the coupon and code level. When a coupon has a limited number of uses, they are consumed on a first-come, first-served basis across all codes.