@medalsocial/sdk 1.2.0 → 1.3.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.
@@ -8,6 +8,25 @@ interface ClientConfig {
8
8
  timeout: number;
9
9
  userAgent: string;
10
10
  }
11
+ /** Per-request options for write operations. */
12
+ interface RequestOptions {
13
+ /**
14
+ * Idempotency key sent as the `Idempotency-Key` header. Retries with the
15
+ * same key return the original result instead of repeating the operation.
16
+ * Required by some endpoints for capability-scoped tokens (e.g. helpdesk
17
+ * replies, webhook creation).
18
+ */
19
+ idempotencyKey?: string;
20
+ /**
21
+ * Capability confirmation token sent as the `X-Capability-Confirmation`
22
+ * header. Required alongside `idempotencyKey` when a token granted a
23
+ * capability-style scope directly (e.g. `helpdesk.webhook.manage`) executes
24
+ * a confirmable write route. Obtain one from
25
+ * `POST /api/v1/capability-confirmations`. API keys with legacy scopes do
26
+ * not need it.
27
+ */
28
+ capabilityConfirmation?: string;
29
+ }
11
30
  /**
12
31
  * Low-level HTTP client used by all resource classes.
13
32
  * Handles authentication, retries, timeout, and error parsing.
@@ -19,11 +38,12 @@ declare class BaseClient {
19
38
  /** Execute an authenticated GET request and return the parsed JSON body. */
20
39
  get<T>(path: string, params?: Record<string, string | undefined>): Promise<T>;
21
40
  /** Execute an authenticated POST request with a JSON body. */
22
- post<T>(path: string, body?: unknown): Promise<T>;
41
+ post<T>(path: string, body?: unknown, options?: RequestOptions): Promise<T>;
23
42
  /** Execute an authenticated PATCH request with a JSON body. */
24
- patch<T>(path: string, body: unknown): Promise<T>;
43
+ patch<T>(path: string, body: unknown, options?: RequestOptions): Promise<T>;
25
44
  /** Execute an authenticated DELETE request. */
26
- delete<T>(path: string): Promise<T>;
45
+ delete<T>(path: string, options?: RequestOptions): Promise<T>;
46
+ private writeHeaders;
27
47
  private buildUrl;
28
48
  private request;
29
49
  }
@@ -484,6 +504,122 @@ declare class Gdpr {
484
504
  }>;
485
505
  }
486
506
 
