supersendtx 0.3.0 → 0.6.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.
package/dist/index.d.ts CHANGED
@@ -1,3 +1,4 @@
1
+ type ApiErrorCode = 'validation_error' | 'unauthorized' | 'forbidden' | 'not_found' | 'conflict' | 'plan_limit' | 'domain_limit' | 'idempotency_conflict' | 'rate_limited' | 'upstream_error' | 'not_configured' | 'internal_error';
1
2
  type SendEmailParams = {
2
3
  from: string | {
3
4
  email: string;
@@ -7,23 +8,63 @@ type SendEmailParams = {
7
8
  subject: string;
8
9
  html?: string;
9
10
  text?: string;
10
- replyTo?: string;
11
- reply_to?: string;
11
+ replyTo?: string | string[];
12
+ reply_to?: string | string[];
12
13
  cc?: string | string[];
13
14
  bcc?: string | string[];
15
+ tags?: Array<{
16
+ name: string;
17
+ value: string;
18
+ }> | Record<string, string>;
19
+ headers?: Record<string, string>;
20
+ tag?: string;
21
+ attachments?: Array<{
22
+ name: string;
23
+ content_type: string;
24
+ data: string;
25
+ content_id?: string;
26
+ }>;
27
+ scheduledAt?: string | Date;
28
+ scheduled_at?: string | Date;
29
+ /** Optional Idempotency-Key (24h TTL). */
30
+ idempotencyKey?: string;
14
31
  };
15
32
  type SendEmailResult = {
16
33
  id: string;
17
34
  status: string;
18
35
  };
36
+ type BatchSendEmailResult = {
37
+ data: Array<{
38
+ index: number;
39
+ id?: string;
40
+ status?: string;
41
+ error?: {
42
+ message: string;
43
+ code?: string;
44
+ details?: unknown;
45
+ status_code?: number;
46
+ };
47
+ }>;
48
+ };
49
+ type UpdateEmailParams = {
50
+ scheduledAt?: string | Date;
51
+ scheduled_at?: string | Date;
52
+ cancel?: boolean;
53
+ };
19
54
  type EmailListItem = {
20
55
  id: string;
21
56
  from: string;
22
57
  to: string[];
58
+ cc: string[];
59
+ bcc: string[];
60
+ reply_to: string[];
23
61
  subject: string;
24
62
  status: string;
25
63
  last_event: string | null;
26
64
  bounce_reason: string | null;
65
+ tags: unknown;
66
+ scheduled_at: string | null;
67
+ cancelled_at: string | null;
27
68
  created_at: string;
28
69
  sent_at: string | null;
29
70
  delivered_at: string | null;
@@ -31,8 +72,44 @@ type EmailListItem = {
31
72
  };
32
73
  type ListEmailsParams = {
33
74
  limit?: number;
75
+ cursor?: string;
76
+ };
77
+ type ListEmailsResult = {
78
+ emails: EmailListItem[];
79
+ has_more: boolean;
80
+ next_cursor: string | null;
81
+ };
82
+ type ApiKeyScope = 'full' | 'sending';
83
+ type ApiKey = {
84
+ id: string;
85
+ name: string;
86
+ scope: ApiKeyScope;
87
+ prefix: string;
88
+ created_at: string;
89
+ last_used_at: string | null;
90
+ };
91
+ type ListApiKeysParams = {
92
+ limit?: number;
93
+ cursor?: string;
34
94
  };
35
- type WebhookEventType = 'email.delivered' | 'email.bounced';
95
+ type ListApiKeysResult = {
96
+ data: ApiKey[];
97
+ has_more: boolean;
98
+ next_cursor: string | null;
99
+ };
100
+ type CreateApiKeyParams = {
101
+ name?: string;
102
+ scope?: ApiKeyScope;
103
+ };
104
+ type CreateApiKeyResult = {
105
+ id: string;
106
+ name: string;
107
+ scope: ApiKeyScope;
108
+ prefix: string;
109
+ token: string;
110
+ created_at: string;
111
+ };
112
+ type WebhookEventType = 'email.sent' | 'email.delivered' | 'email.delivery_delayed' | 'email.bounced' | 'email.complained' | 'email.opened' | 'email.clicked' | 'email.failed' | 'email.suppressed' | 'email.scheduled';
36
113
  type WebhookEndpoint = {
37
114
  id: string;
38
115
  url: string;
@@ -45,10 +122,37 @@ type CreateWebhookParams = {
45
122
  url: string;
46
123
  events?: WebhookEventType[];
47
124
  };
125
+ type UpdateWebhookParams = {
126
+ url?: string;
127
+ events?: WebhookEventType[];
128
+ enabled?: boolean;
129
+ };
48
130
  type WebhookEndpointWithSecret = {
49
131
  webhook: WebhookEndpoint;
50
132
  secret: string;
51
133
  };
134
+ type Suppression = {
135
+ id: string;
136
+ email: string;
137
+ reason: string | null;
138
+ source: string;
139
+ created_at: string;
140
+ updated_at: string;
141
+ };
142
+ type ListSuppressionsParams = {
143
+ limit?: number;
144
+ cursor?: string;
145
+ email?: string;
146
+ };
147
+ type ListSuppressionsResult = {
148
+ data: Suppression[];
149
+ has_more: boolean;
150
+ next_cursor: string | null;
151
+ };
152
+ type CreateSuppressionParams = {
153
+ email: string;
154
+ reason?: string;
155
+ };
52
156
  type SuperSendTXOptions = {
53
157
  baseUrl?: string;
54
158
  fetch?: typeof fetch;
@@ -60,6 +164,8 @@ type Domain = {
60
164
  status: DomainStatus | string;
61
165
  created_at: string;
62
166
  verified_at: string | null;
167
+ open_tracking?: boolean;
168
+ click_tracking?: boolean;
63
169
  };
64
170
  type DnsRecord = {
65
171
  type: string;
@@ -111,14 +217,21 @@ type ApiErrorBody = {
111
217
  error?: string | {
112
218
  message?: string;
113
219
  details?: unknown;
220
+ code?: string;
221
+ upgrade_url?: string;
114
222
  };
115
223
  };
116
224
 
117
225
  declare class DomainsResource {
118
226
  private readonly client;
119
227
  constructor(client: SuperSendTX);
120
- list(): Promise<{
228
+ list(params?: {
229
+ limit?: number;
230
+ cursor?: string;
231
+ }): Promise<{
121
232
  domains: Domain[];
233
+ has_more: boolean;
234
+ next_cursor: string | null;
122
235
  }>;
123
236
  get(idOrName: string): Promise<{
124
237
  domain: Domain;
@@ -146,22 +259,63 @@ declare class DomainsResource {
146
259
  declare class EmailsResource {
147
260
  private readonly client;
148
261
  constructor(client: SuperSendTX);
149
- list(params?: ListEmailsParams): Promise<{
150
- emails: EmailListItem[];
262
+ list(params?: ListEmailsParams): Promise<ListEmailsResult>;
263
+ get(id: string): Promise<{
264
+ email: EmailListItem;
151
265
  }>;
152
266
  send(params: SendEmailParams): Promise<SendEmailResult>;
267
+ batch(emails: SendEmailParams[]): Promise<BatchSendEmailResult>;
268
+ update(id: string, params: UpdateEmailParams): Promise<SendEmailResult>;
269
+ cancel(id: string): Promise<SendEmailResult>;
270
+ private serializeSendParams;
271
+ }
272
+
273
+ declare class KeysResource {
274
+ private readonly client;
275
+ constructor(client: SuperSendTX);
276
+ list(params?: ListApiKeysParams): Promise<ListApiKeysResult>;
277
+ create(params?: CreateApiKeyParams): Promise<CreateApiKeyResult>;
278
+ remove(id: string): Promise<{
279
+ ok: boolean;
280
+ }>;
281
+ }
282
+
283
+ declare class SuppressionsResource {
284
+ private readonly client;
285
+ constructor(client: SuperSendTX);
286
+ list(params?: ListSuppressionsParams): Promise<ListSuppressionsResult>;
287
+ create(params: CreateSuppressionParams): Promise<{
288
+ suppression: Suppression;
289
+ }>;
290
+ /** Remove by suppression id or email address. */
291
+ remove(idOrEmail: string): Promise<{
292
+ ok: boolean;
293
+ }>;
153
294
  }
154
295
 
155
296
  declare class WebhooksResource {
156
297
  private readonly client;
157
298
  constructor(client: SuperSendTX);
158
- list(): Promise<{
299
+ list(params?: {
300
+ limit?: number;
301
+ cursor?: string;
302
+ }): Promise<{
159
303
  webhooks: WebhookEndpoint[];
304
+ has_more: boolean;
305
+ next_cursor: string | null;
306
+ }>;
307
+ get(id: string): Promise<{
308
+ webhook: WebhookEndpoint;
160
309
  }>;
161
310
  create(params: CreateWebhookParams): Promise<WebhookEndpointWithSecret>;
311
+ update(id: string, params: UpdateWebhookParams): Promise<{
312
+ webhook: WebhookEndpoint;
313
+ }>;
162
314
  delete(id: string): Promise<{
163
315
  ok: boolean;
164
316
  }>;
317
+ /** Verify an incoming webhook signature (same as `verifyWebhookSignature`). */
318
+ verify(secret: string, payload: string, header: string | null | undefined, toleranceSec?: number): boolean;
165
319
  }
166
320
 
167
321
  declare const DEFAULT_API_BASE_URL = "https://api.supersendtx.com";
@@ -171,6 +325,8 @@ declare class SuperSendTX {
171
325
  readonly domains: DomainsResource;
172
326
  readonly emails: EmailsResource;
173
327
  readonly webhooks: WebhooksResource;
328
+ readonly apiKeys: KeysResource;
329
+ readonly suppressions: SuppressionsResource;
174
330
  constructor(apiKey: string, options?: SuperSendTXOptions);
175
331
  get baseUrl(): string;
176
332
  get fetchImpl(): typeof fetch;
@@ -180,10 +336,23 @@ declare class SuperSendTX {
180
336
  declare class SuperSendTXError extends Error {
181
337
  readonly status: number;
182
338
  readonly details?: unknown;
183
- constructor(message: string, status: number, details?: unknown);
339
+ readonly code?: string;
340
+ readonly upgradeUrl?: string;
341
+ constructor(message: string, status: number, details?: unknown, options?: {
342
+ code?: string;
343
+ upgradeUrl?: string;
344
+ });
184
345
  static fromResponse(status: number, body: ApiErrorBody): SuperSendTXError;
185
346
  }
186
347
 
348
+ declare function signWebhookPayload(secret: string, payload: string, timestamp: number): string;
349
+ declare function buildSignatureHeader(secret: string, payload: string, timestamp?: number): string;
350
+ /**
351
+ * Verify a SuperSend TX webhook signature header (`SuperSendTX-Signature`).
352
+ * Expects HMAC-SHA256 over `${timestamp}.${rawBody}` with the endpoint secret.
353
+ */
354
+ declare function verifyWebhookSignature(secret: string, payload: string, header: string | null | undefined, toleranceSec?: number): boolean;
355
+
187
356
  /** Merge `include:host` into an existing SPF record (or create a minimal one). */
188
357
  declare function mergeSpfInclude(existing: string | null | undefined, includeHost: string): string;
189
358
 
@@ -214,4 +383,4 @@ declare function applyDnsRecords(input: {
214
383
  fetchImpl?: typeof fetch;
215
384
  }): Promise<ApplyDnsResult>;
216
385
 
217
- export { type ApplyDnsParams, type ApplyDnsRecordResult$1 as ApplyDnsRecordResult, type ApplyDnsResult$1 as ApplyDnsResult, type CreateDomainParams, type CreateDomainResult, type CreateWebhookParams, DEFAULT_API_BASE_URL, type DnsProviderName$1 as DnsProviderName, type DnsRecord, type Domain, type DomainStatus, type EmailListItem, type ListEmailsParams, type SendEmailParams, type SendEmailResult, SuperSendTX, SuperSendTXError, type SuperSendTXOptions, type VerifyDomainResult, type WebhookEndpoint, type WebhookEndpointWithSecret, type WebhookEventType, applyDnsRecords, mergeSpfInclude };
386
+ export { type ApiErrorCode, type ApiKey, type ApiKeyScope, type ApplyDnsParams, type ApplyDnsRecordResult$1 as ApplyDnsRecordResult, type ApplyDnsResult$1 as ApplyDnsResult, type BatchSendEmailResult, type CreateApiKeyParams, type CreateApiKeyResult, type CreateDomainParams, type CreateDomainResult, type CreateSuppressionParams, type CreateWebhookParams, DEFAULT_API_BASE_URL, type DnsProviderName$1 as DnsProviderName, type DnsRecord, type Domain, type DomainStatus, type EmailListItem, type ListApiKeysParams, type ListApiKeysResult, type ListEmailsParams, type ListEmailsResult, type ListSuppressionsParams, type ListSuppressionsResult, type SendEmailParams, type SendEmailResult, SuperSendTX, SuperSendTXError, type SuperSendTXOptions, type Suppression, type UpdateEmailParams, type UpdateWebhookParams, type VerifyDomainResult, type WebhookEndpoint, type WebhookEndpointWithSecret, type WebhookEventType, applyDnsRecords, buildSignatureHeader, mergeSpfInclude, signWebhookPayload, verifyWebhookSignature };
package/dist/index.js CHANGED
@@ -1,16 +1,20 @@
1
1
  // src/errors.ts
2
2
  var SuperSendTXError = class _SuperSendTXError extends Error {
3
- constructor(message, status, details) {
3
+ constructor(message, status, details, options) {
4
4
  super(message);
5
5
  this.name = "SuperSendTXError";
6
6
  this.status = status;
7
7
  this.details = details;
8
+ this.code = options?.code;
9
+ this.upgradeUrl = options?.upgradeUrl;
8
10
  }
9
11
  static fromResponse(status, body) {
10
12
  const err = body.error;
11
13
  const message = typeof err === "string" ? err : err?.message || `Request failed with status ${status}`;
12
14
  const details = typeof err === "object" && err ? err.details : void 0;
13
- return new _SuperSendTXError(message, status, details);
15
+ const code = typeof err === "object" && err && "code" in err ? String(err.code) : void 0;
16
+ const upgradeUrl = typeof err === "object" && err && "upgrade_url" in err ? String(err.upgrade_url) : void 0;
17
+ return new _SuperSendTXError(message, status, details, { code, upgradeUrl });
14
18
  }
15
19
  };
16
20
 
@@ -337,8 +341,12 @@ var DomainsResource = class {
337
341
  constructor(client) {
338
342
  this.client = client;
339
343
  }
340
- async list() {
341
- return this.client.request("/domains", { method: "GET" });
344
+ async list(params = {}) {
345
+ const search = new URLSearchParams();
346
+ if (params.limit != null) search.set("limit", String(params.limit));
347
+ if (params.cursor) search.set("cursor", params.cursor);
348
+ const query = search.toString();
349
+ return this.client.request(`/domains${query ? `?${query}` : ""}`, { method: "GET" });
342
350
  }
343
351
  async get(idOrName) {
344
352
  return this.client.request(`/domains/${encodeURIComponent(idOrName)}`, { method: "GET" });
@@ -400,8 +408,16 @@ var EmailsResource = class {
400
408
  this.client = client;
401
409
  }
402
410
  async list(params = {}) {
403
- const query = params.limit ? `?limit=${params.limit}` : "";
404
- return this.client.request(`/emails${query}`, {
411
+ const search = new URLSearchParams();
412
+ if (params.limit != null) search.set("limit", String(params.limit));
413
+ if (params.cursor) search.set("cursor", params.cursor);
414
+ const query = search.toString();
415
+ return this.client.request(`/emails${query ? `?${query}` : ""}`, {
416
+ method: "GET"
417
+ });
418
+ }
419
+ async get(id) {
420
+ return this.client.request(`/emails/${encodeURIComponent(id)}`, {
405
421
  method: "GET"
406
422
  });
407
423
  }
@@ -411,26 +427,181 @@ var EmailsResource = class {
411
427
  to: params.to,
412
428
  subject: params.subject
413
429
  };
414
- if (params.html) payload.html = params.html;
415
- if (params.text) payload.text = params.text;
430
+ if (params.html !== void 0) payload.html = params.html;
431
+ if (params.text !== void 0) payload.text = params.text;
416
432
  const replyTo = params.replyTo ?? params.reply_to;
417
- if (replyTo) payload.reply_to = replyTo;
418
- if (params.cc) payload.cc = params.cc;
419
- if (params.bcc) payload.bcc = params.bcc;
433
+ if (replyTo !== void 0) payload.reply_to = replyTo;
434
+ if (params.cc !== void 0) payload.cc = params.cc;
435
+ if (params.bcc !== void 0) payload.bcc = params.bcc;
436
+ if (params.tags !== void 0) payload.tags = params.tags;
437
+ if (params.headers !== void 0) payload.headers = params.headers;
438
+ if (params.tag !== void 0) payload.tag = params.tag;
439
+ if (params.attachments !== void 0) payload.attachments = params.attachments;
440
+ const scheduledAt = params.scheduledAt ?? params.scheduled_at;
441
+ if (scheduledAt !== void 0) {
442
+ payload.scheduled_at = scheduledAt instanceof Date ? scheduledAt.toISOString() : scheduledAt;
443
+ }
444
+ const headers = {};
445
+ if (params.idempotencyKey) {
446
+ headers["Idempotency-Key"] = params.idempotencyKey;
447
+ }
420
448
  return this.client.request("/emails", {
421
449
  method: "POST",
450
+ headers,
422
451
  body: JSON.stringify(payload)
423
452
  });
424
453
  }
454
+ async batch(emails) {
455
+ return this.client.request("/emails/batch", {
456
+ method: "POST",
457
+ body: JSON.stringify({ emails: emails.map((email) => this.serializeSendParams(email)) })
458
+ });
459
+ }
460
+ async update(id, params) {
461
+ const payload = {};
462
+ if (params.cancel !== void 0) payload.cancel = params.cancel;
463
+ const scheduledAt = params.scheduledAt ?? params.scheduled_at;
464
+ if (scheduledAt !== void 0) {
465
+ payload.scheduled_at = scheduledAt instanceof Date ? scheduledAt.toISOString() : scheduledAt;
466
+ }
467
+ return this.client.request(`/emails/${encodeURIComponent(id)}`, {
468
+ method: "PATCH",
469
+ body: JSON.stringify(payload)
470
+ });
471
+ }
472
+ async cancel(id) {
473
+ return this.update(id, { cancel: true });
474
+ }
475
+ serializeSendParams(params) {
476
+ const payload = {
477
+ from: params.from,
478
+ to: params.to,
479
+ subject: params.subject
480
+ };
481
+ if (params.html !== void 0) payload.html = params.html;
482
+ if (params.text !== void 0) payload.text = params.text;
483
+ const replyTo = params.replyTo ?? params.reply_to;
484
+ if (replyTo !== void 0) payload.reply_to = replyTo;
485
+ if (params.cc !== void 0) payload.cc = params.cc;
486
+ if (params.bcc !== void 0) payload.bcc = params.bcc;
487
+ if (params.tags !== void 0) payload.tags = params.tags;
488
+ if (params.headers !== void 0) payload.headers = params.headers;
489
+ if (params.tag !== void 0) payload.tag = params.tag;
490
+ if (params.attachments !== void 0) payload.attachments = params.attachments;
491
+ const scheduledAt = params.scheduledAt ?? params.scheduled_at;
492
+ if (scheduledAt !== void 0) {
493
+ payload.scheduled_at = scheduledAt instanceof Date ? scheduledAt.toISOString() : scheduledAt;
494
+ }
495
+ return payload;
496
+ }
497
+ };
498
+
499
+ // src/keys.ts
500
+ var KeysResource = class {
501
+ constructor(client) {
502
+ this.client = client;
503
+ }
504
+ async list(params = {}) {
505
+ const search = new URLSearchParams();
506
+ if (params.limit != null) search.set("limit", String(params.limit));
507
+ if (params.cursor) search.set("cursor", params.cursor);
508
+ const query = search.toString();
509
+ return this.client.request(`/api-keys${query ? `?${query}` : ""}`, {
510
+ method: "GET"
511
+ });
512
+ }
513
+ async create(params = {}) {
514
+ return this.client.request("/api-keys", {
515
+ method: "POST",
516
+ body: JSON.stringify({
517
+ ...params.name ? { name: params.name } : {},
518
+ ...params.scope ? { scope: params.scope } : {}
519
+ })
520
+ });
521
+ }
522
+ async remove(id) {
523
+ return this.client.request(`/api-keys/${encodeURIComponent(id)}`, {
524
+ method: "DELETE"
525
+ });
526
+ }
425
527
  };
426
528
 
427
- // src/webhooks.ts
529
+ // src/suppressions.ts
530
+ var SuppressionsResource = class {
531
+ constructor(client) {
532
+ this.client = client;
533
+ }
534
+ async list(params = {}) {
535
+ const search = new URLSearchParams();
536
+ if (params.limit != null) search.set("limit", String(params.limit));
537
+ if (params.cursor) search.set("cursor", params.cursor);
538
+ if (params.email) search.set("email", params.email);
539
+ const query = search.toString();
540
+ return this.client.request(`/suppressions${query ? `?${query}` : ""}`, { method: "GET" });
541
+ }
542
+ async create(params) {
543
+ return this.client.request("/suppressions", {
544
+ method: "POST",
545
+ body: JSON.stringify(params)
546
+ });
547
+ }
548
+ /** Remove by suppression id or email address. */
549
+ async remove(idOrEmail) {
550
+ if (idOrEmail.includes("@")) {
551
+ return this.client.request(`/suppressions?email=${encodeURIComponent(idOrEmail)}`, {
552
+ method: "DELETE"
553
+ });
554
+ }
555
+ return this.client.request(`/suppressions/${encodeURIComponent(idOrEmail)}`, {
556
+ method: "DELETE"
557
+ });
558
+ }
559
+ };
560
+
561
+ // src/webhooks/verify.ts
562
+ import { createHmac, timingSafeEqual } from "crypto";
563
+ function signWebhookPayload(secret, payload, timestamp) {
564
+ const signed = `${timestamp}.${payload}`;
565
+ return createHmac("sha256", secret).update(signed).digest("hex");
566
+ }
567
+ function buildSignatureHeader(secret, payload, timestamp = Math.floor(Date.now() / 1e3)) {
568
+ const signature = signWebhookPayload(secret, payload, timestamp);
569
+ return `t=${timestamp},v1=${signature}`;
570
+ }
571
+ function verifyWebhookSignature(secret, payload, header, toleranceSec = 300) {
572
+ if (!header) return false;
573
+ const parts = Object.fromEntries(
574
+ header.split(",").map((part) => {
575
+ const [key, value] = part.trim().split("=");
576
+ return [key, value];
577
+ })
578
+ );
579
+ const timestamp = Number(parts.t);
580
+ const signature = parts.v1;
581
+ if (!timestamp || !signature) return false;
582
+ if (Math.abs(Math.floor(Date.now() / 1e3) - timestamp) > toleranceSec) return false;
583
+ const expected = signWebhookPayload(secret, payload, timestamp);
584
+ try {
585
+ return timingSafeEqual(Buffer.from(signature), Buffer.from(expected));
586
+ } catch {
587
+ return false;
588
+ }
589
+ }
590
+
591
+ // src/webhooks/index.ts
428
592
  var WebhooksResource = class {
429
593
  constructor(client) {
430
594
  this.client = client;
431
595
  }
432
- async list() {
433
- return this.client.request("/webhooks", { method: "GET" });
596
+ async list(params = {}) {
597
+ const search = new URLSearchParams();
598
+ if (params.limit != null) search.set("limit", String(params.limit));
599
+ if (params.cursor) search.set("cursor", params.cursor);
600
+ const query = search.toString();
601
+ return this.client.request(`/webhooks${query ? `?${query}` : ""}`, { method: "GET" });
602
+ }
603
+ async get(id) {
604
+ return this.client.request(`/webhooks/${encodeURIComponent(id)}`, { method: "GET" });
434
605
  }
435
606
  async create(params) {
436
607
  return this.client.request("/webhooks", {
@@ -438,9 +609,19 @@ var WebhooksResource = class {
438
609
  body: JSON.stringify(params)
439
610
  });
440
611
  }
612
+ async update(id, params) {
613
+ return this.client.request(`/webhooks/${encodeURIComponent(id)}`, {
614
+ method: "PATCH",
615
+ body: JSON.stringify(params)
616
+ });
617
+ }
441
618
  async delete(id) {
442
619
  return this.client.request(`/webhooks/${id}`, { method: "DELETE" });
443
620
  }
621
+ /** Verify an incoming webhook signature (same as `verifyWebhookSignature`). */
622
+ verify(secret, payload, header, toleranceSec = 300) {
623
+ return verifyWebhookSignature(secret, payload, header, toleranceSec);
624
+ }
444
625
  };
445
626
 
446
627
  // src/client.ts
@@ -455,6 +636,8 @@ var SuperSendTX = class {
455
636
  this.domains = new DomainsResource(this);
456
637
  this.emails = new EmailsResource(this);
457
638
  this.webhooks = new WebhooksResource(this);
639
+ this.apiKeys = new KeysResource(this);
640
+ this.suppressions = new SuppressionsResource(this);
458
641
  }
459
642
  get baseUrl() {
460
643
  return (this.options.baseUrl || DEFAULT_API_BASE_URL).replace(/\/$/, "");
@@ -483,5 +666,8 @@ export {
483
666
  SuperSendTX,
484
667
  SuperSendTXError,
485
668
  applyDnsRecords,
486
- mergeSpfInclude
669
+ buildSignatureHeader,
670
+ mergeSpfInclude,
671
+ signWebhookPayload,
672
+ verifyWebhookSignature
487
673
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "supersendtx",
3
- "version": "0.3.0",
3
+ "version": "0.6.0",
4
4
  "description": "SuperSend TX transactional email API client",
5
5
  "license": "MIT",
6
6
  "type": "module",