@behio/storefront-sdk 2.23.0 → 2.25.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -207,6 +207,7 @@ The provider notifies hooks after restoring browser session storage.
207
207
  | `faq` | FAQ groups and visible questions in the requested language (web + e-shop) |
208
208
  | `blog` | Blogs and published posts (web + e-shop) |
209
209
  | `forms` | Merchant-defined forms: definition + validated submit with per-field errors (web + e-shop) |
210
+ | `bookings` | Online appointments: services and staff, free times, create, change and cancel by token (web + e-shop) |
210
211
 
211
212
  ### React Hooks (30+)
212
213
 
@@ -232,6 +233,47 @@ from `@behio/storefront-sdk/react` within `BehioProvider`. For SEO, include the
232
233
  questions in server-rendered HTML and emit one FAQPage JSON-LD object containing
233
234
  only the questions actually visible on that page.
234
235
 
236
+ ### Withdrawal from contract (2.25.0)
237
+
238
+ EU law (Art. 11a Directive 2011/83/EU, from 19 Jun 2026) requires an online
239
+ withdrawal function for consumer purchases. When `shopInfo.withdrawal.enabled`,
240
+ link it from the footer and the customer account with a clear label such as
241
+ "Withdraw from contract here". The flow has two steps: a form (name, order
242
+ number, e-mail), then a summary with a "Confirm withdrawal" button. Only the
243
+ confirmation calls `withdraw`; show the returned acknowledgement, the same
244
+ content with date and time goes out by e-mail.
245
+
246
+ ```ts
247
+ const {data: order} = await storefront.returns.lookupOrder('B-2026-0042', 'jana@example.com');
248
+ // order.customerName prefills the name, order.withdrawal tells the period and flags
249
+ const {data: ack, error} = await storefront.returns.withdraw({
250
+ orderNumber: 'B-2026-0042',
251
+ email: 'jana@example.com',
252
+ name: 'Jana Nováková',
253
+ confirmed: true, // the consumer pressed "Confirm withdrawal"
254
+ });
255
+ // ack.submittedAt, ack.items, ack.confirmationSent
256
+ ```
257
+
258
+ ### Bookings (2.24.0)
259
+
260
+ Online appointments from the Behio Bookings module. Days are `YYYY-MM-DD` in the
261
+ branch time zone (`config.timezone`); a taken time answers 409
262
+ `be.bookings.slotTaken`, so reload free times and let the customer pick again.
263
+
264
+ ```ts
265
+ const {data: config} = await storefront.bookings.getConfig();
266
+ const {data: free} = await storefront.bookings.getSlots({serviceIds: [config.services[0].id], from: '2026-10-21', to: '2026-11-03'});
267
+ const {data, error} = await storefront.bookings.create({serviceIds: [config.services[0].id], startMs: free.slots[0].startMs, name: 'Jana', email: 'jana@example.com', website: ''});
268
+ // data.booking.code, data.booking.status ('CONFIRMED' or 'PENDING'), data.manageToken
269
+ ```
270
+
271
+ Change and cancel by the token from the confirmation email: `getByToken`,
272
+ `getManageSlots`, `reschedule`, `cancel`. React: `useBookingConfig`,
273
+ `useBookingSlots`, `useCreateBooking`, `useManagedBooking`, `useCancelBooking`,
274
+ `useRescheduleBooking`. Without your own UI, embed the hosted widget instead
275
+ (see the Bookings page of the docs).
276
+
235
277
  ### Framework Support
236
278
 
237
279
  - **Next.js**: Server components + client hooks, SSR ready
@@ -204,6 +204,7 @@ var BehioStorefront = class {
204
204
  this.forms = new FormsModule(this);
205
205
  this.collections = new CollectionsModule(this);
206
206
  this.faq = new FaqModule(this);
207
+ this.bookings = new BookingsModule(this);
207
208
  this.wishlist = new WishlistModule(this);
208
209
  this.reviews = new ReviewsModule(this);
209
210
  this.returns = new ReturnsModule(this);
@@ -1880,6 +1881,60 @@ var FaqModule = class {
1880
1881
  });
1881
1882
  }
1882
1883
  };
1884
+ var BookingsModule = class {
1885
+ constructor(client) {
1886
+ this.client = client;
1887
+ }
1888
+ /** Services, categories, staff, branches and rules of the booking flow. */
1889
+ async getConfig() {
1890
+ return this.client.request("GET", "/bookings/config", { auth: false });
1891
+ }
1892
+ /** Free start times for the selected services (at most 31 days per call). */
1893
+ async getSlots(query) {
1894
+ return this.client.request("GET", "/bookings/slots", {
1895
+ query: {
1896
+ serviceIds: query.serviceIds.join(","),
1897
+ staffId: query.staffId ?? void 0,
1898
+ from: query.from,
1899
+ to: query.to
1900
+ },
1901
+ auth: false
1902
+ });
1903
+ }
1904
+ /**
1905
+ * Create a booking. Counts toward the monthly online limit of the plan.
1906
+ * Keep `manageToken` only to link the customer to the change and cancel
1907
+ * page; the same link arrives in the confirmation email.
1908
+ */
1909
+ async create(input) {
1910
+ return this.client.request("POST", "/bookings", { body: input, auth: false });
1911
+ }
1912
+ /** The booking behind the token from the confirmation email. */
1913
+ async getByToken(token) {
1914
+ return this.client.request("GET", `/bookings/manage/${encodeURIComponent(token)}`, { auth: false });
1915
+ }
1916
+ /** Free times to move the booking to (same services and person rules). */
1917
+ async getManageSlots(token, query) {
1918
+ return this.client.request("GET", `/bookings/manage/${encodeURIComponent(token)}/slots`, {
1919
+ query: { from: query.from, to: query.to },
1920
+ auth: false
1921
+ });
1922
+ }
1923
+ /** Cancel the booking (optional reason for the business). */
1924
+ async cancel(token, input) {
1925
+ return this.client.request("POST", `/bookings/manage/${encodeURIComponent(token)}/cancel`, {
1926
+ body: { reason: input?.reason ?? null },
1927
+ auth: false
1928
+ });
1929
+ }
1930
+ /** Move the booking to `startMs` of a slot from `getManageSlots`. */
1931
+ async reschedule(token, input) {
1932
+ return this.client.request("POST", `/bookings/manage/${encodeURIComponent(token)}/reschedule`, {
1933
+ body: { startMs: input.startMs },
1934
+ auth: false
1935
+ });
1936
+ }
1937
+ };
1883
1938
  var FormsModule = class {
1884
1939
  constructor(client) {
1885
1940
  this.client = client;
@@ -2043,6 +2098,19 @@ var ReturnsModule = class {
2043
2098
  }
2044
2099
  );
2045
2100
  }
