TypeScript Types
Complete type reference for the SDK
TypeScript Types
Complete reference of all types exported by @behio/storefront-sdk. All types are fully exported and can be imported directly:
import type { ProductDetail, Cart, CheckoutInput } from "@behio/storefront-sdk";Configuration
BehioStorefrontConfig
interface BehioStorefrontConfig {
/** API key (public: pk_live_xxx or private: sk_live_xxx) */
apiKey: string;
/** Backend base URL. Default: https://be.behio.com */
baseUrl?: string;
/** Default locale for catalog requests. Default: none (uses shop default) */
locale?: string;
/** Default currency for price resolution. Default: none (uses shop default) */
currency?: string;
/** Custom fetch implementation (for Node.js < 18 or testing) */
fetch?: typeof fetch;
/** Request timeout in milliseconds. Default: 30000 (30s) */
timeout?: number;
/** Number of retries on network/5xx errors. Default: 1 */
retries?: number;
/** Base delay between retries in ms (multiplied by attempt). Default: 1000 */
retryDelay?: number;
/**
* Real visitor IP for server-side rendering, sent as X-Behio-Visitor-Ip so
* the backend rate-limits per visitor instead of per rendering server. The
* Next.js adapter fills this automatically from the request headers; only
* trusted hosting IPs may set it, a browser sending it gains nothing.
*/
visitorIp?: string | (() => string | null | undefined | Promise<string | null | undefined>);
}Products
ProductListItem
Represents a product in list/collection views.
Popisy produktu jsou HTML
shortDescription i longDescription píše obchodník v rich text editoru v administraci,
takže API vrací HTML (<h3>...</h3><p>...</p>), nikdy holý text. Když je vypíšete
jako {product.shortDescription}, React je zaescapuje a návštěvník uvidí doslova značky.
API obsah sanitizuje při čtení (allowlist: nadpisy, seznamy, odkazy, obrázky, tabulky;
skripty, event handlery a javascript: odkazy jdou pryč), takže se dá vložit přes
dangerouslySetInnerHTML. Šablony Behio na to mají komponentu RichText. Do meta
description, JSON-LD, alt textů a jednořádkových popisků na kartách patří čistý text,
ne HTML.
interface ProductListItem {
id: string;
slug: string;
name: string;
/** HTML z rich text editoru (sanitizované), ne holý text. */
shortDescription?: string;
sku: string;
gtin?: string;
price: ProductPrice;
inStock: boolean;
stockQuantity?: number;
/** "Only X left". Non-null ONLY when the merchant enabled the nudge AND 0 < stock <= threshold. */
lowStockRemaining?: number | null;
/** Resolved availability (merchant preset or derived in-stock / sold-out), label localized. */
availability: ProductAvailability;
image?: string | null;
labels: ProductLabel[];
isFeatured: boolean;
}ProductAvailability
interface ProductAvailability {
/** Stable machine code: preset slug or derived 'in-stock' / 'sold-out'. */
code: string;
/** Localized display label, render as-is. */
label: string;
/** Optional merchant hex badge color. */
color?: string | null;
/** "Available from" date (epoch ms) for preorder-style states. */
restockAt?: number | null;
}ProductDetail
Full product detail, extends ProductListItem.
interface ProductDetail extends ProductListItem {
/** HTML z rich text editoru (sanitizované), ne holý text. */
longDescription?: string;
images: Array<{ url: string; alt?: string; order: number }>;
categories: Array<{ id: string; slug: string; name: string }>;
variants: ProductVariant[];
volumePricing: ProductVolumePrice[];
/** Curated spec table. Array order is the display order; empty = render nothing. */
parameterGroups: ProductParameterGroup[];
seo: {
title?: string | null;
description?: string | null;
keywords?: string | null;
};
productGroups?: Array<{
slug: string;
name: string;
products: ProductListItem[];
}>;
/** Product weight (from warehouse item) */
weight?: number | null;
/** Weight unit: GRAM, KILOGRAM, TONNE */
weightUnit?: string | null;
}ProductPrice
interface ProductPrice {
amount: number;
currency: string;
compareAtPrice?: number | null;
}ProductVolumePrice
interface ProductVolumePrice {
minQuantity: number;
price: number;
currency?: string;
}ProductVariant
interface ProductVariant {
id: string;
sku: string;
/** Localized name of this variant. */
name: string;
/**
* Deep-link token, NOT a URL: a variant has no page of its own, so it lives at
* `/product/{product.slug}?variant={variantSlug}`. Since SDK 1.1.0.
*/
variantSlug: string;
/** Own texts; null = inherit the parent's. HTML. Since SDK 1.1.0. */
shortDescription?: string | null;
longDescription?: string | null;
/** Own gallery; empty = keep showing the parent's. Since SDK 1.1.0. */
images: Array<{url: string; alt?: string; order: number; role?: string}>;
/** Own SEO/OG overrides, null when none. Since SDK 1.1.0. */
seo?: {
title?: string | null;
description?: string | null;
keywords?: string | null;
ogTitle?: string | null;
ogDescription?: string | null;
ogImage?: string | null;
} | null;
/** Axis name/value pairs, e.g. [{name: 'Barva', value: 'modrá'}]. */
attributes: Array<{name: string; value: string}>;
price: ProductPrice | null;
inStock: boolean;
stockQuantity?: number;
/** "Only X left" for this variant, same contract as ProductListItem. */
lowStockRemaining?: number | null;
/** Variant's own spec table: own value where it has one, parent's elsewhere. */
parameterGroups: ProductParameterGroup[];
}ProductParameterGroup
One block of the merchant's curated spec table. Groups and parameters arrive in display order, there is nothing to sort by.
interface ProductParameterGroup {
/** Derived from the merchant's own group name, stable, usable in URLs. */
slug: string;
/** Localized group heading, render as-is. */
name: string;
parameters: ProductParameter[];
}ProductParameter
interface ProductParameter {
/** Merchant-written label in the requested language. */
label: string;
/** Preformatted value. null ONLY for boolean parameters. */
value: string | null;
/** Non-null ONLY for boolean parameters, and then `value` is null. */
booleanValue: boolean | null;
/** Display unit: "cm", "g", a currency code, "%". null when the parameter has none. */
unit: string | null;
}/** Response of catalog.getProductParameters(slug, {locale}). */
interface ProductParametersResponse {
groups: ProductParameterGroup[];
}Parameters without a value are omitted server-side, so the array never contains an empty row. Warehouse data groups are not part of the public surface: no data-group id, no field key and no warehouse field type ever appears in a payload.
ProductLabel
interface ProductLabel {
id: string;
slug: string;
name: string;
color?: string;
}ProductsQuery
Query parameters for listing products.
interface ProductsQuery {
page?: number;
limit?: number;
/** Single category slug (OR logic with categories array) */
category?: string;
/** Multiple category slugs (OR logic) */
categories?: string[];
/** Single label slug */
label?: string;
priceMin?: number;
priceMax?: number;
currency?: string;
locale?: string;
sort?: ProductSortValue;
inStock?: boolean;
search?: string;
/**
* Parameter filters, keyed by parameter slug (FilterField.key / Facet.key).
* Array = multi-select, OR within the key. Ranges use `<slug>_min` / `<slug>_max`.
* Only parameters the merchant marked filterable are accepted.
* e.g. { material: 'bavlna', barva: ['cerna', 'bila'], hmotnost_min: 100 }
*/
parameters?: Record<string, unknown>;
/**
* Slug-based facet selection for SEO URLs: parameter slug -> value slugs,
* e.g. { barva: ['cerna'] }. Resolved server-side to the underlying values.
*/
facets?: Record<string, string[]>;
/** Filter by specific product IDs */
ids?: string[];
/** Filter by specific product slugs */
slugs?: string[];
/** Multiple labels (AND logic, product must have ALL) */
labels?: string[];
/** Exclude specific product IDs */
excludeIds?: string[];
/** Exclude products in specific categories */
excludeCategories?: string[];
/** Only products with compareAtPrice (on sale) */
hasDiscount?: boolean;
/** Only featured products */
isFeatured?: boolean;
/** Products created after timestamp (epoch ms) */
createdAfter?: number;
}ProductSort
Available sort values (const object for runtime + autocomplete):
const ProductSort = {
PRICE_ASC: "price_asc",
PRICE_DESC: "price_desc",
NAME_ASC: "name_asc",
NAME_DESC: "name_desc",
NEWEST: "newest",
FEATURED: "featured",
} as const;
type ProductSortValue = (typeof ProductSort)[keyof typeof ProductSort];FilterField
One filterable parameter, as returned by getFilters({locale}).
interface FilterField {
/** Parameter slug. The key you send back in ProductsQuery.parameters. */
key: string;
/** Localized parameter label. */
name: string;
/** How to render the control, not how the value is stored. */
type: "enum" | "range" | "boolean";
/** Parameter group the field belongs to (same grouping as the spec table). */
groupSlug: string;
/** Localized group name. */
groupName: string;
/** Display unit next to the input: "cm", "g", "%", a currency code. */
unit?: string | null;
/** enum only: the selectable values, localized. */
values?: string[];
}Only parameters the merchant explicitly marked filterable are ever returned, so a visitor cannot filter by a field they cannot see on the product.
Categories
Category
interface Category {
id: string;
slug: string;
name: string;
description?: string;
imageUrl?: string;
children: Category[];
productCount?: number;
}CategoryDetail
Extends Category with SEO fields.
interface CategoryDetail extends Category {
seoTitle?: string;
seoDescription?: string;
}Cart
Cart
interface Cart {
id: string;
sessionToken?: string;
items: CartItem[];
subtotal: number;
discountTotal: number;
discount?: CartDiscount;
grandTotal: number;
currency: string;
itemCount: number;
}CartItem
interface CartItem {
id: string;
product: CartItemProduct;
quantity: number;
unitPrice: number;
totalPrice: number;
priceChanged: boolean;
volumePriceApplied: boolean;
}CartItemProduct
interface CartItemProduct {
slug: string;
name: string;
sku: string;
imageUrl?: string;
inStock: boolean;
currentPrice: number;
}CartDiscount
interface CartDiscount {
code: string;
type: string;
value: number;
}AddToCartInput
interface AddToCartInput {
/** Product ID (eshop product ID or warehouse item ID) */
productId: string;
quantity: number;
}Checkout
CheckoutInput
interface CheckoutInput {
shippingAddress: CheckoutAddress;
billingAddress: CheckoutAddress;
email: string;
phone?: string;
customerNote?: string;
}CheckoutAddress
interface CheckoutAddress {
firstName: string;
lastName: string;
company?: string;
street: string;
city: string;
zip: string;
country: string;
phone?: string;
}OrderDetail
Full order detail returned after checkout, extends OrderListItem.
interface OrderDetail extends OrderListItem {
items: OrderItem[];
shippingAddress: CheckoutAddress;
billingAddress: CheckoutAddress;
email: string;
phone?: string;
customerNote?: string;
subtotal: number;
taxTotal: number;
shippingTotal: number;
discountTotal: number;
fulfillmentStatus: FulfillmentStatus;
statusHistory: OrderStatusHistory[];
trackingToken?: string;
}Orders
OrderListItem
interface OrderListItem {
id: string;
orderNumber: string;
status: OrderStatus;
paymentStatus: PaymentStatus;
grandTotal: number;
currency: string;
itemCount: number;
createdAt: number;
}OrderItem
interface OrderItem {
productName: string;
sku: string;
imageUrl?: string;
quantity: number;
unitPrice: number;
totalPrice: number;
totalPriceWithTax: number;
}OrderStatusHistory
interface OrderStatusHistory {
fromStatus?: OrderStatus;
toStatus: OrderStatus;
note?: string;
changedBy?: string;
createdAt: number;
}Status enums
const OrderStatuses = {
PENDING: "PENDING",
CONFIRMED: "CONFIRMED",
PROCESSING: "PROCESSING",
SHIPPED: "SHIPPED",
DELIVERED: "DELIVERED",
CANCELLED: "CANCELLED",
REFUNDED: "REFUNDED",
} as const;
type OrderStatus = (typeof OrderStatuses)[keyof typeof OrderStatuses];
const PaymentStatuses = {
UNPAID: "UNPAID",
PAID: "PAID",
PARTIALLY_REFUNDED: "PARTIALLY_REFUNDED",
REFUNDED: "REFUNDED",
} as const;
type PaymentStatus = (typeof PaymentStatuses)[keyof typeof PaymentStatuses];
const FulfillmentStatuses = {
UNFULFILLED: "UNFULFILLED",
PARTIALLY_FULFILLED: "PARTIALLY_FULFILLED",
FULFILLED: "FULFILLED",
} as const;
type FulfillmentStatus = (typeof FulfillmentStatuses)[keyof typeof FulfillmentStatuses];Auth
AuthTokens
interface AuthTokens {
accessToken: string;
refreshToken: string;
}RegisterInput
interface RegisterInput {
email: string;
password: string;
firstName?: string;
lastName?: string;
}LoginInput
interface LoginInput {
email: string;
password: string;
}Customer
CustomerProfile
interface CustomerProfile {
id: string;
email: string;
firstName?: string;
lastName?: string;
phone?: string;
emailVerified: boolean;
}CustomerAddress
interface CustomerAddress {
id: string;
type: AddressType;
isDefault: boolean;
firstName: string;
lastName: string;
company?: string;
street: string;
city: string;
zip: string;
country: string;
phone?: string;
}AddressType
const AddressTypes = {
SHIPPING: "SHIPPING",
BILLING: "BILLING",
} as const;
type AddressType = (typeof AddressTypes)[keyof typeof AddressTypes];Bundles
Bundle
interface Bundle {
id: string;
slug: string;
name: string;
description: string | null;
bundlePrice: number;
currency: string;
coverImage: string | null;
endsAt: number | null;
itemsSum: number;
savings: number;
savingsPercent: number;
items: BundleItem[];
}BundleItem
interface BundleItem {
productId: string;
slug: string | null;
name: string;
sku: string;
quantity: number;
imageUrl: string | null;
defaultPrice: number | null;
}Cross-sell
CrossSellItem
interface CrossSellItem {
productId: string;
slug: string | null;
name: string; // localized
sku: string;
price: number | null; // in `currency`, incl. customer price-list override
compareAtPrice: number | null; // original price when on sale
currency: string;
imageUrl: string | null;
stockCached: number;
inStock: boolean;
}Promotions
ActivePromotion
interface ActivePromotion {
id: string;
name: string;
slug: string;
type: string;
discountType: string;
discountValue: number;
startsAt: number;
endsAt: number | null;
badgeText: string | null;
badgeColor: string | null;
showCountdown: boolean;
couponRequired: boolean;
}Gift Cards
GiftCardBalance
interface GiftCardBalance {
valid: boolean;
balance: number;
currency: string;
}Wishlist
WishlistItem
interface WishlistItem {
id: string;
productId: string;
productName: string;
productSku: string;
productSlug: string | null;
imageUrl: string | null;
price: number | null;
stockCached: number;
createdAt: number;
}Reviews
ProductReviewsResponse
interface ProductReviewsResponse {
items: ProductReview[];
averageRating: number;
reviewCount: number;
page: number;
totalPages: number;
}ProductReview
interface ProductReview {
id: string;
authorName: string;
rating: number;
title: string | null;
content: string | null;
imageUrls: string[];
isVerifiedPurchase: boolean;
helpfulCount: number;
unhelpfulCount: number;
replyContent: string | null;
createdAt: number;
}SubmitReviewInput
interface SubmitReviewInput {
productId: string;
rating: number;
title?: string;
content?: string;
authorName: string;
authorEmail?: string;
imageUrls?: string[];
}Returns
ReturnRequest
interface ReturnRequest {
id: string;
orderId: string;
status: string;
reason: string;
customerNote: string | null;
refundAmount: number | null;
refundMethod: string | null;
createdAt: number;
}SubmitReturnInput
interface SubmitReturnInput {
orderId: string;
reason: string;
customerNote?: string;
items: {
orderItemId: string;
productName: string;
quantity: number;
reason?: string;
imageUrls?: string[];
}[];
}Cookie Consent
CookieConsent
interface CookieConsent {
necessary: boolean;
analytics: boolean;
marketing: boolean;
preferences: boolean;
consentedAt: number;
}CookieConsentInput
interface CookieConsentInput {
visitorId: string;
analytics: boolean;
marketing: boolean;
preferences: boolean;
}Quotes (B2B)
QuoteRequest
interface QuoteRequest {
id: string;
status: string;
contactName: string;
contactEmail: string;
companyName: string | null;
quotedTotal: number | null;
createdAt: number;
}SubmitQuoteInput
interface SubmitQuoteInput {
contactName: string;
contactEmail: string;
contactPhone?: string;
companyName?: string;
companyIco?: string;
message?: string;
items: {
productId: string;
quantity: number;
requestedPrice?: number;
}[];
}Pages
Page
interface Page {
slug: string;
title: string;
isActive: boolean;
}PageDetail
interface PageDetail {
slug: string;
title: string;
/** {format: "html", html: string} for HTML pages */
content: unknown;
seoTitle?: string;
seoDescription?: string;
/** Downloadable files (e.g. legal form PDFs), render as a download list */
attachments: PageAttachment[];
}
interface PageAttachment {
name: string;
description: string | null;
url: string;
mimeType: string;
fileSize: number;
}Shop
ShopInfo
interface ShopInfo {
id: string;
name: string;
domain: string;
logo?: string;
favicon?: string;
isActive: boolean;
defaultLanguage: string;
supportedLanguages: string[];
defaultCurrency: string;
supportedCurrencies: string[];
metaTitle?: string;
metaDescription?: string;
allowGuestCheckout: boolean;
/** Shop runs in B2B / wholesale mode (unlocks B2B-oriented UX). */
b2bMode: boolean;
/** Whether quote requests make sense for this shop (currently follows B2B mode). */
quotesEnabled: boolean;
}ShopSeo
interface ShopSeo {
locale: string;
title: string | null;
description: string | null;
keywords: string | null;
ogTitle: string | null;
ogDescription: string | null;
ogImage: string | null;
}Errors
BehioApiError
Thrown for HTTP error responses from the API.
class BehioApiError extends Error {
readonly code: BehioErrorCode;
readonly status: number;
readonly body: unknown;
readonly isRetryable: boolean;
constructor(status: number, body: unknown, message?: string);
/** Check if this is a specific error type */
is(code: BehioErrorCode): boolean;
}BehioNetworkError
Thrown for network failures and timeouts.
class BehioNetworkError extends Error {
readonly code: "NETWORK_ERROR" | "TIMEOUT";
readonly isRetryable: true;
constructor(message: string, isTimeout?: boolean);
}BehioErrorCode
type BehioErrorCode =
| "UNAUTHORIZED"
| "FORBIDDEN"
| "NOT_FOUND"
| "VALIDATION_ERROR"
| "CONFLICT"
| "RATE_LIMITED"
| "CART_EMPTY"
| "PRODUCT_NOT_FOUND"
| "INVALID_CREDENTIALS"
| "INVALID_DISCOUNT"
| "DISCOUNT_EXPIRED"
| "TOKEN_EXPIRED"
| "TOKEN_INVALID"
| "EMAIL_ALREADY_EXISTS"
| "ORDER_NOT_CANCELLABLE"
| "INTERNAL_ERROR"
| "NETWORK_ERROR"
| "TIMEOUT"
| "UNKNOWN";Events
BehioEventType
type BehioEventType =
| "auth:login"
| "auth:logout"
| "auth:token-refresh"
| "auth:token-refresh-failed"
| "cart:updated"
| "cart:cleared"
| "order:created"
| "error"
| "request"
| "response"
| "rate-limit-warning";BehioEventHandler
type BehioEventHandler = (data?: unknown) => void;Interceptors
RequestInterceptor
interface RequestInterceptorConfig {
url: string;
method: string;
headers: Record<string, string>;
body?: string;
}
type RequestInterceptor = (
config: RequestInterceptorConfig,
) => RequestInterceptorConfig | Promise<RequestInterceptorConfig>;ResponseInterceptor
interface ResponseInterceptorData {
status: number;
data: unknown;
headers: Headers;
}
type ResponseInterceptor = (
response: ResponseInterceptorData,
) => void | Promise<void>;Pagination
PaginatedResponse
Generic wrapper for paginated list endpoints.
interface PaginatedResponse<T> {
items: T[];
total: number;
page: number;
limit: number;
totalPages: number;
}MessageResponse
interface MessageResponse {
message: string;
}