507
+ /** Lifecycle status of a helpdesk conversation. */
508
+ type ConversationStatus = "open" | "snoozed" | "closed";
509
+ /** Who authored a helpdesk message. */
510
+ type MessageAuthorType = "visitor" | "operator" | "ai" | "system";
511
+ /** Kind of helpdesk message. `note` is operator-internal and never delivered to the customer. */
512
+ type HelpdeskMessageType = "chat" | "email" | "note";
513
+ /** A helpdesk conversation across any connected channel (widget, email, social DMs, …). */
514
+ interface Conversation {
515
+ id: string;
516
+ /** Channel type, e.g. 'widget', 'instagram', 'messenger', 'whatsapp', 'email'. */
517
+ channel: string;
518
+ channel_connection_id: string | null;
519
+ status: ConversationStatus;
520
+ subject: string | null;
521
+ assignee_user_id: string | null;
522
+ contact_id: string | null;
523
+ visitor_name: string | null;
524
+ visitor_email: string | null;
525
+ external_conversation_id: string | null;
526
+ channel_account_id: string | null;
527
+ message_count: number;
528
+ unread_for_operator: number;
529
+ /** Unix timestamp in milliseconds. */
530
+ last_message_at: number;
531
+ last_message_preview: string | null;
532
+ last_message_author_type: MessageAuthorType | null;
533
+ /** Unix timestamp in milliseconds. */
534
+ created_at: number;
535
+ /** Unix timestamp in milliseconds. */
536
+ updated_at: number;
537
+ }
538
+ /** A single message inside a helpdesk conversation. */
539
+ interface ConversationMessage {
540
+ id: string;
541
+ conversation_id: string;
542
+ author_type: MessageAuthorType;
543
+ message_type: HelpdeskMessageType;
544
+ author_user_id: string | null;
545
+ author_name: string | null;
546
+ body: string;
547
+ /** Unix timestamp in milliseconds. */
548
+ created_at: number;
549
+ }
550
+ /** Filters for listing/searching helpdesk conversations. */
551
+ interface ListConversationsOptions extends PaginationOptions {
552
+ status?: ConversationStatus;
553
+ /** Only conversations assigned to this user. */
554
+ assignee_user_id?: string;
555
+ /** Match against visitor name/email. */
556
+ requester?: string;
557
+ /** Free-text search query. */
558
+ query?: string;
559
+ /** Only conversations on these channels (serialized as CSV). */
560
+ channels?: string[];
561
+ }
562
+ /** Input for updating a conversation's status and/or assignee. At least one field is required. */
563
+ interface UpdateConversationInput {
564
+ status?: ConversationStatus;
565
+ /** User ID to assign, or `null` to unassign. */
566
+ assignee_user_id?: string | null;
567
+ }
568
+ /** Result of a conversation update. */
569
+ interface ConversationUpdateResult {
570
+ id: string;
571
+ status: ConversationStatus;
572
+ assignee_user_id: string | null;
573
+ }
574
+ /** Input for sending an operator reply (or internal note) into a conversation. */
575
+ interface CreateReplyInput {
576
+ conversation_id: string;
577
+ /** Message body (max 20,000 characters). */
578
+ body: string;
579
+ /** `note` = operator-internal note (not delivered to the customer). Default `chat`. */
580
+ message_type?: "chat" | "note";
581
+ /** Agent display name for bridged replies (shown in widget + inbox). */
582
+ author_name?: string;
583
+ }
584
+ /** Result returned after creating a reply (HTTP 201). */
585
+ interface ReplyCreateResult {
586
+ id: string;
587
+ conversation_id: string;
588
+ status: string;
589
+ }
590
+
591
+ /** Browse and manage helpdesk conversations. */
592
+ declare class HelpdeskConversations {
593
+ private client;
594
+ constructor(client: BaseClient);
595
+ /** List/search conversations with cursor-based pagination and optional filters. */
596
+ list(options?: ListConversationsOptions): Promise<PaginatedResponse<Conversation>>;
597
+ /** Get a conversation by ID. */
598
+ get(id: string): Promise<ApiResponse<Conversation>>;
599
+ /** Update a conversation's status and/or assignee (pass `assignee_user_id: null` to unassign). */
600
+ update(id: string, input: UpdateConversationInput, options?: RequestOptions): Promise<ApiResponse<ConversationUpdateResult>>;
601
+ /** Read a conversation's messages with cursor-based pagination. */
602
+ messages(id: string, options?: PaginationOptions): Promise<PaginatedResponse<ConversationMessage>>;
603
+ }
604
+ /** Send operator replies (or internal notes) into conversations. */
605
+ declare class HelpdeskReplies {
606
+ private client;
607
+ constructor(client: BaseClient);
608
+ /**
609
+ * Send an operator reply or internal note. Returns HTTP 201.
610
+ *
611
+ * Pass an `idempotencyKey` so retried requests do not create duplicate
612
+ * messages — it is REQUIRED for capability-scoped tokens.
613
+ */
614
+ create(input: CreateReplyInput, options?: RequestOptions): Promise<ApiResponse<ReplyCreateResult>>;
615
+ }
616
+ /** Helpdesk bridge — read conversations, reply, and manage assignment/status. */
617
+ declare class Helpdesk {
618
+ readonly conversations: HelpdeskConversations;
619
+ readonly replies: HelpdeskReplies;
620
+ constructor(client: BaseClient);
621
+ }
622
+
487
623
  /** A post in the workspace (list view). */
