@medalsocial/sdk 1.8.0 → 1.10.0

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.
@@ -635,6 +635,20 @@ type BookingStatus = "pending" | "confirmed" | "completed" | "cancelled" | "no_s
635
635
  type BookingCancelledBy = "customer" | "staff" | "system";
636
636
  /** Payment state of a booking. */
637
637
  type BookingPaymentStatus = "none" | "reserved" | "captured" | "refunded";
638
+ /**
639
+ * What a booking must have paid before the business honours it: nothing, a
640
+ * reservation taken at booking time and captured later, or the full amount up
641
+ * front.
642
+ */
643
+ type BookingPaymentMode = "none" | "reserve" | "prepay";
644
+ /**
645
+ * The state of one attempt at paying for a booking.
646
+ *
647
+ * This is Medal's vocabulary, not the wallet's — a Vipps payment stays
648
+ * `AUTHORIZED` after a capture, so read the øre aggregates on
649
+ * {@link BookingPayment} to learn what actually moved.
650
+ */
651
+ type BookingPaymentState = "created" | "authorized" | "captured" | "cancelled" | "refunded" | "failed" | "expired";
638
652
  /** Surface a booking was created through. API-created bookings are `api`. */
639
653
  type BookingCreatedVia = "web" | "dashboard" | "walk_in" | "api";
640
654
  /** Kind of bookable resource a booking lands on. */
