Promo Codes
Discount codes, campaigns, and validation
The Promo Codes module manages discount codes for orders and reservations 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
interface Discount {
type: 'ITEMS_PERCENTAGE' | 'ITEMS_FIXED' | 'SHIPPING_PERCENTAGE';
marketId: string; // Market/currency identifier
bps?: number; // Basis points for percentage (e.g., 2000 = 20%)
amount?: number; // Fixed amount in cents (for ITEMS_FIXED)
}
Condition Types
interface Condition {
type: 'PRODUCTS' | 'SERVICES' | 'MIN_ORDER_AMOUNT' | 'DATE_RANGE' | 'MAX_USES';
value: ConditionValue;
}
// ConditionValue varies by type:
// - PRODUCTS/SERVICES: { type: 'IDS', value: string[] }
// - MIN_ORDER_AMOUNT: { type: 'AMOUNT', value: number }
// - MAX_USES: { type: 'COUNT', value: number }
// - DATE_RANGE: { type: 'DATE_RANGE', value: { start?: number, end?: number } }
Create Promo Code
POST
/v1/businesses/{businessId}/promo-codes SDK:
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/currency identifier (e.g., 'USD', 'EUR') |
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 |
DATE_RANGE | { type: 'DATE_RANGE', value: { start?: number, end?: number } } | Valid date range (Unix timestamps) |
Get Promo Code
GET
/v1/businesses/{businessId}/promo-codes/{id} SDK:
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.discounts);
console.log(result.conditions);
console.log('Uses:', result.currentUses);
Parameters
| Name | Type | Description |
|---|---|---|
id required | string | Promo code ID |
List Promo Codes
GET
/v1/businesses/{businessId}/promo-codes SDK:
sdk.promoCode.getPromoCodes() List all promo codes with filtering.
const result = await sdk.promoCode.getPromoCodes({
query: 'SUMMER',
ids: ['promo_1', 'promo_2'],
statuses: ['ACTIVE'],
sortField: 'createdAt',
sortDirection: 'desc',
cursor: null,
limit: 50,
createdAtFrom: '2024-01-01',
createdAtTo: '2024-12-31'
});
result.items.forEach(promo => {
console.log(promo.code, promo.discounts, promo.conditions);
});Parameters
| Name | Type | Description |
|---|---|---|
query optional | string | Search query in code |
ids optional | string[] | Filter by specific promo code IDs |
statuses optional | string[] | Filter by statuses (ACTIVE, INACTIVE) |
sortField optional | string | Sort field |
sortDirection optional | asc | desc | Sort direction |
cursor optional | string | Pagination cursor |
limit optional | number | Items per page |
createdAtFrom optional | string | Filter by creation date (start) |
createdAtTo optional | string | Filter by creation date (end) |
Update Promo Code
PUT
/v1/businesses/{businessId}/promo-codes/{id} SDK:
sdk.promoCode.updatePromoCode() Update a promo code.
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 } } }
]
});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 |
Delete Promo Code
DELETE
/v1/businesses/{businessId}/promo-codes/{id} SDK:
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 Reservations
// Get quote with promo code
const quote = await sdk.reservation.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.reservation.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 |
Tip
Use MAX_USES with a low count for limited campaigns. Combine with SERVICES or PRODUCTS conditions to target specific offerings.