Promo Codes
Discount codes, campaigns, and validation
The Promo Codes module manages discount codes for product and scheduled services 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
market_key refers to the market key (for example, "us" or "eu"), not a
currency code or UUID. Basis points: 2000 = 20%. Fixed amounts are in the minor units of the
market’s configured currency.
type Discount =
| { type: "items_percentage"; market_key: string; bps: number }
| { type: "items_fixed"; market_key: string; amount: number }
| { type: "shipping_percentage"; market_key: string; bps: number }
| {
type: "audience_percentage";
audience_id: string;
tier_ids: string[];
price_ids: string[];
bps: number;
};
Condition Types
type Condition =
| { type: "products"; product_ids: string[] }
| { type: "services"; service_ids: string[] }
| { type: "min_order_amount"; amount: number }
| { type: "date_range"; start?: number; end?: number }
| { type: "max_uses"; count: number }
| { type: "max_uses_per_user"; count: number };
Create Promo Code
/v1/stores/{storeId}/promo-codes sdk.eshop.promoCode.createPromoCode() Create a new promotional code.
// Percentage discount (20% off)
const percentResult = await sdk.eshop.promoCode.createPromoCode({
code: 'SUMMER20',
discounts: [
{
type: 'items_percentage',
market_key: 'us',
bps: 2000 // 20% = 2000 basis points
},
{
type: 'items_percentage',
market_key: 'eu',
bps: 2000
}
],
conditions: [
{ type: 'min_order_amount', amount: 5000 },
{ type: 'max_uses', count: 1000 },
{ type: 'date_range', start: 1717200000, end: 1725148800 }
]
});
// Fixed amount discount for the "us" market
const fixedResult = await sdk.eshop.promoCode.createPromoCode({
code: 'SAVE10',
discounts: [
{
type: 'items_fixed',
market_key: 'us',
amount: 1000 // 1,000 minor units in the market's configured currency
}
],
conditions: [
{ type: 'max_uses', count: 500 }
]
});
// Product-specific discount
const productResult = await sdk.eshop.promoCode.createPromoCode({
code: 'WIDGETS20',
discounts: [
{
type: 'items_percentage',
market_key: 'us',
bps: 2000
}
],
conditions: [
{ type: 'products', product_ids: ['prod_widget1', 'prod_widget2'] }
]
});
// Service-specific discount
const serviceResult = await sdk.eshop.promoCode.createPromoCode({
code: 'FIRSTVISIT',
discounts: [
{
type: 'items_percentage',
market_key: 'us',
bps: 1500 // 15% off
}
],
conditions: [
{ type: 'services', service_ids: ['svc_haircut', 'svc_coloring'] },
{ type: 'max_uses', count: 100 }
]
});Parameters
| Name | Type | Description |
|---|---|---|
code required | string | Promo code string (uppercase recommended) |
discounts required | Discount[] | Array of discount configurations per market |
conditions required | Condition[] | Array of conditions for code validity |
Discount Object
Parameters
| Name | Type | Description |
|---|---|---|
type required | items_percentage | items_fixed | shipping_percentage | audience_percentage | Discount type |
market_key required | string | Market key (e.g. 'us', 'eu') |
bps optional | number | Basis points for percentage discount (2000 = 20%) |
amount optional | number | Fixed amount in the market currency's minor units for items_fixed |
Condition Types:
| Type | Fields | Description |
| ------------------- | --------------------------------------- | ------------------------------------------------------------------- |
| products | product_ids: string[] | Restrict to specific products |
| services | service_ids: string[] | Restrict to specific services |
| min_order_amount | amount: number | Minimum order amount in the evaluated market currency’s minor units |
| max_uses | count: number | Total redemption limit across all contacts |
| max_uses_per_user | count: number | Redemption limit per contact |
| date_range | start?: number, end?: number | Valid date range (Unix timestamps) |
Get Promo Code
/v1/stores/{storeId}/promo-codes/{id} sdk.eshop.promoCode.getPromoCode() Retrieve a promo code by ID.
const result = await sdk.eshop.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/stores/{storeId}/promo-codes sdk.eshop.promoCode.getPromoCodes() List all promo codes for the store, or look up specific codes by ID.
// List all promo codes for the store
const all = await sdk.eshop.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.eshop.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/stores/{storeId}/promo-codes/{id} sdk.eshop.promoCode.updatePromoCode() Update a promo code. Use status to archive or re-activate a code.
// Update discounts and conditions
await sdk.eshop.promoCode.updatePromoCode({
id: 'promo_xyz789',
code: 'SUMMER25', // Change the code
discounts: [
{
type: 'items_percentage',
market_key: 'us',
bps: 2500 // Increase to 25%
}
],
conditions: [
{ type: 'max_uses', count: 2000 },
{ type: 'date_range', end: 1727740800 }
]
});
// Archive a promo code
await sdk.eshop.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/stores/{storeId}/promo-codes/{id} sdk.eshop.promoCode.deletePromoCode() Delete a promo code.
await sdk.eshop.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 to carts before quoting or checkout:
// Get quote with promo code
const cart = await sdk.eshop.cart.current();
await sdk.eshop.cart.update({
id: cart.id,
product_items: [{ product_id: "prod_xyz", variant_id: "var_1", quantity: 2 }],
shipping_method_id: "ship_standard",
promo_code: "SUMMER20", // Code string
});
const quote = await sdk.eshop.cart.quote({ id: cart.id });
console.log("Subtotal:", quote.money.subtotal);
console.log("Discount:", quote.money.discount);
console.log("Total:", quote.money.total);
// Checkout the same cart
const result = await sdk.eshop.cart.checkout({
id: cart.id,
payment_method_key: "credit_card",
});
In Scheduled Services
// Get quote with promo code
const cart = await sdk.eshop.cart.current();
await sdk.eshop.cart.update({
id: cart.id,
booking_items: [
{
service_id: "svc_haircut",
provider_id: "prv_sarah",
slots: [{ from: 1704110400, to: 1704112200 }],
},
],
promo_code: "FIRSTVISIT", // Code string
forms: [/* contact info */],
});
const quote = await sdk.eshop.cart.quote({ id: cart.id });
// Checkout the same cart
const result = await sdk.eshop.cart.checkout({
id: cart.id,
payment_method_key: "credit_card",
});
Multi-Market Pricing Example
Support multiple currencies with different discount amounts:
const result = await sdk.eshop.promoCode.createPromoCode({
code: "WELCOME",
discounts: [
{
type: "items_fixed",
market_key: "us",
amount: 1000, // 1,000 minor units in the "us" market
},
{
type: "items_fixed",
market_key: "eu",
amount: 900, // 900 minor units in the "eu" market
},
{
type: "items_fixed",
market_key: "uk",
amount: 800, // 800 minor units in the "uk" market
},
],
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.