mailchannels-sdk 0.7.4 → 0.7.6

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
@@ -12,10 +12,10 @@ Node.js SDK to integrate [MailChannels API](https://docs.mailchannels.net/) into
12
12
  This library provides a simple way to interact with the [MailChannels API](https://docs.mailchannels.net/). It is written in TypeScript and can be used in both JavaScript and TypeScript projects and in different runtimes.
13
13
  <!-- #endregion overview -->
14
14
 
15
- <!-- #region note -->
15
+ <!-- #region disclaimer -->
16
16
  > [!IMPORTANT]
17
17
  > **Disclaimer**: This library is not associated with [MailChannels Corporation](https://mailchannels.com/).
18
- <!-- #endregion note -->
18
+ <!-- #endregion disclaimer -->
19
19
 
20
20
  - [✨ Release Notes](CHANGELOG.md)
21
21
  - [📖 Documentation](https://mailchannels.yizack.com)
@@ -24,13 +24,19 @@ This library provides a simple way to interact with the [MailChannels API](https
24
24
 
25
25
  - 🚀 [Features](#features)
26
26
  - 📏 [Requirements](#requirements)
27
- - 🏃 [Quick setup](#quick-setup)
28
- - 🚧 [Roadmap](#roadmap)
27
+ - 📦 [Installation](#installation)
28
+ - 📚 [Usage](#usage)
29
+ - 📐 [Naming Conventions](#naming-conventions)
29
30
  - ⚖️ [License](#license)
30
31
  - 💻 [Development](#development)
31
32
 
32
33
  ## <a name="features">🚀 Features</a>
33
34
 
35
+ <!-- #region features -->
36
+ This SDK fully supports all features and operations available in the [MailChannels API](https://docs.mailchannels.net/). It is actively maintained to ensure compatibility and to quickly add support for new API features as they are released.
37
+
38
+ Some of the things you can do with the SDK:
39
+
34
40
  - Send transactional emails
35
41
  - Check DKIM, SPF & Domain Lockdown
36
42
  - Configure DKIM keys
@@ -41,14 +47,18 @@ This library provides a simple way to interact with the [MailChannels API](https
41
47
  - Configure inbound domains
42
48
  - Manage account and recipient lists
43
49
 
50
+ > [!TIP]
51
+ > For a detailed reference mapping each SDK method to its corresponding MailChannels API endpoint reference, see the [SDK-API Mapping](https://mailchannels.yizack.com/sdk-api-mapping)
52
+ <!-- #endregion features -->
53
+
44
54
  ## <a name="requirements">📏 Requirements</a>
45
55
 
46
56
  - [Create a MailChannels account](https://www.mailchannels.com/pricing/#for_devs)
47
57
  - [Create an API key](https://console.mailchannels.net/settings/accountSettings#APIKeys)
48
58
 
49
- ## <a name="quick-setup">🏃 Quick setup</a>
59
+ ## <a name="installation">📦 Installation</a>
50
60
 
51
- 1. Add `mailchannels-sdk` dependency to your project
61
+ Add `mailchannels-sdk` dependency to your project
52
62
 
53
63
  ```sh
54
64
  # npm
@@ -61,92 +71,43 @@ yarn add mailchannels-sdk
61
71
  pnpm add mailchannels-sdk
62
72
  ```
63
73
 
74
+ ## <a name="usage">📚 Usage</a>
75
+
76
+ To authenticate, you'll need an API key. You can create and manage API keys in **Dashboard** > **Account Settings** > **API Keys**.
77
+
78
+ Pass your API key while initializing a new MailChannels client.
79
+
80
+ ```ts
81
+ import { MailChannels } from 'mailchannels-sdk'
82
+
83
+ const mailchannels = new MailChannels('your-api-key')
84
+ ```
85
+
86
+ Send an email:
87
+
88
+ ```ts
89
+ const { data, error } = await mailchannels.emails.send({
90
+ from: 'Name <from@example.com>',
91
+ to: 'to@example.com',
92
+ subject: 'Test email',
93
+ html: '<p>Hello World</p>'
94
+ })
95
+ ```
96
+
97
+ ## <a name="naming-conventions">📐 Naming Conventions</a>
98
+
99
+ <!-- #region naming-conventions -->
100
+ Most properties in the MailChannels API use `snake_case`. To follow JavaScript conventions, the SDK adopts `camelCase` for all properties. This means:
101
+
102
+ - Most options and responses match the API docs, but field names are `camelCase` rather than `snake_case`.
103
+ - Some fields are grouped into nested objects or renamed for simplicity and better developer experience.
104
+ - While most fields match the API docs (just with `camelCase`), a few may be simplified or reorganized to feel more natural for JavaScript developers.
105
+ <!-- #endregion naming-conventions -->
106
+
64
107
  ## <a name="license">⚖️ License</a>
65
108
 
66
109
  [MIT License](LICENSE)
67
110
 
68
- <!-- #region roadmap -->
69
- ## <a name="roadmap">🚧 Roadmap</a>
70
-
71
- Already implemented features are marked with a checkmark. Please open an issue if you find any bugs or missing features.
72
-
73
- > [!NOTE]
74
- > Links below point to the official MailChannels API documentation, options and responses may differ slightly when using this SDK. Please refer to the [documentation](https://mailchannels.yizack.com) for the correct usage of each feature.
75
-
76
- ### [Email API](https://docs.mailchannels.net/email-api/api-reference/email-api)
77
-
78
- - 📧 Emails
79
- - ✅ [Send an Email](https://docs.mailchannels.net/email-api/api-reference/send-an-email)
80
- - ✅ [Send an Email Asynchronously](https://docs.mailchannels.net/email-api/api-reference/send-an-email-asynchronously)
81
- - ✅ [DKIM, SPF & Domain Lockdown Check](https://docs.mailchannels.net/email-api/api-reference/dkim-spf-domain-lockdown-check)
82
- - ✅ [Create DKIM Key Pair](https://docs.mailchannels.net/email-api/api-reference/create-dkim-key-pair)
83
- - ✅ [Retrieve DKIM Keys](https://docs.mailchannels.net/email-api/api-reference/retrieve-dkim-keys)
84
- - ✅ [Update DKIM Key Status](https://docs.mailchannels.net/email-api/api-reference/update-dkim-key-status)
85
- - ✅ [Rotate DKIM Key Pair](https://docs.mailchannels.net/email-api/api-reference/rotate-dkim-key-pair)
86
- - 📢 Webhooks
87
- - ✅ [Enroll for Webhook Notifications](https://docs.mailchannels.net/email-api/api-reference/enroll-for-webhook-notifications)
88
- - ✅ [Retrieve Customer Webhooks](https://docs.mailchannels.net/email-api/api-reference/retrieve-customer-webhooks)
89
- - ✅ [Delete Customer Webhooks](https://docs.mailchannels.net/email-api/api-reference/delete-customer-webhooks)
90
- - ✅ [Retrieve Webhook Signing Key](https://docs.mailchannels.net/email-api/api-reference/retrieve-webhook-signing-key)
91
- - ✅ [Validate Enrolled Webhook](https://docs.mailchannels.net/email-api/api-reference/validate-enrolled-webhook)
92
- - 🪪 Sub-accounts
93
- - ✅ [Create Sub-account](https://docs.mailchannels.net/email-api/api-reference/create-sub-account)
94
- - ✅ [Retrieve Sub-accounts](https://docs.mailchannels.net/email-api/api-reference/retrieve-sub-accounts)
95
- - ✅ [Delete Sub-account](https://docs.mailchannels.net/email-api/api-reference/delete-sub-account)
96
- - ✅ [Suspend Sub-account](https://docs.mailchannels.net/email-api/api-reference/suspend-sub-account)
97
- - ✅ [Activate Sub-account](https://docs.mailchannels.net/email-api/api-reference/activate-sub-account)
98
- - ✅ [Create Sub-account API Key](https://docs.mailchannels.net/email-api/api-reference/create-sub-account-api-key)
99
- - ✅ [Delete Sub-account API Key](https://docs.mailchannels.net/email-api/api-reference/delete-sub-account-api-key)
100
- - ✅ [Retrieve Sub-account API Keys](https://docs.mailchannels.net/email-api/api-reference/retrieve-sub-account-api-keys)
101
- - ✅ [Create Sub-account SMTP Password](https://docs.mailchannels.net/email-api/api-reference/create-sub-account-smtp-password)
102
- - ✅ [Delete Sub-account SMTP Password](https://docs.mailchannels.net/email-api/api-reference/delete-sub-account-smtp-password)
103
- - ✅ [Retrieve Sub-account SMTP Passwords](https://docs.mailchannels.net/email-api/api-reference/retrieve-sub-account-smtp-passwords)
104
- - ✅ [Retrieve Sub-account Limit](https://docs.mailchannels.net/email-api/api-reference/retrieve-sub-account-limit)
105
- - ✅ [Set Sub-account Limit](https://docs.mailchannels.net/email-api/api-reference/set-sub-account-limit)
106
- - ✅ [Delete Sub-account Limit](https://docs.mailchannels.net/email-api/api-reference/delete-sub-account-limit)
107
- - ✅ [Retrieve Sub-account Usage Stats](https://docs.mailchannels.net/email-api/api-reference/retrieve-sub-account-usage-stats)
108
- - 📊 Metrics
109
- - ✅ [Retrieve Engagement Metrics](https://docs.mailchannels.net/email-api/api-reference/retrieve-engagement-metrics)
110
- - ✅ [Retrieve Performance Metrics](https://docs.mailchannels.net/email-api/api-reference/retrieve-performance-metrics)
111
- - ✅ [Retrieve Recipient Behaviour Metrics](https://docs.mailchannels.net/email-api/api-reference/retrieve-recipient-behaviour-metrics)
112
- - ✅ [Retrieve Usage Stats](https://docs.mailchannels.net/email-api/api-reference/retrieve-usage-stats)
113
- - ✅ [Retrieve Volume Metrics](https://docs.mailchannels.net/email-api/api-reference/retrieve-volume-metrics)
114
- - ✅ [Retrieve Sender Metrics](https://docs.mailchannels.net/email-api/api-reference/retrieve-sender-metrics)
115
- - 🚫 Suppressions
116
- - ✅ [Create Suppression Entries](https://docs.mailchannels.net/email-api/api-reference/create-suppression-entries)
117
- - ✅ [Delete Suppression Entry](https://docs.mailchannels.net/email-api/api-reference/delete-suppression-entry)
118
- - ✅ [Retrieve Suppression List](https://docs.mailchannels.net/email-api/api-reference/retrieve-suppression-list)
119
-
120
- ### [Inbound API](https://docs.mailchannels.net/inbound-api/API-reference/inbound-api)
121
-
122
- - 🌐 Domains
123
- - ✅ [Provision domain](https://docs.mailchannels.net/inbound-api/API-reference/provision-domain)
124
- - ✅ [Remove domain](https://docs.mailchannels.net/inbound-api/API-reference/remove-domain)
125
- - ✅ [List domains](https://docs.mailchannels.net/inbound-api/API-reference/list-domains)
126
- - ✅ [Bulk provision domains](https://docs.mailchannels.net/inbound-api/API-reference/bulk-provision-domains)
127
- - ✅ [Add domain list entry](https://docs.mailchannels.net/inbound-api/API-reference/add-domain-list-entry)
128
- - ✅ [Get domain list entries](https://docs.mailchannels.net/inbound-api/API-reference/get-domain-list-entries)
129
- - ✅ [Delete domain list entry](https://docs.mailchannels.net/inbound-api/API-reference/delete-domain-list-entry)
130
- - ✅ [Create login link](https://docs.mailchannels.net/inbound-api/API-reference/create-login-link)
131
- - ✅ [Bulk create login links](https://docs.mailchannels.net/inbound-api/API-reference/bulk-create-login-links)
132
- - ✅ [Set downstream address](https://docs.mailchannels.net/inbound-api/API-reference/set-downstream-address)
133
- - ✅ [Fetch downstream addresses](https://docs.mailchannels.net/inbound-api/API-reference/fetch-downstream-addresses)
134
- - ✅ [Update API key](https://docs.mailchannels.net/inbound-api/API-reference/update-api-key)
135
- - 📋 Lists
136
- - ✅ [Add item to customer list](https://docs.mailchannels.net/inbound-api/API-reference/add-item-to-customer-list)
137
- - ✅ [Delete item from customer list](https://docs.mailchannels.net/inbound-api/API-reference/delete-item-from-customer-list)
138
- - ✅ [Get customer list entries](https://docs.mailchannels.net/inbound-api/API-reference/get-customer-list-entries)
139
- - 📥 Users
140
- - ✅ [Create a recipient](https://docs.mailchannels.net/inbound-api/API-reference/create-a-recipient)
141
- - ✅ [Add item to recipient list](https://docs.mailchannels.net/inbound-api/API-reference/add-item-to-recipient-list)
142
- - ✅ [Get recipient list entries](https://docs.mailchannels.net/inbound-api/API-reference/get-recipient-list-entries)
143
- - ✅ [Delete item from recipient list](https://docs.mailchannels.net/inbound-api/API-reference/delete-item-from-recipient-list)
144
- - ⚙️ Service
145
- - ✅ [Retrieve the condition of the service](https://docs.mailchannels.net/inbound-api/API-reference/retrieve-the-condition-of-the-service)
146
- - ✅ [Submit a false negative or false positive report](https://docs.mailchannels.net/inbound-api/API-reference/submit-a-false-negative-or-false-positive-report)
147
- - ✅ [Get a list of your subscriptions to MailChannels Inbound](https://docs.mailchannels.net/inbound-api/API-reference/get-a-list-of-your-subscriptions-to-mail-channels-inbound)
148
- <!-- #endregion roadmap -->
149
-
150
111
  ## <a name="development">💻 Development</a>
151
112
 
152
113
  <details>
@@ -1,6 +1,4 @@
1
1
  import { FetchOptions } from "ofetch";
2
-
3
- //#region src/client.d.ts
4
2
  declare class MailChannelsClient {
5
3
  #private;
6
4
  private static BASE_URL;
@@ -12,8 +10,6 @@ declare class MailChannelsClient {
12
10
  put<T>(path: string, options?: Omit<FetchOptions<"json">, "method">): Promise<T>;
13
11
  patch<T>(path: string, options?: Omit<FetchOptions<"json">, "method">): Promise<T>;
14
12
  }
15
- //#endregion
16
- //#region src/types/responses.d.ts
17
13
  interface ErrorResponse {
18
14
  message: string;
19
15
  statusCode: number | null;
@@ -47,8 +43,6 @@ type DataResponse<T> = {
47
43
  */
48
44
  error: ErrorResponse;
49
45
  };
50
- //#endregion
51
- //#region src/types/emails/send.d.ts
52
46
  interface EmailsSendRecipient {
53
47
  /**
54
48
  * The email address of the recipient.
@@ -288,8 +282,6 @@ type EmailsSendResponse = SuccessResponse & DataResponse<{
288
282
  status: "sent" | "failed";
289
283
  }[];
290
284
  }>;
291
- //#endregion
292
- //#region src/types/emails/send-async.d.ts
293
285
  type EmailsSendAsyncResponse = DataResponse<{
294
286
  /**
295
287
  * ISO 8601 timestamp when the request was queued for processing.
@@ -300,8 +292,6 @@ type EmailsSendAsyncResponse = DataResponse<{
300
292
  */
301
293
  requestId: string;
302
294
  }>;
303
- //#endregion
304
- //#region src/types/emails/create-dkim-key.d.ts
305
295
  interface EmailsCreateDkimKeyOptions {
306
296
  /**
307
297
  * Algorithm used for the new key pair Currently, only RSA is supported.
@@ -367,8 +357,6 @@ interface EmailsDkimKey {
367
357
  statusModifiedAt?: string;
368
358
  }
369
359
  type EmailsCreateDkimKeyResponse = DataResponse<EmailsDkimKey>;
370
- //#endregion
371
- //#region src/types/emails/check-domain.d.ts
372
360
  interface EmailsCheckDomainDkim {
373
361
  /**
374
362
  * Domain used for DKIM signing.
@@ -457,8 +445,6 @@ type EmailsCheckDomainResponse = DataResponse<{
457
445
  };
458
446
  references?: string[];
459
447
  }>;
460
- //#endregion
461
- //#region src/types/emails/get-dkim-keys.d.ts
462
448
  interface EmailsGetDkimKeysOptions {
463
449
  /**
464
450
  * Selector to filter keys by. Must be a maximum of 63 characters.
@@ -486,8 +472,6 @@ interface EmailsGetDkimKeysOptions {
486
472
  }
487
473
  type Optional<T, K extends keyof T> = Omit<T, K> & Partial<Pick<T, K>>;
488
474
  type EmailsGetDkimKeysResponse = DataResponse<Optional<EmailsDkimKey, "dnsRecords">[]>;
489
- //#endregion
490
- //#region src/types/emails/update-dkim-key.d.ts
491
475
  interface EmailsUpdateDkimKeyOptions {
492
476
  /**
493
477
  * Selector of the DKIM key pair to update. Must be a maximum of 63 characters.
@@ -501,8 +485,6 @@ interface EmailsUpdateDkimKeyOptions {
501
485
  */
502
486
  status: Exclude<EmailsDkimKey["status"], "active">;
503
487
  }
504
- //#endregion
505
- //#region src/types/emails/rotate-dkim-key.d.ts
506
488
  interface EmailsRotateDkimKeyOptions {
507
489
  newKey: {
508
490
  /**
@@ -515,8 +497,6 @@ type EmailsRotateDkimKeyResponse = DataResponse<{
515
497
  new: EmailsDkimKey;
516
498
  rotated: EmailsDkimKey;
517
499
  }>;
518
- //#endregion
519
- //#region src/modules/emails.d.ts
520
500
  declare class Emails {
521
501
  protected mailchannels: MailChannelsClient;
522
502
  constructor(mailchannels: MailChannelsClient);
@@ -631,16 +611,17 @@ declare class Emails {
631
611
  */
632
612
  rotateDkimKey(domain: string, selector: string, options: EmailsRotateDkimKeyOptions): Promise<EmailsRotateDkimKeyResponse>;
633
613
  }
634
- //#endregion
635
- //#region src/types/webhooks/list.d.ts
636
614
  type WebhooksListResponse = DataResponse<string[]>;
637
- //#endregion
638
- //#region src/types/webhooks/signing-key.d.ts
639
615
  type WebhooksSigningKeyResponse = DataResponse<{
616
+ /**
617
+ * The ID of the key.
618
+ */
619
+ id: string;
620
+ /**
621
+ * The public key used to verify webhook signatures.
622
+ */
640
623
  key: string;
641
624
  }>;
642
- //#endregion
643
- //#region src/types/webhooks/validate.d.ts
644
625
  type WebhooksValidateResponse = DataResponse<{
645
626
  /**
646
627
  * Indicates whether all webhook validations passed.
@@ -673,8 +654,92 @@ type WebhooksValidateResponse = DataResponse<{
673
654
  } | null;
674
655
  }[];
675
656
  }>;
676
- //#endregion
677
- //#region src/modules/webhooks.d.ts
657
+ interface WebhooksVerifyOptions {
658
+ /**
659
+ * The raw body of the incoming webhook request as a string. This should be the exact payload received from the webhook, without any modifications or parsing, to ensure accurate signature verification.
660
+ */
661
+ payload: string;
662
+ /**
663
+ * The headers of the incoming webhook request as a record of key-value pairs. These headers should include `content-digest`, `signature`, and `signature-input` required for validating the authenticity of the webhook request.
664
+ */
665
+ headers: Record<string, string> | {
666
+ "content-digest": string;
667
+ "signature": string;
668
+ "signature-input": string;
669
+ };
670
+ /**
671
+ * The public key used to verify the webhook signature. If not provided, the SDK will attempt to retrieve the appropriate public key based on the `keyId` specified in the `signature-input` header.
672
+ */
673
+ publicKey?: string;
674
+ }
675
+ type WebhooksBatchStatus = "1xx" | "2xx" | "3xx" | "4xx" | "5xx" | "no_response";
676
+ type WebhooksBatchResponseStatus = "1xx_response" | "2xx_response" | "3xx_response" | "4xx_response" | "5xx_response" | "no_response";
677
+ interface WebhooksBatchesOptions {
678
+ /**
679
+ * Inclusive lower bound (UTC) for filtering webhook batches by creation time. Formats: `YYYY-MM-DD` or `YYYY-MM-DDTHH:MM:SSZ`.
680
+ */
681
+ createdAfter?: string;
682
+ /**
683
+ * Exclusive upper bound (UTC) for filtering webhook batches by creation time. Formats: `YYYY-MM-DD` or `YYYY-MM-DDTHH:MM:SSZ`.
684
+ */
685
+ createdBefore?: string;
686
+ /**
687
+ * Filters webhook batches by webhook response status category. If not provided, batches with all categories are returned.
688
+ */
689
+ statuses?: WebhooksBatchStatus[];
690
+ /**
691
+ * Filters webhook batches by the webhook endpoint to which events in the batch were posted.
692
+ */
693
+ webhook?: string;
694
+ /**
695
+ * The maximum number of webhook batches to return. Must be between `1` and `500`.
696
+ * @default 500
697
+ */
698
+ limit?: number;
699
+ /**
700
+ * The number of webhook batches to skip before starting to collect the result set.
701
+ * @default 0
702
+ */
703
+ offset?: number;
704
+ }
705
+ interface WebhooksBatch {
706
+ /**
707
+ * Unique identifier for the webhook batch.
708
+ */
709
+ batchId: number;
710
+ /**
711
+ * Timestamp of when the webhook batch was created.
712
+ */
713
+ createdAt: string;
714
+ /**
715
+ * Customer handle associated with the webhook batch.
716
+ */
717
+ customerHandle: string;
718
+ /**
719
+ * Duration of the webhook batch, measured from the time the request was sent to the webhook endpoint until the response was received.
720
+ */
721
+ duration?: {
722
+ unit: "milliseconds";
723
+ value: number;
724
+ };
725
+ /**
726
+ * Number of events in the webhook batch.
727
+ */
728
+ eventCount: number;
729
+ /**
730
+ * Status of the webhook batch.
731
+ */
732
+ status: WebhooksBatchResponseStatus;
733
+ /**
734
+ * HTTP status code returned by the webhook endpoint.
735
+ */
736
+ statusCode: number | null;
737
+ /**
738
+ * Webhook endpoint to which events in the batch were posted.
739
+ */
740
+ webhook: string;
741
+ }
742
+ type WebhooksBatchesResponse = DataResponse<WebhooksBatch[]>;
678
743
  declare class Webhooks {
679
744
  protected mailchannels: MailChannelsClient;
680
745
  constructor(mailchannels: MailChannelsClient);
@@ -726,9 +791,36 @@ declare class Webhooks {
726
791
  * ```
727
792
  */
728
793
  validate(requestId?: string): Promise<WebhooksValidateResponse>;
794
+ /**
795
+ * Verifies the authenticity of incoming webhook requests by validating their signatures using the provided options.
796
+ * @param options - The options for verifying the webhook.
797
+ * @example
798
+ * ```ts
799
+ * const isValid = await Webhooks.verify({ payload: rawBody, headers })
800
+ * ```
801
+ */
802
+ static verify(options: WebhooksVerifyOptions): Promise<boolean>;
803
+ /**
804
+ * Verifies the authenticity of incoming webhook requests by validating their signatures using the provided options.
805
+ * @param options - The options for verifying the webhook.
806
+ * @example
807
+ * ```ts
808
+ * const mailchannels = new MailChannels('your-api-key')
809
+ * const isValid = await mailchannels.webhooks.verify({ payload: rawBody, headers })
810
+ * ```
811
+ */
812
+ verify(options: WebhooksVerifyOptions): Promise<boolean>;
813
+ /**
814
+ * Retrieves paged webhook batches associated with the customer. The time range specified by `createdAfter` and `createdBefore` must not exceed 31 days. If neither is specified, the default time range is the last 3 days.
815
+ * @param options - The options for listing webhook batches.
816
+ * @example
817
+ * ```ts
818
+ * const mailchannels = new MailChannels('your-api-key')
819
+ * const { data, error } = await mailchannels.webhooks.batches()
820
+ * ```
821
+ */
822
+ batches(options?: WebhooksBatchesOptions): Promise<WebhooksBatchesResponse>;
729
823
  }
730
- //#endregion
731
- //#region src/types/sub-accounts/create.d.ts
732
824
  interface SubAccountsAccount {
733
825
  /**
734
826
  * The name of the company associated with the sub-account.
@@ -744,8 +836,6 @@ interface SubAccountsAccount {
744
836
  handle: string;
745
837
  }
746
838
  type SubAccountsCreateResponse = DataResponse<SubAccountsAccount>;
747
- //#endregion
748
- //#region src/types/sub-accounts/list.d.ts
749
839
  interface SubAccountsListOptions {
750
840
  /**
751
841
  * Possible values are `1` to `1000`.
@@ -759,8 +849,6 @@ interface SubAccountsListOptions {
759
849
  offset?: number;
760
850
  }
761
851
  type SubAccountsListResponse = DataResponse<SubAccountsAccount[]>;
762
- //#endregion
763
- //#region src/types/sub-accounts/api-key.d.ts
764
852
  interface SubAccountsApiKey {
765
853
  /**
766
854
  * The API key ID for the sub-account.
@@ -785,8 +873,6 @@ interface SubAccountsListApiKeyOptions {
785
873
  offset?: number;
786
874
  }
787
875
  type SubAccountsListApiKeyResponse = DataResponse<SubAccountsApiKey[]>;
788
- //#endregion
789
- //#region src/types/sub-accounts/smtp-password.d.ts
790
876
  interface SubAccountsSmtpPassword {
791
877
  /**
792
878
  * Whether the SMTP password is enabled.
@@ -803,14 +889,10 @@ interface SubAccountsSmtpPassword {
803
889
  }
804
890
  type SubAccountsCreateSmtpPasswordResponse = DataResponse<SubAccountsSmtpPassword>;
805
891
  type SubAccountsListSmtpPasswordResponse = DataResponse<SubAccountsSmtpPassword[]>;
806
- //#endregion
807
- //#region src/types/sub-accounts/limit.d.ts
808
892
  interface SubAccountsLimit {
809
893
  sends: number;
810
894
  }
811
895
  type SubAccountsLimitResponse = DataResponse<SubAccountsLimit>;
812
- //#endregion
813
- //#region src/types/sub-accounts/usage.d.ts
814
896
  interface SubAccountsUsage {
815
897
  /**
816
898
  * The end date of the current billing period (ISO 8601 format).
@@ -828,8 +910,6 @@ interface SubAccountsUsage {
828
910
  total: number;
829
911
  }
830
912
  type SubAccountsUsageResponse = DataResponse<SubAccountsUsage>;
831
- //#endregion
832
- //#region src/modules/sub-accounts.d.ts
833
913
  declare class SubAccounts {
834
914
  protected mailchannels: MailChannelsClient;
835
915
  private static readonly COMPANY_PATTERN;
@@ -859,6 +939,7 @@ declare class SubAccounts {
859
939
  /**
860
940
  * Deletes the sub-account identified by its handle.
861
941
  * @param handle - Handle of sub-account to be deleted.
942
+ * @example
862
943
  * ```ts
863
944
  * const mailchannels = new MailChannels('your-api-key')
864
945
  * const { success, error } = await mailchannels.subAccounts.delete('validhandle123')
@@ -990,8 +1071,6 @@ declare class SubAccounts {
990
1071
  */
991
1072
  getUsage(handle: string): Promise<SubAccountsUsageResponse>;
992
1073
  }
993
- //#endregion
994
- //#region src/types/metrics/engagement.d.ts
995
1074
  interface MetricsEngagement {
996
1075
  /**
997
1076
  * A series of metrics aggregations bucketed by time interval (e.g. hour, day).
@@ -1010,8 +1089,6 @@ interface MetricsEngagement {
1010
1089
  startTime: string;
1011
1090
  }
1012
1091
  type MetricsEngagementResponse = DataResponse<MetricsEngagement>;
1013
- //#endregion
1014
- //#region src/types/metrics/performance.d.ts
1015
1092
  interface MetricsPerformance {
1016
1093
  /**
1017
1094
  * Count of messages bounced during the specified time range.
@@ -1043,8 +1120,6 @@ interface MetricsPerformance {
1043
1120
  startTime: string;
1044
1121
  }
1045
1122
  type MetricsPerformanceResponse = DataResponse<MetricsPerformance>;
1046
- //#endregion
1047
- //#region src/types/metrics/recipient-behaviour.d.ts
1048
1123
  interface MetricsRecipientBehaviour {
1049
1124
  /**
1050
1125
  * A series of metrics aggregations bucketed by time interval (e.g. hour, day).
@@ -1071,8 +1146,6 @@ interface MetricsRecipientBehaviour {
1071
1146
  unsubscribed: number;
1072
1147
  }
1073
1148
  type MetricsRecipientBehaviourResponse = DataResponse<MetricsRecipientBehaviour>;
1074
- //#endregion
1075
- //#region src/types/metrics/volume.d.ts
1076
1149
  interface MetricsVolume {
1077
1150
  /**
1078
1151
  * A series of metrics aggregations bucketed by time interval (e.g. hour, day).
@@ -1104,8 +1177,6 @@ interface MetricsVolume {
1104
1177
  startTime: string;
1105
1178
  }
1106
1179
  type MetricsVolumeResponse = DataResponse<MetricsVolume>;
1107
- //#endregion
1108
- //#region src/types/metrics/usage.d.ts
1109
1180
  type MetricsUsageResponse = DataResponse<{
1110
1181
  /**
1111
1182
  * The end date of the current billing period (ISO 8601 format).
@@ -1122,8 +1193,6 @@ type MetricsUsageResponse = DataResponse<{
1122
1193
  */
1123
1194
  total: number;
1124
1195
  }>;
1125
- //#endregion
1126
- //#region src/types/metrics/senders.d.ts
1127
1196
  type MetricsSendersType = "sub-accounts" | "campaigns";
1128
1197
  interface MetricsSendersOptions {
1129
1198
  /**
@@ -1173,8 +1242,6 @@ interface MetricsSenders {
1173
1242
  total: number;
1174
1243
  }
1175
1244
  type MetricsSendersResponse = DataResponse<MetricsSenders>;
1176
- //#endregion
1177
- //#region src/types/metrics/index.d.ts
1178
1245
  interface MetricsBucket {
1179
1246
  /**
1180
1247
  * The number of events or occurrences aggregated within this time period.
@@ -1206,8 +1273,6 @@ interface MetricsOptions {
1206
1273
  */
1207
1274
  interval?: "hour" | "day" | "week" | "month";
1208
1275
  }
1209
- //#endregion
1210
- //#region src/modules/metrics.d.ts
1211
1276
  declare class Metrics {
1212
1277
  protected mailchannels: MailChannelsClient;
1213
1278
  constructor(mailchannels: MailChannelsClient);
@@ -1272,8 +1337,6 @@ declare class Metrics {
1272
1337
  */
1273
1338
  senders(type: MetricsSendersType, options?: MetricsSendersOptions): Promise<MetricsSendersResponse>;
1274
1339
  }
1275
- //#endregion
1276
- //#region src/types/suppressions/create.d.ts
1277
1340
  type SuppressionsTypes = "transactional" | "non-transactional";
1278
1341
  interface SuppressionsCreateOptions {
1279
1342
  /**
@@ -1300,8 +1363,6 @@ interface SuppressionsCreateOptions {
1300
1363
  types?: SuppressionsTypes[];
1301
1364
  }[];
1302
1365
  }
1303
- //#endregion
1304
- //#region src/types/suppressions/list.d.ts
1305
1366
  type SuppressionsSource = "api" | "unsubscribe_link" | "list_unsubscribe" | "hard_bounce" | "spam_complaint" | "all";
1306
1367
  interface SuppressionsListOptions {
1307
1368
  /**
@@ -1343,8 +1404,6 @@ interface SuppressionsListEntry {
1343
1404
  types: SuppressionsTypes[];
1344
1405
  }
1345
1406
  type SuppressionsListResponse = DataResponse<SuppressionsListEntry[]>;
1346
- //#endregion
1347
- //#region src/modules/suppressions.d.ts
1348
1407
  declare class Suppressions {
1349
1408
  protected mailchannels: MailChannelsClient;
1350
1409
  constructor(mailchannels: MailChannelsClient);
@@ -1372,17 +1431,15 @@ declare class Suppressions {
1372
1431
  delete(recipient: string, source?: SuppressionsSource): Promise<SuccessResponse>;
1373
1432
  /**
1374
1433
  * Retrieve suppression entries associated with the specified account. Supports filtering by recipient, source and creation date range. The response is paginated, with a default limit of `1000` entries per page and an offset of `0`.
1434
+ * @param options - Options to filter and customize the suppression entries retrieval.
1375
1435
  * @example
1376
1436
  * ```ts
1377
1437
  * const mailchannels = new MailChannels('your-api-key')
1378
1438
  * const { data, error } = await mailchannels.suppressions.list();
1379
1439
  * ```
1380
- * @param options - Options to filter and customize the suppression entries retrieval.
1381
1440
  */
1382
1441
  list(options?: SuppressionsListOptions): Promise<SuppressionsListResponse>;
1383
1442
  }
1384
- //#endregion
1385
- //#region src/types/lists/entry.d.ts
1386
1443
  type ListNames = "blocklist" | "safelist" | "blacklist" | "whitelist";
1387
1444
  interface ListEntryOptions {
1388
1445
  /**
@@ -1401,8 +1458,6 @@ interface ListEntry {
1401
1458
  }
1402
1459
  type ListEntryResponse = DataResponse<ListEntry>;
1403
1460
  type ListEntriesResponse = DataResponse<ListEntry[]>;
1404
- //#endregion
1405
- //#region src/types/domains/provision.d.ts
1406
1461
  interface DomainsData {
1407
1462
  /**
1408
1463
  * The domain name.
@@ -1499,8 +1554,6 @@ type DomainsBulkProvisionResponse = DataResponse<{
1499
1554
  comment?: string;
1500
1555
  }[];
1501
1556
  }>;
1502
- //#endregion
1503
- //#region src/types/domains/list.d.ts
1504
1557
  interface DomainsListOptions {
1505
1558
  /**
1506
1559
  * A list of domains to fetch. If this parameter is present, only domains whose name matches an item in this list are returned.
@@ -1527,8 +1580,6 @@ type DomainsListResponse = DataResponse<{
1527
1580
  */
1528
1581
  total: number;
1529
1582
  }>;
1530
- //#endregion
1531
- //#region src/types/domains/create-login-link.d.ts
1532
1583
  interface DomainsCreateLoginLink {
1533
1584
  /**
1534
1585
  * If a user browses to this URL, they will be automatically logged in as a domain admin.
@@ -1536,8 +1587,6 @@ interface DomainsCreateLoginLink {
1536
1587
  link: string;
1537
1588
  }
1538
1589
  type DomainsCreateLoginLinkResponse = DataResponse<DomainsCreateLoginLink>;
1539
- //#endregion
1540
- //#region src/types/domains/downstream-addresses.d.ts
1541
1590
  interface DomainsListDownstreamAddressesOptions {
1542
1591
  /**
1543
1592
  * The number of records to return.
@@ -1569,8 +1618,6 @@ interface DomainsDownstreamAddress {
1569
1618
  weight: number;
1570
1619
  }
1571
1620
  type DomainsListDownstreamAddressesResponse = DataResponse<DomainsDownstreamAddress[]>;
1572
- //#endregion
1573
- //#region src/types/domains/bulk-create-login-links.d.ts
1574
1621
  interface DomainsBulkCreateLoginLinkResult {
1575
1622
  /**
1576
1623
  * The domain the request was for.
@@ -1591,8 +1638,6 @@ interface DomainsBulkCreateLoginLinks {
1591
1638
  errors: Omit<DomainsBulkCreateLoginLinkResult, "loginLink">[];
1592
1639
  }
1593
1640
  type DomainsBulkCreateLoginLinksResponse = DataResponse<DomainsBulkCreateLoginLinks>;
1594
- //#endregion
1595
- //#region src/modules/domains.d.ts
1596
1641
  declare class Domains {
1597
1642
  protected mailchannels: MailChannelsClient;
1598
1643
  constructor(mailchannels: MailChannelsClient);
@@ -1750,8 +1795,6 @@ declare class Domains {
1750
1795
  */
1751
1796
  bulkCreateLoginLinks(domains: string[]): Promise<DomainsBulkCreateLoginLinksResponse>;
1752
1797
  }
1753
- //#endregion
1754
- //#region src/modules/lists.d.ts
1755
1798
  declare class Lists {
1756
1799
  protected mailchannels: MailChannelsClient;
1757
1800
  constructor(mailchannels: MailChannelsClient);
@@ -1792,8 +1835,6 @@ declare class Lists {
1792
1835
  */
1793
1836
  deleteListEntry(options: ListEntryOptions): Promise<SuccessResponse>;
1794
1837
  }
1795
- //#endregion
1796
- //#region src/types/users/create.d.ts
1797
1838
  interface UsersCreateOptions {
1798
1839
  /**
1799
1840
  * Flag to indicate if the user is a domain admin or a regular user.
@@ -1826,8 +1867,6 @@ type UsersCreateResponse = DataResponse<{
1826
1867
  action: "safelist" | "blocklist";
1827
1868
  }[];
1828
1869
  }>;
1829
- //#endregion
1830
- //#region src/modules/users.d.ts
1831
1870
  declare class Users {
1832
1871
  protected mailchannels: MailChannelsClient;
1833
1872
  constructor(mailchannels: MailChannelsClient);
@@ -1884,8 +1923,6 @@ declare class Users {
1884
1923
  */
1885
1924
  deleteListEntry(email: string, options: ListEntryOptions): Promise<SuccessResponse>;
1886
1925
  }
1887
- //#endregion
1888
- //#region src/types/service/subscriptions.d.ts
1889
1926
  type ServiceSubscriptionsResponse = DataResponse<{
1890
1927
  active: boolean;
1891
1928
  activeAccountsCount: number;
@@ -1899,8 +1936,6 @@ type ServiceSubscriptionsResponse = DataResponse<{
1899
1936
  name: string;
1900
1937
  };
1901
1938
  }[]>;
1902
- //#endregion
1903
- //#region src/types/service/report.d.ts
1904
1939
  interface ServiceReportOptions {
1905
1940
  /**
1906
1941
  * The report type. It can be either `false_negative` or `false_positive`.
@@ -1914,19 +1949,17 @@ interface ServiceReportOptions {
1914
1949
  * The SMTP envelope information.
1915
1950
  */
1916
1951
  smtpEnvelopeInformation?: {
1917
- ehlo: string;
1918
- mailFrom: string;
1919
- rcptTo: string;
1952
+ ehlo?: string;
1953
+ mailFrom?: string;
1954
+ rcptTo?: string;
1920
1955
  };
1921
1956
  /**
1922
1957
  * The sending host information.
1923
1958
  */
1924
1959
  sendingHostInformation?: {
1925
- name: string;
1960
+ name?: string;
1926
1961
  };
1927
1962
  }
1928
- //#endregion
1929
- //#region src/modules/service.d.ts
1930
1963
  declare class Service {
1931
1964
  protected mailchannels: MailChannelsClient;
1932
1965
  constructor(mailchannels: MailChannelsClient);
@@ -1961,8 +1994,79 @@ declare class Service {
1961
1994
  */
1962
1995
  report(options: ServiceReportOptions): Promise<SuccessResponse>;
1963
1996
  }
1964
- //#endregion
1965
- //#region src/mailchannels.d.ts
1997
+ type WebhookEventType = "processed" | "delivered" | "open" | "click" | "hard-bounced" | "soft-bounced" | "dropped" | "complained" | "unsubscribed" | "test";
1998
+ interface WebhookEventBase<T extends WebhookEventType> {
1999
+ /**
2000
+ * The sender's email address
2001
+ */
2002
+ email?: string;
2003
+ /**
2004
+ * The MailChannels account ID that generated the webhook.
2005
+ * If the message was sent by a sub-account, this field contains the sub-account handle.
2006
+ */
2007
+ customer_handle: string;
2008
+ /**
2009
+ * The Unix timestamp (in seconds) when the event occurred; the timezone is always UTC
2010
+ */
2011
+ timestamp: number;
2012
+ /**
2013
+ * The Message-Id of the message that generated the event
2014
+ */
2015
+ smtp_id?: string;
2016
+ /**
2017
+ * The type of event that occurred
2018
+ */
2019
+ event: T;
2020
+ /**
2021
+ * A unique identifier generated to track the original HTTP request
2022
+ */
2023
+ request_id?: string;
2024
+ /**
2025
+ * The campaign identifier for the message that generated the event
2026
+ */
2027
+ campaign_id?: string;
2028
+ /**
2029
+ * The recipients of the message
2030
+ */
2031
+ recipients?: string[];
2032
+ }
2033
+ interface WebhookEventProcessed extends WebhookEventBase<"processed"> {}
2034
+ interface WebhookEventDelivered extends WebhookEventBase<"delivered"> {}
2035
+ interface WebhookEventWithTracking {
2036
+ /**
2037
+ * The User-Agent header given when the recipient opened the message
2038
+ */
2039
+ user_agent?: string;
2040
+ /**
2041
+ * The IP address of the host that made the HTTP request
2042
+ */
2043
+ ip?: string;
2044
+ }
2045
+ interface WebhookEventOpen extends WebhookEventBase<"open">, WebhookEventWithTracking {}
2046
+ interface WebhookEventClick extends WebhookEventBase<"click">, WebhookEventWithTracking {
2047
+ /**
2048
+ * The URL that was clicked by the recipient
2049
+ */
2050
+ url?: string;
2051
+ }
2052
+ interface WebhookEventWithStatus {
2053
+ /**
2054
+ * The SMTP status code that caused the bounce
2055
+ */
2056
+ status?: string;
2057
+ /**
2058
+ * A human-readable explanation of why the message hard-bounced
2059
+ */
2060
+ reason?: string;
2061
+ }
2062
+ interface WebhookEventHardBounced extends WebhookEventBase<"hard-bounced">, WebhookEventWithStatus {}
2063
+ interface WebhookEventSoftBounced extends WebhookEventBase<"soft-bounced">, WebhookEventWithStatus {}
2064
+ interface WebhookEventDropped extends WebhookEventBase<"dropped">, WebhookEventWithStatus {}
2065
+ interface WebhookEventComplained extends WebhookEventBase<"complained"> {}
2066
+ interface WebhookEventUnsubscribed extends WebhookEventBase<"unsubscribed"> {}
2067
+ interface WebhookEventTest extends Omit<WebhookEventBase<"test">, "recipients" | "campaign_id"> {}
2068
+ type WebhookEvent = WebhookEventProcessed | WebhookEventDelivered | WebhookEventOpen | WebhookEventClick | WebhookEventHardBounced | WebhookEventSoftBounced | WebhookEventDropped | WebhookEventComplained | WebhookEventUnsubscribed | WebhookEventTest;
2069
+ type WebhookEvents = WebhookEvent[];
1966
2070
  declare class MailChannels extends MailChannelsClient {
1967
2071
  readonly emails: Emails;
1968
2072
  readonly webhooks: Webhooks;
@@ -1975,5 +2079,4 @@ declare class MailChannels extends MailChannelsClient {
1975
2079
  readonly service: Service;
1976
2080
  constructor(key: string);
1977
2081
  }
1978
- //#endregion
1979
- export { DataResponse, Domains, DomainsBulkCreateLoginLinks, DomainsBulkCreateLoginLinksResponse, DomainsBulkProvisionOptions, DomainsBulkProvisionResponse, DomainsCreateLoginLink, DomainsCreateLoginLinkResponse, DomainsData, DomainsDownstreamAddress, DomainsListDownstreamAddressesOptions, DomainsListDownstreamAddressesResponse, DomainsListOptions, DomainsListResponse, DomainsProvisionOptions, DomainsProvisionResponse, Emails, EmailsCheckDomainOptions, EmailsCheckDomainResponse, EmailsCheckDomainVerdict, EmailsCreateDkimKeyOptions, EmailsCreateDkimKeyResponse, EmailsDkimKey, EmailsDkimKeyStatus, EmailsGetDkimKeysOptions, EmailsGetDkimKeysResponse, EmailsRotateDkimKeyOptions, EmailsRotateDkimKeyResponse, EmailsSendAsyncResponse, EmailsSendAttachment, EmailsSendOptions, EmailsSendRecipient, EmailsSendResponse, EmailsSendTracking, EmailsUpdateDkimKeyOptions, ErrorResponse, ListEntriesResponse, ListEntry, ListEntryOptions, ListEntryResponse, ListNames, Lists, MailChannels, MailChannelsClient, Metrics, MetricsBucket, MetricsEngagement, MetricsEngagementResponse, MetricsOptions, MetricsPerformance, MetricsPerformanceResponse, MetricsRecipientBehaviour, MetricsRecipientBehaviourResponse, MetricsSenders, MetricsSendersOptions, MetricsSendersResponse, MetricsSendersType, MetricsUsageResponse, MetricsVolume, MetricsVolumeResponse, Service, ServiceReportOptions, ServiceSubscriptionsResponse, SubAccounts, SubAccountsAccount, SubAccountsApiKey, SubAccountsCreateApiKeyResponse, SubAccountsCreateResponse, SubAccountsCreateSmtpPasswordResponse, SubAccountsLimit, SubAccountsLimitResponse, SubAccountsListApiKeyOptions, SubAccountsListApiKeyResponse, SubAccountsListOptions, SubAccountsListResponse, SubAccountsListSmtpPasswordResponse, SubAccountsSmtpPassword, SubAccountsUsage, SubAccountsUsageResponse, SuccessResponse, Suppressions, SuppressionsCreateOptions, SuppressionsListEntry, SuppressionsListOptions, SuppressionsListResponse, SuppressionsSource, SuppressionsTypes, Users, UsersCreateOptions, UsersCreateResponse, Webhooks, WebhooksListResponse, WebhooksSigningKeyResponse, WebhooksValidateResponse };
2082
+ export { DataResponse, Domains, DomainsBulkCreateLoginLinks, DomainsBulkCreateLoginLinksResponse, DomainsBulkProvisionOptions, DomainsBulkProvisionResponse, DomainsCreateLoginLink, DomainsCreateLoginLinkResponse, DomainsData, DomainsDownstreamAddress, DomainsListDownstreamAddressesOptions, DomainsListDownstreamAddressesResponse, DomainsListOptions, DomainsListResponse, DomainsProvisionOptions, DomainsProvisionResponse, Emails, EmailsCheckDomainOptions, EmailsCheckDomainResponse, EmailsCheckDomainVerdict, EmailsCreateDkimKeyOptions, EmailsCreateDkimKeyResponse, EmailsDkimKey, EmailsDkimKeyStatus, EmailsGetDkimKeysOptions, EmailsGetDkimKeysResponse, EmailsRotateDkimKeyOptions, EmailsRotateDkimKeyResponse, EmailsSendAsyncResponse, EmailsSendAttachment, EmailsSendOptions, EmailsSendRecipient, EmailsSendResponse, EmailsSendTracking, EmailsUpdateDkimKeyOptions, ErrorResponse, ListEntriesResponse, ListEntry, ListEntryOptions, ListEntryResponse, ListNames, Lists, MailChannels, MailChannelsClient, Metrics, MetricsBucket, MetricsEngagement, MetricsEngagementResponse, MetricsOptions, MetricsPerformance, MetricsPerformanceResponse, MetricsRecipientBehaviour, MetricsRecipientBehaviourResponse, MetricsSenders, MetricsSendersOptions, MetricsSendersResponse, MetricsSendersType, MetricsUsageResponse, MetricsVolume, MetricsVolumeResponse, Service, ServiceReportOptions, ServiceSubscriptionsResponse, SubAccounts, SubAccountsAccount, SubAccountsApiKey, SubAccountsCreateApiKeyResponse, SubAccountsCreateResponse, SubAccountsCreateSmtpPasswordResponse, SubAccountsLimit, SubAccountsLimitResponse, SubAccountsListApiKeyOptions, SubAccountsListApiKeyResponse, SubAccountsListOptions, SubAccountsListResponse, SubAccountsListSmtpPasswordResponse, SubAccountsSmtpPassword, SubAccountsUsage, SubAccountsUsageResponse, SuccessResponse, Suppressions, SuppressionsCreateOptions, SuppressionsListEntry, SuppressionsListOptions, SuppressionsListResponse, SuppressionsSource, SuppressionsTypes, Users, UsersCreateOptions, UsersCreateResponse, WebhookEvent, WebhookEventClick, WebhookEventComplained, WebhookEventDelivered, WebhookEventDropped, WebhookEventHardBounced, WebhookEventOpen, WebhookEventProcessed, WebhookEventSoftBounced, WebhookEventTest, WebhookEventType, WebhookEventUnsubscribed, WebhookEvents, Webhooks, WebhooksBatch, WebhooksBatchResponseStatus, WebhooksBatchStatus, WebhooksBatchesOptions, WebhooksBatchesResponse, WebhooksListResponse, WebhooksSigningKeyResponse, WebhooksValidateResponse, WebhooksVerifyOptions };
@@ -1,4 +1,6 @@
1
1
  import { $fetch } from "ofetch";
2
+ import { subtle } from "node:crypto";
3
+ import { Buffer } from "node:buffer";
2
4
  var MailChannelsClient = class MailChannelsClient {
3
5
  static BASE_URL = "https://api.mailchannels.net";
4
6
  #headers;
@@ -505,7 +507,73 @@ var Emails = class {
505
507
  };
506
508
  }
507
509
  };
508
- var Webhooks = class {
510
+ const HMAC_SHA256 = {
511
+ name: "HMAC",
512
+ hash: "SHA-256"
513
+ };
514
+ const ED25519 = {
515
+ name: "Ed25519",
516
+ namedCurve: "Ed25519"
517
+ };
518
+ const encoder = new TextEncoder();
519
+ const HEADER_CONTENT_DIGEST = "content-digest";
520
+ const HEADER_SIGNATURE = "signature";
521
+ const HEADER_SIGNATURE_INPUT = "signature-input";
522
+ const validateContentDigest = async (header, body) => {
523
+ const match = header.match(/^(.*?)=:(.*?):$/);
524
+ if (!match) return false;
525
+ const [, algorithm, hash] = match;
526
+ if (!algorithm || !hash) return false;
527
+ const normalizedAlgorithm = algorithm.replace("-", "").toLowerCase();
528
+ if (!["sha256"].includes(normalizedAlgorithm)) return false;
529
+ const signatureBuffer = await subtle.digest(HMAC_SHA256.hash, encoder.encode(body));
530
+ return Buffer.from(signatureBuffer).toString("base64") === hash;
531
+ };
532
+ const extractSignature = (signatureHeader) => {
533
+ const signatureMatch = signatureHeader.match(/sig_\d+=:([^:]+):/);
534
+ return signatureMatch && signatureMatch[1] ? signatureMatch[1] : null;
535
+ };
536
+ const extractInputValues = (header) => {
537
+ const match = header.match(/^(\w+)=\(([^)]+)\);created=(\d+);alg="([^"]+)";keyid="([^"]+)"$/);
538
+ if (!match) return null;
539
+ return {
540
+ name: match[1],
541
+ timestamp: Number.parseInt(match[3], 10),
542
+ algorithm: match[4],
543
+ keyId: match[5]
544
+ };
545
+ };
546
+ async function isValidWebhook(options) {
547
+ const { payload, headers } = options;
548
+ const contentDigest = headers[HEADER_CONTENT_DIGEST];
549
+ const messageSignature = headers[HEADER_SIGNATURE];
550
+ const signatureInput = headers[HEADER_SIGNATURE_INPUT];
551
+ if (!payload || !contentDigest || !messageSignature || !signatureInput || !await validateContentDigest(contentDigest, payload)) return false;
552
+ const signature = extractSignature(messageSignature);
553
+ if (!signature) return false;
554
+ const values = extractInputValues(signatureInput);
555
+ if (!values) return false;
556
+ if (Math.floor(Date.now() / 1e3) - values.timestamp > 300) return false;
557
+ const signingString = `"content-digest": ${contentDigest}
558
+ "@signature-params": ("content-digest");created=${values.timestamp};alg="${values.algorithm}";keyid="${values.keyId}"`;
559
+ let publicKey = options.publicKey;
560
+ if (!publicKey) {
561
+ const publicKeyResponse = await $fetch("/tx/v1/webhook/public-key", {
562
+ baseURL: "https://api.mailchannels.net",
563
+ query: { id: values.keyId }
564
+ }).catch(() => null);
565
+ if (!publicKeyResponse) return false;
566
+ publicKey = publicKeyResponse.key;
567
+ }
568
+ publicKey = stripPemHeaders(publicKey);
569
+ const encoding = "base64";
570
+ const format = "spki";
571
+ const publicKeyBuffer = Buffer.from(publicKey, encoding);
572
+ const webhookSignatureBuffer = Buffer.from(signature, encoding);
573
+ const key = await subtle.importKey(format, publicKeyBuffer, ED25519, false, ["verify"]);
574
+ return subtle.verify(ED25519.name, key, webhookSignatureBuffer, encoder.encode(signingString));
575
+ }
576
+ var Webhooks = class Webhooks {
509
577
  constructor(mailchannels) {
510
578
  this.mailchannels = mailchannels;
511
579
  }
@@ -586,7 +654,10 @@ var Webhooks = class {
586
654
  error
587
655
  };
588
656
  return {
589
- data: clean({ key: response.key }),
657
+ data: clean({
658
+ id: response.id,
659
+ key: response.key
660
+ }),
590
661
  error: null
591
662
  };
592
663
  }
@@ -623,6 +694,56 @@ var Webhooks = class {
623
694
  error: null
624
695
  };
625
696
  }
697
+ static async verify(options) {
698
+ return isValidWebhook(options).catch(() => false);
699
+ }
700
+ async verify(options) {
701
+ return Webhooks.verify(options);
702
+ }
703
+ async batches(options) {
704
+ let error = null;
705
+ error = validatePagination({
706
+ ...options,
707
+ max: 500
708
+ });
709
+ if (error) return {
710
+ data: null,
711
+ error
712
+ };
713
+ const response = await this.mailchannels.get("/tx/v1/webhook-batch", {
714
+ query: {
715
+ created_after: options?.createdAfter,
716
+ created_before: options?.createdBefore,
717
+ statuses: options?.statuses,
718
+ webhook: options?.webhook,
719
+ limit: options?.limit,
720
+ offset: options?.offset
721
+ },
722
+ onResponseError: async ({ response }) => {
723
+ error = getStatusError(response, { [ErrorCode.BadRequest]: "Bad Request." });
724
+ }
725
+ }).catch((e) => {
726
+ error ||= getResultError(e, "Failed to fetch webhook batches.");
727
+ return null;
728
+ });
729
+ if (!response) return {
730
+ data: null,
731
+ error
732
+ };
733
+ return {
734
+ data: clean(response.webhook_batches.map((batch) => ({
735
+ batchId: batch.batch_id,
736
+ createdAt: batch.created_at,
737
+ customerHandle: batch.customer_handle,
738
+ duration: batch.duration,
739
+ eventCount: batch.event_count,
740
+ status: batch.status,
741
+ statusCode: batch.status_code,
742
+ webhook: batch.webhook
743
+ }))),
744
+ error: null
745
+ };
746
+ }
626
747
  };
627
748
  var SubAccounts = class SubAccounts {
628
749
  static COMPANY_PATTERN = /^.{3,128}$/;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mailchannels-sdk",
3
- "version": "0.7.4",
3
+ "version": "0.7.6",
4
4
  "description": "Node.js SDK to integrate MailChannels API into your JavaScript or TypeScript server-side applications.",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -37,20 +37,20 @@
37
37
  "ofetch": "^2.0.0-alpha.3"
38
38
  },
39
39
  "devDependencies": {
40
- "@stylistic/eslint-plugin": "^5.8.0",
40
+ "@stylistic/eslint-plugin": "^5.10.0",
41
41
  "@types/markdown-it": "^14.1.2",
42
- "@types/node": "^25.2.3",
43
- "@vitest/coverage-v8": "^4.0.18",
42
+ "@types/node": "^25.5.2",
43
+ "@vitest/coverage-v8": "^4.1.2",
44
44
  "changelogen": "^0.6.2",
45
45
  "jiti": "^2.6.1",
46
- "obuild": "^0.4.27",
47
- "oxlint": "^1.47.0",
46
+ "obuild": "^0.4.33",
47
+ "oxlint": "^1.58.0",
48
48
  "scule": "^1.3.0",
49
- "typescript": "^5.9.3",
50
- "vitepress": "^2.0.0-alpha.16",
51
- "vitepress-plugin-group-icons": "^1.7.1",
52
- "vitepress-plugin-llms": "^1.11.0",
53
- "vitest": "^4.0.18"
49
+ "typescript": "^6.0.2",
50
+ "vitepress": "^2.0.0-alpha.17",
51
+ "vitepress-plugin-group-icons": "^1.7.3",
52
+ "vitepress-plugin-llms": "^1.12.0",
53
+ "vitest": "^4.1.2"
54
54
  },
55
55
  "scripts": {
56
56
  "build": "obuild",