shipmail 0.1.31 → 0.1.33

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
@@ -18,6 +18,7 @@ Official TypeScript SDK for the [Shipmail](https://shipmail.to) API. Zero runtim
18
18
  - [Domains](#domains)
19
19
  - [Mailboxes](#mailboxes)
20
20
  - [Messages](#messages)
21
+ - [Sandbox](#sandbox)
21
22
  - [Threads](#threads)
22
23
  - [Webhooks](#webhooks)
23
24
  - [Suppressions](#suppressions)
@@ -60,7 +61,12 @@ const message = await shipmail.messages.send({
60
61
  subject: "Hello",
61
62
  text: "Hi there",
62
63
  html: "<p>Hi there</p>",
64
+ client_reference: "crm-123",
65
+ metadata: { campaign: "onboarding" },
66
+ source_rfc_message_id: "<crm-123@example.com>",
63
67
  });
68
+
69
+ const sameMessage = await shipmail.messages.list({ client_reference: "crm-123" });
64
70
  ```
65
71
 
66
72
  The SDK does not auto-read environment variables. Pass the key explicitly.
@@ -81,6 +87,7 @@ const shipmail = new ShipMailClient({
81
87
  timeout: 30_000,
82
88
  fetch: customFetch,
83
89
  defaultHeaders: { "x-app-name": "my-app" },
90
+ organizationId: "00000000-0000-4000-8000-000000000123",
84
91
  });
85
92
  ```
86
93
 
@@ -92,6 +99,7 @@ const shipmail = new ShipMailClient({
92
99
  | `timeout` | `number` | `30_000` | Per-request timeout in ms. |
93
100
  | `fetch` | `typeof fetch` | `globalThis.fetch` | Custom fetch implementation. |
94
101
  | `defaultHeaders` | `Record<string, string>` | `{}` | Headers added to every request. |
102
+ | `organizationId` | `string` | none | Delegated child organization for approved infrastructure calls. |
95
103
 
96
104
  ## Domains
97
105
 
@@ -99,6 +107,7 @@ const shipmail = new ShipMailClient({
99
107
  await shipmail.domains.create({ name: "example.com" });
100
108
  await shipmail.domains.list({ limit: 10 });
101
109
  await shipmail.domains.get("dom_...");
110
+ await shipmail.domains.getDnsRecords("dom_...");
102
111
  await shipmail.domains.update("dom_...", { catch_all_mailbox_id: "mbx_..." });
103
112
  await shipmail.domains.delete("dom_...");
104
113
  await shipmail.domains.verify("dom_...");
@@ -121,12 +130,20 @@ await shipmail.domains.register({
121
130
  await shipmail.mailboxes.create({
122
131
  domain_id: "dom_...",
123
132
  address: "hello",
133
+ password: "StrongPass123",
124
134
  display_name: "Hello",
125
135
  });
126
136
  await shipmail.mailboxes.list({ domain_id: "dom_..." });
127
137
  await shipmail.mailboxes.get("mbx_...");
128
138
  await shipmail.mailboxes.update("mbx_...", { display_name: "New Name" });
139
+ await shipmail.mailboxes.suspend("mbx_...");
140
+ await shipmail.mailboxes.resume("mbx_...");
129
141
  await shipmail.mailboxes.resetPassword("mbx_...", { password: "NewPassword1" });
142
+ const forwarding = await shipmail.mailboxes.createForwarding("mbx_...", {
143
+ destination: "owner@example.net",
144
+ });
145
+ const forwardingList = await shipmail.mailboxes.listForwarding("mbx_...");
146
+ await shipmail.mailboxes.deleteForwarding("mbx_...", forwarding.id);
130
147
  const folders = await shipmail.mailboxes.listFolders("mbx_...");
131
148
  const folder = await shipmail.mailboxes.createFolder("mbx_...", {
132
149
  name: "VIP",
@@ -170,6 +187,28 @@ await shipmail.messages.reply("msg_...", {
170
187
  });
171
188
  ```
172
189
 
190
+ ## Sandbox
191
+
192
+ Create a test API key (`sm_test_...`) to simulate email without contacting real recipients. Test messages, threads, rules, webhooks, quota, suppressions, and reputation are isolated from live mode.
193
+
194
+ ```ts
195
+ const testClient = new ShipMailClient("sm_test_...");
196
+
197
+ await testClient.messages.send({
198
+ mailbox_id: "mbx_...",
199
+ to: ["customer@example.com"],
200
+ subject: "Sandbox test",
201
+ text: "Not delivered",
202
+ sandbox_outcome: "bounced",
203
+ });
204
+
205
+ await testClient.mailboxes.injectSandboxInbound("mbx_...", {
206
+ from: "customer@example.com",
207
+ subject: "Re: Sandbox test",
208
+ text: "Fake inbound reply",
209
+ });
210
+ ```
211
+
173
212
  ## Threads
174
213
 
175
214
  ```ts
@@ -200,6 +239,10 @@ await shipmail.webhooks.delete("whk_...");
200
239
  await shipmail.webhooks.rotateSecret("whk_...");
201
240
  await shipmail.webhooks.test("whk_...");
202
241
  await shipmail.webhooks.listDeliveries("whk_...");
242
+ await shipmail.webhooks.getDelivery("whk_...", "dlv_...");
243
+ await shipmail.webhooks.replayDelivery("whk_...", "dlv_...", {
244
+ idempotencyKey: "replay-dlv-123",
245
+ });
203
246
  ```
204
247
 
205
248
  Supported event types:
@@ -308,6 +351,42 @@ URLs, and video thumbnails contribute to deliverability checks.
308
351
  Block prose fields are plain text in API requests. Use newlines for paragraph
309
352
  breaks, and use `body_html` or `custom_html` only when you need raw HTML.
310
353
 
354
+ ## Partner beta
355
+
356
+ Approved partner accounts can create isolated operator-owned organizations and read consolidated
357
+ usage:
358
+
359
+ ```ts
360
+ const child = await shipmail.partner.createOrganization(
361
+ {
362
+ name: "Operator",
363
+ external_reference: "operator_123",
364
+ owner_email: "owner@example.com",
365
+ mailbox_limit: 3,
366
+ data_classification: "internal_test",
367
+ },
368
+ { idempotencyKey: "operator-123" },
369
+ );
370
+
371
+ const delegated = new ShipMailClient({
372
+ apiKey: process.env.SHIPMAIL_API_KEY!,
373
+ organizationId: child.organization_id,
374
+ });
375
+
376
+ await delegated.domains.list();
377
+ await delegated.mailboxes.create({
378
+ domain_id: "dom_...",
379
+ address: "support",
380
+ generate_password: true,
381
+ });
382
+ await shipmail.partner.usage();
383
+ ```
384
+
385
+ Use a separate client for delegated infrastructure. Partner target context is not accepted by
386
+ message, thread, calendar, contacts, export, suppression, billing, or password endpoints. The beta
387
+ requires Shipmail approval and externally owned domains. Delegated mailbox creation must use
388
+ `generate_password: true`; the generated primary password is never returned to the partner.
389
+
311
390
  ## Status
312
391
 
313
392
  ```ts
@@ -394,6 +473,7 @@ type MethodOptions = {
394
473
  signal?: AbortSignal;
395
474
  headers?: Record<string, string>;
396
475
  idempotencyKey?: string;
476
+ organizationId?: string;
397
477
  };
398
478
  ```
399
479
 
package/dist/index.cjs CHANGED
@@ -446,6 +446,13 @@ var Domains = class extends ApiResource {
446
446
  methodOptions: options
447
447
  });
448
448
  }
449
+ getDnsRecords(id, options) {
450
+ return this.client.request({
451
+ method: "GET",
452
+ path: `/domains/${encodeURIComponent(id)}/dns-records`,
453
+ methodOptions: options
454
+ });
455
+ }
449
456
  update(id, params, options) {
450
457
  return this.client.request({
451
458
  method: "PATCH",
@@ -488,6 +495,14 @@ var Domains = class extends ApiResource {
488
495
 
489
496
  // src/resources/mailboxes.ts
490
497
  var Mailboxes = class extends ApiResource {
498
+ injectSandboxInbound(id, params, options) {
499
+ return this.client.request({
500
+ method: "POST",
501
+ path: `/mailboxes/${encodeURIComponent(id)}/sandbox/inbound`,
502
+ body: params,
503
+ methodOptions: options
504
+ });
505
+ }
491
506
  create(params, options) {
492
507
  return this.client.request({
493
508
  method: "POST",
@@ -536,6 +551,34 @@ var Mailboxes = class extends ApiResource {
536
551
  methodOptions: options
537
552
  });
538
553
  }
554
+ suspend(id, options) {
555
+ return this.client.request({
556
+ method: "POST",
557
+ path: `/mailboxes/${encodeURIComponent(id)}/suspend`,
558
+ methodOptions: options
559
+ });
560
+ }
561
+ resume(id, options) {
562
+ return this.client.request({
563
+ method: "POST",
564
+ path: `/mailboxes/${encodeURIComponent(id)}/resume`,
565
+ methodOptions: options
566
+ });
567
+ }
568
+ createExport(id, options) {
569
+ return this.client.request({
570
+ method: "POST",
571
+ path: `/mailboxes/${encodeURIComponent(id)}/exports`,
572
+ methodOptions: options
573
+ });
574
+ }
575
+ getExport(id, exportId, options) {
576
+ return this.client.request({
577
+ method: "GET",
578
+ path: `/mailboxes/${encodeURIComponent(id)}/exports/${encodeURIComponent(exportId)}`,
579
+ methodOptions: options
580
+ });
581
+ }
539
582
  listFolders(id, options) {
540
583
  return this.client.request({
541
584
  method: "GET",
@@ -653,6 +696,28 @@ var Mailboxes = class extends ApiResource {
653
696
  methodOptions: options
654
697
  });
655
698
  }
699
+ listForwarding(id, options) {
700
+ return this.client.request({
701
+ method: "GET",
702
+ path: `/mailboxes/${encodeURIComponent(id)}/forwarding`,
703
+ methodOptions: options
704
+ });
705
+ }
706
+ createForwarding(id, params, options) {
707
+ return this.client.request({
708
+ method: "POST",
709
+ path: `/mailboxes/${encodeURIComponent(id)}/forwarding`,
710
+ body: params,
711
+ methodOptions: options
712
+ });
713
+ }
714
+ deleteForwarding(id, forwardingId, options) {
715
+ return this.client.request({
716
+ method: "DELETE",
717
+ path: `/mailboxes/${encodeURIComponent(id)}/forwarding/${encodeURIComponent(forwardingId)}`,
718
+ methodOptions: options
719
+ });
720
+ }
656
721
  updateAutoReply(id, params, options) {
657
722
  return this.client.request({
658
723
  method: "PATCH",
@@ -731,6 +796,7 @@ var Messages = class extends ApiResource {
731
796
  path: "/messages",
732
797
  query: {
733
798
  mailbox_id: params.mailbox_id,
799
+ client_reference: params.client_reference,
734
800
  cursor: params.cursor,
735
801
  limit: params.limit
736
802
  },
@@ -740,6 +806,7 @@ var Messages = class extends ApiResource {
740
806
  listAutoPaginating(params) {
741
807
  return new Page(this.client, "/messages", {
742
808
  mailbox_id: params.mailbox_id,
809
+ client_reference: params.client_reference,
743
810
  limit: params.limit
744
811
  });
745
812
  }
@@ -911,6 +978,72 @@ var Newsletters = class extends ApiResource {
911
978
  }
912
979
  };
913
980
 
981
+ // src/resources/partner.ts
982
+ var Partner = class extends ApiResource {
983
+ listOrganizations(options) {
984
+ return this.client.request({
985
+ method: "GET",
986
+ path: "/partner/organizations",
987
+ methodOptions: options
988
+ });
989
+ }
990
+ createOrganization(params, options) {
991
+ return this.client.request({
992
+ method: "POST",
993
+ path: "/partner/organizations",
994
+ body: params,
995
+ methodOptions: options
996
+ });
997
+ }
998
+ getOrganization(id, options) {
999
+ return this.client.request({
1000
+ method: "GET",
1001
+ path: `/partner/organizations/${encodeURIComponent(id)}`,
1002
+ methodOptions: options
1003
+ });
1004
+ }
1005
+ updateOrganization(id, params, options) {
1006
+ return this.client.request({
1007
+ method: "PATCH",
1008
+ path: `/partner/organizations/${encodeURIComponent(id)}`,
1009
+ body: params,
1010
+ methodOptions: options
1011
+ });
1012
+ }
1013
+ resendOwnershipInvitation(id, params = {}, options) {
1014
+ return this.client.request({
1015
+ method: "POST",
1016
+ path: `/partner/organizations/${encodeURIComponent(id)}/ownership-invitations`,
1017
+ body: params,
1018
+ methodOptions: options
1019
+ });
1020
+ }
1021
+ suspendOrganization(id, options) {
1022
+ return this.client.request({
1023
+ method: "POST",
1024
+ path: `/partner/organizations/${encodeURIComponent(id)}/suspend`,
1025
+ methodOptions: options
1026
+ });
1027
+ }
1028
+ resumeOrganization(id, options) {
1029
+ return this.client.request({
1030
+ method: "POST",
1031
+ path: `/partner/organizations/${encodeURIComponent(id)}/resume`,
1032
+ methodOptions: options
1033
+ });
1034
+ }
1035
+ offboardOrganization(id, options) {
1036
+ return this.client.request({
1037
+ method: "DELETE",
1038
+ path: `/partner/organizations/${encodeURIComponent(id)}`,
1039
+ methodOptions: options
1040
+ });
1041
+ }
1042
+ usage(options) {
1043
+ return this.client.request({ method: "GET", path: "/partner/usage", methodOptions: options });
1044
+ }
1045
+ };
1046
+
914
1047
  // src/resources/status.ts
915
1048
  var Status = class extends ApiResource {
916
1049
  get(options) {
@@ -1076,10 +1209,24 @@ var Webhooks = class extends ApiResource {
1076
1209
  }
1077
1210
  );
1078
1211
  }
1212
+ getDelivery(id, deliveryId, options) {
1213
+ return this.client.request({
1214
+ method: "GET",
1215
+ path: `/webhooks/${encodeURIComponent(id)}/deliveries/${encodeURIComponent(deliveryId)}`,
1216
+ methodOptions: options
1217
+ });
1218
+ }
1219
+ replayDelivery(id, deliveryId, options) {
1220
+ return this.client.request({
1221
+ method: "POST",
1222
+ path: `/webhooks/${encodeURIComponent(id)}/deliveries/${encodeURIComponent(deliveryId)}/replay`,
1223
+ methodOptions: options
1224
+ });
1225
+ }
1079
1226
  };
1080
1227
 
1081
1228
  // src/version.ts
1082
- var VERSION = "0.1.31";
1229
+ var VERSION = "0.1.33";
1083
1230
 
1084
1231
  // src/client.ts
1085
1232
  var DEFAULT_BASE_URL = "https://shipmail.to/api/v1";
@@ -1122,6 +1269,7 @@ var ShipMailClient = class {
1122
1269
  this.timeout = DEFAULT_TIMEOUT;
1123
1270
  this.fetchFn = globalThis.fetch;
1124
1271
  this.defaultHeaders = {};
1272
+ this.organizationId = void 0;
1125
1273
  } else {
1126
1274
  this.apiKey = config.apiKey;
1127
1275
  this.baseUrl = config.baseUrl ?? DEFAULT_BASE_URL;
@@ -1129,6 +1277,7 @@ var ShipMailClient = class {
1129
1277
  this.timeout = config.timeout ?? DEFAULT_TIMEOUT;
1130
1278
  this.fetchFn = config.fetch ?? globalThis.fetch;
1131
1279
  this.defaultHeaders = config.defaultHeaders ? { ...config.defaultHeaders } : {};
1280
+ this.organizationId = config.organizationId;
1132
1281
  }
1133
1282
  this.audiences = new Audiences(this);
1134
1283
  this.bookingPages = new BookingPages(this);
@@ -1137,6 +1286,7 @@ var ShipMailClient = class {
1137
1286
  this.mailboxes = new Mailboxes(this);
1138
1287
  this.messages = new Messages(this);
1139
1288
  this.newsletters = new Newsletters(this);
1289
+ this.partner = new Partner(this);
1140
1290
  this.suppressions = new Suppressions(this);
1141
1291
  this.threads = new Threads(this);
1142
1292
  this.webhooks = new Webhooks(this);
@@ -1177,6 +1327,10 @@ var ShipMailClient = class {
1177
1327
  if (methodOpts?.idempotencyKey) {
1178
1328
  headers["Idempotency-Key"] = methodOpts.idempotencyKey;
1179
1329
  }
1330
+ const targetOrganizationId = methodOpts?.organizationId ?? this.organizationId;
1331
+ if (targetOrganizationId) {
1332
+ headers["X-ShipMail-Organization-Id"] = targetOrganizationId;
1333
+ }
1180
1334
  let body = null;
1181
1335
  if (options.rawBody !== void 0) {
1182
1336
  headers["Content-Type"] = options.contentType ?? "application/octet-stream";
@@ -1233,6 +1387,9 @@ var ShipMailClient = class {
1233
1387
  }
1234
1388
  };
1235
1389
 
1390
+ // src/types/booking-page.ts
1391
+ var CONFERENCING_PROVIDER_IDS = ["zoom", "google_meet"];
1392
+
1236
1393
  // src/types/common.ts
1237
1394
  var WEBHOOK_EVENT_TYPES = [
1238
1395
  "message.received",
@@ -1240,6 +1397,7 @@ var WEBHOOK_EVENT_TYPES = [
1240
1397
  "message.delivered",
1241
1398
  "message.bounced",
1242
1399
  "message.complained",
1400
+ "mailbox.rule_matched",
1243
1401
  "domain.verified",
1244
1402
  "domain.verification_failed",
1245
1403
  "domain.degraded",
@@ -1248,6 +1406,7 @@ var WEBHOOK_EVENT_TYPES = [
1248
1406
  "org.sending_suspended",
1249
1407
  "org.reputation_recovered"
1250
1408
  ];
1409
+ var WEBHOOK_DELIVERY_EVENT_TYPES = ["webhook.test", ...WEBHOOK_EVENT_TYPES];
1251
1410
  var DOMAIN_STATUSES = ["pending", "verifying", "verified", "degraded", "failed"];
1252
1411
  var MESSAGE_STATUSES = [
1253
1412
  "scheduled",
@@ -1313,6 +1472,7 @@ async function verifyWebhook(body, headers, secret, options) {
1313
1472
 
1314
1473
  exports.AuthenticationError = AuthenticationError;
1315
1474
  exports.AuthorizationError = AuthorizationError;
1475
+ exports.CONFERENCING_PROVIDER_IDS = CONFERENCING_PROVIDER_IDS;
1316
1476
  exports.ConflictError = ConflictError;
1317
1477
  exports.ConnectionError = ConnectionError;
1318
1478
  exports.DOMAIN_STATUSES = DOMAIN_STATUSES;
@@ -1326,6 +1486,7 @@ exports.RateLimitError = RateLimitError;
1326
1486
  exports.ShipMailClient = ShipMailClient;
1327
1487
  exports.ShipMailError = ShipMailError;
1328
1488
  exports.ValidationError = ValidationError;
1489
+ exports.WEBHOOK_DELIVERY_EVENT_TYPES = WEBHOOK_DELIVERY_EVENT_TYPES;
1329
1490
  exports.WEBHOOK_DELIVERY_STATUSES = WEBHOOK_DELIVERY_STATUSES;
1330
1491
  exports.WEBHOOK_EVENT_TYPES = WEBHOOK_EVENT_TYPES;
1331
1492
  exports.WebhookVerificationError = WebhookVerificationError;