shipmail 0.2.2 → 0.2.3

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
@@ -20,6 +20,7 @@ Official TypeScript SDK for the [Shipmail](https://shipmail.to) API. Zero runtim
20
20
  - [Messages](#messages)
21
21
  - [Sandbox](#sandbox)
22
22
  - [Threads](#threads)
23
+ - [Reply scans](#reply-scans)
23
24
  - [Webhooks](#webhooks)
24
25
  - [Suppressions](#suppressions)
25
26
  - [Audiences](#audiences)
@@ -170,6 +171,26 @@ await shipmail.mailboxes.updateAutoReply("mbx_...", {
170
171
  from_date: "2026-06-01",
171
172
  to_date: "2026-06-07",
172
173
  });
174
+
175
+ const mailboxId = "550e8400-e29b-41d4-a716-446655440000";
176
+ const inbox = await shipmail.mailboxes.listInboxMessages(mailboxId, {
177
+ after: "2025-07-20T00:00:00.000Z",
178
+ before: "2026-07-20T00:00:00.000Z",
179
+ limit: 50,
180
+ });
181
+ const exact = await shipmail.mailboxes.getInboxMessage(mailboxId, inbox.data[0].id);
182
+
183
+ const queue = await shipmail.mailboxes.listInboxThreads(mailboxId, {
184
+ reply_state: "needs_reply",
185
+ after: "2025-07-20T00:00:00.000Z",
186
+ });
187
+ const candidate = queue.data[0];
188
+ const draft = await shipmail.mailboxes.createInboxReplyDraft(mailboxId, candidate.thread_id, {
189
+ text: "Thanks for the note.",
190
+ expected_reply_version: candidate.reply_version,
191
+ });
192
+ // Apply your approval policy before sending. Stale versions fail with 409 without delivery.
193
+ await shipmail.mailboxes.sendInboxReplyDraft(mailboxId, candidate.thread_id, draft.id);
173
194
  ```
174
195
 
175
196
  ## Messages
@@ -229,6 +250,21 @@ await shipmail.threads.reply(threadId, {
229
250
  });
230
251
  ```
231
252
 
253
+ ## Reply scans
254
+
255
+ Use a durable, atomically captured scan for a historical window. Creation returns a completed
256
+ snapshot; retry a `409` with bounded backoff while historical classification finishes, then follow
257
+ every opaque `next_cursor`; never parse or fabricate cursors. Scans are retained for 30 days.
258
+
259
+ ```ts
260
+ const scan = await shipmail.replyScans.create({
261
+ mailbox_ids: ["550e8400-e29b-41d4-a716-446655440000"],
262
+ after: new Date(Date.now() - 365 * 86_400_000).toISOString(),
263
+ });
264
+ const results = await shipmail.replyScans.listResults(scan.id, { limit: 100 });
265
+ console.log(results.data);
266
+ ```
267
+
232
268
  ## Webhooks
233
269
 
234
270
  ```ts
@@ -261,6 +297,7 @@ message.sent
261
297
  message.delivered
262
298
  message.bounced
263
299
  message.complained
300
+ thread.needs_reply
264
301
  domain.verified
265
302
  domain.verification_failed
266
303
  domain.degraded
@@ -428,6 +465,10 @@ if (page.pagination.has_more) {
428
465
  }
429
466
  ```
430
467
 
468
+ Cursors are opaque and operation-specific. Return them unchanged to the same operation. Inbox and
469
+ reply-queue cursors are bound to their mailbox, time window, sort, and filters; omit those filters on
470
+ later pages or repeat them exactly.
471
+
431
472
  Auto-paginate over all pages:
432
473
 
433
474
  ```ts
package/dist/index.cjs CHANGED
@@ -624,7 +624,9 @@ var Mailboxes = class extends ApiResource {
624
624
  folder_id: params?.folder_id,
625
625
  folder_role: params?.folder_role,
626
626
  search_text: params?.search_text,
627
- position: params?.position,
627
+ cursor: params?.cursor,
628
+ after: params?.after,
629
+ before: params?.before,
628
630
  limit: params?.limit,
629
631
  has_keyword: params?.has_keyword,
630
632
  not_keyword: params?.not_keyword
@@ -632,6 +634,29 @@ var Mailboxes = class extends ApiResource {
632
634
  methodOptions: options
633
635
  });
634
636
  }
637
+ getInboxMessage(id, messageId, options) {
638
+ return this.client.request({
639
+ method: "GET",
640
+ path: `/mailboxes/${encodeURIComponent(id)}/inbox/messages/${encodeURIComponent(messageId)}`,
641
+ methodOptions: options
642
+ });
643
+ }
644
+ listInboxThreads(id, params, options) {
645
+ return this.client.request({
646
+ method: "GET",
647
+ path: `/mailboxes/${encodeURIComponent(id)}/inbox/threads`,
648
+ query: {
649
+ reply_state: params?.reply_state,
650
+ sort_by: params?.sort_by,
651
+ order: params?.order,
652
+ after: params?.after,
653
+ before: params?.before,
654
+ cursor: params?.cursor,
655
+ limit: params?.limit
656
+ },
657
+ methodOptions: options
658
+ });
659
+ }
635
660
  getInboxThread(id, threadId, options) {
636
661
  return this.client.request({
637
662
  method: "GET",
@@ -639,6 +664,29 @@ var Mailboxes = class extends ApiResource {
639
664
  methodOptions: options
640
665
  });
641
666
  }
667
+ updateInboxThreadReplyState(id, threadId, params, options) {
668
+ return this.client.request({
669
+ method: "PATCH",
670
+ path: `/mailboxes/${encodeURIComponent(id)}/inbox/threads/${encodeURIComponent(threadId)}`,
671
+ body: params,
672
+ methodOptions: options
673
+ });
674
+ }
675
+ createInboxReplyDraft(id, threadId, params, options) {
676
+ return this.client.request({
677
+ method: "POST",
678
+ path: `/mailboxes/${encodeURIComponent(id)}/inbox/threads/${encodeURIComponent(threadId)}/drafts`,
679
+ body: params,
680
+ methodOptions: options
681
+ });
682
+ }
683
+ sendInboxReplyDraft(id, threadId, draftId, options) {
684
+ return this.client.request({
685
+ method: "POST",
686
+ path: `/mailboxes/${encodeURIComponent(id)}/inbox/threads/${encodeURIComponent(threadId)}/drafts/${encodeURIComponent(draftId)}/send`,
687
+ methodOptions: options
688
+ });
689
+ }
642
690
  replyToInboxMessage(id, messageId, params, options) {
643
691
  return this.client.request({
644
692
  method: "POST",
@@ -1097,6 +1145,33 @@ var Partner = class extends ApiResource {
1097
1145
  }
1098
1146
  };
1099
1147
 
1148
+ // src/resources/reply-scans.ts
1149
+ var ReplyScans = class extends ApiResource {
1150
+ create(params, options) {
1151
+ return this.client.request({
1152
+ method: "POST",
1153
+ path: "/reply-scans",
1154
+ body: params,
1155
+ methodOptions: options
1156
+ });
1157
+ }
1158
+ get(id, options) {
1159
+ return this.client.request({
1160
+ method: "GET",
1161
+ path: `/reply-scans/${encodeURIComponent(id)}`,
1162
+ methodOptions: options
1163
+ });
1164
+ }
1165
+ listResults(id, params, options) {
1166
+ return this.client.request({
1167
+ method: "GET",
1168
+ path: `/reply-scans/${encodeURIComponent(id)}/results`,
1169
+ query: { cursor: params?.cursor, limit: params?.limit },
1170
+ methodOptions: options
1171
+ });
1172
+ }
1173
+ };
1174
+
1100
1175
  // src/resources/status.ts
1101
1176
  var Status = class extends ApiResource {
1102
1177
  get(options) {
@@ -1280,7 +1355,7 @@ var Webhooks = class extends ApiResource {
1280
1355
  };
1281
1356
 
1282
1357
  // src/version.ts
1283
- var VERSION = "0.2.2";
1358
+ var VERSION = "0.2.3";
1284
1359
 
1285
1360
  // src/client.ts
1286
1361
  var DEFAULT_BASE_URL = "https://shipmail.to/api/v1";
@@ -1341,6 +1416,7 @@ var ShipMailClient = class {
1341
1416
  this.messages = new Messages(this);
1342
1417
  this.newsletters = new Newsletters(this);
1343
1418
  this.partner = new Partner(this);
1419
+ this.replyScans = new ReplyScans(this);
1344
1420
  this.suppressions = new Suppressions(this);
1345
1421
  this.threads = new Threads(this);
1346
1422
  this.webhooks = new Webhooks(this);
@@ -1451,6 +1527,7 @@ var WEBHOOK_EVENT_TYPES = [
1451
1527
  "message.delivered",
1452
1528
  "message.bounced",
1453
1529
  "message.complained",
1530
+ "thread.needs_reply",
1454
1531
  "mailbox.rule_matched",
1455
1532
  "domain.verified",
1456
1533
  "domain.verification_failed",
@@ -1473,7 +1550,14 @@ var MESSAGE_STATUSES = [
1473
1550
  "suppressed",
1474
1551
  "cancelled"
1475
1552
  ];
1476
- var MESSAGE_SOURCES = ["api", "newsletter", "dashboard", "inbound", "smtp"];
1553
+ var MESSAGE_SOURCES = [
1554
+ "api",
1555
+ "newsletter",
1556
+ "dashboard",
1557
+ "inbound",
1558
+ "smtp",
1559
+ "agent"
1560
+ ];
1477
1561
  var WEBHOOK_DELIVERY_STATUSES = ["pending", "delivered", "failed"];
1478
1562
 
1479
1563
  // src/webhook-verification.ts