Back to arky.io

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

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 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:

TypeValue TypeDescription
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

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.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

GET /v1/businesses/{businessId}/promo-codes
SDK: 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

PUT /v1/businesses/{businessId}/promo-codes/{id}
SDK: 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

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 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

PercentageBasis 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.