npm install --save-dev @komerza/types
.d.ts file in your project - src/komerza.d.ts, say:
/// <reference types="@komerza/types" />
tsconfig.json already has a compilerOptions.types list, add "@komerza/types" to it
instead.
komerza is then typed everywhere, window.komerza and globalThis.komerza included. Every type
lives in the Komerza namespace, so none of them collide with your own Product or Order:
const response = await komerza.getStore();
const products: Komerza.Product[] = response.data?.products ?? [];
Without npm
Save this askomerza.d.ts anywhere your tsconfig.json includes. It’s the package’s file, unchanged:
komerza.d.ts
// Types for the Komerza Storefront SDK - https://cdn.komerza.com/komerza.min.js
// Docs: https://docs.komerza.com/storefront/typescript
//
// Generated from the SDK's source by commerce-script/tools/build-types.ts.
// Don't edit by hand - change src/models.ts or src/main.ts and regenerate.
export {};
declare global {
/** The Komerza Storefront SDK. */
var komerza: Komerza.Client;
namespace Komerza {
/**
* A single item in the shopping basket.
*/
interface BasketItem {
/**
* The unique identifier of the product.
*/
productId: string;
/**
* The unique identifier of the product variant. Every item added through the public API has one;
* checkout refuses a line without it.
*/
variantId: string;
/**
* How many of this product are in the basket.
*/
quantity: number;
}
/**
* Details about a field that failed validation.
*/
interface InvalidField {
/**
* The name of the invalid field.
*/
fieldName: string;
/**
* A human-readable reason why this field is considered invalid.
*/
reason: string;
}
/**
* Standard wrapper for API responses.
*
* @template T The type of the 'data' payload.
*/
interface ApiResponse<T> {
/**
* Indicates whether the request completed successfully.
*/
success: boolean;
/**
* An optional human-readable message from the server.
*/
message?: string;
/**
* A list of fields that failed validation, if any.
*/
invalidFields?: InvalidField[];
/**
* The payload of the response, of generic type 'T'.
*/
data?: T;
/**
* A machine-readable error code from the server when a request fails (e.g. "ValidationError",
* "ProductUnavailable", "NotFound"). Absent on success and on errors raised inside the SDK.
*/
code?: string;
}
/**
* Standard wrapper for paginated API responses.
*/
interface PaginatedApiResponse<T> extends ApiResponse<T[]> {
/** The total number of pages available. */
pages: number;
}
/**
* Base entity with an ID and creation timestamp.
*/
interface Entity {
/**
* Unique identifier for the entity.
*/
id: string;
/**
* ISO 8601 timestamp when the entity was created.
*/
dateCreated: string;
}
/**
* An adaptive-currency quote: the shopper's local currency and the rate to reach it from the store's.
*
* Display-only. The store's currency stays the authoritative one for money movement — the rate that
* actually charges a card is snapshotted onto the order when it is created, not taken from here.
*/
interface PresentmentQuote {
/** The shopper's currency code (lowercase, e.g. "eur"). */
currencyCode: string;
/** Multiply a store-currency amount by this to get the shopper's. Includes the merchant's FX margin. */
rate: number;
}
/**
* A store owned by a merchant that can be used as a front for selling products to customers.
*/
interface Store extends Entity {
/** The name of the store. */
name: string;
/** The description of the store, shown on their about page and on the home of their store page. */
description: string;
/**
* The subdomain for the store, ONLY the subdomain, not the fully qualified domain.
* @example "store"
*/
url: string;
/** The custom domain set for the store, or null if not set. */
customDomain?: string;
/** The store’s preferred currency code (ISO 4217). */
currencyCode: string;
/**
* The shopper's adaptive-currency quote, when one applies to this request.
*
* Absent means every price renders in `currencyCode` — which is equally what happens when the store
* has the feature off, when the shopper's browser already prefers the store's own currency, and when
* no rate was available. All three are the same instruction as far as display goes.
*/
presentment?: PresentmentQuote;
/**
* Whether the store has adaptive currency switched on at all.
*
* Distinct from `presentment` being set, and the distinction is load-bearing: this payload can arrive
* server-rendered from a cache shared by every visitor, which therefore has to stay currency-agnostic.
* An absent quote cannot tell the runtime whether no quote applied or whether it simply was not in the
* shared copy — this can, so the runtime only spends a request resolving one when it would count.
*
* Three states, not two. `false` is the server saying the feature is off, and costs nothing. `undefined`
* is an older payload that predates this field — which every already-rendered storefront is — and has to
* be treated as unknown rather than off, or the feature never reaches those pages at all.
*/
isAdaptiveCurrencyEnabled?: boolean;
/**
* The store's products: public ones and unlisted ones (`visibility` 1), plus any on hold (3). Private
* products are never included. Filter to `visibility === 0` (public) before listing them.
*/
products: ProductReference[];
/** The list of categories configured for this store. */
categories?: Category[];
/** The domain the store is associated with. */
domain: string;
/** The reason the store is in maintenance; null if not in maintenance mode. */
maintenanceReason?: string;
/**
* The average (median) review rating for the product based on past customer reviews.
*/
rating: number;
/**
* The store branding options
*/
branding?: Branding;
/**
* The list of discount dialogs configured for this store.
*/
discountDialogs?: DiscountDialog[];
/** Affiliate program options for the store. */
affiliateOptions?: AffiliateOptions;
/** Whether the ticketing (support) system is enabled. */
isTicketingEnabled?: boolean;
/** Whether the product name is prepended to the receipt. */
prependProductNameToReceipt?: boolean;
/** Whether automatic review collection is enabled. */
isAutomaticReviewsEnabled?: boolean;
/** Whether public store statistics are shown. */
showPublicStats?: boolean;
/** Whether recent order toast notifications are shown to visitors. */
showRecentOrderToasts?: boolean;
/** The merchant's terms of service URL, if they set one. */
termsOfServiceUrl?: string;
/** The merchant's refund policy URL, if they set one. */
refundPolicyUrl?: string;
/** The merchant's privacy policy URL, if they set one. */
privacyPolicyUrl?: string;
/** Where the merchant handles support, when it isn't Komerza's ticketing. */
externalSupportUrl?: string;
/** Text to show alongside `externalSupportUrl`. */
externalSupportDescription?: string;
/** Whether the customer download center is enabled. */
isDownloadCenterEnabled?: boolean;
/** Whether the store is accepting reseller applications. */
isAcceptingResellerApplications?: boolean;
/** The Google Search Console verification token, if the merchant set one. */
googleSiteVerification?: string;
}
interface Branding {
/**
* The banner logo file name
*/
bannerFileName?: string;
/**
* The icon file name
*/
iconFileName?: string;
/**
* The accent color for the store (hex color code).
* Used for buttons, links, and other interactive elements.
* @example "#6366f1"
*/
accentColor?: string;
}
/**
* Affiliate program configuration for a store.
*/
interface AffiliateOptions {
/** Whether the affiliate program is enabled. */
isEnabled: boolean;
/** The default return percentage for affiliates. */
defaultReturnPercentage: number;
/** The default percentage discount given via affiliate links. */
defaultPercentageOff: number;
/** Whether affiliates can convert their balance. */
canConvertAffiliateBalance: boolean;
/** Whether public affiliate registration is enabled. */
isPublicRegistrationEnabled: boolean;
/** Whether affiliates can edit their links. */
isLinkEditingEnabled: boolean;
}
/**
* The trigger type for a discount dialog.
* 0 Entrance, 1 ExitIntent.
*/
type DiscountDialogTriggerType = 0 | 1;
/**
* A discount dialog that can be shown to users.
*/
interface DiscountDialog extends Entity {
/** The type of trigger that shows this dialog. */
triggerType: DiscountDialogTriggerType;
/** The title of the dialog. */
title: string;
/** The message displayed in the dialog. */
message: string;
/** The text displayed on the action button. */
buttonText: string;
/** Whether this dialog is currently enabled. */
isEnabled: boolean;
/** Delay in seconds before showing the dialog. */
displayDelaySeconds: number;
/** Whether to show the dialog only once per session. */
showOncePerSession: boolean;
/** Whether to show the dialog only once ever (persisted). */
showOnceEver: boolean;
/** The coupon code to display/copy. */
couponCode: string;
/** The ID of the associated coupon. */
couponId: string;
}
/**
* A category used to group products within a store.
*/
interface Category extends Entity {
/** The display name of the category. */
name: string;
/** The visibility level of the category. */
visibility: Privacy;
/** URL-friendly slug for the category, if one was set. */
slug?: string;
/** The image file name for the category. */
imageName?: string;
/** The display order of the category (ascending). */
order: number;
/** The ID of the store this category belongs to. */
storeId: string;
/** The number of products in this category. */
productCount: number;
/** The list of product IDs that belong to this category. */
products: string[];
}
/**
* A reference to a product, with limited details.
*/
interface ProductReference extends Entity {
/** The name of the product. */
name: string;
/** The description of the product; supports markdown. */
description: string;
/** The list of image names that will be displayed for the product. */
imageNames: string[];
/** The average (median) review rating for the product. */
rating: number;
/** The order number of the product group (ascending). */
order: number;
/**
* The visibility level of the product. Sent for the products in `getStore()`; `getProduct()` does
* not include it.
*/
visibility?: Privacy;
/** The store ID that owns this product. */
storeId: string;
/** URL-friendly slug for the product. */
slug?: string;
/** The list of variants associated with this product. */
variants: Variant[];
/** The merchant's display badges for this product, e.g. "New" or "Sale". */
badges?: ProductBadge[];
/** Whether this product is marked as a best seller. */
isBestSeller?: boolean;
/** When true the merchant has hidden stock levels; every variant then reports `stock: 0`. */
hideStock?: boolean;
/** Custom metadata the merchant attached to the product, if any. */
metadata?: string;
/** The affiliate discount mode for this product: 0 = store default, 1 = none, 2 = custom. */
affiliateDiscountMode?: number;
/** The custom affiliate discount percentage, when `affiliateDiscountMode` is 2. */
customAffiliateDiscountPercentage?: number;
}
/**
* A display badge on a product.
*/
interface ProductBadge {
/** The badge's unique identifier. */
id: string;
/** The product the badge belongs to. */
productId: string;
/** The badge text. */
label: string;
/** The badge color as a hex code, if the merchant picked one. */
color?: string;
/** The display order (ascending). */
order: number;
}
/**
* Represents a variant tied to a product.
*/
interface Variant extends Entity {
/** The name of the variant. */
name: string;
/** The ID of the product this variant belongs to. */
productId: string;
/** The ID of the store this variant belongs to. */
storeId: string;
/** The cost of the product variant in the store’s currency. */
cost: number;
/** The minimum quantity allowed for purchase (defaults to 1). */
minimumQuantity: number;
/**
* The maximum quantity allowed for purchase (-1 equals infinity).
*/
maximumQuantity: number;
/** The ordering number of the product variant (defaults to 1). */
order: number;
/**
* Whether purchasing this variant requires Discord authorization.
*/
requireDiscordAuthorization: boolean;
/** An optional description of this specific variant. */
description?: string;
/** The type of product being sold. */
type: ProductType;
/** How often a subscription variant bills. Absent on one-time variants. */
billingInterval?: BillingInterval;
/** The billing period in days, when `billingInterval` is `BillingInterval.Custom`. */
customIntervalDays?: number;
/**
* The list of image names for this variant; inherits from product if empty.
*/
imageNames: string[];
/**
* The available stock count for this variant. Always 0 when `hideStock` is true, so never read
* 0 as "sold out" on its own — use `isOutOfStock`.
*/
stock: number;
/** The mode used to calculate stock levels. */
stockMode: StockCalculationMode;
/** Whether the merchant has hidden stock levels (inherited from the product). */
hideStock: boolean;
/**
* Whether this variant is sold out. Computed by the server: never true when stock is hidden or
* not tracked. This is the flag to disable "Add to cart" on.
*/
isOutOfStock: boolean;
/** Quantity-based price tiers. The highest tier the line's quantity reaches applies to every unit. */
volumeDiscounts: VolumeDiscount[];
/** When true, volume discounts stop applying once a coupon is used. */
disableVolumeDiscountOnCoupon: boolean;
/** Questions the hosted checkout asks the buyer for this variant. */
customFields: CustomField[];
/** How the variant is delivered: "license_keys", "dynamic", "instructions", "files", "custom_fields". */
deliveryTypes: string[];
/** Whether license keys are handed out in random order rather than first-in, first-out. */
randomizeKeyDelivery: boolean;
}
/**
* A quantity-based price tier on a variant.
*/
interface VolumeDiscount {
/** The tier's unique identifier. */
id: string;
/** The variant this tier belongs to. */
variantId: string;
/** The minimum quantity that unlocks this tier. */
quantity: number;
/** How `discountValue` is applied. */
discountType: VolumeDiscountType;
/**
* Percentage: 10 means 10% off. FixedAmount: an amount off each unit, in the store's currency.
* FixedPrice: the new unit price, in the store's currency.
*/
discountValue: number;
}
/**
* A question the hosted checkout asks the buyer.
*/
interface CustomField {
id: string;
variantId: string;
label: string;
identifier: string;
placeholder?: string;
type: string;
isRequired: boolean;
hint?: string;
options: CustomFieldOption[];
}
/**
* One option of a select-style custom field.
*/
interface CustomFieldOption {
id: string;
customFieldId: string;
label: string;
value: string;
order: number;
}
/**
* The stock calculation modes that are used.
* 0 Calculated, 1 Ignored, 2 Fixed.
*/
type StockCalculationMode = 0 | 1 | 2;
/**
* The type of product that is being sold.
* 0 OneTime, 1 Subscription.
*/
type ProductType = 0 | 1;
/**
* How often a subscription variant bills.
* 0 Weekly, 1 Monthly, 2 Quarterly, 3 Yearly, 4 Custom.
*/
type BillingInterval = 0 | 1 | 2 | 3 | 4;
/**
* How a volume discount tier's `discountValue` is applied.
* 0 Percentage, 1 FixedAmount, 2 FixedPrice.
*/
type VolumeDiscountType = 0 | 1 | 2;
/**
* List of product visibility (privacy) levels.
* 0 Public, 1 Unlisted, 2 Private, 3 OnHold.
*/
type Privacy = 0 | 1 | 2 | 3;
/**
* Details about a single line item within an order.
*/
interface LineItem extends Entity {
productName: string;
productId: string;
variantId: string;
variantName: string;
/** The unit price, in the order's currency. */
amount: number;
/** `amount` × `quantity`. */
lineTotal: number;
quantity: number;
/** Set on subscription line items. */
billingInterval?: BillingInterval;
customIntervalDays?: number;
}
/** Order details associated with an order. */
interface OrderDetails extends Entity {
countryCode: string;
emailAddress: string;
customerId: string;
}
/** Gateway-specific metadata for the order. */
interface GatewayMetadata extends Entity {
transactionId?: string;
clientSecret?: string;
note?: string;
cryptocurrencyAddress?: string;
cryptocurrencyAmount?: number;
cryptocurrencyExpiration?: string;
}
/** Coupon usage information on an order. */
interface OrderCoupon extends Entity {
percentageDecrease?: number;
netDecrease: number;
code: string;
couponId: string;
}
/**
* Public order returned by the API.
*/
interface Order extends Entity {
items: LineItem[];
currencyCode: string;
/** The shopper's currency, when adaptive currency priced the order in it. */
presentmentCurrencyCode?: string;
/** The rate from `currencyCode` to `presentmentCurrencyCode`, snapshotted when the order was created. */
presentmentFxRate?: number;
gateway: string;
customer: OrderDetails;
gatewayMetadata?: GatewayMetadata;
status: string;
amountPaid: number;
amount: number;
coupon?: OrderCoupon;
}
/**
* What a `komerza.on("basketchange", …)` listener receives.
*/
interface BasketChangeEvent {
/** The basket as it is now. */
items: BasketItem[];
/** The total quantity across every item, the same number `getBasketItemCount()` returns. */
itemCount: number;
}
/** Represents a single product review. */
interface Review extends Entity {
rating: number;
reason: string;
productId?: string;
reply?: string;
}
/**
* Anonymized public statistics for a store.
* All counts are bucketed into broad ranges to protect exact figures.
*/
interface PublicStoreStats {
/** Approximate total completed orders (e.g. "100+", "10-50"). */
totalOrders: string;
/** Approximate total unique customers. */
totalCustomers: string;
/** Approximate number of listed products. */
totalProducts: string;
/** Average review rating out of 5, or null if no reviews. */
averageRating: number | null;
/** Approximate number of reviews. */
totalReviews: string;
/** How long the store has been active (e.g. "6 months", "2 years"). */
storeAge: string;
}
/** What `getStore()` lists in `products` and what `getProduct()` returns. */
type Product = ProductReference;
/**
* The `komerza` global: the Komerza Storefront SDK.
*/
interface Client {
/**
* Initialize the commerce library for a specific store.
* Must be called before any other methods that rely on a 'storeId'.
* @param storeId Unique identifier of your store.
*/
init(storeId: string): void;
/**
* Gets the URL to the stores logo
*/
getStoreLogoUrl(): Promise<string>;
/**
* Gets the URL to the stores banner
*/
getStoreBannerUrl(): Promise<string>;
/**
* Creates a number formatter for the current store's currency.
*/
createFormatter(): Promise<Intl.NumberFormat>;
/**
* Retrieve the items currently in the basket.
* @returns Array of BasketItem.
*/
getBasket(): BasketItem[];
/**
* Get the current total item count in the basket.
* @returns Number of items.
*/
getBasketItemCount(): number;
/**
* Add a product to the basket.
* @param productId Unique identifier of the product.
* @param variantId Unique identifier of the variant
* @param quantity Quantity to add (defaults to 1).
*/
addToBasket(productId: string, variantId: string, quantity?: number): void;
/**
* Clear the basket and add a product to the basket.
* @param productId Unique identifier of the product.
* @param variantId Unique identifier of the variant
* @param quantity Quantity to add (defaults to 1).
*/
buyNow(productId: string, variantId: string, quantity?: number): void;
/**
* Remove a product from the basket.
* @param productId Unique identifier of the product.
* @param variantId Unique identifier of the variant
*/
removeFromBasket(productId: string, variantId: string): void;
/**
* Set the quantity of an item already in the basket. A quantity of 0 or less removes it; an item
* that isn't in the basket is left alone (use addToBasket for that).
* @param productId Unique identifier of the product.
* @param variantId Unique identifier of the variant
* @param quantity The new quantity.
*/
setBasketItemQuantity(
productId: string,
variantId: string,
quantity: number,
): void;
/**
* Listen for basket changes, whether this page or another tab made them.
* @param event The event to listen for. "basketchange" is the only one.
* @param handler Called with the basket as it is after the change.
* @returns A function that removes the listener.
*/
on(
event: "basketchange",
handler: (event: BasketChangeEvent) => void,
): () => void;
/**
* Remove all items from the basket.
*/
clearBasket(): void;
/**
* Get details of the currently initialized store (must be initialized).
* @returns ApiResponse containing the Store.
*/
getStore(): Promise<ApiResponse<Store>>;
/**
* Retrieve a product by ID or slug for the current store (must be initialized).
* @param idOrSlug The product's unique identifier or slug.
* @returns ApiResponse containing the product.
*/
getProduct(idOrSlug: string): Promise<ApiResponse<ProductReference>>;
/**
* Retrieve reviews for a product.
* @param productId The product's unique identifier (not its slug).
* @param page The page number, starting at 1 (the default).
* @returns ApiResponse containing an array of reviews.
*/
getProductReviews(
productId: string,
page?: number,
): Promise<PaginatedApiResponse<Review>>;
/**
* Create an order from the current basket and redirect to the hosted checkout page.
* @param emailAddress Email address for the order.
* @param couponCode Optional coupon code to apply.
* @returns ApiResponse containing the created order.
*/
checkout(
emailAddress: string,
couponCode?: string,
): Promise<ApiResponse<Order>>;
/**
* Create a backup of the current basket state.
* @returns True if backup was successful, false otherwise.
*/
createBasketBackup(): boolean;
/**
* Restore basket from backup.
* @returns True if restore was successful, false otherwise.
*/
restoreBasketFromBackup(): boolean;
/**
* Validate the integrity of the basket data.
* @returns True if basket integrity is valid, false otherwise.
*/
validateBasketIntegrity(): boolean;
/**
* Merge items from another basket into the current basket and save the result. Where both
* baskets hold the same item, the higher quantity wins.
* @param otherBasket Array of BasketItem to merge.
* @returns The basket after the merge.
*/
mergeBaskets(otherBasket: BasketItem[]): BasketItem[];
/**
* Move an item from one product/variant to another.
* @param fromProductId Product ID of the source item.
* @param fromVariantId Variant ID of the source item.
* @param toProductId Product ID of the destination.
* @param toVariantId Variant ID of the destination.
* @returns True if move was successful, false otherwise.
*/
moveBasketItem(
fromProductId: string,
fromVariantId: string,
toProductId: string,
toVariantId: string,
): boolean;
/**
* Get comprehensive statistics about the basket.
* @returns Detailed basket statistics.
*/
getBasketStats(): {
itemCount: number;
totalQuantity: number;
lastModified: number;
version: number;
hasBackup: boolean;
integrityValid: boolean;
};
/**
* Retrieve public store statistics (order counts, customer counts, etc.).
* Returns empty data gracefully if stats are disabled.
* @returns ApiResponse containing PublicStoreStats.
*/
getPublicStoreStats(): Promise<ApiResponse<PublicStoreStats>>;
}
}
}
visibility and stockMode are unions of their values rather than TypeScript
enums: an enum needs an object at runtime, and the script doesn’t provide one.