@peektravel/app-utilities 0.9.2 → 0.9.3

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/dist/index.d.cts CHANGED
@@ -748,6 +748,11 @@ interface Booking {
748
748
  portalUrl: string | null;
749
749
  /** Operator notes on the booking (`""` when none). */
750
750
  notes: string;
751
+ /**
752
+ * Operator-facing custom status set on the booking (via
753
+ * {@link BookingService.updateCustomStatus}), or `null` when none is set.
754
+ */
755
+ customStatus: string | null;
751
756
  /** Total booking value, human-formatted (e.g. `"$75.00"`). `""` if absent. */
752
757
  valueDisplay: string;
753
758
  /** Total booking value as a numeric string. `""` if absent. */
@@ -899,6 +904,15 @@ interface CreateBookingInput {
899
904
  guest: CreateBookingGuest;
900
905
  /** Operator notes to attach. */
901
906
  operatorNotes?: string;
907
+ /**
908
+ * Total list price for the booking, as a positive number string (commas
909
+ * allowed — `"100"`, `"1,000"`, `"10.00"`). When set, it is split evenly
910
+ * across the booking's tickets (each of the first n-1 tickets gets
911
+ * `floor(total / n)`, the last ticket the remainder) and sent per ticket in
912
+ * the activity's currency (falling back to `"USD"`). Omit to let Peek price
913
+ * the tickets from the activity's configured pricing.
914
+ */
915
+ listPrice?: string;
902
916
  /**
903
917
  * Answers to the activity's custom questions. When non-empty, the activity's
904
918
  * custom questions are fetched and each answer is validated/resolved before
@@ -953,6 +967,206 @@ interface CreatedBooking {
953
967
  transactionId?: string;
954
968
  }
955
969
 
970
+ /**
971
+ * The clean, transport-agnostic data model for a booking's custom-field
972
+ * metadata (the booking's `fieldResponses`).
973
+ *
974
+ * Each {@link MetaData} entry flattens the field definition (id/name/slug/type),
975
+ * its prompt (label/hint/required), and the response `refid`, and carries a
976
+ * single typed {@link MetaDataValue} — a discriminated union (keyed by `kind`)
977
+ * mirroring the gateway's `FieldResponseValue` variants, so exactly one shape is
978
+ * present per entry and consumers narrow on `kind`.
979
+ */
980
+ /** Barcode symbology reported on a `kind: "barcode"` metadata value. */
981
+ type MetaDataBarcodeType = "BARCODE_CODE128" | "BARCODE_CODE39" | "DATA_MATRIX" | "EAN_13" | "ITF" | "QR_CODE" | "TEXT" | "UPC";
982
+ /** Time unit reported on a `kind: "duration"` metadata value. */
983
+ type MetaDataDurationUnit = "SECONDS" | "MINUTES" | "HOURS" | "DAYS" | "WEEKS" | "MONTHS" | "YEARS";
984
+ /** Mass unit reported on a `kind: "weight"` metadata value. */
985
+ type MetaDataWeightUnit = "KILOGRAM" | "POUND" | "STONE";
986
+ /** Volume unit reported on a `kind: "volume"` metadata value. */
987
+ type MetaDataVolumeUnit = "GALLON";
988
+ /**
989
+ * A booking custom-field response value — a discriminated union keyed by `kind`,
990
+ * one variant per gateway `…FieldResponseValue` type. Numeric `Int` values are
991
+ * `number`; `Decimal` values are kept as strings to avoid float-precision loss;
992
+ * `Date`/`Time` values are ISO strings.
993
+ *
994
+ * Every variant also carries a `displayValue` — a human-readable, display-safe
995
+ * string rendering of the value (empty when the underlying value is absent). The
996
+ * `html` variant's `displayValue` is HTML-escaped so it is safe to render as
997
+ * text.
998
+ */
999
+ type MetaDataValue = {
1000
+ kind: "age";
1001
+ age: number;
1002
+ displayValue: string;
1003
+ } | {
1004
+ kind: "attachment";
1005
+ attachmentUrl: string;
1006
+ mime: string | null;
1007
+ name: string | null;
1008
+ size: number | null;
1009
+ displayValue: string;
1010
+ } | {
1011
+ kind: "barcode";
1012
+ barcodeType: MetaDataBarcodeType | null;
1013
+ barcodeValue: string;
1014
+ displayValue: string;
1015
+ } | {
1016
+ kind: "boolean";
1017
+ boolean: boolean;
1018
+ displayValue: string;
1019
+ } | {
1020
+ kind: "checkbox";
1021
+ isChecked: boolean;
1022
+ displayValue: string;
1023
+ } | {
1024
+ kind: "currency";
1025
+ currency: string;
1026
+ displayValue: string;
1027
+ } | {
1028
+ kind: "date";
1029
+ date: string;
1030
+ displayValue: string;
1031
+ } | {
1032
+ kind: "decimal";
1033
+ decimal: string | null;
1034
+ displayValue: string;
1035
+ } | {
1036
+ kind: "duration";
1037
+ amount: number;
1038
+ unit: MetaDataDurationUnit | null;
1039
+ displayValue: string;
1040
+ } | {
1041
+ kind: "email";
1042
+ email: string | null;
1043
+ displayValue: string;
1044
+ } | {
1045
+ kind: "guest";
1046
+ name: string | null;
1047
+ email: string | null;
1048
+ dateOfBirth: string | null;
1049
+ notes: string | null;
1050
+ waiverSigned: boolean | null;
1051
+ displayValue: string;
1052
+ } | {
1053
+ kind: "html";
1054
+ html: string;
1055
+ displayValue: string;
1056
+ } | {
1057
+ kind: "imageUrl";
1058
+ imageUrl: string;
1059
+ displayValue: string;
1060
+ } | {
1061
+ kind: "integer";
1062
+ integer: number;
1063
+ displayValue: string;
1064
+ } | {
1065
+ kind: "location";
1066
+ country: string | null;
1067
+ county: string | null;
1068
+ locality: string | null;
1069
+ postalCode: string | null;
1070
+ region: string | null;
1071
+ streetAddress: string | null;
1072
+ displayValue: string;
1073
+ } | {
1074
+ kind: "longText";
1075
+ longText: string;
1076
+ displayValue: string;
1077
+ } | {
1078
+ kind: "meta";
1079
+ meta: unknown;
1080
+ displayValue: string;
1081
+ } | {
1082
+ kind: "percent";
1083
+ percent: string | null;
1084
+ displayValue: string;
1085
+ } | {
1086
+ kind: "phone";
1087
+ phone: string;
1088
+ displayValue: string;
1089
+ } | {
1090
+ kind: "shortText";
1091
+ shortText: string;
1092
+ displayValue: string;
1093
+ } | {
1094
+ kind: "time";
1095
+ time: string;
1096
+ displayValue: string;
1097
+ } | {
1098
+ kind: "url";
1099
+ url: string | null;
1100
+ displayValue: string;
1101
+ } | {
1102
+ kind: "volume";
1103
+ amount: string;
1104
+ unit: MetaDataVolumeUnit | null;
1105
+ displayValue: string;
1106
+ } | {
1107
+ kind: "weight";
1108
+ amount: string;
1109
+ unit: MetaDataWeightUnit | null;
1110
+ displayValue: string;
1111
+ };
1112
+ /** A single booking custom-field response (one `fieldResponse`). */
1113
+ interface MetaData {
1114
+ /** Field definition id. */
1115
+ id: string;
1116
+ /** Field name (human label). */
1117
+ name: string;
1118
+ /**
1119
+ * Field slug. When an `integrator` filter is applied, the matched
1120
+ * `integrator:<integrator>:` prefix is stripped off (e.g.
1121
+ * `integrator:bob:booking_url` → `booking_url`).
1122
+ */
1123
+ slug: string;
1124
+ /** Raw field type reported by the gateway (kept as a string). */
1125
+ type: string;
1126
+ /** Prompt label shown for the field, or `null` when the field has no prompt. */
1127
+ prompt: string | null;
1128
+ /** Prompt hint text, or `null`. */
1129
+ promptHint: string | null;
1130
+ /** Whether the field is required (`false` when the field has no prompt). */
1131
+ isRequired: boolean;
1132
+ /** The response's reference id. */
1133
+ refid: string;
1134
+ /**
1135
+ * The typed response value, or `null` when absent or of an unrecognized
1136
+ * (future) variant.
1137
+ */
1138
+ value: MetaDataValue | null;
1139
+ }
1140
+ /** A guest entry for `BookingService.setMetaDataGuest`. */
1141
+ interface SetMetaDataGuestInput {
1142
+ /** Guest name (required). */
1143
+ name: string;
1144
+ /** Guest email (required). */
1145
+ email: string;
1146
+ /** Date of birth as an ISO date (e.g. `"2010-06-21"`). */
1147
+ dateOfBirth?: string;
1148
+ /** Whether the guest signed the waiver. */
1149
+ waiverSigned?: boolean;
1150
+ /** Free-text notes. */
1151
+ notes?: string;
1152
+ }
1153
+ /** An attachment entry for `BookingService.setMetaDataAttachment`. */
1154
+ interface SetMetaDataAttachmentInput {
1155
+ /** Display name for the attachment (required). */
1156
+ name: string;
1157
+ /** URL of the attachment (required). */
1158
+ attachmentUrl: string;
1159
+ }
1160
+ /** The result of a `setMetaData…` write. */
1161
+ interface SetMetaDataResult {
1162
+ /** Whether the gateway reported the upsert succeeded. */
1163
+ success: boolean;
1164
+ /** The booking id echoed back (falls back to the requested id). */
1165
+ bookingId: string;
1166
+ /** The gateway's success or error message (`""` when none). */
1167
+ message: string;
1168
+ }
1169
+
956
1170
  /**
957
1171
  * The clean data model for a booking's payments on file.
958
1172
  */
@@ -1129,6 +1343,12 @@ interface BookingServiceOptions {
1129
1343
  pageSize?: number;
1130
1344
  /** Cross-cutting access options (PII exposure). Default: PII off. */
1131
1345
  accessOptions?: AccessOptions;
1346
+ /**
1347
+ * Integrator id used to scope `getMetaData` results — only fields whose slug
1348
+ * starts with `integrator:<integrator>:` are returned. Defaults to `""` (set
1349
+ * by the access service to the install's issuer).
1350
+ */
1351
+ integrator?: string;
1132
1352
  }
1133
1353
  /** Dependencies the {@link BookingService} composes for add-on resolution. */
1134
1354
  interface BookingServiceDeps {
@@ -1152,6 +1372,8 @@ declare class BookingService {
1152
1372
  private readonly pageSize;
1153
1373
  /** Whether customer PII is requested and payment operations are allowed. */
1154
1374
  private readonly fullCustomerAccess;
1375
+ /** Integrator id scoping `getMetaData` results. */
1376
+ private readonly integrator;
1155
1377
  constructor(client: GraphQLClient, deps: BookingServiceDeps, options?: BookingServiceOptions);
1156
1378
  /**
1157
1379
  * Throws a {@link PiiAccessDisabledError} for `operation` when this service was
@@ -1181,6 +1403,51 @@ declare class BookingService {
1181
1403
  searchByTimeslot(timeslotId: string, options?: BookingReadOptions): Promise<Booking[]>;
1182
1404
  /** Returns the guests on a booking (primary guest included). */
1183
1405
  getGuests(bookingId: string): Promise<Guest[]>;
1406
+ /**
1407
+ * Returns a booking's custom-field metadata (its `fieldResponses`), scoped to
1408
+ * this service's integrator. Only fields whose slug starts with
1409
+ * `integrator:<integrator>:` are returned, and that prefix is stripped from
1410
+ * each returned `slug`. Returns `[]` when the booking is not found or has no
1411
+ * matching fields.
1412
+ *
1413
+ * @example
1414
+ * ```ts
1415
+ * const meta = await peek.getBookingService().getMetaData("b_abc123");
1416
+ * for (const field of meta) {
1417
+ * if (field.value?.kind === "url") console.log(field.slug, field.value.url);
1418
+ * }
1419
+ * ```
1420
+ */
1421
+ getMetaData(bookingId: string): Promise<MetaData[]>;
1422
+ /**
1423
+ * Sets the booking's `guest` metadata field. Each guest requires a `name` and
1424
+ * `email`; `dateOfBirth`/`waiverSigned`/`notes` are optional.
1425
+ */
1426
+ setMetaDataGuest(bookingId: string, guests: SetMetaDataGuestInput[]): Promise<SetMetaDataResult>;
1427
+ /**
1428
+ * Sets the booking's `attachment` metadata field. Each attachment requires a
1429
+ * `name` and `attachmentUrl`.
1430
+ */
1431
+ setMetaDataAttachment(bookingId: string, attachments: SetMetaDataAttachmentInput[]): Promise<SetMetaDataResult>;
1432
+ /** Sets the booking's `manifest_url` metadata field. */
1433
+ setMetaDataManifestUrl(bookingId: string, url: string): Promise<SetMetaDataResult>;
1434
+ /** Sets the booking's `reservation_id` metadata field. */
1435
+ setMetaDataReservationId(bookingId: string, reservationId: string): Promise<SetMetaDataResult>;
1436
+ /** Sets the booking's `booking_status` metadata field. */
1437
+ setMetaDataBookingStatus(bookingId: string, status: string): Promise<SetMetaDataResult>;
1438
+ /** Sets the booking's `assigned_product` metadata field. */
1439
+ setMetaDataAssignedProduct(bookingId: string, productName: string): Promise<SetMetaDataResult>;
1440
+ /** Sets the booking's `assigned_employee` metadata field. */
1441
+ setMetaDataAssignedEmployee(bookingId: string, employeeName: string): Promise<SetMetaDataResult>;
1442
+ /** Sets the booking's `insurance_purchased` metadata field. */
1443
+ setMetaDataInsurancePurchased(bookingId: string, insurancePurchased: boolean): Promise<SetMetaDataResult>;
1444
+ /** Validates a non-empty `shortText` value and upserts it under `fieldName`. */
1445
+ private setShortTextField;
1446
+ /**
1447
+ * Validates the booking id and upserts a single field response (scoped to this
1448
+ * service's integrator), mapping the result union into a {@link SetMetaDataResult}.
1449
+ */
1450
+ private upsertFieldResponse;
1184
1451
  /** Returns the payments on file for a booking, or null when not found. */
1185
1452
  getPaymentsOnFile(bookingId: string): Promise<BookingPaymentsOnFile | null>;
1186
1453
  /**
@@ -1193,6 +1460,20 @@ declare class BookingService {
1193
1460
  * when not found.
1194
1461
  */
1195
1462
  setCheckinStatus(bookingId: string, checkedIn: boolean): Promise<Booking | null>;
1463
+ /**
1464
+ * Sets a booking's operator-facing custom status. Returns `true` when the
1465
+ * gateway confirms the stored `operatorStatus` equals the requested
1466
+ * `customStatus`, `false` otherwise.
1467
+ *
1468
+ * @example
1469
+ * ```ts
1470
+ * const ok = await peek.getBookingService().updateCustomStatus("b_abc123", "Awaiting deposit");
1471
+ * ```
1472
+ *
1473
+ * @throws {Error} when `bookingId` is not a valid booking id (`b_…`/`B-…`) or
1474
+ * when `customStatus` is not a non-empty string.
1475
+ */
1476
+ updateCustomStatus(bookingId: string, customStatus: string): Promise<boolean>;
1196
1477
  /** Cancels a booking and returns its id/displayId/status. */
1197
1478
  cancel(bookingId: string, notes?: string): Promise<CancelBookingResult>;
1198
1479
  /**
@@ -1311,6 +1592,11 @@ declare class BookingService {
1311
1592
  */
1312
1593
  private buildQuestionAnswers;
1313
1594
  private markCreatedBookingPaid;
1595
+ /**
1596
+ * Resolves an activity's ISO currency via the product service, falling back to
1597
+ * {@link DEFAULT_CURRENCY} when the activity (or its currency) can't be found.
1598
+ */
1599
+ private resolveActivityCurrency;
1314
1600
  /** Finds the parent item id of an add-on by matching its option id. */
1315
1601
  private resolveParentItemId;
1316
1602
  private validatePaymentInput;
@@ -2146,6 +2432,7 @@ declare class PeekAccessService {
2146
2432
  private readonly productServiceOptions;
2147
2433
  private readonly accessOptions;
2148
2434
  private readonly jwtSecret;
2435
+ private readonly issuer;
2149
2436
  private productService?;
2150
2437
  private accountUserService?;
2151
2438
  private resourcePoolService?;
@@ -2156,7 +2443,7 @@ declare class PeekAccessService {
2156
2443
  private dailyNoteService?;
2157
2444
  private availabilityService?;
2158
2445
  private membershipService?;
2159
- private bookingService?;
2446
+ private readonly bookingServices;
2160
2447
  private reviewService?;
2161
2448
  constructor(config: PeekAccessServiceConfig);
2162
2449
  /**
@@ -2237,9 +2524,14 @@ declare class PeekAccessService {
2237
2524
  getMembershipService(): MembershipService;
2238
2525
  /**
2239
2526
  * Returns the {@link BookingService} for this install, bound to the shared
2240
- * authenticated transport. The instance is created lazily and reused.
2527
+ * authenticated transport. Instances are created lazily and reused per
2528
+ * `integrator`.
2529
+ *
2530
+ * `integrator` scopes `getMetaData` results to a custom integrator id. **Do
2531
+ * not set it** unless Peek engineering created a custom integrator id for this
2532
+ * integration — omit it and the correct default is used.
2241
2533
  */
2242
- getBookingService(): BookingService;
2534
+ getBookingService(integrator?: string): BookingService;
2243
2535
  /**
2244
2536
  * Returns the {@link ReviewService} for this install, bound to the shared
2245
2537
  * authenticated transport. The instance is created lazily and reused.
@@ -3043,4 +3335,4 @@ declare class AcmeApiError extends Error {
3043
3335
  constructor(statusCode: number, body: unknown, message?: string);
3044
3336
  }
3045
3337
 
3046
- export { ACTIVITY_PRODUCT_TYPE, ADD_ON_PRODUCT_TYPE, type AccessOptions, type AccountUser, AccountUserService, type AccountUserServiceOptions, AcmeAccessService, type AcmeAccessServiceConfig, type AcmeActivity, type AcmeActivityTicket, AcmeApiError, AcmeProductService, type Activity, type ActivityOverrides, type ActivityTicket, type AddAddonInput, AdminAccountRequiredError, type Agent, type AssignGuideResult, type AssignedActivity, type AssignedResource, type Availability, AvailabilityService, type AvailabilityTime, type AvailabilityTimesQuery, type Booking, type BookingAddon, type BookingAddonMoney, type BookingAddonOption, type BookingAddons, type BookingAddonsMutationResult, type BookingPaymentsOnFile, type BookingReadOptions, type BookingSearchBy, BookingService, type BookingServiceOptions, type BookingTimeRangeSearch, type CancelBookingResult, type Channel, type ClearOverridesInput, CngAccessService, type CngAccessServiceConfig, CngApiError, CngPermissionError, CngProductService, type CreateBookingGuest, type CreateBookingInput, type CreateBookingTicket, type CreateEngineInput, type CreatePromoCodeInput, type CreatedBooking, type CreatedPricingEngine, type CreatedPromoCode, type CustomQuestion, type CustomQuestionAnswer, type CustomQuestionAnswerInput, type CustomQuestionOption, type DailyNote, DailyNoteService, type Duration, type Guest, type GuestMetadata, type Guide, type GuideAssignment, INSTALL_STATUSES, type InstallAccessConfig, type InstallAccessService, type InstallAccessTarget, type InstallStatus, type InstallWebhook, type InstallWebhookAccount, type InstallWebhookClaims, type InvoiceLinkResult, type Logger, type MakePaymentInput, type MakePaymentResult, type Membership, type MembershipPurchaseInput, MembershipService, type NoteMode, type Payment, type PaymentSource, PeekAccessService, type PeekAccessServiceConfig, type PeekAuthTokenClaims, type PeekAuthTokenUser, PeekGraphQLError, PeekHttpError, type PeekPlatform, PiiAccessDisabledError, type Price, type PricingActivityContext, type PricingEngine, type PricingMoney, type PricingNamedRef, type PricingOverride, type PricingOverrideFilter, PricingService, type Product, type ProductMeetingLocation, type ProductReviewSummary, ProductService, type ProductServiceOptions, type ProductTicket, type PromoCode, type PromoCodeFixedAmount, PromoCodeService, type PromoCodeServiceOptions, type PurchasedMembership, RENTAL_PRODUCT_TYPE, RateLimitError, type RefundInput, type RefundResult, ResellerService, type ResolvedOverride, type ResolvedPricingOverride, type ResolvedResourceOption, type Resource, type ResourceOptionOverride, type ResourceOptionQuantity, type ResourcePool, type ResourcePoolAccountUser, type ResourcePoolAssignment, type ResourcePoolMode, ResourcePoolService, type Review, ReviewService, type Ticket, type Timeslot, type TimeslotFilter, TimeslotService, type UpdateEngineInput, type UpdateTimeslotResult, type UpsertOverridesInput, type UpsertOverridesResult, type Waiver, createAccessServiceForInstall, noopLogger, parseBookingWebhook, parseInstallWebhook, parseWaiverWebhook, verifyInstallWebhook };
3338
+ export { ACTIVITY_PRODUCT_TYPE, ADD_ON_PRODUCT_TYPE, type AccessOptions, type AccountUser, AccountUserService, type AccountUserServiceOptions, AcmeAccessService, type AcmeAccessServiceConfig, type AcmeActivity, type AcmeActivityTicket, AcmeApiError, AcmeProductService, type Activity, type ActivityOverrides, type ActivityTicket, type AddAddonInput, AdminAccountRequiredError, type Agent, type AssignGuideResult, type AssignedActivity, type AssignedResource, type Availability, AvailabilityService, type AvailabilityTime, type AvailabilityTimesQuery, type Booking, type BookingAddon, type BookingAddonMoney, type BookingAddonOption, type BookingAddons, type BookingAddonsMutationResult, type BookingPaymentsOnFile, type BookingReadOptions, type BookingSearchBy, BookingService, type BookingServiceOptions, type BookingTimeRangeSearch, type CancelBookingResult, type Channel, type ClearOverridesInput, CngAccessService, type CngAccessServiceConfig, CngApiError, CngPermissionError, CngProductService, type CreateBookingGuest, type CreateBookingInput, type CreateBookingTicket, type CreateEngineInput, type CreatePromoCodeInput, type CreatedBooking, type CreatedPricingEngine, type CreatedPromoCode, type CustomQuestion, type CustomQuestionAnswer, type CustomQuestionAnswerInput, type CustomQuestionOption, type DailyNote, DailyNoteService, type Duration, type Guest, type GuestMetadata, type Guide, type GuideAssignment, INSTALL_STATUSES, type InstallAccessConfig, type InstallAccessService, type InstallAccessTarget, type InstallStatus, type InstallWebhook, type InstallWebhookAccount, type InstallWebhookClaims, type InvoiceLinkResult, type Logger, type MakePaymentInput, type MakePaymentResult, type Membership, type MembershipPurchaseInput, MembershipService, type MetaData, type MetaDataBarcodeType, type MetaDataDurationUnit, type MetaDataValue, type MetaDataVolumeUnit, type MetaDataWeightUnit, type NoteMode, type Payment, type PaymentSource, PeekAccessService, type PeekAccessServiceConfig, type PeekAuthTokenClaims, type PeekAuthTokenUser, PeekGraphQLError, PeekHttpError, type PeekPlatform, PiiAccessDisabledError, type Price, type PricingActivityContext, type PricingEngine, type PricingMoney, type PricingNamedRef, type PricingOverride, type PricingOverrideFilter, PricingService, type Product, type ProductMeetingLocation, type ProductReviewSummary, ProductService, type ProductServiceOptions, type ProductTicket, type PromoCode, type PromoCodeFixedAmount, PromoCodeService, type PromoCodeServiceOptions, type PurchasedMembership, RENTAL_PRODUCT_TYPE, RateLimitError, type RefundInput, type RefundResult, ResellerService, type ResolvedOverride, type ResolvedPricingOverride, type ResolvedResourceOption, type Resource, type ResourceOptionOverride, type ResourceOptionQuantity, type ResourcePool, type ResourcePoolAccountUser, type ResourcePoolAssignment, type ResourcePoolMode, ResourcePoolService, type Review, ReviewService, type SetMetaDataAttachmentInput, type SetMetaDataGuestInput, type SetMetaDataResult, type Ticket, type Timeslot, type TimeslotFilter, TimeslotService, type UpdateEngineInput, type UpdateTimeslotResult, type UpsertOverridesInput, type UpsertOverridesResult, type Waiver, createAccessServiceForInstall, noopLogger, parseBookingWebhook, parseInstallWebhook, parseWaiverWebhook, verifyInstallWebhook };