@@ -655,6 +669,12 @@ interface Booking {
655
669
  booked_for_name: string | null;
656
670
  /** Birth year (not a birthdate) of whoever the appointment is for. */
657
671
  booked_for_birth_year: number | null;
672
+ /** The {@link ContactPerson} this booking was made for, if any. */
673
+ booked_for_person_id: string | null;
674
+ /** The {@link BookingEvent} this booking is a registration for, if any. */
675
+ event_id: string | null;
676
+ /** Position of this booking within its event's registrations, if any. */
677
+ event_order: number | null;
658
678
  /** Shared by every booking created in the same party request. */
659
679
  party_sequence_id: string | null;
660
680
  status: BookingStatus;
@@ -663,6 +683,13 @@ interface Booking {
663
683
  /** Set on the booking a reschedule created, pointing at the one it replaced. */
664
684
  rescheduled_from_id: string | null;
665
685
  payment_status: BookingPaymentStatus;
686
+ /**
687
+ * What this booking required when it was made — frozen at creation, so
688
+ * changing the workspace or service rule later does not rewrite history.
689
+ * `payment_status` alone cannot tell "owes nothing" from "has not paid yet";
690
+ * this is the field that does.
691
+ */
692
+ payment_mode: BookingPaymentMode;
666
693
  /** Price in integer øre. */
667
694
  amount_ore: number | null;
668
695
  /** Customer-visible note. */
@@ -688,6 +715,11 @@ interface BookingService {
688
715
  /** Resource types this service needs, e.g. `["staff"]`. */
689
716
  resource_requirements: string[];
690
717
  bookable_online: boolean;
718
+ /**
719
+ * Per-service payment requirement. `null` means "no override" — the
720
+ * workspace rule decides.
721
+ */
722
+ payment: BookingPaymentMode | null;
691
723
  max_per_booking: number | null;
692
724
  color: string | null;
693
725
  sort_order: number | null;
@@ -740,6 +772,8 @@ interface CreateBookingItemInput {
740
772
  booked_for_name?: string;
741
773
  /** Birth year (not a birthdate) of whoever the appointment is for. */
742
774
  booked_for_birth_year?: number;
775
+ /** Book this line on behalf of a {@link ContactPerson} rather than the contact. */
776
+ booked_for_person_id?: string;
743
777
  }
744
778
  /** The person the booking is made under. Phone is the CRM dedupe key. */
745
779
  interface BookingContactInput {
@@ -829,6 +863,12 @@ interface ManageSummary {
829
863
  /** Price in integer øre. */
830
864
  amount_ore: number | null;
831
865
  payment_status: BookingPaymentStatus | null;
866
+ /**
867
+ * What this booking requires. `payment_status: "none"` is the same answer
868
+ * for a booking that owes nothing and one that has not paid yet, so this is
869
+ * what a manage page checks before offering «Betal nå».
870
+ */
871
+ payment_mode: BookingPaymentMode;
832
872
  /** IANA zone the booking's local times should be rendered in. */
833
873
  time_zone: string | null;
834
874
  cancel_window_hours: number | null;
@@ -866,6 +906,78 @@ interface RescheduleBookingInput {
866
906
  new_start_ts: BookingTimestampInput;
867
907
  new_resource_id?: string;
868
908
  }
909
+ /**
910
+ * One payment attempt on a booking.
911
+ *
912
+ * Money is integer øre, and the four aggregates are numbers rather than nulls:
913
+ * "nothing has been captured" is `0`, so summing them never needs a null
914
+ * guard. `redirect_url` is deliberately absent — it is handed over once by
915
+ * {@link BookingPaymentStart} and never re-read.
916
+ */
917
+ interface BookingPayment {
918
+ reference: string;
919
+ provider: "vipps";
920
+ state: BookingPaymentState;
921
+ mode: Exclude<BookingPaymentMode, "none">;
922
+ /** 1 for the first attempt on this booking, incrementing per retry. */
923
+ attempt: number;
924
+ /** The amount the attempt is for, in integer øre. */
925
+ amount_ore: number;
926
+ authorized_ore: number;
927
+ captured_ore: number;
928
+ refunded_ore: number;
929
+ cancelled_ore: number;
930
+ currency: "NOK";
931
+ /**
932
+ * The last moment a capture is GUARANTEED to succeed. The card behind the
933
+ * wallet may release the reservation after this, so a capture past it can
934
+ * fail even though the payment still looks authorized. Null until the
935
+ * customer has approved.
936
+ */
937
+ capture_guaranteed_until: string | null;
938
+ terms_version: string | null;
939
+ terms_accepted_at: string | null;
940
+ /**
941
+ * The wallet's numeric error code from the last failed operation. Branch on
942
+ * this; the human-readable reason and the trace id stay in Medal's own logs.
943
+ */
944
+ failure_code: string | null;
945
+ created_at: string | null;
946
+ updated_at: string | null;
947
+ }
948
+ /** What `payment.start(...)` hands back. The redirect URL is shown ONCE. */
949
+ interface BookingPaymentStart {
950
+ reference: string;
951
+ /**
952
+ * Send the customer here UNCHANGED — hand it to the Vipps Widget SDK, do not
953
+ * put it in an iframe of your own and do not rewrite it. It is not returned
954
+ * again by `payment.get(...)`: the payment behind it expires after ten
955
+ * minutes, so a cached redirect leads into a payment that no longer exists.
956
+ * Start a new attempt instead of caching this.
957
+ */
958
+ redirect_url: string;
959
+ state: BookingPaymentState;
960
+ }
961
+ /** Input for `bookings.payment.start(...)` and its manage-token twin. */
962
+ interface StartBookingPaymentInput {
963
+ /**
964
+ * Where the wallet returns the customer. Must be a URL one of your own sites
965
+ * vouches for — anything else is refused with 422, not 400: the URL is
966
+ * well-formed, it is just not yours.
967
+ */
968
+ return_url: string;
969
+ /**
970
+ * REQUIRED, and must be `true`. The customer has to actively accept your
971
+ * terms BEFORE a payment is initiated — sending them to a payment link with
972
+ * no acceptance step makes the integration non-compliant, so the API refuses
973
+ * a body that omits it or sends `false` with a 400.
974
+ */
975
+ terms_accepted: true;
976
+ /** Your own version label for the terms they accepted. */
977
+ terms_version?: string;
978
+ /** The exact text they accepted, stored with the consent record. */
979
+ terms_text?: string;
980
+ }
869
981
  /**
870
982
  * Pagination for a bookings page.
871
983
  *
@@ -918,7 +1030,170 @@ interface BookingAvailabilityOptions {
918
1030
  /** Restrict slots to one resource. Defaults to every capable resource. */
919
1031
  resource_id?: string;
920
1032
  }
1033
+ /** How a {@link ContactPerson} or {@link ContactRelation} relates to a contact. */
1034
+ type RelationType = "guardian" | "owner" | "employer" | "caregiver" | "partner" | "custom";
1035
+ /** A person a contact books for — a child, a pet, an employee. No login of its own. */
1036
+ interface ContactPerson {
1037
+ person_id: string;
1038
+ contact_id: string;
1039
+ name: string;
1040
+ birth_year: number | null;
1041
+ relation_type: RelationType;
1042
+ relation_label: string | null;
1043
+ notes: string | null;
1044
+ active: boolean;
1045
+ promoted_to_contact_id: string | null;
1046
+ /** ISO 8601. */
1047
+ created_at: string;
1048
+ /** ISO 8601. */
1049
+ updated_at: string;
1050
+ }
1051
+ /** Input for `bookings.persons.create(...)`. */
1052
+ interface CreateContactPersonInput {
1053
+ contact_id: string;
1054
+ name: string;
1055
+ birth_year?: number;
1056
+ relation_type: RelationType;
1057
+ relation_label?: string;
1058
+ notes?: string;
1059
+ }
1060
+ /** One directional relation between two contacts. */
1061
+ interface ContactRelation {
1062
+ relation_id: string;
1063
+ from_contact_id: string;
1064
+ to_contact_id: string;
1065
+ type: RelationType;
1066
+ custom_label: string | null;
1067
+ since: number | null;
1068
+ note: string | null;
1069
+ /** Empty string when the counterpart contact no longer exists. */
1070
+ counterpart_name: string;
1071
+ /** ISO 8601. */
1072
+ created_at: string;
1073
+ }
1074
+ /** Relations a contact holds, split by direction. */
1075
+ interface ContactRelations {
1076
+ outgoing: ContactRelation[];
1077
+ incoming: ContactRelation[];
1078
+ }
1079
+ /** Input for `bookings.relations.create(...)`. */
1080
+ interface CreateContactRelationInput {
1081
+ from_contact_id: string;
1082
+ to_contact_id: string;
1083
+ type: RelationType;
1084
+ custom_label?: string;
1085
+ since?: number;
1086
+ note?: string;
1087
+ }
1088
+ /** Result of `bookings.relations.create(...)`. */
1089
+ interface CreateContactRelationResult {
1090
+ relation_id: string;
1091
+ }
1092
+ /** Lifecycle state of an arrangement. */
1093
+ type BookingEventStatus = "draft" | "open" | "closed" | "completed" | "cancelled";
1094
+ /** Which prebuilt template an arrangement was created from. */
1095
+ type BookingEventTemplateKey = "kindergarten_visit" | "company_day" | "class" | "open_day" | "custom";
1096
+ /** An arrangement — a scheduled group session bookings register against. */
1097
+ interface BookingEvent {
1098
+ event_id: string;
1099
+ template_id: string;
1100
+ host_id: string | null;
1101
+ /** yyyy-mm-dd in the workspace time zone. */
1102
+ date: string;
1103
+ window_start_minute: number;
1104
+ window_end_minute: number;
1105
+ place: "at_host" | "in_house";
1106
+ capacity: number;
1107
+ minimum: number;
1108
+ registered_count: number;
1109
+ service_ids: string[];
1110
+ resource_ids: string[];
1111
+ price_override_ore: number | null;
1112
+ status: BookingEventStatus;
1113
+ /** ISO 8601. */
1114
+ registration_closes_at: string;
1115
+ slug: string;
1116
+ /** ISO 8601. */
1117
+ created_at: string;
1118
+ /** ISO 8601. */
1119
+ updated_at: string;
1120
+ }
1121
+ /** Options for `bookings.events.list(...)`. The window is `yyyy-mm-dd`, inclusive. */
1122
+ interface ListBookingEventsOptions {
1123
+ from: string;
1124
+ to: string;
1125
+ status?: BookingEventStatus;
1126
+ }
1127
+ /** Input for `bookings.events.create(...)`. */
1128
+ interface CreateBookingEventInput {
1129
+ template_key: BookingEventTemplateKey;
1130
+ host_id?: string;
1131
+ date: string;
1132
+ window_start_minute: number;
1133
+ window_end_minute?: number;
1134
+ place: "at_host" | "in_house";
1135
+ capacity?: number;
1136
+ minimum?: number;
1137
+ service_ids: string[];
1138
+ resource_ids: string[];
1139
+ }
921
1140
 
1141
+ /**
1142
+ * Payments on a booking addressed by BOOKING ID — the business starting or
1143
+ * inspecting a payment for one of its own bookings.
1144
+ *
1145
+ * The outcome reaches your system through Medal, never through the browser: a
1146
+ * customer can close the tab, hit back, or edit the return URL, so treat the
1147
+ * return redirect as a hint to re-read and nothing more. Poll {@link get} on
1148
+ * your return page, or read the booking's `payment_status`.
1149
+ *
1150
+ * @example
1151
+ * ```ts
1152
+ * const { data } = await medal.bookings.payment.start("bk_1", {
1153
+ * return_url: "https://example.no/retur",
1154
+ * terms_accepted: true,
1155
+ * });
1156
+ * // Hand data.redirect_url to the Vipps Widget SDK, unchanged.
1157
+ * ```
1158
+ */
1159
+ declare class BookingsPayment {
1160
+ private client;
1161
+ constructor(client: BaseClient);
1162
+ /**
1163
+ * Reserve (or charge) the booking's amount and get the wallet redirect.
1164
+ *
1165
+ * Automatically idempotent: the SDK mints an `Idempotency-Key` so its own
1166
+ * 5xx retries replay instead of reserving twice. One live payment per
1167
+ * booking — starting a second while one is outstanding answers 409; wait for
1168
+ * the first to be approved, aborted, or to expire (ten minutes).
1169
+ *
1170
+ * A `return_url` the workspace's own sites do not vouch for is refused with
1171
+ * 422, not 400: the URL parses, it is just not yours.
1172
+ */
1173
+ start(id: string, input: StartBookingPaymentInput, options?: RequestOptions): Promise<ApiResponse<BookingPaymentStart>>;
1174
+ /**
1175
+ * The newest payment attempt on the booking.
1176
+ *
1177
+ * Throws `MedalApiError` with status 404 when the booking has no payment at
1178
+ * all — "not started" and "unknown booking" answer alike, so this is not an
1179
+ * existence oracle. Earlier attempts are not returned; attempt N+1 is what
1180
+ * "the payment" means to a caller polling a retry.
1181
+ */
1182
+ get(id: string): Promise<ApiResponse<BookingPayment>>;
1183
+ }
1184
+ /**
1185
+ * The same two payment operations, authorized by the customer's manage token
1186
+ * instead of by booking id — for relaying a click on their own confirmation
1187
+ * link. Identical wire shapes; only the credential differs.
1188
+ */
1189
+ declare class BookingsManagePayment {
1190
+ private client;
1191
+ constructor(client: BaseClient);
1192
+ /** Start a payment on the customer's behalf. See {@link BookingsPayment.start}. */
1193
+ start(token: string, input: StartBookingPaymentInput, options?: RequestOptions): Promise<ApiResponse<BookingPaymentStart>>;
1194
+ /** Read the payment on the customer's own booking. 404 when there is none. */
1195
+ get(token: string): Promise<ApiResponse<BookingPayment>>;
1196
+ }
922
1197
  /**
923
1198
  * Customer-side booking management, addressed by the show-once manage token
924
1199
  * from `bookings.create(...)` rather than by booking id.
@@ -933,6 +1208,8 @@ interface BookingAvailabilityOptions {
933
1208
  */
934
1209
  declare class BookingsManage {
935
1210
  private client;
1211
+ /** Payments authorized by the manage token rather than by booking id. */
1212
+ readonly payment: BookingsManagePayment;
936
1213
  constructor(client: BaseClient);
937
1214
  /**
938
1215
  * Read what the holder of a manage token may see and do. Honour
@@ -948,6 +1225,45 @@ declare class BookingsManage {
948
1225
  */
949
1226
  reschedule(token: string, input: RescheduleBookingInput, options?: RequestOptions): Promise<ApiResponse<BookingRescheduleResult>>;
950
1227
  }
1228
+ /**
1229
+ * Persons a contact books for — children, pets, employees. Each has no login
1230
+ * of its own; bookings made on their behalf still hang off the contact via
1231
+ * `booked_for_person_id`.
1232
+ */
1233
+ declare class BookingsPersons {
1234
+ private client;
1235
+ constructor(client: BaseClient);
1236
+ /** Persons a contact books for. Active-only unless `include_inactive`. */
1237
+ list(contactId: string, options?: {
1238
+ include_inactive?: boolean;
1239
+ }): Promise<ApiResponse<ContactPerson[]>>;
1240
+ /** Add a person under a contact. */
1241
+ create(input: CreateContactPersonInput, options?: RequestOptions): Promise<ApiResponse<ContactPerson>>;
1242
+ }
1243
+ /** Directional relations between contacts — guardian, partner, employer, and so on. */
1244
+ declare class BookingsRelations {
1245
+ private client;
1246
+ constructor(client: BaseClient);
1247
+ /** Relations a contact holds, split into outgoing and incoming. */
1248
+ list(contactId: string): Promise<ApiResponse<ContactRelations>>;
1249
+ /** Create a relation from one contact to another. */
1250
+ create(input: CreateContactRelationInput, options?: RequestOptions): Promise<ApiResponse<CreateContactRelationResult>>;
1251
+ }
1252
+ /**
1253
+ * Arrangementer — scheduled group sessions bookings register against.
1254
+ * Registration itself lands in a later release; this is the read/create
1255
+ * surface for the events.
1256
+ */
1257
+ declare class BookingsEvents {
1258
+ private client;
1259
+ constructor(client: BaseClient);
1260
+ /** Arrangementer in a date range (`yyyy-mm-dd`, inclusive). */
1261
+ list(options: ListBookingEventsOptions): Promise<ApiResponse<BookingEvent[]>>;
1262
+ /** Get an arrangement by ID. */
1263
+ get(id: string): Promise<ApiResponse<BookingEvent>>;
1264
+ /** Create an arrangement from a template. */
1265
+ create(input: CreateBookingEventInput, options?: RequestOptions): Promise<ApiResponse<BookingEvent>>;
1266
+ }
951
1267
  /**
952
1268
  * Appointment bookings: the service catalogue, free slots, and the bookings
953
1269
  * themselves.
@@ -977,6 +1293,14 @@ declare class Bookings {
977
1293
  private client;
978
1294
  /** Customer-side actions addressed by manage token. */
979
1295
  readonly manage: BookingsManage;
1296
+ /** Persons a contact books for — children, pets, employees. */
1297
+ readonly persons: BookingsPersons;
1298
+ /** Directional relations between contacts. */
1299
+ readonly relations: BookingsRelations;
1300
+ /** Arrangementer — scheduled group sessions bookings register against. */
1301
+ readonly events: BookingsEvents;
1302
+ /** Vipps payments on a booking, as the business. */
1303
+ readonly payment: BookingsPayment;
980
1304
  constructor(client: BaseClient);
981
1305
  /** List the bookable service catalogue. Active-only unless asked otherwise. */
982
1306
  listServices(options?: ListBookingServicesOptions): Promise<ApiResponse<BookingService[]>>;
@@ -1790,6 +2114,22 @@ interface PortalFamilyMember {
1790
2114
  name: string;
1791
2115
  birth_year: number;
1792
2116
  }
2117
+ /** A person the contact books for — a child, a pet — with no login of its own. */
2118
+ interface PortalPerson {
2119
+ person_id: string;
2120
+ name: string;
2121
+ birth_year: number | null;
2122
+ relation_type: RelationType;
2123
+ relation_label: string | null;
2124
+ notes: string | null;
2125
+ /** `false` for a person the customer removed or that was promoted to its own contact; `me` returns active persons only, the export returns all. */
2126
+ active: boolean;
2127
+ }
2128
+ /** The workspace's own words for the person concept, e.g. `"Barn"`. */
2129
+ interface PortalLabels {
2130
+ person: string;
2131
+ persons: string;
2132
+ }
1793
2133
  /** The signed-in contact's own profile. */
1794
2134
  interface PortalProfile {
1795
2135
  contact_id: string;
@@ -1798,6 +2138,8 @@ interface PortalProfile {
1798
2138
  last_name: string | null;
1799
2139
  phone: string | null;
1800
2140
  family: PortalFamilyMember[];
2141
+ persons: PortalPerson[];
2142
+ labels: PortalLabels;
1801
2143
  marketing_consent: boolean;
1802
2144
  /** Unix timestamp in milliseconds. */
1803
2145
  created_at: number;
@@ -1850,6 +2192,15 @@ interface PortalConsentRecord {
1850
2192
  revoked_at: number | null;
1851
2193
  source: string;
1852
2194
  }
2195
+ /** A relation the exporting contact is a party to; only the counterpart's display name is exposed. */
2196
+ interface PortalExportRelation {
2197
+ direction: "outgoing" | "incoming";
2198
+ type: RelationType;
2199
+ custom_label: string | null;
2200
+ since: number | null;
2201
+ note: string | null;
2202
+ counterpart_name: string;
2203
+ }
1853
2204
  /** Everything the workspace holds about the signed-in contact (GDPR Art. 15). */
1854
2205
  interface PortalExport {
1855
2206
  /** Unix timestamp in milliseconds. */
@@ -1858,6 +2209,7 @@ interface PortalExport {
1858
2209
  family: PortalFamilyMember[];
1859
2210
  consents: PortalConsentRecord[];
1860
2211
  bookings: PortalBooking[];
2212
+ relations: PortalExportRelation[];
1861
2213
  }
1862
2214
 
1863
2215
  /**
@@ -2635,4 +2987,4 @@ declare class Medal {
2635
2987
  /** Convenience factory — equivalent to `new Medal(apiKey, options)`. */
2636
2988
  declare function createMedalClient(apiKey: string, options?: MedalOptions): Medal;
2637
2989
 
2638
- export { type Activity, type AddNoteInput, type ApiResponse, type AutoConfirmContext, type AutoConfirmOptions, BaseClient, type BatchSendInput, type BatchSendResult, type BatchSendSummary, type Booking, type BookingActionResult, type BookingAvailabilityOptions, type BookingCancelledBy, type BookingClaimableCreatedVia, type BookingContactInput, type BookingCreateResult, type BookingCreatedVia, type BookingPaymentStatus, type BookingRescheduleResult, type BookingResource, type BookingResourceType, type BookingScheduleDay, type BookingScheduleOptions, type BookingService, type BookingSlot, type BookingStatus, type BookingTimestampInput, Bookings, type BookingsPage, type BookingsPagination, CAPABILITY_IDS, CAPABILITY_ROUTES, type CancelBookingInput, type CapabilityConfirmation, CapabilityConfirmations, CapabilityConfirmer, type CapabilityId, type CapabilityPathParamValue, type CapabilityRoute, type CapabilityWriteBodies, type CapabilityWriteRequest, type Channel, type ChannelConnectedEvent, type ChannelConnection, type ChannelConnectionDisconnectResult, type ChannelConnectionState, type ChannelDisconnectReason, type ChannelDisconnectedEvent, Channels, type ConnectLink, type ConnectLinkCreateResult, type ConnectLinkRevokeResult, type ConnectLinkStatus, type ConsentRecord, type ConsentResult, type ConsentType, type Contact, type ContactConsents, type ContactCreateResult, type ContactNoteResult, type ContactRemoveResult, type ContactStatus, type ContactUpdateResult, Contacts, type Conversation, type ConversationAssignedEvent, type ConversationCreatedEvent, type ConversationMessage, type ConversationStatus, type ConversationStatusChangedEvent, type ConversationUpdateResult, type CookieCategoryConsent, type CookieConsentInput, type CreateBookingInput, type CreateBookingItemInput, type CreateConnectLinkInput, type CreateContactInput, type CreateDealInput, type CreatePostInput, type CreateReplyInput, type CreateWebhookInput, type CreatedBooking, DEFAULT_WEBHOOK_TOLERANCE_MS, type Deal, type DealCreateResult, type DealRemoveResult, type DealStatus, type DealUpdateResult, Deals, type EmailSend, type EmailSendResult, type EmailStatus, type EmailTemplate, type EmailTemplateDetail, Emails, Gdpr, type GdprExport, type GetTemplateOptions, Helpdesk, type HelpdeskMessageType, type ImportContactInput, type ImportContactsResult, type IssueCapabilityConfirmationInput, type ListBookingServicesOptions, type ListBookingsOptions, type ListConnectLinksOptions, type ListContactsOptions, type ListConversationsOptions, type ListDealsOptions, type ListDeliveriesOptions, type ListPostsOptions, type ManageSummary, Medal, MedalApiError, type MedalOptions, type MessageAuthorType, type MessageDeliveryStatus, type MessageDeliveryUpdatedEvent, type MessageReceivedEvent, type MessageSentEvent, type PaginatedResponse, type PaginationOptions, Portal, type PortalBooking, type PortalBookingStatus, type PortalBookings, type PortalConsentRecord, type PortalContactSummary, type PortalExport, type PortalFamilyMember, type PortalLoginStartInput, type PortalLoginStartResult, type PortalProfile, type PortalProfilePatch, type PortalSession, type PortalVerifyInput, type Post, type PostDetail, type PostType, type PostVariant, Posts, type PublishResult, type RecordConsentInput, type ReplyCreateResult, type RequestOptions, type RescheduleBookingInput, Scan, type ScanCompany, type ScanCreateInput, type ScanCreateResult, type ScanJob, type ScanResultPayload, type ScanStatus, type ScanSubScores, type SchedulePostInput, type ScheduleResult, type SendEmailInput, type TestPingEvent, type UpdateBookingInput, type UpdateContactInput, type UpdateConversationInput, type UpdateDealInput, type UpdatePostInput, type UpdateWebhookInput, type VerifyWebhookSignatureInput, type WaitForScanOptions, type WebhookChannelLifecycleData, type WebhookConversationSnapshot, type WebhookDeleteResult, type WebhookDelivery, type WebhookEndpoint, type WebhookEvent, type WebhookMessageSnapshot, type WebhookTestResult, WebhookVerificationError, type WebhookVerificationErrorCode, Webhooks, type Workspace, Workspaces, createMedalClient, Medal as default, verifyWebhookSignature };
2990
+ export { type Activity, type AddNoteInput, type ApiResponse, type AutoConfirmContext, type AutoConfirmOptions, BaseClient, type BatchSendInput, type BatchSendResult, type BatchSendSummary, type Booking, type BookingActionResult, type BookingAvailabilityOptions, type BookingCancelledBy, type BookingClaimableCreatedVia, type BookingContactInput, type BookingCreateResult, type BookingCreatedVia, type BookingEvent, type BookingEventStatus, type BookingEventTemplateKey, type BookingPayment, type BookingPaymentMode, type BookingPaymentStart, type BookingPaymentState, type BookingPaymentStatus, type BookingRescheduleResult, type BookingResource, type BookingResourceType, type BookingScheduleDay, type BookingScheduleOptions, type BookingService, type BookingSlot, type BookingStatus, type BookingTimestampInput, Bookings, type BookingsPage, type BookingsPagination, CAPABILITY_IDS, CAPABILITY_ROUTES, type CancelBookingInput, type CapabilityConfirmation, CapabilityConfirmations, CapabilityConfirmer, type CapabilityId, type CapabilityPathParamValue, type CapabilityRoute, type CapabilityWriteBodies, type CapabilityWriteRequest, type Channel, type ChannelConnectedEvent, type ChannelConnection, type ChannelConnectionDisconnectResult, type ChannelConnectionState, type ChannelDisconnectReason, type ChannelDisconnectedEvent, Channels, type ConnectLink, type ConnectLinkCreateResult, type ConnectLinkRevokeResult, type ConnectLinkStatus, type ConsentRecord, type ConsentResult, type ConsentType, type Contact, type ContactConsents, type ContactCreateResult, type ContactNoteResult, type ContactPerson, type ContactRelation, type ContactRelations, type ContactRemoveResult, type ContactStatus, type ContactUpdateResult, Contacts, type Conversation, type ConversationAssignedEvent, type ConversationCreatedEvent, type ConversationMessage, type ConversationStatus, type ConversationStatusChangedEvent, type ConversationUpdateResult, type CookieCategoryConsent, type CookieConsentInput, type CreateBookingEventInput, type CreateBookingInput, type CreateBookingItemInput, type CreateConnectLinkInput, type CreateContactInput, type CreateContactPersonInput, type CreateContactRelationInput, type CreateContactRelationResult, type CreateDealInput, type CreatePostInput, type CreateReplyInput, type CreateWebhookInput, type CreatedBooking, DEFAULT_WEBHOOK_TOLERANCE_MS, type Deal, type DealCreateResult, type DealRemoveResult, type DealStatus, type DealUpdateResult, Deals, type EmailSend, type EmailSendResult, type EmailStatus, type EmailTemplate, type EmailTemplateDetail, Emails, Gdpr, type GdprExport, type GetTemplateOptions, Helpdesk, type HelpdeskMessageType, type ImportContactInput, type ImportContactsResult, type IssueCapabilityConfirmationInput, type ListBookingEventsOptions, type ListBookingServicesOptions, type ListBookingsOptions, type ListConnectLinksOptions, type ListContactsOptions, type ListConversationsOptions, type ListDealsOptions, type ListDeliveriesOptions, type ListPostsOptions, type ManageSummary, Medal, MedalApiError, type MedalOptions, type MessageAuthorType, type MessageDeliveryStatus, type MessageDeliveryUpdatedEvent, type MessageReceivedEvent, type MessageSentEvent, type PaginatedResponse, type PaginationOptions, Portal, type PortalBooking, type PortalBookingStatus, type PortalBookings, type PortalConsentRecord, type PortalContactSummary, type PortalExport, type PortalExportRelation, type PortalFamilyMember, type PortalLabels, type PortalLoginStartInput, type PortalLoginStartResult, type PortalPerson, type PortalProfile, type PortalProfilePatch, type PortalSession, type PortalVerifyInput, type Post, type PostDetail, type PostType, type PostVariant, Posts, type PublishResult, type RecordConsentInput, type RelationType, type ReplyCreateResult, type RequestOptions, type RescheduleBookingInput, Scan, type ScanCompany, type ScanCreateInput, type ScanCreateResult, type ScanJob, type ScanResultPayload, type ScanStatus, type ScanSubScores, type SchedulePostInput, type ScheduleResult, type SendEmailInput, type StartBookingPaymentInput, type TestPingEvent, type UpdateBookingInput, type UpdateContactInput, type UpdateConversationInput, type UpdateDealInput, type UpdatePostInput, type UpdateWebhookInput, type VerifyWebhookSignatureInput, type WaitForScanOptions, type WebhookChannelLifecycleData, type WebhookConversationSnapshot, type WebhookDeleteResult, type WebhookDelivery, type WebhookEndpoint, type WebhookEvent, type WebhookMessageSnapshot, type WebhookTestResult, WebhookVerificationError, type WebhookVerificationErrorCode, Webhooks, type Workspace, Workspaces, createMedalClient, Medal as default, verifyWebhookSignature };
package/dist/src/index.js CHANGED
@@ -340,11 +340,67 @@ var CapabilityConfirmer = class {
340
340
  };
341
341
 
342
342
  // src/resources/bookings.ts
343
+ var BookingsPayment = class {
344
+ constructor(client) {
345
+ this.client = client;
346
+ }
347
+ client;
348
+ /**
349
+ * Reserve (or charge) the booking's amount and get the wallet redirect.
350
+ *
351
+ * Automatically idempotent: the SDK mints an `Idempotency-Key` so its own
352
+ * 5xx retries replay instead of reserving twice. One live payment per
353
+ * booking — starting a second while one is outstanding answers 409; wait for
354
+ * the first to be approved, aborted, or to expire (ten minutes).
355
+ *
356
+ * A `return_url` the workspace's own sites do not vouch for is refused with
357
+ * 422, not 400: the URL parses, it is just not yours.
358
+ */
359
+ async start(id, input, options) {
360
+ return this.client.postOnce(
361
+ `/api/v1/bookings/${encodeURIComponent(id)}/payment`,
362
+ input,
363
+ options
364
+ );
365
+ }
366
+ /**
367
+ * The newest payment attempt on the booking.
368
+ *
369
+ * Throws `MedalApiError` with status 404 when the booking has no payment at
370
+ * all — "not started" and "unknown booking" answer alike, so this is not an
371
+ * existence oracle. Earlier attempts are not returned; attempt N+1 is what
372
+ * "the payment" means to a caller polling a retry.
373
+ */
374
+ async get(id) {
375
+ return this.client.get(`/api/v1/bookings/${encodeURIComponent(id)}/payment`);
376
+ }
377
+ };
378
+ var BookingsManagePayment = class {
379
+ constructor(client) {
380
+ this.client = client;
381
+ }
382
+ client;
383
+ /** Start a payment on the customer's behalf. See {@link BookingsPayment.start}. */
384
+ async start(token, input, options) {
385
+ return this.client.postOnce(
386
+ `/api/v1/bookings/manage/${encodeURIComponent(token)}/payment`,
387
+ input,
388
+ options
389
+ );
390
+ }
391
+ /** Read the payment on the customer's own booking. 404 when there is none. */
392
+ async get(token) {
393
+ return this.client.get(`/api/v1/bookings/manage/${encodeURIComponent(token)}/payment`);
394
+ }
395
+ };
343
396
  var BookingsManage = class {
344
397
  constructor(client) {
345
398
  this.client = client;
399
+ this.payment = new BookingsManagePayment(client);
346
400
  }
347
401
  client;
402
+ /** Payments authorized by the manage token rather than by booking id. */
403
+ payment;
348
404
  /**
349
405
  * Read what the holder of a manage token may see and do. Honour
350
406
  * `can_cancel` / `can_reschedule` — they already apply the policy windows.
@@ -373,14 +429,78 @@ var BookingsManage = class {
373
429
  );
374
430
  }
375
431
  };
432
+ var BookingsPersons = class {
433
+ constructor(client) {
434
+ this.client = client;
435
+ }
436
+ client;
437
+ /** Persons a contact books for. Active-only unless `include_inactive`. */
438
+ async list(contactId, options) {
439
+ const params = { contact_id: contactId };
440
+ if (options?.include_inactive !== void 0) {
441
+ params.include_inactive = String(options.include_inactive);
442
+ }
443
+ return this.client.get("/api/v1/bookings/persons", params);
444
+ }
445
+ /** Add a person under a contact. */
446
+ async create(input, options) {
447
+ return this.client.postOnce("/api/v1/bookings/persons", input, options);
448
+ }
449
+ };
450
+ var BookingsRelations = class {
451
+ constructor(client) {
452
+ this.client = client;
453
+ }
454
+ client;
455
+ /** Relations a contact holds, split into outgoing and incoming. */
456
+ async list(contactId) {
457
+ return this.client.get("/api/v1/bookings/relations", { contact_id: contactId });
458
+ }
459
+ /** Create a relation from one contact to another. */
460
+ async create(input, options) {
461
+ return this.client.postOnce("/api/v1/bookings/relations", input, options);
462
+ }
463
+ };
464
+ var BookingsEvents = class {
465
+ constructor(client) {
466
+ this.client = client;
467
+ }
468
+ client;
469
+ /** Arrangementer in a date range (`yyyy-mm-dd`, inclusive). */
470
+ async list(options) {
471
+ const params = { from: options.from, to: options.to };
472
+ if (options.status) params.status = options.status;
473
+ return this.client.get("/api/v1/bookings/events", params);
474
+ }
475
+ /** Get an arrangement by ID. */
476
+ async get(id) {
477
+ return this.client.get(`/api/v1/bookings/events/${encodeURIComponent(id)}`);
478
+ }
479
+ /** Create an arrangement from a template. */
480
+ async create(input, options) {
481
+ return this.client.postOnce("/api/v1/bookings/events", input, options);
482
+ }
483
+ };
376
484
  var Bookings = class {
377
485
  constructor(client) {
378
486
  this.client = client;
379
487
  this.manage = new BookingsManage(client);
488
+ this.persons = new BookingsPersons(client);
489
+ this.relations = new BookingsRelations(client);
490
+ this.events = new BookingsEvents(client);
491
+ this.payment = new BookingsPayment(client);
380
492
  }
381
493
  client;
382
494
  /** Customer-side actions addressed by manage token. */
383
495
  manage;
496
+ /** Persons a contact books for — children, pets, employees. */
497
+ persons;
498
+ /** Directional relations between contacts. */
499
+ relations;
500
+ /** Arrangementer — scheduled group sessions bookings register against. */
501
+ events;
502
+ /** Vipps payments on a booking, as the business. */
503
+ payment;
384
504
  /** List the bookable service catalogue. Active-only unless asked otherwise. */
385
505
  async listServices(options) {
386
506
  const params = {};