488
624
  interface Post {
489
625
  id: string;
@@ -590,6 +726,129 @@ declare class Posts {
590
726
  channels(): Promise<ApiResponse<Channel[]>>;
591
727
  }
592
728
 
729
+ /** A webhook endpoint registered in the workspace. */
730
+ interface WebhookEndpoint {
731
+ id: string;
732
+ name: string;
733
+ /** Destination URL (must be https). */
734
+ url: string;
735
+ enabled: boolean;
736
+ /** Subscribed event types. Empty array = all events. */
737
+ event_types: string[];
738
+ /** Channel-type filter (e.g. ['widget', 'whatsapp']), or `null` for all channels. */
739
+ channels: string[] | null;
740
+ /** Channel-connection filter, or `null` for all connections. */
741
+ channel_connection_ids: string[] | null;
742
+ /** Last 4 characters of the signing secret, for identification. */
743
+ secret_last4: string;
744
+ consecutive_failures: number;
745
+ /** Unix timestamps in milliseconds, or `null` if never. */
746
+ last_delivery_at: number | null;
747
+ last_success_at: number | null;
748
+ last_error_at: number | null;
749
+ last_error: string | null;
750
+ created_at: number;
751
+ updated_at: number;
752
+ /**
753
+ * Full signing secret (`whsec_…`) — present ONLY in the `create` response.
754
+ * It is returned exactly once and can never be retrieved again. Store it
755
+ * securely immediately; you need it to verify delivery signatures.
756
+ */
757
+ secret?: string;
758
+ }
759
+ /** Input for creating a webhook endpoint. */
760
+ interface CreateWebhookInput {
761
+ /** Display name (max 100 characters). */
762
+ name: string;
763
+ /** Destination URL — must be https. */
764
+ url: string;
765
+ /** Event types to subscribe to (e.g. 'helpdesk.message_received'). Empty = all. */
766
+ event_types: string[];
767
+ /** Restrict to these channel types (e.g. ['widget', 'whatsapp']). */
768
+ channels?: string[];
769
+ /** Restrict to these channel connection IDs. */
770
+ channel_connection_ids?: string[];
771
+ }
772
+ /**
773
+ * Input for updating a webhook endpoint. Only provided fields change.
774
+ * Pass `null` for `channels` or `channel_connection_ids` to CLEAR an existing
775
+ * filter (deliver for all channels / all accounts again); omitting the field
776
+ * leaves the current filter unchanged.
777
+ */
778
+ interface UpdateWebhookInput {
779
+ name?: string;
780
+ url?: string;
781
+ event_types?: string[];
782
+ channels?: string[] | null;
783
+ channel_connection_ids?: string[] | null;
784
+ enabled?: boolean;
785
+ }
786
+ /** Result of deleting a webhook endpoint. */
787
+ interface WebhookDeleteResult {
788
+ id: string;
789
+ status: string;
790
+ }
791
+ /** A delivery attempt record for a webhook endpoint. */
792
+ interface WebhookDelivery {
793
+ id: string;
794
+ event_type: string;
795
+ status: "pending" | "delivered" | "dead_letter";
796
+ attempt_count: number;
797
+ /** Unix timestamp in milliseconds of the next retry, or `null`. */
798
+ next_attempt_at: number | null;
799
+ response_status: number | null;
800
+ duration_ms: number | null;
801
+ last_error: string | null;
802
+ /** Unix timestamp in milliseconds, or `null` if not delivered. */
803
+ delivered_at: number | null;
804
+ created_at: number;
805
+ }
806
+ /** Options for listing recent deliveries. */
807
+ interface ListDeliveriesOptions {
808
+ limit?: number;
809
+ }
810
+ /** Result returned after queuing a test delivery (HTTP 202). */
811
+ interface WebhookTestResult {
812
+ delivery_id: string;
813
+ status: string;
814
+ }
815
+
816
+ /** Manage webhook endpoints and inspect their deliveries. */
817
+ declare class Webhooks {
818
+ private client;
819
+ constructor(client: BaseClient);
820
+ /** List all webhook endpoints in the workspace. */
821
+ list(): Promise<ApiResponse<WebhookEndpoint[]>>;
822
+ /**
823
+ * Create a webhook endpoint. Returns HTTP 201.
824
+ *
825
+ * **The response's `data.secret` contains the signing secret EXACTLY ONCE.**
826
+ * It can never be retrieved again — store it securely immediately. You need
827
+ * it to verify the `X-Medal-Signature` header on incoming deliveries (see
828
+ * `verifyWebhookSignature`).
829
+ *
830
+ * `secret` is typed optional because an idempotent replay (retrying with the
831
+ * same `Idempotency-Key`, `X-Idempotent-Replayed: true`) returns the existing
832
+ * endpoint WITHOUT the secret — handle that case (rotate if you lost it).
833
+ */
834
+ create(input: CreateWebhookInput, options?: RequestOptions): Promise<ApiResponse<WebhookEndpoint>>;
835
+ /** Get a webhook endpoint by ID. */
836
+ get(id: string): Promise<ApiResponse<WebhookEndpoint>>;
837
+ /** Update a webhook endpoint (name, url, event types, filters, enabled). */
838
+ update(id: string, input: UpdateWebhookInput, options?: RequestOptions): Promise<ApiResponse<WebhookEndpoint>>;
839
+ /**
840
+ * Permanently delete a webhook endpoint (stops all outbound deliveries).
841
+ * Capability-scoped tokens must pass `idempotencyKey` — the API requires
842
+ * `Idempotency-Key` + `X-Capability-Confirmation` for direct capability
843
+ * grants on this route. API keys with legacy scopes may omit it.
844
+ */
845
+ delete(id: string, options?: RequestOptions): Promise<ApiResponse<WebhookDeleteResult>>;
846
+ /** List recent deliveries for an endpoint (most recent first). */
847
+ deliveries(id: string, options?: ListDeliveriesOptions): Promise<ApiResponse<WebhookDelivery[]>>;
848
+ /** Queue a signed `test.ping` delivery to the endpoint. Returns HTTP 202. */
849
+ test(id: string): Promise<ApiResponse<WebhookTestResult>>;
850
+ }
851
+
593
852
  /** A Medal Social workspace accessible to the authenticated credential. */
594
853
  interface Workspace {
595
854
  id: string;
@@ -606,6 +865,178 @@ declare class Workspaces {
606
865
  list(): Promise<ApiResponse<Workspace[]>>;
607
866
  }
608
867
 
868
+ /**
869
+ * Webhook event types and signature verification for the Medal Social
870
+ * outbound webhook bridge.
871
+ *
872
+ * Every delivery is an HTTP POST with headers:
873
+ * - `X-Medal-Timestamp` — Unix milliseconds when the request was signed
874
+ * - `X-Medal-Signature` — `sha256=<base64(HMAC-SHA256("{timestamp}.{rawBody}", secret))>`
875
+ * - `X-Medal-Event` — the event type
876
+ * - `X-Medal-Delivery-Id` / `Idempotency-Key` — unique delivery ID (deduplicate on this)
877
+ *
878
+ * Use {@link verifyWebhookSignature} to authenticate a delivery and get the
879
+ * parsed, typed event back. Uses Web Crypto (`crypto.subtle`) so it works in
880
+ * Node.js 18+, Deno, Bun, Cloudflare Workers, and browsers.
881
+ */
882
+ /** Snapshot of a conversation included in every helpdesk webhook event. */
883
+ interface WebhookConversationSnapshot {
884
+ id: string;
885
+ channel: string;
886
+ channelConnectionId: string | null;
887
+ status: string;
888
+ subject: string | null;
889
+ assigneeUserId: string | null;
890
+ contactId: string | null;
891
+ visitorName: string | null;
892
+ visitorEmail: string | null;
893
+ externalConversationId: string | null;
894
+ channelAccountId: string | null;
895
+ messageCount: number;
896
+ /** Unix timestamp in milliseconds. */
897
+ lastMessageAt: number;
898
+ /** Unix timestamp in milliseconds. */
899
+ createdAt: number;
900
+ }
901
+ /** Snapshot of a message included in helpdesk message events. */
902
+ interface WebhookMessageSnapshot {
903
+ id: string;
904
+ authorType: "visitor" | "operator" | "ai" | "system";
905
+ messageType: "chat" | "email" | "note";
906
+ body: string;
907
+ authorUserId: string | null;
908
+ authorName: string | null;
909
+ externalMessageId: string | null;
910
+ deliveryStatus: string | null;
911
+ deliveryError: string | null;
912
+ /** Unix timestamp in milliseconds. */
913
+ createdAt: number;
914
+ }
915
+ /** Fields present in the `data` of every helpdesk event. */
916
+ interface HelpdeskEventData {
917
+ /** Channel type at the top level, for quick filtering. */
918
+ channel: string;
919
+ channelConnectionId: string | null;
920
+ conversation: WebhookConversationSnapshot;
921
+ }
922
+ /** Envelope fields shared by all webhook events. */
923
+ interface WebhookEventBase {
924
+ /** Unique delivery/event ID — use for deduplication. */
925
+ id: string;
926
+ /** Unix timestamp in milliseconds when the event was created. */
927
+ created_at: number;
928
+ workspace_id: string;
929
+ }
930
+ /** A new conversation was created. */
931
+ interface ConversationCreatedEvent extends WebhookEventBase {
932
+ type: "helpdesk.conversation_created";
933
+ data: HelpdeskEventData;
934
+ }
935
+ /** A conversation was assigned or unassigned. */
936
+ interface ConversationAssignedEvent extends WebhookEventBase {
937
+ type: "helpdesk.conversation_assigned";
938
+ data: HelpdeskEventData & {
939
+ assigneeUserId: string | null;
940
+ previousAssigneeUserId: string | null;
941
+ };
942
+ }
943
+ /** A conversation's status changed (open / snoozed / closed). */
944
+ interface ConversationStatusChangedEvent extends WebhookEventBase {
945
+ type: "helpdesk.conversation_status_changed";
946
+ data: HelpdeskEventData & {
947
+ status: string;
948
+ previousStatus: string;
949
+ };
950
+ }
951
+ /** A message arrived from the visitor/customer. */
952
+ interface MessageReceivedEvent extends WebhookEventBase {
953
+ type: "helpdesk.message_received";
954
+ data: HelpdeskEventData & {
955
+ message: WebhookMessageSnapshot;
956
+ };
957
+ }
958
+ /** A message was sent by an operator, AI, or the system. */
959
+ interface MessageSentEvent extends WebhookEventBase {
960
+ type: "helpdesk.message_sent";
961
+ data: HelpdeskEventData & {
962
+ message: WebhookMessageSnapshot;
963
+ };
964
+ }
965
+ /** The delivery status of an outbound message changed (sent / delivered / failed …). */
966
+ interface MessageDeliveryUpdatedEvent extends WebhookEventBase {
967
+ type: "helpdesk.message_delivery_updated";
968
+ data: HelpdeskEventData & {
969
+ message: WebhookMessageSnapshot;
970
+ };
971
+ }
972
+ /** A `test.ping` delivery queued via `medal.webhooks.test(id)`. Carries sample data. */
973
+ interface TestPingEvent extends WebhookEventBase {
974
+ type: "test.ping";
975
+ data: Record<string, unknown>;
976
+ }
977
+ /**
978
+ * Discriminated union of all webhook events, keyed on `type`.
979
+ *
980
+ * @example
981
+ * ```ts
982
+ * switch (event.type) {
983
+ * case 'helpdesk.message_received':
984
+ * console.log(event.data.message.body);
985
+ * break;
986
+ * case 'helpdesk.conversation_status_changed':
987
+ * console.log(event.data.previousStatus, '→', event.data.status);
988
+ * break;
989
+ * }
990
+ * ```
991
+ */
992
+ type WebhookEvent = ConversationCreatedEvent | ConversationAssignedEvent | ConversationStatusChangedEvent | MessageReceivedEvent | MessageSentEvent | MessageDeliveryUpdatedEvent | TestPingEvent;
993
+ /** Machine-readable reason a webhook verification failed. */
994
+ type WebhookVerificationErrorCode = "malformed_header" | "timestamp_out_of_tolerance" | "invalid_signature" | "invalid_payload";
995
+ /** Thrown by {@link verifyWebhookSignature} when a delivery cannot be authenticated. */
996
+ declare class WebhookVerificationError extends Error {
997
+ readonly code: WebhookVerificationErrorCode;
998
+ constructor(code: WebhookVerificationErrorCode, message: string);
999
+ }
1000
+ /** Input for {@link verifyWebhookSignature}. */
1001
+ interface VerifyWebhookSignatureInput {
1002
+ /** The RAW request body string, exactly as received (do not re-serialize parsed JSON). */
1003
+ payload: string;
1004
+ /** Value of the `X-Medal-Timestamp` header (Unix milliseconds). */
1005
+ timestamp: string;
1006
+ /** Value of the `X-Medal-Signature` header (`sha256=<base64>`). */
1007
+ signature: string;
1008
+ /** The endpoint signing secret (`whsec_…`) returned once at creation time. */
1009
+ secret: string;
1010
+ /** Max allowed clock skew between now and the signed timestamp. Default 5 minutes. */
1011
+ toleranceMs?: number;
1012
+ }
1013
+ /** Default allowed clock skew for webhook verification (5 minutes). */
1014
+ declare const DEFAULT_WEBHOOK_TOLERANCE_MS: number;
1015
+ /**
1016
+ * Verify a webhook delivery's signature and timestamp, then return the parsed
1017
+ * typed event.
1018
+ *
1019
+ * Recomputes `HMAC-SHA256("{timestamp}.{payload}", secret)` with Web Crypto
1020
+ * and compares it against the signature in constant time. Deliveries whose
1021
+ * timestamp deviates from the current time by more than `toleranceMs`
1022
+ * (default 5 minutes) are rejected to prevent replay attacks.
1023
+ *
1024
+ * @throws {WebhookVerificationError} if the headers are malformed, the
1025
+ * timestamp is outside the tolerance window, the signature does not match,
1026
+ * or the payload is not valid JSON.
1027
+ *
1028
+ * @example
1029
+ * ```ts
1030
+ * const event = await verifyWebhookSignature({
1031
+ * payload: rawBody,
1032
+ * timestamp: req.headers['x-medal-timestamp'],
1033
+ * signature: req.headers['x-medal-signature'],
1034
+ * secret: process.env.MEDAL_WEBHOOK_SECRET,
1035
+ * });
1036
+ * ```
1037
+ */
1038
+ declare function verifyWebhookSignature(input: VerifyWebhookSignatureInput): Promise<WebhookEvent>;
1039
+
609
1040
  /** Options for configuring the {@link Medal} client. */
610
1041
  interface MedalOptions {
611
1042
  /** Override the base URL (defaults to https://io.medalsocial.com). */
@@ -670,7 +1101,9 @@ declare class Medal {
670
1101
  readonly contacts: Contacts;
671
1102
  readonly deals: Deals;
672
1103
  readonly gdpr: Gdpr;
1104
+ readonly helpdesk: Helpdesk;
673
1105
  readonly posts: Posts;
1106
+ readonly webhooks: Webhooks;
674
1107
  readonly workspaces: Workspaces;
675
1108
  constructor(token: string, options?: MedalOptions);
676
1109
  }
@@ -678,4 +1111,4 @@ declare class Medal {
678
1111
  /** Convenience factory — equivalent to `new Medal(apiKey, options)`. */
679
1112
  declare function createMedalClient(apiKey: string, options?: MedalOptions): Medal;
680
1113
 
681
- export { type Activity, type AddNoteInput, type ApiResponse, BaseClient, type BatchSendInput, type BatchSendResult, type BatchSendSummary, type Channel, type ConsentRecord, type ConsentResult, type ConsentType, type Contact, type ContactConsents, type ContactCreateResult, type ContactNoteResult, type ContactRemoveResult, type ContactStatus, type ContactUpdateResult, Contacts, type CookieCategoryConsent, type CookieConsentInput, type CreateContactInput, type CreateDealInput, type CreatePostInput, 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, type ImportContactInput, type ImportContactsResult, type ListContactsOptions, type ListDealsOptions, type ListPostsOptions, Medal, MedalApiError, type MedalOptions, type PaginatedResponse, type PaginationOptions, type Post, type PostDetail, type PostType, type PostVariant, Posts, type PublishResult, type RecordConsentInput, type SchedulePostInput, type ScheduleResult, type SendEmailInput, type UpdateContactInput, type UpdateDealInput, type UpdatePostInput, type Workspace, Workspaces, createMedalClient, Medal as default };
1114
+ export { type Activity, type AddNoteInput, type ApiResponse, BaseClient, type BatchSendInput, type BatchSendResult, type BatchSendSummary, type Channel, 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 CreateContactInput, type CreateDealInput, type CreatePostInput, type CreateReplyInput, type CreateWebhookInput, 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 ListContactsOptions, type ListConversationsOptions, type ListDealsOptions, type ListDeliveriesOptions, type ListPostsOptions, Medal, MedalApiError, type MedalOptions, type MessageAuthorType, type MessageDeliveryUpdatedEvent, type MessageReceivedEvent, type MessageSentEvent, type PaginatedResponse, type PaginationOptions, type Post, type PostDetail, type PostType, type PostVariant, Posts, type PublishResult, type RecordConsentInput, type ReplyCreateResult, type RequestOptions, type SchedulePostInput, type ScheduleResult, type SendEmailInput, type TestPingEvent, type UpdateContactInput, type UpdateConversationInput, type UpdateDealInput, type UpdatePostInput, type UpdateWebhookInput, type VerifyWebhookSignatureInput, 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 };