shipmail 0.1.5 → 0.1.20

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
@@ -1,6 +1,6 @@
1
1
  # ShipMail TypeScript SDK
2
2
 
3
- Official TypeScript SDK for the [ShipMail](https://shipmail.to) API. Zero runtime dependencies. Works with Node.js 20+, Bun, and Deno.
3
+ Official TypeScript SDK for the [ShipMail](https://shipmail.to) API. Zero runtime dependencies. Works with Node.js 18+, Bun, and Deno.
4
4
 
5
5
  ## Installation
6
6
 
@@ -38,7 +38,7 @@ import { ShipMailClient } from "shipmail";
38
38
 
39
39
  const client = new ShipMailClient({
40
40
  apiKey: "sm_live_...",
41
- baseUrl: "https://api.shipmail.to/v1", // default
41
+ baseUrl: "https://shipmail.to/api/v1", // default
42
42
  maxRetries: 2, // default, retries on 5xx and 429
43
43
  timeout: 30_000, // default, in milliseconds
44
44
  });
@@ -69,10 +69,6 @@ const mailboxes = await client.mailboxes.list({ domain_id: "dom_..." });
69
69
  const mailbox = await client.mailboxes.get("mbx_...");
70
70
  const updated = await client.mailboxes.update("mbx_...", { display_name: "New Name" });
71
71
  await client.mailboxes.delete("mbx_...");
72
-
73
- // Avatar
74
- const avatar = await client.mailboxes.uploadAvatar("mbx_...", imageBuffer, "image/png");
75
- await client.mailboxes.deleteAvatar("mbx_...");
76
72
  ```
77
73
 
78
74
  ### Messages
@@ -161,7 +157,7 @@ Verify incoming webhook signatures without instantiating a client:
161
157
  import { verifyWebhook, WebhookVerificationError } from "shipmail";
162
158
 
163
159
  try {
164
- const event = verifyWebhook(rawBody, request.headers, webhookSecret);
160
+ const event = await verifyWebhook(rawBody, request.headers, webhookSecret);
165
161
  console.log(event.event_type); // e.g., "message.received"
166
162
  console.log(event.data);
167
163
  } catch (err) {
package/dist/index.cjs CHANGED
@@ -2,8 +2,6 @@
2
2
 
3
3
  Object.defineProperty(exports, '__esModule', { value: true });
4
4
 
5
- var crypto = require('crypto');
6
-
7
5
  // src/errors.ts
8
6
  var ShipMailError = class extends Error {
9
7
  constructor(message, options) {
@@ -39,6 +37,12 @@ var ValidationError = class extends ShipMailError {
39
37
  this.details = options?.details;
40
38
  }
41
39
  };
40
+ var QuotaExceededError = class extends ShipMailError {
41
+ constructor(message, requestId) {
42
+ super(message, { status: 403, type: "quota_exceeded", requestId, retryable: false });
43
+ this.name = "QuotaExceededError";
44
+ }
45
+ };
42
46
  var NotFoundError = class extends ShipMailError {
43
47
  constructor(message, requestId) {
44
48
  super(message, { status: 404, type: "not_found", requestId, retryable: false });
@@ -89,6 +93,8 @@ function mapErrorFromResponse(status, body, requestId) {
89
93
  return new AuthenticationError(error.message, rid);
90
94
  case "authorization_error":
91
95
  return new AuthorizationError(error.message, rid);
96
+ case "quota_exceeded":
97
+ return new QuotaExceededError(error.message, rid);
92
98
  case "validation_error":
93
99
  return new ValidationError(error.message, { requestId: rid, details: error.details });
94
100
  case "not_found":
@@ -142,21 +148,23 @@ var ApiResource = class {
142
148
 
143
149
  // src/resources/domains.ts
144
150
  var Domains = class extends ApiResource {
145
- create(params) {
151
+ create(params, options) {
146
152
  return this.client.request({
147
153
  method: "POST",
148
154
  path: "/domains",
149
- body: params
155
+ body: params,
156
+ methodOptions: options
150
157
  });
151
158
  }
152
- list(params) {
159
+ list(params, options) {
153
160
  return this.client.request({
154
161
  method: "GET",
155
162
  path: "/domains",
156
163
  query: {
157
164
  cursor: params?.cursor,
158
165
  limit: params?.limit
159
- }
166
+ },
167
+ methodOptions: options
160
168
  });
161
169
  }
162
170
  listAutoPaginating(params) {
@@ -164,43 +172,64 @@ var Domains = class extends ApiResource {
164
172
  limit: params?.limit
165
173
  });
166
174
  }
167
- get(id) {
175
+ get(id, options) {
168
176
  return this.client.request({
169
177
  method: "GET",
170
- path: `/domains/${id}`
178
+ path: `/domains/${encodeURIComponent(id)}`,
179
+ methodOptions: options
171
180
  });
172
181
  }
173
- update(id, params) {
182
+ update(id, params, options) {
174
183
  return this.client.request({
175
184
  method: "PATCH",
176
- path: `/domains/${id}`,
177
- body: params
185
+ path: `/domains/${encodeURIComponent(id)}`,
186
+ body: params,
187
+ methodOptions: options
178
188
  });
179
189
  }
180
- delete(id) {
190
+ delete(id, options) {
181
191
  return this.client.request({
182
192
  method: "DELETE",
183
- path: `/domains/${id}`
193
+ path: `/domains/${encodeURIComponent(id)}`,
194
+ methodOptions: options
195
+ });
196
+ }
197
+ verify(id, options) {
198
+ return this.client.request({
199
+ method: "POST",
200
+ path: `/domains/${encodeURIComponent(id)}/verification`,
201
+ methodOptions: options
184
202
  });
185
203
  }
186
- verify(id) {
204
+ search(params, options) {
187
205
  return this.client.request({
188
206
  method: "POST",
189
- path: `/domains/${id}/verification`
207
+ path: "/domains/search",
208
+ body: params,
209
+ methodOptions: options
210
+ });
211
+ }
212
+ register(params, options) {
213
+ return this.client.request({
214
+ method: "POST",
215
+ path: "/domains/register",
216
+ body: params,
217
+ methodOptions: options
190
218
  });
191
219
  }
192
220
  };
193
221
 
194
222
  // src/resources/mailboxes.ts
195
223
  var Mailboxes = class extends ApiResource {
196
- create(params) {
224
+ create(params, options) {
197
225
  return this.client.request({
198
226
  method: "POST",
199
227
  path: "/mailboxes",
200
- body: params
228
+ body: params,
229
+ methodOptions: options
201
230
  });
202
231
  }
203
- list(params) {
232
+ list(params, options) {
204
233
  return this.client.request({
205
234
  method: "GET",
206
235
  path: "/mailboxes",
@@ -208,7 +237,8 @@ var Mailboxes = class extends ApiResource {
208
237
  domain_id: params?.domain_id,
209
238
  cursor: params?.cursor,
210
239
  limit: params?.limit
211
- }
240
+ },
241
+ methodOptions: options
212
242
  });
213
243
  }
214
244
  listAutoPaginating(params) {
@@ -217,71 +247,124 @@ var Mailboxes = class extends ApiResource {
217
247
  limit: params?.limit
218
248
  });
219
249
  }
220
- get(id) {
250
+ get(id, options) {
221
251
  return this.client.request({
222
252
  method: "GET",
223
- path: `/mailboxes/${id}`
253
+ path: `/mailboxes/${encodeURIComponent(id)}`,
254
+ methodOptions: options
224
255
  });
225
256
  }
226
- update(id, params) {
257
+ update(id, params, options) {
227
258
  return this.client.request({
228
259
  method: "PATCH",
229
- path: `/mailboxes/${id}`,
230
- body: params
260
+ path: `/mailboxes/${encodeURIComponent(id)}`,
261
+ body: params,
262
+ methodOptions: options
231
263
  });
232
264
  }
233
- delete(id) {
265
+ delete(id, options) {
234
266
  return this.client.request({
235
267
  method: "DELETE",
236
- path: `/mailboxes/${id}`
237
- });
238
- }
239
- uploadAvatar(id, data, contentType) {
240
- return this.client.request({
241
- method: "PUT",
242
- path: `/mailboxes/${id}/avatar`,
243
- rawBody: data,
244
- contentType
268
+ path: `/mailboxes/${encodeURIComponent(id)}`,
269
+ methodOptions: options
245
270
  });
246
271
  }
247
- deleteAvatar(id) {
272
+ updateAutoReply(id, params, options) {
248
273
  return this.client.request({
249
- method: "DELETE",
250
- path: `/mailboxes/${id}/avatar`
274
+ method: "PATCH",
275
+ path: `/mailboxes/${encodeURIComponent(id)}/auto-reply`,
276
+ body: params,
277
+ methodOptions: options
251
278
  });
252
279
  }
253
280
  };
254
281
 
255
282
  // src/resources/messages.ts
256
283
  var Messages = class extends ApiResource {
257
- send(params) {
284
+ send(params, options) {
258
285
  return this.client.request({
259
286
  method: "POST",
260
287
  path: "/messages",
261
- body: params
288
+ body: params,
289
+ methodOptions: options
262
290
  });
263
291
  }
264
- get(id) {
292
+ list(params, options) {
265
293
  return this.client.request({
266
294
  method: "GET",
267
- path: `/messages/${id}`
295
+ path: "/messages",
296
+ query: {
297
+ mailbox_id: params.mailbox_id,
298
+ cursor: params.cursor,
299
+ limit: params.limit
300
+ },
301
+ methodOptions: options
302
+ });
303
+ }
304
+ listAutoPaginating(params) {
305
+ return new Page(this.client, "/messages", {
306
+ mailbox_id: params.mailbox_id,
307
+ limit: params.limit
308
+ });
309
+ }
310
+ get(id, options) {
311
+ return this.client.request({
312
+ method: "GET",
313
+ path: `/messages/${encodeURIComponent(id)}`,
314
+ methodOptions: options
315
+ });
316
+ }
317
+ reply(id, params, options) {
318
+ return this.client.request({
319
+ method: "POST",
320
+ path: `/messages/${encodeURIComponent(id)}/reply`,
321
+ body: params,
322
+ methodOptions: options
268
323
  });
269
324
  }
270
325
  };
271
326
 
272
327
  // src/resources/status.ts
273
328
  var Status = class extends ApiResource {
274
- get() {
329
+ get(options) {
330
+ return this.client.request({
331
+ method: "GET",
332
+ path: "/status",
333
+ methodOptions: options
334
+ });
335
+ }
336
+ };
337
+
338
+ // src/resources/suppressions.ts
339
+ var Suppressions = class extends ApiResource {
340
+ list(params, options) {
275
341
  return this.client.request({
276
342
  method: "GET",
277
- path: "/status"
343
+ path: "/suppressions",
344
+ query: {
345
+ cursor: params?.cursor,
346
+ limit: params?.limit
347
+ },
348
+ methodOptions: options
349
+ });
350
+ }
351
+ listAutoPaginating(params) {
352
+ return new Page(this.client, "/suppressions", {
353
+ limit: params?.limit
354
+ });
355
+ }
356
+ remove(email, options) {
357
+ return this.client.request({
358
+ method: "DELETE",
359
+ path: `/suppressions/${encodeURIComponent(email)}`,
360
+ methodOptions: options
278
361
  });
279
362
  }
280
363
  };
281
364
 
282
365
  // src/resources/threads.ts
283
366
  var Threads = class extends ApiResource {
284
- list(params) {
367
+ list(params, options) {
285
368
  return this.client.request({
286
369
  method: "GET",
287
370
  path: "/threads",
@@ -289,7 +372,8 @@ var Threads = class extends ApiResource {
289
372
  mailbox_id: params.mailbox_id,
290
373
  cursor: params.cursor,
291
374
  limit: params.limit
292
- }
375
+ },
376
+ methodOptions: options
293
377
  });
294
378
  }
295
379
  listAutoPaginating(params) {
@@ -298,42 +382,46 @@ var Threads = class extends ApiResource {
298
382
  limit: params.limit
299
383
  });
300
384
  }
301
- get(id, params) {
385
+ get(id, params, options) {
302
386
  return this.client.request({
303
387
  method: "GET",
304
- path: `/threads/${id}`,
388
+ path: `/threads/${encodeURIComponent(id)}`,
305
389
  query: {
306
390
  cursor: params?.cursor,
307
391
  limit: params?.limit
308
- }
392
+ },
393
+ methodOptions: options
309
394
  });
310
395
  }
311
- reply(id, params) {
396
+ reply(id, params, options) {
312
397
  return this.client.request({
313
398
  method: "POST",
314
- path: `/threads/${id}/reply`,
315
- body: params
399
+ path: `/threads/${encodeURIComponent(id)}/reply`,
400
+ body: params,
401
+ methodOptions: options
316
402
  });
317
403
  }
318
404
  };
319
405
 
320
406
  // src/resources/webhooks.ts
321
407
  var Webhooks = class extends ApiResource {
322
- create(params) {
408
+ create(params, options) {
323
409
  return this.client.request({
324
410
  method: "POST",
325
411
  path: "/webhooks",
326
- body: params
412
+ body: params,
413
+ methodOptions: options
327
414
  });
328
415
  }
329
- list(params) {
416
+ list(params, options) {
330
417
  return this.client.request({
331
418
  method: "GET",
332
419
  path: "/webhooks",
333
420
  query: {
334
421
  cursor: params?.cursor,
335
422
  limit: params?.limit
336
- }
423
+ },
424
+ methodOptions: options
337
425
  });
338
426
  }
339
427
  listAutoPaginating(params) {
@@ -341,69 +429,82 @@ var Webhooks = class extends ApiResource {
341
429
  limit: params?.limit
342
430
  });
343
431
  }
344
- get(id) {
432
+ get(id, options) {
345
433
  return this.client.request({
346
434
  method: "GET",
347
- path: `/webhooks/${id}`
435
+ path: `/webhooks/${encodeURIComponent(id)}`,
436
+ methodOptions: options
348
437
  });
349
438
  }
350
- update(id, params) {
439
+ update(id, params, options) {
351
440
  return this.client.request({
352
441
  method: "PATCH",
353
- path: `/webhooks/${id}`,
354
- body: params
442
+ path: `/webhooks/${encodeURIComponent(id)}`,
443
+ body: params,
444
+ methodOptions: options
355
445
  });
356
446
  }
357
- delete(id) {
447
+ delete(id, options) {
358
448
  return this.client.request({
359
449
  method: "DELETE",
360
- path: `/webhooks/${id}`
450
+ path: `/webhooks/${encodeURIComponent(id)}`,
451
+ methodOptions: options
361
452
  });
362
453
  }
363
- rotateSecret(id) {
454
+ rotateSecret(id, options) {
364
455
  return this.client.request({
365
456
  method: "POST",
366
- path: `/webhooks/${id}/rotate-secret`
457
+ path: `/webhooks/${encodeURIComponent(id)}/rotate-secret`,
458
+ methodOptions: options
367
459
  });
368
460
  }
369
- test(id) {
461
+ test(id, options) {
370
462
  return this.client.request({
371
463
  method: "POST",
372
- path: `/webhooks/${id}/test`
464
+ path: `/webhooks/${encodeURIComponent(id)}/test`,
465
+ methodOptions: options
373
466
  });
374
467
  }
375
- listDeliveries(id, params) {
468
+ listDeliveries(id, params, options) {
376
469
  return this.client.request({
377
470
  method: "GET",
378
- path: `/webhooks/${id}/deliveries`,
471
+ path: `/webhooks/${encodeURIComponent(id)}/deliveries`,
379
472
  query: {
380
473
  status: params?.status,
381
474
  event_type: params?.event_type,
382
475
  cursor: params?.cursor,
383
476
  limit: params?.limit
384
- }
477
+ },
478
+ methodOptions: options
385
479
  });
386
480
  }
387
481
  listDeliveriesAutoPaginating(id, params) {
388
- return new Page(this.client, `/webhooks/${id}/deliveries`, {
389
- status: params?.status,
390
- event_type: params?.event_type,
391
- limit: params?.limit
392
- });
482
+ return new Page(
483
+ this.client,
484
+ `/webhooks/${encodeURIComponent(id)}/deliveries`,
485
+ {
486
+ status: params?.status,
487
+ event_type: params?.event_type,
488
+ limit: params?.limit
489
+ }
490
+ );
393
491
  }
394
492
  };
395
493
 
396
494
  // src/version.ts
397
- var VERSION = "0.1.5";
495
+ var VERSION = "0.1.20";
398
496
 
399
497
  // src/client.ts
400
- var DEFAULT_BASE_URL = "https://api.shipmail.to/v1";
498
+ var DEFAULT_BASE_URL = "https://shipmail.to/api/v1";
401
499
  var DEFAULT_MAX_RETRIES = 2;
402
500
  var DEFAULT_TIMEOUT = 3e4;
403
501
  function isRetryableStatus(status) {
404
502
  return status === 429 || status >= 500;
405
503
  }
406
- function calculateBackoff(attempt) {
504
+ function calculateBackoff(attempt, retryAfterMs) {
505
+ if (retryAfterMs !== void 0 && retryAfterMs > 0) {
506
+ return retryAfterMs;
507
+ }
407
508
  const base = Math.min(2 ** attempt * 500, 8e3);
408
509
  const jitter = Math.random() * base * 0.5;
409
510
  return base + jitter;
@@ -416,6 +517,10 @@ function isApiErrorBody(value) {
416
517
  return typeof error["type"] === "string" && typeof error["message"] === "string";
417
518
  }
418
519
  var ShipMailClient = class {
520
+ /**
521
+ * Create a new ShipMail client.
522
+ * @param config - API key string or full configuration object.
523
+ */
419
524
  constructor(config) {
420
525
  if (typeof config === "string") {
421
526
  this.apiKey = config;
@@ -423,16 +528,19 @@ var ShipMailClient = class {
423
528
  this.maxRetries = DEFAULT_MAX_RETRIES;
424
529
  this.timeout = DEFAULT_TIMEOUT;
425
530
  this.fetchFn = globalThis.fetch;
531
+ this.defaultHeaders = {};
426
532
  } else {
427
533
  this.apiKey = config.apiKey;
428
534
  this.baseUrl = config.baseUrl ?? DEFAULT_BASE_URL;
429
535
  this.maxRetries = config.maxRetries ?? DEFAULT_MAX_RETRIES;
430
536
  this.timeout = config.timeout ?? DEFAULT_TIMEOUT;
431
537
  this.fetchFn = config.fetch ?? globalThis.fetch;
538
+ this.defaultHeaders = config.defaultHeaders ? { ...config.defaultHeaders } : {};
432
539
  }
433
540
  this.domains = new Domains(this);
434
541
  this.mailboxes = new Mailboxes(this);
435
542
  this.messages = new Messages(this);
543
+ this.suppressions = new Suppressions(this);
436
544
  this.threads = new Threads(this);
437
545
  this.webhooks = new Webhooks(this);
438
546
  this.status = new Status(this);
@@ -440,18 +548,25 @@ var ShipMailClient = class {
440
548
  async request(options) {
441
549
  const url = this.buildUrl(options.path, options.query);
442
550
  let lastError;
551
+ const methodOpts = options.methodOptions;
443
552
  for (let attempt = 0; attempt <= this.maxRetries; attempt++) {
444
553
  if (attempt > 0) {
445
- const delay = calculateBackoff(attempt - 1);
554
+ const retryAfterMs = lastError instanceof RateLimitError && lastError.retryAfter !== void 0 ? lastError.retryAfter * 1e3 : void 0;
555
+ const delay = calculateBackoff(attempt - 1, retryAfterMs);
446
556
  await new Promise((resolve) => setTimeout(resolve, delay));
447
557
  }
448
558
  let response;
449
559
  try {
450
560
  const headers = {
561
+ ...this.defaultHeaders,
451
562
  Authorization: `Bearer ${this.apiKey}`,
452
563
  "User-Agent": `shipmail-node/${VERSION}`,
453
- Accept: "application/json"
564
+ Accept: "application/json",
565
+ ...methodOpts?.headers
454
566
  };
567
+ if (methodOpts?.idempotencyKey) {
568
+ headers["Idempotency-Key"] = methodOpts.idempotencyKey;
569
+ }
455
570
  let body = null;
456
571
  if (options.rawBody !== void 0) {
457
572
  headers["Content-Type"] = options.contentType ?? "application/octet-stream";
@@ -460,11 +575,12 @@ var ShipMailClient = class {
460
575
  headers["Content-Type"] = "application/json";
461
576
  body = JSON.stringify(options.body);
462
577
  }
578
+ const effectiveTimeout = methodOpts?.timeout ?? this.timeout;
463
579
  response = await this.fetchFn(url, {
464
580
  method: options.method,
465
581
  headers,
466
582
  body,
467
- signal: AbortSignal.timeout(this.timeout)
583
+ signal: methodOpts?.signal ?? AbortSignal.timeout(effectiveTimeout)
468
584
  });
469
585
  } catch (err) {
470
586
  lastError = new ConnectionError(err instanceof Error ? err.message : "Request failed");
@@ -513,15 +629,31 @@ var ShipMailClient = class {
513
629
  // src/types/common.ts
514
630
  var WEBHOOK_EVENT_TYPES = [
515
631
  "message.received",
516
- "message.queued",
517
632
  "message.sent",
518
633
  "message.delivered",
519
634
  "message.bounced",
520
635
  "message.complained",
521
636
  "domain.verified",
522
637
  "domain.verification_failed",
523
- "domain.degraded"
638
+ "domain.degraded",
639
+ "org.reputation_warning",
640
+ "org.sending_throttled",
641
+ "org.sending_suspended",
642
+ "org.reputation_recovered"
524
643
  ];
644
+ var DOMAIN_STATUSES = ["pending", "verifying", "verified", "degraded", "failed"];
645
+ var MESSAGE_STATUSES = [
646
+ "queued",
647
+ "sent",
648
+ "delivered",
649
+ "bounced",
650
+ "complained",
651
+ "failed"
652
+ ];
653
+ var MESSAGE_SOURCES = ["api", "dashboard", "inbound", "smtp"];
654
+ var WEBHOOK_DELIVERY_STATUSES = ["pending", "delivered", "failed"];
655
+
656
+ // src/webhook-verification.ts
525
657
  var DEFAULT_TOLERANCE_SECONDS = 300;
526
658
  function getHeader(headers, name) {
527
659
  if (headers instanceof Headers) {
@@ -529,12 +661,13 @@ function getHeader(headers, name) {
529
661
  }
530
662
  return headers[name] ?? headers[name.toLowerCase()];
531
663
  }
532
- function signPayload(secret, timestamp, body) {
664
+ async function signPayload(secret, timestamp, body) {
665
+ const { createHmac } = await import('crypto');
533
666
  const payload = `v1=${timestamp}
534
667
  ${body}`;
535
- return crypto.createHmac("sha256", secret).update(payload).digest("hex");
668
+ return createHmac("sha256", secret).update(payload).digest("hex");
536
669
  }
537
- function verifyWebhook(body, headers, secret, options) {
670
+ async function verifyWebhook(body, headers, secret, options) {
538
671
  const signature = getHeader(headers, "x-shipmail-signature");
539
672
  const timestampStr = getHeader(headers, "x-shipmail-timestamp");
540
673
  if (!signature) {
@@ -552,10 +685,11 @@ function verifyWebhook(body, headers, secret, options) {
552
685
  if (Math.abs(now - timestamp) > tolerance) {
553
686
  throw new WebhookVerificationError("Webhook timestamp is outside tolerance window");
554
687
  }
555
- const expected = signPayload(secret, timestamp, body);
688
+ const expected = await signPayload(secret, timestamp, body);
689
+ const { timingSafeEqual } = await import('crypto');
556
690
  const sigBuffer = Buffer.from(signature, "hex");
557
691
  const expectedBuffer = Buffer.from(expected, "hex");
558
- if (sigBuffer.length !== expectedBuffer.length || !crypto.timingSafeEqual(sigBuffer, expectedBuffer)) {
692
+ if (sigBuffer.length !== expectedBuffer.length || !timingSafeEqual(sigBuffer, expectedBuffer)) {
559
693
  throw new WebhookVerificationError("Webhook signature verification failed");
560
694
  }
561
695
  let parsed;
@@ -571,13 +705,18 @@ exports.AuthenticationError = AuthenticationError;
571
705
  exports.AuthorizationError = AuthorizationError;
572
706
  exports.ConflictError = ConflictError;
573
707
  exports.ConnectionError = ConnectionError;
708
+ exports.DOMAIN_STATUSES = DOMAIN_STATUSES;
574
709
  exports.InternalServerError = InternalServerError;
710
+ exports.MESSAGE_SOURCES = MESSAGE_SOURCES;
711
+ exports.MESSAGE_STATUSES = MESSAGE_STATUSES;
575
712
  exports.NotFoundError = NotFoundError;
576
713
  exports.Page = Page;
714
+ exports.QuotaExceededError = QuotaExceededError;
577
715
  exports.RateLimitError = RateLimitError;
578
716
  exports.ShipMailClient = ShipMailClient;
579
717
  exports.ShipMailError = ShipMailError;
580
718
  exports.ValidationError = ValidationError;
719
+ exports.WEBHOOK_DELIVERY_STATUSES = WEBHOOK_DELIVERY_STATUSES;
581
720
  exports.WEBHOOK_EVENT_TYPES = WEBHOOK_EVENT_TYPES;
582
721
  exports.WebhookVerificationError = WebhookVerificationError;
583
722
  exports.default = ShipMailClient;