2101
+ /**
2102
+ * EU withdrawal function (Art. 11a Directive 2011/83/EU, 2.25.0). Two steps
2103
+ * in the template: the form (name, order number, e-mail), then a summary
2104
+ * with the "Confirm withdrawal" button that calls this. The result is the
2105
+ * acknowledgement to show; the same content with date and time goes out by
2106
+ * e-mail. Guests welcome, the order e-mail is the gate.
2107
+ */
2108
+ async withdraw(input) {
2109
+ return this.client.request("POST", "/returns/withdrawal", {
2110
+ body: input
2111
+ });
2112
+ }
2113
+ /** Return or complaint. Reason CHANGED_MIND is recorded as a withdrawal on the server. */
2046
2114
  async submit(input) {
2047
2115
  return this.client.request("POST", "/returns", {
2048
2116
  body: input
@@ -204,6 +204,7 @@ var BehioStorefront = class {
204
204
  this.forms = new FormsModule(this);
205
205
  this.collections = new CollectionsModule(this);
206
206
  this.faq = new FaqModule(this);
207
+ this.bookings = new BookingsModule(this);
207
208
  this.wishlist = new WishlistModule(this);
208
209
  this.reviews = new ReviewsModule(this);
209
210
  this.returns = new ReturnsModule(this);
@@ -1880,6 +1881,60 @@ var FaqModule = class {
1880
1881
  });
1881
1882
  }
1882
1883
  };
1884
+ var BookingsModule = class {
1885
+ constructor(client) {
1886
+ this.client = client;
1887
+ }
1888
+ /** Services, categories, staff, branches and rules of the booking flow. */
1889
+ async getConfig() {
1890
+ return this.client.request("GET", "/bookings/config", { auth: false });
1891
+ }
1892
+ /** Free start times for the selected services (at most 31 days per call). */
1893
+ async getSlots(query) {
1894
+ return this.client.request("GET", "/bookings/slots", {
1895
+ query: {
1896
+ serviceIds: query.serviceIds.join(","),
1897
+ staffId: _nullishCoalesce(query.staffId, () => ( void 0)),
1898
+ from: query.from,
1899
+ to: query.to
1900
+ },
1901
+ auth: false
1902
+ });
1903
+ }
1904
+ /**
1905
+ * Create a booking. Counts toward the monthly online limit of the plan.
1906
+ * Keep `manageToken` only to link the customer to the change and cancel
1907
+ * page; the same link arrives in the confirmation email.
1908
+ */
1909
+ async create(input) {
1910
+ return this.client.request("POST", "/bookings", { body: input, auth: false });
1911
+ }
1912
+ /** The booking behind the token from the confirmation email. */
1913
+ async getByToken(token) {
1914
+ return this.client.request("GET", `/bookings/manage/${encodeURIComponent(token)}`, { auth: false });
1915
+ }
1916
+ /** Free times to move the booking to (same services and person rules). */
1917
+ async getManageSlots(token, query) {
1918
+ return this.client.request("GET", `/bookings/manage/${encodeURIComponent(token)}/slots`, {
1919
+ query: { from: query.from, to: query.to },
1920
+ auth: false
1921
+ });
1922
+ }
1923
+ /** Cancel the booking (optional reason for the business). */
1924
+ async cancel(token, input) {
1925
+ return this.client.request("POST", `/bookings/manage/${encodeURIComponent(token)}/cancel`, {
1926
+ body: { reason: _nullishCoalesce(_optionalChain([input, 'optionalAccess', _51 => _51.reason]), () => ( null)) },
1927
+ auth: false
1928
+ });
1929
+ }
1930
+ /** Move the booking to `startMs` of a slot from `getManageSlots`. */
1931
+ async reschedule(token, input) {
1932
+ return this.client.request("POST", `/bookings/manage/${encodeURIComponent(token)}/reschedule`, {
1933
+ body: { startMs: input.startMs },
1934
+ auth: false
1935
+ });
1936
+ }
1937
+ };
1883
1938
  var FormsModule = class {
1884
1939
  constructor(client) {
1885
1940
  this.client = client;
@@ -2043,6 +2098,19 @@ var ReturnsModule = class {
2043
2098
  }
2044
2099
  );
2045
2100
  }
2101
+ /**
2102
+ * EU withdrawal function (Art. 11a Directive 2011/83/EU, 2.25.0). Two steps
2103
+ * in the template: the form (name, order number, e-mail), then a summary
2104
+ * with the "Confirm withdrawal" button that calls this. The result is the
2105
+ * acknowledgement to show; the same content with date and time goes out by
2106
+ * e-mail. Guests welcome, the order e-mail is the gate.
2107
+ */
2108
+ async withdraw(input) {
2109
+ return this.client.request("POST", "/returns/withdrawal", {
2110
+ body: input
2111
+ });
2112
+ }
2113
+ /** Return or complaint. Reason CHANGED_MIND is recorded as a withdrawal on the server. */
2046
2114
  async submit(input) {
2047
2115
  return this.client.request("POST", "/returns", {
2048
2116
  body: input
@@ -2081,7 +2149,7 @@ var ConsentModule = class {
2081
2149
  }
2082
2150
  if (result.error) return { data: null, error: result.error };
2083
2151
  return {
2084
- data: _optionalChain([result, 'access', _51 => _51.data, 'optionalAccess', _52 => _52.consented]) ? result.data.consent : null,
2152
+ data: _optionalChain([result, 'access', _52 => _52.data, 'optionalAccess', _53 => _53.consented]) ? result.data.consent : null,
2085
2153
  error: null
2086
2154
  };
2087
2155
  }
@@ -2168,10 +2236,10 @@ var ShippingModule = class {
2168
2236
  */
2169
2237
  async listMethods(opts) {
2170
2238
  const query = {};
2171
- if (_optionalChain([opts, 'optionalAccess', _53 => _53.currency])) query.currency = opts.currency;
2172
- if (_optionalChain([opts, 'optionalAccess', _54 => _54.country])) query.country = opts.country;
2173
- if (_optionalChain([opts, 'optionalAccess', _55 => _55.cartTotal]) != null) query.cartTotal = String(opts.cartTotal);
2174
- if (_optionalChain([opts, 'optionalAccess', _56 => _56.cartWeightKg]) != null)
2239
+ if (_optionalChain([opts, 'optionalAccess', _54 => _54.currency])) query.currency = opts.currency;
2240
+ if (_optionalChain([opts, 'optionalAccess', _55 => _55.country])) query.country = opts.country;
2241
+ if (_optionalChain([opts, 'optionalAccess', _56 => _56.cartTotal]) != null) query.cartTotal = String(opts.cartTotal);
2242
+ if (_optionalChain([opts, 'optionalAccess', _57 => _57.cartWeightKg]) != null)
2175
2243
  query.cartWeightKg = String(opts.cartWeightKg);
2176
2244
  return this.client.request(
2177
2245
  "GET",
@@ -261,6 +261,20 @@ interface ShopInfo {
261
261
  * may still be served.
262
262
  */
263
263
  seo?: ShopSeoIdentity;
264
+ /**
265
+ * Online withdrawal function (Art. 11a Directive 2011/83/EU, mandatory in
266
+ * the EU from 19 Jun 2026). When `enabled`, render a clearly labelled link
267
+ * ("Withdraw from contract here") in the footer and in the customer account,
268
+ * leading to the withdrawal form (`returns.withdraw`). Optional because
269
+ * cached ShopInfo payloads predating the field may still be served (2.25.0).
270
+ */
271
+ withdrawal?: WithdrawalSettings;
272
+ }
273
+ /** Merchant setting of the online withdrawal function (2.25.0). */
274
+ interface WithdrawalSettings {
275
+ enabled: boolean;
276
+ /** Withdrawal period in days from receipt of the goods (14 by law). */
277
+ periodDays: number;
264
278
  }
265
279
  interface ShopAppearance {
266
280
  primaryColor: string | null;
@@ -1786,7 +1800,22 @@ interface OrderPaymentInstructions {
1786
1800
  currency: string;
1787
1801
  instructions: string | null;
1788
1802
  }
1803
+ /** Issued document visible only to the authorized order owner. Its page offers a PDF download. */
1804
+ interface OrderDocument {
1805
+ id: string;
1806
+ number: string;
1807
+ type: "INVOICE" | "PROFORMA" | "RECEIPT" | "CREDIT_NOTE";
1808
+ currency: string;
1809
+ totalAmount: number;
1810
+ /** Actual invoice ledger amounts, independent of the order payment status. */
1811
+ paidAmount: number;
1812
+ remainingAmount: number;
1813
+ /** Capability URL: do not expose in public tracking, analytics or logs. */
1814
+ url: string;
1815
+ }
1789
1816
  interface OrderDetail extends OrderListItem {
1817
+ /** Issued invoices/proformas/receipts/credit notes. Drafts and revoked links are excluded. */
1818
+ documents?: OrderDocument[];
1790
1819
  /** Payment is recorded; access delivery will retry automatically. Do not place a duplicate order. */
1791
1820
  contentDeliveryPending?: boolean;
1792
1821
  /** False for an order without physical delivery. */
@@ -3110,9 +3139,70 @@ interface ReturnableOrder {
3110
3139
  orderId: string;
3111
3140
  orderNumber: string;
3112
3141
  status: string;
3142
+ /** Name from the order billing address, to prefill the withdrawal form (2.25.0). */
3143
+ customerName: string | null;
3113
3144
  items: ReturnableOrderItem[];
3145
+ /** Withdrawal window of this order (2.25.0). */
3146
+ withdrawal: WithdrawalWindow;
3114
3147
  createdAt: number;
3115
3148
  }
3149
+ /**
3150
+ * What the withdrawal form should say about the period. The form stays
3151
+ * usable outside the window: the consumer may always submit, the merchant
3152
+ * decides. (2.25.0)
3153
+ */
3154
+ interface WithdrawalWindow {
3155
+ /** The e-shop offers the online withdrawal function. */
3156
+ enabled: boolean;
3157
+ periodDays: number;
3158
+ /** Last moment of the period (ms). Null while it has not started or delivery is not recorded. */
3159
+ deadlineAt: number | null;
3160
+ /** False only when the period demonstrably ended. */
3161
+ withinPeriod: boolean;
3162
+ /** AFTER_DEADLINE | BEFORE_DISPATCH | DELIVERY_UNKNOWN | DIGITAL_CONTENT_CONSENT */
3163
+ flags: WithdrawalFlag[];
3164
+ }
3165
+ type WithdrawalFlag = "AFTER_DEADLINE" | "BEFORE_DISPATCH" | "DELIVERY_UNKNOWN" | "DIGITAL_CONTENT_CONSENT";
3166
+ /**
3167
+ * Input of `returns.withdraw()`: the withdrawal statement of Art. 11a(2):
3168
+ * the consumer's name, the contract (order number) and the e-mail the
3169
+ * acknowledgement goes to. Send it only after the consumer pressed the
3170
+ * confirmation button ("Confirm withdrawal"), hence `confirmed: true`. (2.25.0)
3171
+ */
3172
+ interface SubmitWithdrawalInput {
3173
+ orderNumber: string;
3174
+ /** Order e-mail: the ownership gate and where the acknowledgement is sent. */
3175
+ email: string;
3176
+ name: string;
3177
+ /** Omit to withdraw from every still returnable item of the order. */
3178
+ items?: {
3179
+ orderItemId: string;
3180
+ quantity: number;
3181
+ }[];
3182
+ note?: string;
3183
+ confirmed: true;
3184
+ }
3185
+ /**
3186
+ * Returned by `returns.withdraw()`. Show it as the acknowledgement: the same
3187
+ * content with date and time also goes out by e-mail. `confirmationSent`
3188
+ * says whether that e-mail really went out. (2.25.0)
3189
+ */
3190
+ interface WithdrawalAcknowledgement {
3191
+ id: string;
3192
+ orderNumber: string;
3193
+ customerName: string;
3194
+ email: string;
3195
+ /** Date and time of submission (ms). */
3196
+ submittedAt: number;
3197
+ items: {
3198
+ productName: string;
3199
+ quantity: number;
3200
+ }[];
3201
+ note: string | null;
3202
+ deadlineAt: number | null;
3203
+ withinPeriod: boolean;
3204
+ confirmationSent: boolean;
3205
+ }
3116
3206
  interface ReturnRequestItem {
3117
3207
  id: string;
3118
3208
  orderItemId: string;
@@ -3143,6 +3233,8 @@ interface ReturnStatusItem {
3143
3233
  interface ReturnStatus {
3144
3234
  id: string;
3145
3235
  orderNumber: string;
3236
+ /** WITHDRAWAL = withdrawal from the contract, RETURN = return or complaint (2.25.0). */
3237
+ type: "RETURN" | "WITHDRAWAL";
3146
3238
  /** REQUESTED | APPROVED | SHIPPED_BACK | RECEIVED | REFUNDED | REJECTED | CLOSED */
3147
3239
  status: string;
3148
3240
  reason: string;
@@ -3302,6 +3394,145 @@ interface GamificationRefreshResult {
3302
3394
  awarded: number;
3303
3395
  completed: number;
3304
3396
  }
3397
+ type BookingLocale = "cs" | "sk" | "en";
3398
+ type BookingStatus = "PENDING" | "CONFIRMED" | "CANCELLED" | "NO_SHOW" | "COMPLETED";
3399
+ interface BookingService {
3400
+ id: string;
3401
+ categoryId: string | null;
3402
+ name: string;
3403
+ description: string | null;
3404
+ durationMinutes: number;
3405
+ /** Null = price on site (show it as such, never as 0). */
3406
+ price: number | null;
3407
+ /** ISO 4217 code (CZK, EUR, ...). */
3408
+ currency: string;
3409
+ }
3410
+ interface BookingCategory {
3411
+ id: string;
3412
+ name: string;
3413
+ }
3414
+ interface BookingStaff {
3415
+ id: string;
3416
+ name: string;
3417
+ title: string | null;
3418
+ bio: string | null;
3419
+ /** `#rrggbb` or null. */
3420
+ color: string | null;
3421
+ /** Services this person does. */
3422
+ serviceIds: string[];
3423
+ }
3424
+ interface BookingLocation {
3425
+ id: string;
3426
+ name: string;
3427
+ address: string | null;
3428
+ timezone: string;
3429
+ }
3430
+ /** Public booking setup of the site owner (`GET /bookings/config`). */
3431
+ interface BookingConfig {
3432
+ businessName: string;
3433
+ intro: string | null;
3434
+ /** `#rrggbb` brand colour of the widget, or null. */
3435
+ accentColor: string | null;
3436
+ defaultLocale: BookingLocale;
3437
+ /** Offer a staff choice step (otherwise send `staffId: null`). */
3438
+ allowStaffChoice: boolean;
3439
+ /** New bookings start as PENDING and the business confirms them. */
3440
+ requireApproval: boolean;
3441
+ /** How many days ahead a customer may book. */
3442
+ maxAdvanceDays: number;
3443
+ /** Customer may change or cancel until this many hours before the start. */
3444
+ customerCancelHours: number;
3445
+ contactPhone: string | null;
3446
+ contactEmail: string | null;
3447
+ /**
3448
+ * Online booking is paused (plan limit). Do not offer the flow, show the
3449
+ * contact instead: `create` would answer `be.bookings.onlineLimitReached`.
3450
+ */
3451
+ onlinePaused: boolean;
3452
+ /** IANA time zone of the branch; show every day and time in it. */
3453
+ timezone: string;
3454
+ locations: BookingLocation[];
3455
+ categories: BookingCategory[];
3456
+ services: BookingService[];
3457
+ staff: BookingStaff[];
3458
+ }
3459
+ interface BookingSlot {
3460
+ startMs: number;
3461
+ endMs: number;
3462
+ }
3463
+ interface BookingSlots {
3464
+ timezone: string;
3465
+ /** Total length of the selected services. */
3466
+ durationMinutes: number;
3467
+ slots: BookingSlot[];
3468
+ }
3469
+ interface BookingSlotsQuery {
3470
+ /** Selected services in the order they follow each other (1 to 10). */
3471
+ serviceIds: string[];
3472
+ /** Only this person; omit for anyone free. */
3473
+ staffId?: string | null;
3474
+ /** First day `YYYY-MM-DD` (branch time zone). */
3475
+ from: string;
3476
+ /** Last day `YYYY-MM-DD`, at most 31 days after `from`. */
3477
+ to: string;
3478
+ }
3479
+ interface BookingManageSlotsQuery {
3480
+ from: string;
3481
+ to: string;
3482
+ }
3483
+ interface BookingCreateInput {
3484
+ serviceIds: string[];
3485
+ /** Null or omitted = anyone free. */
3486
+ staffId?: string | null;
3487
+ /** `startMs` of a slot from `getSlots`. */
3488
+ startMs: number;
3489
+ name: string;
3490
+ email: string;
3491
+ phone?: string | null;
3492
+ note?: string | null;
3493
+ /** Language of the confirmation email. */
3494
+ locale?: BookingLocale;
3495
+ /** Honeypot: render a hidden input and send its value; people leave it empty. */
3496
+ website?: string;
3497
+ /** Analytics visitor (consent-gated), only for the CRM. */
3498
+ visitorId?: string | null;
3499
+ }
3500
+ /** One booking as the customer sees it. */
3501
+ interface Booking {
3502
+ id: string;
3503
+ /** Short code shown to the customer and in emails. */
3504
+ code: string;
3505
+ status: BookingStatus;
3506
+ startMs: number;
3507
+ endMs: number;
3508
+ timezone: string;
3509
+ businessName: string;
3510
+ staffName: string;
3511
+ locationName: string;
3512
+ locationAddress: string | null;
3513
+ services: string[];
3514
+ serviceIds: string[];
3515
+ /** Person chosen by the customer; null = anyone. */
3516
+ staffId: string | null;
3517
+ totalPrice: number | null;
3518
+ currency: string;
3519
+ customerName: string;
3520
+ /** The customer may still change or cancel (deadline from the settings). */
3521
+ canChange: boolean;
3522
+ /** Until when (ms) the customer may change or cancel. */
3523
+ changeDeadline: number | null;
3524
+ /** Phone of the business to show once `canChange` is false. */
3525
+ contactPhone: string | null;
3526
+ locale: string;
3527
+ }
3528
+ interface BookingCreated {
3529
+ booking: Booking;
3530
+ /**
3531
+ * Token for the change and cancel link (the same one the confirmation email
3532
+ * carries). Treat it like a password: never put it in analytics or logs.
3533
+ */
3534
+ manageToken: string;
3535
+ }
3305
3536
 
3306
3537
  declare class BehioStorefront {
3307
3538
  private baseUrl;
@@ -3356,6 +3587,7 @@ declare class BehioStorefront {
3356
3587
  readonly forms: FormsModule;
3357
3588
  readonly collections: CollectionsModule;
3358
3589
  readonly faq: FaqModule;
3590
+ readonly bookings: BookingsModule;
3359
3591
  readonly wishlist: WishlistModule;
3360
3592
  readonly reviews: ReviewsModule;
3361
3593
  readonly returns: ReturnsModule;
@@ -4109,6 +4341,49 @@ declare class FaqModule {
4109
4341
  */
4110
4342
  get(group: string, query?: StorefrontFaqQuery): Promise<SdkResult<StorefrontFaqGroup>>;
4111
4343
  }
4344
+ /**
4345
+ * Online booking of the site owner's services (hair salon, clinic, lessons):
4346
+ * the public setup, free times, a new booking, and the change and cancel flow
4347
+ * behind the token from the confirmation email. Works with website keys that
4348
+ * have no e-shop attached; the Bookings module must be on in the admin
4349
+ * (otherwise 404 `be.bookings.widgetNotFound`).
4350
+ *
4351
+ * Days are `YYYY-MM-DD` in the branch time zone (`config.timezone`), not the
4352
+ * visitor's; format times with `timeZone: config.timezone`.
4353
+ *
4354
+ * Errors worth handling: 409 `be.bookings.slotTaken` (someone was faster:
4355
+ * reload the slots and let the customer pick again), 403
4356
+ * `be.bookings.onlineLimitReached` (online booking paused, show the contact),
4357
+ * 403 `be.bookings.changeTooLate` (too late to change, show
4358
+ * `booking.contactPhone`), 404 `be.bookings.manageNotFound` (old or wrong
4359
+ * token), 429 (rate limit: 10 new bookings and 20 changes per minute).
4360
+ */
4361
+ declare class BookingsModule {
4362
+ private client;
4363
+ constructor(client: BehioStorefront);
4364
+ /** Services, categories, staff, branches and rules of the booking flow. */
4365
+ getConfig(): Promise<SdkResult<BookingConfig>>;
4366
+ /** Free start times for the selected services (at most 31 days per call). */
4367
+ getSlots(query: BookingSlotsQuery): Promise<SdkResult<BookingSlots>>;
4368
+ /**
4369
+ * Create a booking. Counts toward the monthly online limit of the plan.
4370
+ * Keep `manageToken` only to link the customer to the change and cancel
4371
+ * page; the same link arrives in the confirmation email.
4372
+ */
4373
+ create(input: BookingCreateInput): Promise<SdkResult<BookingCreated>>;
4374
+ /** The booking behind the token from the confirmation email. */
4375
+ getByToken(token: string): Promise<SdkResult<Booking>>;
4376
+ /** Free times to move the booking to (same services and person rules). */
4377
+ getManageSlots(token: string, query: BookingManageSlotsQuery): Promise<SdkResult<BookingSlots>>;
4378
+ /** Cancel the booking (optional reason for the business). */
4379
+ cancel(token: string, input?: {
4380
+ reason?: string | null;
4381
+ }): Promise<SdkResult<Booking>>;
4382
+ /** Move the booking to `startMs` of a slot from `getManageSlots`. */
4383
+ reschedule(token: string, input: {
4384
+ startMs: number;
4385
+ }): Promise<SdkResult<Booking>>;
4386
+ }
4112
4387
  /**
4113
4388
  * Merchant-defined forms (contact, demand, registration to an event...).
4114
4389
  * The definition is public and cacheable; a submit is validated server-side
@@ -4193,6 +4468,15 @@ declare class ReturnsModule {
4193
4468
  * quantities. POST so the email never appears in a URL.
4194
4469
  */
4195
4470
  lookupOrder(orderNumber: string, email: string): Promise<SdkResult<ReturnableOrder>>;
4471
+ /**
4472
+ * EU withdrawal function (Art. 11a Directive 2011/83/EU, 2.25.0). Two steps
4473
+ * in the template: the form (name, order number, e-mail), then a summary
4474
+ * with the "Confirm withdrawal" button that calls this. The result is the
4475
+ * acknowledgement to show; the same content with date and time goes out by
4476
+ * e-mail. Guests welcome, the order e-mail is the gate.
4477
+ */
4478
+ withdraw(input: SubmitWithdrawalInput): Promise<SdkResult<WithdrawalAcknowledgement>>;
4479
+ /** Return or complaint. Reason CHANGED_MIND is recorded as a withdrawal on the server. */
4196
4480
  submit(input: SubmitReturnInput): Promise<SdkResult<ReturnRequest>>;
4197
4481
  /** Email is the ownership gate; POST so it never lands in a URL / log. */
4198
4482
  getStatus(returnId: string, email: string): Promise<SdkResult<ReturnStatus>>;
@@ -4330,4 +4614,4 @@ declare function clearCartSummary(): void;
4330
4614
  /** Publish only authoritative current totals; server cart consumers call this after hydration and revalidation. */
4331
4615
  declare function publishCartSummary(summary: CartSummaryEvent): void;
4332
4616
 
4333
- export { type CourseCommentReply as $, type ActivePromotion as A, BehioStorefront as B, type CookieConsent as C, type Cart as D, type CartBundleLine as E, type CartBundleLineItem as F, type CartDiscount as G, type CartItem as H, type CartItemProduct as I, type CartLinkClaimed as J, type CartPromotion as K, type CartSummaryEvent as L, type Category as M, type CategoryDetail as N, type CertificateVerification as O, type ProductDetail as P, type CheckoutAddress as Q, type CheckoutInput as R, type SdkResult as S, type CheckoutPaymentMethod as T, type CheckoutPreview as U, type CheckoutResult as V, type CheckoutSettings as W, type CookieConsentInput as X, type CourseAttachment as Y, type CourseCertificate as Z, type CourseComment as _, type ProductVariant as a, type OrderPaymentInstructions as a$, type CourseCommentsList as a0, type CourseDetail as a1, type CourseLesson as a2, type CourseListItem as a3, type CourseModule as a4, type CoursePostedComment as a5, type CourseProgress as a6, type CourseTutorMessage as a7, type CourseTutorThread as a8, type CrossSellItem as a9, type LessonNote as aA, type LessonQuiz as aB, type LoginInput as aC, type LoyaltyBalance as aD, type LoyaltyNextTier as aE, type LoyaltyProgram as aF, type LoyaltyQuery as aG, type LoyaltyReferralResult as aH, type LoyaltySummary as aI, type LoyaltyTier as aJ, type LoyaltyTierPerks as aK, type LoyaltyTransaction as aL, type Menu as aM, type MenuItem as aN, type MenuItemRef as aO, type MenuItemType as aP, type MessageResponse as aQ, type NewsletterOptInDefault as aR, type NewsletterSubscribeInput as aS, type NewsletterSubscribeResult as aT, type NewsletterUnsubscribeResult as aU, type OrderAccessRequestResponse as aV, type OrderAccessVerifyResponse as aW, type OrderDetail as aX, type OrderDiscount as aY, type OrderItem as aZ, type OrderListItem as a_, type CurrencyDisplayFormat as aa, type CustomerAddress as ab, type CustomerBadge as ac, type CustomerChallenge as ad, type CustomerGamification as ae, type CustomerGamificationQuery as af, type CustomerProfile as ag, type DigitalDownload as ah, type DownloadUrl as ai, type Facet as aj, type FacetAvailability as ak, type FacetCategory as al, type FacetLabel as am, type FacetPriceRange as an, type FacetRange as ao, type FacetRatingBucket as ap, type FacetValue as aq, type FacetsResponse as ar, type FilterField as as, type FulfillmentStatus as at, FulfillmentStatuses as au, type GamificationRefreshResult as av, type GiftCardBalance as aw, type GiftCardPurchaseInput as ax, type GiftCardPurchaseResult as ay, type GiftCardSummary as az, type StorefrontFormFieldError as b, type ShopCommerce as b$, type OrderPickupPoint as b0, type OrderShipment as b1, type OrderStatus as b2, type OrderStatusHistory as b3, OrderStatuses as b4, type OrderTracking as b5, type Page as b6, type PageAttachment as b7, type PageDetail as b8, type PaginatedResponse as b9, type ProductSortValue as bA, type ProductVolumePrice as bB, type ProductsQuery as bC, type QuizAnswerInput as bD, type QuizAnswerResult as bE, type QuizQuestion as bF, type QuizResult as bG, type QuoteItem as bH, type QuoteRequest as bI, type RegisterInput as bJ, type RegisterResult as bK, type RequestInterceptor as bL, type RequestInterceptorConfig as bM, type ResponseInterceptor as bN, type ResponseInterceptorData as bO, type ReturnRequest as bP, type ReturnRequestItem as bQ, type ReturnStatus as bR, type ReturnStatusItem as bS, type ReturnableOrder as bT, type ReturnableOrderItem as bU, type SdkError as bV, type ShippingMethodSummary as bW, type ShippingPublicConfig as bX, type ShippingQuote as bY, type ShippingQuoteInput as bZ, type ShopAppearance as b_, type PaymentInstrument as ba, type PaymentStatus as bb, PaymentStatuses as bc, type PaymentSwift as bd, type PickupPoint as be, type PickupPointHours as bf, type PickupPointsInput as bg, type PickupWidgetConfig as bh, type PriceDisplay as bi, type ProductAssetGroup as bj, type ProductAssetItem as bk, type ProductAvailability as bl, type ProductGroup as bm, type ProductLabel as bn, type ProductListItem as bo, type ProductMedia as bp, type ProductMediaVariant as bq, type ProductParameter as br, type ProductParameterGroup as bs, type ProductParametersResponse as bt, type ProductPrice as bu, type ProductPromotionSummary as bv, type ProductReview as bw, type ProductReviewsResponse as bx, type ProductSibling as by, ProductSort as bz, type AddToCartInput as c, type ShopInfo as c0, type ShopScript as c1, type ShopScriptPlacement as c2, type ShopScriptType as c3, type ShopScripts as c4, type ShopSeo as c5, type ShopSeoIdentity as c6, type SiteFormField as c7, type SiteFormFieldOption as c8, type SiteFormFieldType as c9, type SubscriptionFrequency as cA, type SubscriptionItem as cB, type SubscriptionStatus as cC, type TaxBreakdownLine as cD, type VariantAxis as cE, type VariantAxisValue as cF, type WishlistItem as cG, clearCartSummary as cH, err as cI, ok as cJ, publishCartSummary as cK, toSdkError as cL, type Sitemap as ca, type SitemapEntry as cb, type StockBehavior as cc, type StockMode as cd, type StorefrontCollection as ce, type StorefrontCollectionField as cf, type StorefrontCollectionFieldType as cg, type StorefrontCollectionItem as ch, type StorefrontCollectionQuery as ci, type StorefrontFaqGroup as cj, type StorefrontFaqGroupSummary as ck, type StorefrontFaqGroups as cl, type StorefrontFaqItem as cm, type StorefrontFaqQuery as cn, type StorefrontForm as co, type StorefrontFormFieldErrorCode as cp, type StorefrontFormFile as cq, type StorefrontFormSettings as cr, type StorefrontFormSubmitInput as cs, type StorefrontFormSubmitResult as ct, type StorefrontFormUpload as cu, type SubmitQuoteInput as cv, type SubmitReturnInput as cw, type SubmitReviewInput as cx, type Subscription as cy, type SubscriptionAction as cz, type AddressDetail as d, type AddressSuggestion as e, type AddressType as f, AddressTypes as g, type AuthTokens as h, type BackInStockSubscription as i, type BadgeTone as j, BehioApiError as k, type BehioErrorCode as l, type BehioEventHandler as m, type BehioEventType as n, BehioNetworkError as o, type BehioStorefrontConfig as p, type Blog as q, type BlogPostDetail as r, type BlogPostListItem as s, type BlogPostsPage as t, type BlogPostsQuery as u, type BlogSettings as v, type BlogTag as w, type Bundle as x, type BundleCatalogQuery as y, type BundleItem as z };
4617
+ export { type CartSummaryEvent as $, type ActivePromotion as A, BehioStorefront as B, type CookieConsent as C, type BookingCreateInput as D, type BookingCreated as E, type BookingLocale as F, type BookingLocation as G, type BookingManageSlotsQuery as H, type BookingService as I, type BookingSlot as J, type BookingSlots as K, type BookingSlotsQuery as L, type BookingStaff as M, type BookingStatus as N, type Bundle as O, type ProductDetail as P, type BundleCatalogQuery as Q, type BundleItem as R, type SdkResult as S, type Cart as T, type CartBundleLine as U, type CartBundleLineItem as V, type CartDiscount as W, type CartItem as X, type CartItemProduct as Y, type CartLinkClaimed as Z, type CartPromotion as _, type ProductVariant as a, type MenuItem as a$, type Category as a0, type CategoryDetail as a1, type CertificateVerification as a2, type CheckoutAddress as a3, type CheckoutInput as a4, type CheckoutPaymentMethod as a5, type CheckoutPreview as a6, type CheckoutResult as a7, type CheckoutSettings as a8, type CookieConsentInput as a9, type FacetLabel as aA, type FacetPriceRange as aB, type FacetRange as aC, type FacetRatingBucket as aD, type FacetValue as aE, type FacetsResponse as aF, type FilterField as aG, type FulfillmentStatus as aH, FulfillmentStatuses as aI, type GamificationRefreshResult as aJ, type GiftCardBalance as aK, type GiftCardPurchaseInput as aL, type GiftCardPurchaseResult as aM, type GiftCardSummary as aN, type LessonNote as aO, type LessonQuiz as aP, type LoginInput as aQ, type LoyaltyBalance as aR, type LoyaltyNextTier as aS, type LoyaltyProgram as aT, type LoyaltyQuery as aU, type LoyaltyReferralResult as aV, type LoyaltySummary as aW, type LoyaltyTier as aX, type LoyaltyTierPerks as aY, type LoyaltyTransaction as aZ, type Menu as a_, type CourseAttachment as aa, type CourseCertificate as ab, type CourseComment as ac, type CourseCommentReply as ad, type CourseCommentsList as ae, type CourseDetail as af, type CourseLesson as ag, type CourseListItem as ah, type CourseModule as ai, type CoursePostedComment as aj, type CourseProgress as ak, type CourseTutorMessage as al, type CourseTutorThread as am, type CrossSellItem as an, type CurrencyDisplayFormat as ao, type CustomerAddress as ap, type CustomerBadge as aq, type CustomerChallenge as ar, type CustomerGamification as as, type CustomerGamificationQuery as at, type CustomerProfile as au, type DigitalDownload as av, type DownloadUrl as aw, type Facet as ax, type FacetAvailability as ay, type FacetCategory as az, type StorefrontFormFieldError as b, type RequestInterceptorConfig as b$, type MenuItemRef as b0, type MenuItemType as b1, type MessageResponse as b2, type NewsletterOptInDefault as b3, type NewsletterSubscribeInput as b4, type NewsletterSubscribeResult as b5, type NewsletterUnsubscribeResult as b6, type OrderAccessRequestResponse as b7, type OrderAccessVerifyResponse as b8, type OrderDetail as b9, type ProductAvailability as bA, type ProductGroup as bB, type ProductLabel as bC, type ProductListItem as bD, type ProductMedia as bE, type ProductMediaVariant as bF, type ProductParameter as bG, type ProductParameterGroup as bH, type ProductParametersResponse as bI, type ProductPrice as bJ, type ProductPromotionSummary as bK, type ProductReview as bL, type ProductReviewsResponse as bM, type ProductSibling as bN, ProductSort as bO, type ProductSortValue as bP, type ProductVolumePrice as bQ, type ProductsQuery as bR, type QuizAnswerInput as bS, type QuizAnswerResult as bT, type QuizQuestion as bU, type QuizResult as bV, type QuoteItem as bW, type QuoteRequest as bX, type RegisterInput as bY, type RegisterResult as bZ, type RequestInterceptor as b_, type OrderDiscount as ba, type OrderDocument as bb, type OrderItem as bc, type OrderListItem as bd, type OrderPaymentInstructions as be, type OrderPickupPoint as bf, type OrderShipment as bg, type OrderStatus as bh, type OrderStatusHistory as bi, OrderStatuses as bj, type OrderTracking as bk, type Page as bl, type PageAttachment as bm, type PageDetail as bn, type PaginatedResponse as bo, type PaymentInstrument as bp, type PaymentStatus as bq, PaymentStatuses as br, type PaymentSwift as bs, type PickupPoint as bt, type PickupPointHours as bu, type PickupPointsInput as bv, type PickupWidgetConfig as bw, type PriceDisplay as bx, type ProductAssetGroup as by, type ProductAssetItem as bz, type AddToCartInput as c, clearCartSummary as c$, type ResponseInterceptor as c0, type ResponseInterceptorData as c1, type ReturnRequest as c2, type ReturnRequestItem as c3, type ReturnStatus as c4, type ReturnStatusItem as c5, type ReturnableOrder as c6, type ReturnableOrderItem as c7, type SdkError as c8, type ShippingMethodSummary as c9, type StorefrontFaqGroups as cA, type StorefrontFaqItem as cB, type StorefrontFaqQuery as cC, type StorefrontForm as cD, type StorefrontFormFieldErrorCode as cE, type StorefrontFormFile as cF, type StorefrontFormSettings as cG, type StorefrontFormSubmitInput as cH, type StorefrontFormSubmitResult as cI, type StorefrontFormUpload as cJ, type SubmitQuoteInput as cK, type SubmitReturnInput as cL, type SubmitReviewInput as cM, type SubmitWithdrawalInput as cN, type Subscription as cO, type SubscriptionAction as cP, type SubscriptionFrequency as cQ, type SubscriptionItem as cR, type SubscriptionStatus as cS, type TaxBreakdownLine as cT, type VariantAxis as cU, type VariantAxisValue as cV, type WishlistItem as cW, type WithdrawalAcknowledgement as cX, type WithdrawalFlag as cY, type WithdrawalSettings as cZ, type WithdrawalWindow as c_, type ShippingPublicConfig as ca, type ShippingQuote as cb, type ShippingQuoteInput as cc, type ShopAppearance as cd, type ShopCommerce as ce, type ShopInfo as cf, type ShopScript as cg, type ShopScriptPlacement as ch, type ShopScriptType as ci, type ShopScripts as cj, type ShopSeo as ck, type ShopSeoIdentity as cl, type SiteFormField as cm, type SiteFormFieldOption as cn, type SiteFormFieldType as co, type Sitemap as cp, type SitemapEntry as cq, type StockBehavior as cr, type StockMode as cs, type StorefrontCollection as ct, type StorefrontCollectionField as cu, type StorefrontCollectionFieldType as cv, type StorefrontCollectionItem as cw, type StorefrontCollectionQuery as cx, type StorefrontFaqGroup as cy, type StorefrontFaqGroupSummary as cz, type AddressDetail as d, err as d0, ok as d1, publishCartSummary as d2, toSdkError as d3, type AddressSuggestion as e, type AddressType as f, AddressTypes as g, type AuthTokens as h, type BackInStockSubscription as i, type BadgeTone as j, BehioApiError as k, type BehioErrorCode as l, type BehioEventHandler as m, type BehioEventType as n, BehioNetworkError as o, type BehioStorefrontConfig as p, type Blog as q, type BlogPostDetail as r, type BlogPostListItem as s, type BlogPostsPage as t, type BlogPostsQuery as u, type BlogSettings as v, type BlogTag as w, type Booking as x, type BookingCategory as y, type BookingConfig as z };