@praxium/sdk 0.5.94 → 0.6.97

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
@@ -88,6 +88,24 @@ const result = await client.submitContactForm({
88
88
  // → { success: true, emailStatus: 'sent' }
89
89
  ```
90
90
 
91
+ ### Multiple Locations
92
+
93
+ Practices with more than one location expose each location under a stable slug. List them with `getLocations()`, then pass `{ location: slug }` to any location-aware method to narrow the response:
94
+
95
+ ```typescript
96
+ const locations = await client.getLocations()
97
+ // → [{ slug: 'centrum', name: 'Centrum', kind: 'PHYSICAL',
98
+ // phone: '...', email: '...', fullAddress: '...',
99
+ // openingHours: { schedule: [...], globalNote: null } }, ...]
100
+
101
+ // Per-location data:
102
+ const hours = await client.getOpeningHours({ location: 'zuid' })
103
+ const team = await client.getTeamMembers({ location: 'zuid' })
104
+ const services = await client.getBookableServices({ location: 'zuid' })
105
+ ```
106
+
107
+ Without the filter, single-value methods (`getContactDetails`, `getLocation`, `getOpeningHours`, `getSocialLinks`) return the practice's main location, and collection methods (`getTeamMembers`, `getFaq`, `getServiceVariants`, `getBookableServices`) return the practice-wide data set. An unknown slug — or one outside your API key's location scope — throws `PraxiumNotFoundError` (HTTP 404).
108
+
91
109
  ## Configuration
92
110
 
93
111
  Your website needs two environment variables to connect to the Praxium platform, plus an optional third for webhook-based cache revalidation:
@@ -116,21 +134,24 @@ PRAXIUM_WEBHOOK_SECRET="your-webhook-secret-from-admin-portal" # optional
116
134
 
117
135
  ## Available Methods
118
136
 
137
+ Methods marked with `options?` accept an optional `{ location: slug }` filter — see [Multiple Locations](#multiple-locations).
138
+
119
139
  | Method | Description |
120
140
  |--------|-------------|
121
- | `getOpeningHours()` | Weekly opening schedule |
122
- | `getTeamMembers()` | Staff members with photos and custom fields |
123
- | `getContactDetails()` | Practice contact information |
124
- | `getLocation()` | Address and map coordinates |
141
+ | `getLocations(options?)` | Practice locations with address, contact, and weekly hours |
142
+ | `getOpeningHours(options?)` | Weekly opening schedule |
143
+ | `getTeamMembers(options?)` | Staff members with photos and custom fields |
144
+ | `getContactDetails(options?)` | Practice contact information |
145
+ | `getLocation(options?)` | Address and map coordinates |
125
146
  | `getBusinessName()` | Practice display name |
126
- | `getSocialLinks()` | Social media URLs |
127
- | `getFaq()` | FAQ grouped by category |
128
- | `getServiceVariants()` | Service pricing and variants |
147
+ | `getSocialLinks(options?)` | Social media URLs |
148
+ | `getFaq(options?)` | FAQ grouped by category |
149
+ | `getServiceVariants(options?)` | Service pricing and variants |
129
150
  | `getInsuranceInfo()` | Accepted insurance providers |
130
151
  | `getFeatures()` | Practice features and amenities |
131
152
  | `getPaymentMethods()` | Accepted payment methods |
132
153
  | `getPolicyInfo()` | Practice policies |
133
- | `getBookableServices()` | Services available for online booking |
154
+ | `getBookableServices(options?)` | Services available for online booking |
134
155
  | `submitContactForm(body)` | Submit a contact form |
135
156
 
136
157
  ## Error Handling
package/dist/index.d.ts CHANGED
@@ -145,6 +145,92 @@ type Location = {
145
145
  */
146
146
  accessibility: string | null;
147
147
  } | null;
148
+ /**
149
+ * Practice locations ordered by display order, clamped to the API key location scope. Filter with ?location={slug} (unknown or out-of-scope slugs return 404).
150
+ */
151
+ type Locations = Array<PublicLocationDetail>;
152
+ /**
153
+ * One practice location: identity, address, contact, and weekly hours
154
+ */
155
+ type PublicLocationDetail = {
156
+ /**
157
+ * URL-safe location identifier — the value the `location` query parameter accepts on every public endpoint
158
+ */
159
+ slug: string;
160
+ /**
161
+ * Location display name (localized)
162
+ */
163
+ name: string;
164
+ /**
165
+ * Location kind (e.g. PHYSICAL, MOBILE, VIRTUAL)
166
+ */
167
+ kind: string;
168
+ /**
169
+ * Location phone number
170
+ */
171
+ phone: string;
172
+ /**
173
+ * WhatsApp contact number
174
+ */
175
+ whatsappPhone: string;
176
+ /**
177
+ * Location email address
178
+ */
179
+ email: string;
180
+ /**
181
+ * Street address
182
+ */
183
+ address: string;
184
+ /**
185
+ * City name
186
+ */
187
+ city: string;
188
+ /**
189
+ * Postal/ZIP code
190
+ */
191
+ postalCode: string;
192
+ /**
193
+ * Country name (localized)
194
+ */
195
+ country: string;
196
+ /**
197
+ * Complete formatted address
198
+ */
199
+ fullAddress: string;
200
+ /**
201
+ * GPS latitude coordinate
202
+ */
203
+ latitude: number | null;
204
+ /**
205
+ * GPS longitude coordinate
206
+ */
207
+ longitude: number | null;
208
+ /**
209
+ * Google Maps URL for this location
210
+ */
211
+ googleMapsUrl: string | null;
212
+ /**
213
+ * Parking information (localized)
214
+ */
215
+ parkingInfo: string | null;
216
+ /**
217
+ * Accessibility information (localized)
218
+ */
219
+ accessibility: string | null;
220
+ /**
221
+ * Weekly opening hours for this location
222
+ */
223
+ openingHours: {
224
+ /**
225
+ * Weekly schedule (7 entries)
226
+ */
227
+ schedule: Array<PublicDaySchedule>;
228
+ /**
229
+ * General note about opening hours
230
+ */
231
+ globalNote: string | null;
232
+ };
233
+ };
148
234
  /**
149
235
  * Practice business name
150
236
  */
@@ -715,30 +801,49 @@ interface PraxiumClientConfig {
715
801
  /** Locale for server-side content resolution */
716
802
  locale: ClientLocale;
717
803
  }
804
+ /**
805
+ * Options accepted by every location-aware read method.
806
+ *
807
+ * Multi-location practices expose each location under a stable slug
808
+ * (see `getLocations()` — the `slug` field of each entry). Passing
809
+ * `{ location: slug }` narrows the response to that location, within
810
+ * the location scope of your API key. An unknown or out-of-scope slug
811
+ * rejects with `PraxiumNotFoundError` (HTTP 404).
812
+ *
813
+ * Omitting the filter keeps the default behavior: the practice's main
814
+ * location for single-value endpoints (contact details, address,
815
+ * opening hours, social links), and the practice-wide data set for
816
+ * collections (team, FAQ, services, prices).
817
+ */
818
+ interface LocationFilterOptions {
819
+ /** Location slug (e.g., 'zuid') from `getLocations()`. */
820
+ location?: string;
821
+ }
718
822
  /** Shared methods available on both client types */
719
823
  interface PraxiumClientBase {
720
- getOpeningHours: () => Promise<OpeningHours>;
721
- getContactDetails: () => Promise<ContactDetails>;
722
- getLocation: () => Promise<Location>;
824
+ getOpeningHours: (options?: LocationFilterOptions) => Promise<OpeningHours>;
825
+ getContactDetails: (options?: LocationFilterOptions) => Promise<ContactDetails>;
826
+ getLocation: (options?: LocationFilterOptions) => Promise<Location>;
827
+ getLocations: (options?: LocationFilterOptions) => Promise<Locations>;
723
828
  getBusinessName: () => Promise<BusinessName>;
724
- getSocialLinks: () => Promise<SocialLinks>;
725
- getServiceVariants: () => Promise<PricingVariants>;
829
+ getSocialLinks: (options?: LocationFilterOptions) => Promise<SocialLinks>;
830
+ getServiceVariants: (options?: LocationFilterOptions) => Promise<PricingVariants>;
726
831
  getInsuranceInfo: () => Promise<InsuranceList>;
727
832
  getFeatures: () => Promise<FeatureList>;
728
833
  getPaymentMethods: () => Promise<PaymentMethodList>;
729
834
  getPolicyInfo: () => Promise<PolicyList>;
730
- getBookableServices: () => Promise<BookableServices>;
835
+ getBookableServices: (options?: LocationFilterOptions) => Promise<BookableServices>;
731
836
  submitContactForm: (body: SubmitContactFormData['body']) => Promise<ContactFormResult>;
732
837
  }
733
838
  /** Client for locale-specific responses (locale='nl', 'en', etc.) */
734
839
  interface PraxiumClient extends PraxiumClientBase {
735
- getFaq: () => Promise<FaqContent>;
736
- getTeamMembers: () => Promise<TeamMembers>;
840
+ getFaq: (options?: LocationFilterOptions) => Promise<FaqContent>;
841
+ getTeamMembers: (options?: LocationFilterOptions) => Promise<TeamMembers>;
737
842
  }
738
843
  /** Client for multilingual responses (locale='*') */
739
844
  interface MultilingualPraxiumClient extends PraxiumClientBase {
740
- getFaq: () => Promise<MultilingualFaqContent>;
741
- getTeamMembers: () => Promise<MultilingualTeamMember[]>;
845
+ getFaq: (options?: LocationFilterOptions) => Promise<MultilingualFaqContent>;
846
+ getTeamMembers: (options?: LocationFilterOptions) => Promise<MultilingualTeamMember[]>;
742
847
  }
743
848
  /** Multilingual mode: returns MultilingualTeamMember[] (use localizeText() helper for resolution) */
744
849
  declare function createPraxiumClient(config: PraxiumClientConfig & {
@@ -891,4 +996,4 @@ declare function getCustomField(member: MultilingualTeamMember, identifier: stri
891
996
  */
892
997
  declare function localizeText(text: MultilingualText | null | undefined, locale: SupportedLocale): string;
893
998
 
894
- export { API_KEY_PREFIX, API_KEY_PREFIX_WITH_SEPARATOR, API_KEY_SEPARATOR, type ApiError, type BilingualText, type BookableService, type BookableServices, type BookableVariantInfo, type BusinessName, type ClientLocale, type ContactDetails, type ContactFormResult, type CustomField, type FaqCategory, type FaqContent, type FaqGroup, type FaqItem, type FeatureItem, type FeatureList, type InsuranceInfo, type InsuranceList, type Location, type MultilingualCustomField, type MultilingualFaqCategory, type MultilingualFaqContent, type MultilingualFaqGroup, type MultilingualFaqItem, type MultilingualPraxiumClient, type MultilingualTeamMember, type MultilingualText, type OpeningHours, type PaymentMethod, type PaymentMethodList, type PolicyInfo, type PolicyList, PraxiumAuthError, type PraxiumClient, type PraxiumClientConfig, PraxiumError, PraxiumForbiddenError, PraxiumNotFoundError, PraxiumRateLimitError, PraxiumValidationError, type PricingVariant, type PricingVariants, type PublicDaySchedule, type PublicTeamMember, type ServiceCategoryInfo, type SocialLinks, type SupportedLocale, type TeamMembers, type ValidationDetail, createPraxiumClient, extractTenantSlugFromApiKey, getCustomField, getCustomFieldValue, localizeText };
999
+ export { API_KEY_PREFIX, API_KEY_PREFIX_WITH_SEPARATOR, API_KEY_SEPARATOR, type ApiError, type BilingualText, type BookableService, type BookableServices, type BookableVariantInfo, type BusinessName, type ClientLocale, type ContactDetails, type ContactFormResult, type CustomField, type FaqCategory, type FaqContent, type FaqGroup, type FaqItem, type FeatureItem, type FeatureList, type InsuranceInfo, type InsuranceList, type Location, type LocationFilterOptions, type Locations, type MultilingualCustomField, type MultilingualFaqCategory, type MultilingualFaqContent, type MultilingualFaqGroup, type MultilingualFaqItem, type MultilingualPraxiumClient, type MultilingualTeamMember, type MultilingualText, type OpeningHours, type PaymentMethod, type PaymentMethodList, type PolicyInfo, type PolicyList, PraxiumAuthError, type PraxiumClient, type PraxiumClientConfig, PraxiumError, PraxiumForbiddenError, PraxiumNotFoundError, PraxiumRateLimitError, PraxiumValidationError, type PricingVariant, type PricingVariants, type PublicDaySchedule, type PublicLocationDetail, type PublicTeamMember, type ServiceCategoryInfo, type SocialLinks, type SupportedLocale, type TeamMembers, type ValidationDetail, createPraxiumClient, extractTenantSlugFromApiKey, getCustomField, getCustomFieldValue, localizeText };
package/dist/index.js CHANGED
@@ -827,6 +827,11 @@ var getLocation = (options) => (options.client ?? client).get({
827
827
  url: "/api/{tenantSlug}/location",
828
828
  ...options
829
829
  });
830
+ var getLocations = (options) => (options.client ?? client).get({
831
+ security: [{ scheme: "bearer", type: "http" }],
832
+ url: "/api/{tenantSlug}/locations",
833
+ ...options
834
+ });
830
835
  var getBusinessName = (options) => (options.client ?? client).get({
831
836
  security: [{ scheme: "bearer", type: "http" }],
832
837
  url: "/api/{tenantSlug}/business",
@@ -973,34 +978,42 @@ function createPraxiumClient(config) {
973
978
  return request;
974
979
  });
975
980
  const path = { tenantSlug };
981
+ const baseRequest = { client: clientInstance, path };
982
+ const requestOptions = (options) => ({
983
+ ...baseRequest,
984
+ ...options?.location !== void 0 && {
985
+ query: { location: options.location }
986
+ }
987
+ });
976
988
  const baseMethods = {
977
989
  // ─── Layout Endpoints ───
978
- getOpeningHours: () => getOpeningHours({ client: clientInstance, path }).then(unwrapOrThrow),
979
- getContactDetails: () => getContactDetails({ client: clientInstance, path }).then(unwrapOrThrow),
980
- getLocation: () => getLocation({ client: clientInstance, path }).then(unwrapOrThrow),
981
- getBusinessName: () => getBusinessName({ client: clientInstance, path }).then(unwrapOrThrow),
982
- getSocialLinks: () => getSocialLinks({ client: clientInstance, path }).then(unwrapOrThrow),
990
+ getOpeningHours: (options) => getOpeningHours(requestOptions(options)).then(unwrapOrThrow),
991
+ getContactDetails: (options) => getContactDetails(requestOptions(options)).then(unwrapOrThrow),
992
+ getLocation: (options) => getLocation(requestOptions(options)).then(unwrapOrThrow),
993
+ getLocations: (options) => getLocations(requestOptions(options)).then(unwrapOrThrow),
994
+ getBusinessName: () => getBusinessName(baseRequest).then(unwrapOrThrow),
995
+ getSocialLinks: (options) => getSocialLinks(requestOptions(options)).then(unwrapOrThrow),
983
996
  // ─── Content Endpoints ───
984
- getServiceVariants: () => getServiceVariants({ client: clientInstance, path }).then(unwrapOrThrow),
985
- getInsuranceInfo: () => getInsuranceInfo({ client: clientInstance, path }).then(unwrapOrThrow),
986
- getFeatures: () => getFeatures({ client: clientInstance, path }).then(unwrapOrThrow),
987
- getPaymentMethods: () => getPaymentMethods({ client: clientInstance, path }).then(unwrapOrThrow),
988
- getPolicyInfo: () => getPolicyInfo({ client: clientInstance, path }).then(unwrapOrThrow),
989
- getBookableServices: () => getBookableServices({ client: clientInstance, path }).then(unwrapOrThrow),
997
+ getServiceVariants: (options) => getServiceVariants(requestOptions(options)).then(unwrapOrThrow),
998
+ getInsuranceInfo: () => getInsuranceInfo(baseRequest).then(unwrapOrThrow),
999
+ getFeatures: () => getFeatures(baseRequest).then(unwrapOrThrow),
1000
+ getPaymentMethods: () => getPaymentMethods(baseRequest).then(unwrapOrThrow),
1001
+ getPolicyInfo: () => getPolicyInfo(baseRequest).then(unwrapOrThrow),
1002
+ getBookableServices: (options) => getBookableServices(requestOptions(options)).then(unwrapOrThrow),
990
1003
  // ─── Contact Form ───
991
- submitContactForm: (body) => submitContactForm({ client: clientInstance, path, body }).then(unwrapOrThrow)
1004
+ submitContactForm: (body) => submitContactForm({ ...baseRequest, body }).then(unwrapOrThrow)
992
1005
  };
993
1006
  if (config.locale === "*") {
994
1007
  return {
995
1008
  ...baseMethods,
996
- getFaq: () => getFaq({ client: clientInstance, path }).then(unwrapOrThrow),
997
- getTeamMembers: () => getTeamMembers({ client: clientInstance, path }).then(unwrapOrThrow)
1009
+ getFaq: (options) => getFaq(requestOptions(options)).then(unwrapOrThrow),
1010
+ getTeamMembers: (options) => getTeamMembers(requestOptions(options)).then(unwrapOrThrow)
998
1011
  };
999
1012
  }
1000
1013
  return {
1001
1014
  ...baseMethods,
1002
- getFaq: () => getFaq({ client: clientInstance, path }).then(unwrapOrThrow),
1003
- getTeamMembers: () => getTeamMembers({ client: clientInstance, path }).then(unwrapOrThrow)
1015
+ getFaq: (options) => getFaq(requestOptions(options)).then(unwrapOrThrow),
1016
+ getTeamMembers: (options) => getTeamMembers(requestOptions(options)).then(unwrapOrThrow)
1004
1017
  };
1005
1018
  }
1006
1019
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@praxium/sdk",
3
- "version": "0.5.94",
3
+ "version": "0.6.97",
4
4
  "description": "Official TypeScript SDK for the Praxium platform API",
5
5
  "type": "module",
6
6
  "exports": {