Promo Codes
Discount codes, campaigns, and validation
The Promo Codes module manages discount codes for orders and bookings using a flexible discount and condition system.
Data Structure
Promo codes use a nested structure with discounts and conditions arrays for maximum flexibility.
Discount Types
marketId refers to the market key (e.g. "us", "eu", "booking"), not a UUID. Basis points: 2000 = 20%. amount is in minor units (cents).
interface Discount {
type: 'ITEMS_PERCENTAGE' | 'ITEMS_FIXED' | 'SHIPPING_PERCENTAGE';
marketId: string;
bps?: number;
amount?: number;
}
Condition Types
interface Condition {
type: 'PRODUCTS' | 'SERVICES' | 'MIN_ORDER_AMOUNT' | 'DATE_RANGE' | 'MAX_USES' | 'MAX_USES_PER_USER';
value: ConditionValue;
}
// ConditionValue varies by type:
// - PRODUCTS/SERVICES: { type: 'IDS', value: string[] }
// - MIN_ORDER_AMOUNT: { type: 'AMOUNT', value: number }
// - MAX_USES / MAX_USES_PER_USER: { type: 'COUNT', value: number }
// - DATE_RANGE: { type: 'DATE_RANGE', value: { start?: number, end?: number } }
Create Promo Code
/v1/businesses/{businessId}/promo-codes sdk.promoCode.createPromoCode() Create a new promotional code.
// Percentage discount (20% off)
const percentResult = await sdk.promoCode.createPromoCode({
code: 'SUMMER20',
discounts: [
{
type: 'ITEMS_PERCENTAGE',
marketId: 'USD',
bps: 2000 // 20% = 2000 basis points
},
{
type: 'ITEMS_PERCENTAGE',
marketId: 'EUR',
bps: 2000
}
],
conditions: [
{ type: 'MIN_ORDER_AMOUNT', value: { type: 'AMOUNT', value: 5000 } },
{ type: 'MAX_USES', value: { type: 'COUNT', value: 1000 } },
{ type: 'DATE_RANGE', value: { type: 'DATE_RANGE', value: { start: 1717200000, end: 1725148800 } } }
]
});
// Fixed amount discount ($10 off)
const fixedResult = await sdk.promoCode.createPromoCode({
code: 'SAVE10',
discounts: [
{
type: 'ITEMS_FIXED',
marketId: 'USD',
amount: 1000 // $10.00 in cents
}
],
conditions: [
{ type: 'MAX_USES', value: { type: 'COUNT', value: 500 } }
]
});
// Product-specific discount
const productResult = await sdk.promoCode.createPromoCode({
code: 'WIDGETS20',
discounts: [
{
type: 'ITEMS_PERCENTAGE',
marketId: 'USD',
bps: 2000
}
],
conditions: [
{ type: 'PRODUCTS', value: { type: 'IDS', value: ['prod_widget1', 'prod_widget2'] } }
]
});
// Service-specific discount
const serviceResult = await sdk.promoCode.createPromoCode({
code: 'FIRSTVISIT',
discounts: [
{
type: 'ITEMS_PERCENTAGE',
marketId: 'USD',
bps: 1500 // 15% off
}
],
conditions: [
{ type: 'SERVICES', value: { type: 'IDS', value: ['svc_haircut', 'svc_coloring'] } },
{ type: 'MAX_USES', value: { type: 'COUNT', value: 100 } }
]
});Parameters
| Name | Type | Description |
|---|---|---|
code required | string | Promo code string (uppercase recommended) |
discounts required | Discount[] | Array of discount configurations per market |
conditions optional | Condition[] | Array of conditions for code validity |
Discount Object
Parameters
| Name | Type | Description |
|---|---|---|
type required | ITEMS_PERCENTAGE | ITEMS_FIXED | SHIPPING_PERCENTAGE | Discount type |
marketId required | string | Market key (e.g. 'us', 'eu', 'booking') |
bps optional | number | Basis points for percentage discount (2000 = 20%) |
amount optional | number | Fixed amount in cents for FIXED type |
Condition Object
Parameters
| Name | Type | Description |
|---|---|---|
type required | string | Condition type (see below) |
value required | string | number | string[] | Condition value |
Condition Types:
| Type | Value Type | Description |
|---|---|---|
PRODUCTS | { type: 'IDS', value: string[] } | Restrict to specific products |
SERVICES | { type: 'IDS', value: string[] } | Restrict to specific services |
MIN_ORDER_AMOUNT | { type: 'AMOUNT', value: number } | Minimum order amount in cents |
MAX_USES | { type: 'COUNT', value: number } | Total redemption limit across all customers |
MAX_USES_PER_USER | { type: 'COUNT', value: number } | Redemption limit per customer account |
DATE_RANGE | { type: 'DATE_RANGE', value: { start?: number, end?: number } } | Valid date range (Unix timestamps) |
Get Promo Code
/v1/businesses/{businessId}/promo-codes/{id} sdk.promoCode.getPromoCode() Retrieve a promo code by ID.
const result = await sdk.promoCode.getPromoCode({
id: 'promo_xyz789'
});
console.log(result.code);
console.log(result.status); // 'active' | 'archived'
console.log(result.discounts);
console.log(result.conditions);
console.log('Uses:', result.uses);
Parameters
| Name | Type | Description |
|---|---|---|
id required | string | Promo code ID |
List Promo Codes
/v1/businesses/{businessId}/promo-codes sdk.promoCode.getPromoCodes() List all promo codes for the business, or look up specific codes by ID.
// List all promo codes for the business
const all = await sdk.promoCode.getPromoCodes({});
all.items.forEach(promo => {
console.log(promo.code, promo.status, promo.uses);
});
// Look up specific promo codes by ID
const specific = await sdk.promoCode.getPromoCodes({
ids: ['promo_1', 'promo_2']
});Parameters
| Name | Type | Description |
|---|---|---|
ids optional | string[] | Filter by specific promo code IDs. When provided, other filters are ignored. |
Update Promo Code
/v1/businesses/{businessId}/promo-codes/{id} sdk.promoCode.updatePromoCode() Update a promo code. Use status to archive or re-activate a code.
// Update discounts and conditions
await sdk.promoCode.updatePromoCode({
id: 'promo_xyz789',
code: 'SUMMER25', // Change the code
discounts: [
{
type: 'ITEMS_PERCENTAGE',
marketId: 'USD',
bps: 2500 // Increase to 25%
}
],
conditions: [
{ type: 'MAX_USES', value: { type: 'COUNT', value: 2000 } },
{ type: 'DATE_RANGE', value: { type: 'DATE_RANGE', value: { end: 1727740800 } } }
]
});
// Archive a promo code
await sdk.promoCode.updatePromoCode({
id: 'promo_xyz789',
status: 'archived'
});Parameters
| Name | Type | Description |
|---|---|---|
id required | string | Promo code ID to update |
code optional | string | Updated code string |
discounts optional | Discount[] | Updated discounts |
conditions optional | Condition[] | Updated conditions |
status optional | active | archived | Promo code status |
Delete Promo Code
/v1/businesses/{businessId}/promo-codes/{id} sdk.promoCode.deletePromoCode() Delete a promo code.
await sdk.promoCode.deletePromoCode({
id: 'promo_xyz789'
});
Parameters
| Name | Type | Description |
|---|---|---|
id required | string | Promo code ID to delete |
Using Promo Codes
In E-shop Checkout
Apply promo codes when creating orders or getting quotes:
// Get quote with promo code
const quote = await sdk.eshop.getQuote({
items: [
{ productId: 'prod_xyz', variantId: 'var_1', quantity: 2 }
],
promoCode: 'SUMMER20' // Code string
});
console.log('Subtotal:', quote.subtotal);
console.log('Discount:', quote.discount);
console.log('Total:', quote.total);
// Checkout with promo code ID
const result = await sdk.eshop.checkout({
items: [
{ productId: 'prod_xyz', variantId: 'var_1', quantity: 2 }
],
shippingMethodId: 'ship_standard',
paymentMethodId: 'pm_card_visa',
promoCodeId: 'promo_xyz789' // Promo code ID
});
In Bookings
// Get quote with promo code
const quote = await sdk.booking.getQuote({
items: [
{
serviceId: 'svc_haircut',
providerId: 'prv_sarah',
from: 1704110400,
to: 1704112200
}
],
promoCode: 'FIRSTVISIT' // Code string
});
// Checkout with promo code ID
const result = await sdk.booking.checkout({
paymentMethodId: 'pm_card_visa',
promoCodeId: 'promo_firstvisit123', // Promo code ID
blocks: [/* customer info */]
});
Multi-Market Pricing Example
Support multiple currencies with different discount amounts:
const result = await sdk.promoCode.createPromoCode({
code: 'WELCOME',
discounts: [
{
type: 'ITEMS_FIXED',
marketId: 'USD',
amount: 1000 // $10 off in USD
},
{
type: 'ITEMS_FIXED',
marketId: 'EUR',
amount: 900 // €9 off in EUR
},
{
type: 'ITEMS_FIXED',
marketId: 'GBP',
amount: 800 // £8 off in GBP
}
],
conditions: [
{ type: 'MAX_USES', value: { type: 'COUNT', value: 100 } },
{ type: 'MIN_ORDER_AMOUNT', value: { type: 'AMOUNT', value: 3000 } }
]
});
Basis Points Reference
| Percentage | Basis Points (bps) |
|---|---|
| 5% | 500 |
| 10% | 1000 |
| 15% | 1500 |
| 20% | 2000 |
| 25% | 2500 |
| 50% | 5000 |
| 100% | 10000 |
Use MAX_USES with a low count for limited campaigns. Combine with SERVICES or PRODUCTS conditions to target specific offerings.