Data Models
This page describes the data structures used in the Storefront API.
Basket
The basket represents the shopping cart state.
interface Basket {
items: LineItem[];
promoCode: string | null;
stage: BasketStage;
}
Properties
| Property | Type | Description |
|---|---|---|
items | LineItem[] | Array of line items in the basket |
promoCode | string | null | The currently applied promotional code |
stage | BasketStage | The current stage of the basket |
BasketStage
| Value | Description |
|---|---|
Basket | The basket is active and accepts modifications |
Settled | The order has been completed; the basket can no longer be modified |
Product
A product represents a voucher that can be added to the basket. Products are retrieved using the GetVouchers method.
interface Product {
id: string;
catalogueId: string;
name: string;
venueName: string | null;
price: Money;
isPrivate: boolean;
limitedAvailability: unknown | null;
marketingDescription: string;
detailedDescription: string;
images: string[];
parentPath: string[];
tags: string[];
terms: string;
validity: Validity;
version: number;
reservationEmail: string;
reservationPhone: string;
reservationWebsite: string | null;
reservationInstructions: string | null;
isActive: boolean;
}
// Validity can be either month-based or date-based
type Validity = MonthBasedValidity | DateBasedValidity;
interface MonthBasedValidity {
validMonths: number;
}
interface DateBasedValidity {
startDate: string; // ISO 8601 date string
endDate: string; // ISO 8601 date string
}
Validity
The validity field can have two different formats:
Month-based validity - The voucher is valid for a number of months from the purchase date:
{
"validity": {
"validMonths": 12
}
}
Date-based validity - The voucher is valid between specific dates:
{
"validity": {
"startDate": "2024-04-02T00:00:00Z",
"endDate": "2025-04-02T00:00:00Z"
}
}
Properties
| Property | Type | Description |
|---|---|---|
id | string | Unique product identifier (UUID) - use this for AddItem |
catalogueId | string | The catalogue this product belongs to |
name | string | Display name of the product |
venueName | string | null | Optional venue name |
price | Money | The product price |
isPrivate | boolean | Whether the product is private |
limitedAvailability | unknown | Availability constraints, if any |
marketingDescription | string | Short description for marketing purposes |
detailedDescription | string | Full product description |
images | string[] | Array of image URLs |
parentPath | string[] | Category hierarchy (array of UUIDs) |
tags | string[] | Product tags for filtering/categorization |
terms | string | Terms and conditions (HTML) |
validity | Validity | Voucher validity period |
version | number | Product version number |
reservationEmail | string | Email for reservations |
reservationPhone | string | Phone number for reservations |
reservationWebsite | string | null | Website for reservations |
reservationInstructions | string | null | Special reservation instructions |
isActive | boolean | Whether the product is currently available |
Example
// Format validity for display
function formatValidity(validity) {
if (validity.validMonths) {
return "Valid for " + validity.validMonths + " months";
}
if (validity.startDate && validity.endDate) {
const start = new Date(validity.startDate);
const end = new Date(validity.endDate);
return "Valid from " + start.toLocaleDateString() + " to " + end.toLocaleDateString();
}
return "";
}
// Display a product card
function renderProductCard(product) {
const formatter = new Intl.NumberFormat("en-US", {
style: "currency",
currency: product.price.currency,
});
return (
'<div class="product-card">' +
'<img src="' + product.images[0] + '" alt="' + product.name + '">' +
"<h3>" + product.name + "</h3>" +
"<p>" + product.marketingDescription + "</p>" +
'<p class="price">' + formatter.format(product.price.amount) + "</p>" +
'<p class="validity">' + formatValidity(product.validity) + "</p>" +
'<button data-product-id="' + product.id + '">Add to Cart</button>' +
"</div>"
);
}
LineItem
A line item represents a single product instance in the basket.
interface LineItem {
lineItemId: string;
productId: string;
productName: string;
retailPrice: Money;
quotedPrice: Money;
}
Properties
| Property | Type | Description |
|---|---|---|
lineItemId | string | Unique identifier for this line item (UUID) |
productId | string | The product identifier |
productName | string | Display name of the product |
retailPrice | Money | The original price before discounts |
quotedPrice | Money | The price after applying discounts |
Understanding Line Items
Each AddItem call creates a new line item. If a customer adds the same product twice, there will be two line items with the same productId but different lineItemId values.
To display quantity in your UI, group line items by productId:
function groupItemsByProduct(items) {
const grouped = {};
items.forEach((item) => {
if (!grouped[item.productId]) {
grouped[item.productId] = {
...item,
quantity: 0,
lineItemIds: [],
};
}
grouped[item.productId].quantity++;
grouped[item.productId].lineItemIds.push(item.lineItemId);
});
return Object.values(grouped);
}
Money
Represents a monetary value with currency.
interface Money {
amount: string | number;
currency: string;
}
Properties
| Property | Type | Description |
|---|---|---|
amount | string | number | The monetary amount |
currency | string | ISO 4217 currency code (e.g., "USD", "GBP", "EUR") |
The amount field may be returned as a string in some responses (e.g., from GetVouchers). Always use parseFloat() or Number() when performing arithmetic operations.
Formatting Example
function formatPrice(money) {
return new Intl.NumberFormat("en-US", {
style: "currency",
currency: money.currency,
}).format(parseFloat(money.amount));
}
// Usage
const item = basket.items[0];
console.log(formatPrice(item.retailPrice)); // "$50.00"
console.log(formatPrice(item.quotedPrice)); // "$45.00"
Error
Represents an error returned by the SomethingHappened event.
interface Error {
errorCode: string;
message: string;
}
Properties
| Property | Type | Description |
|---|---|---|
errorCode | string | Machine-readable error identifier |
message | string | Human-readable error description |
Error Codes
| Code | Description |
|---|---|
PromoCodeDoesntExist | The provided promotional code is invalid or has expired |
UnavailableProduct | The product is not available for purchase |
OrderWasProcessed | The basket has already been settled and cannot be modified |
ResumeShopping Response
The response returned by the ResumeShopping method.
interface ResumeShoppingResponse {
result: Basket | null;
}
Properties
| Property | Type | Description |
|---|---|---|
result | Basket | null | The basket state, or null if no basket exists |