shipmail 0.2.1 → 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 +46 -1
- package/dist/index.cjs +106 -5
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +263 -112
- package/dist/index.d.ts +263 -112
- package/dist/index.js +106 -5
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
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
|
|
@@ -220,13 +241,30 @@ await testClient.mailboxes.injectSandboxInbound("mbx_...", {
|
|
|
220
241
|
```ts
|
|
221
242
|
const threads = await shipmail.threads.list({ mailbox_id: "mbx_..." });
|
|
222
243
|
const threadId = threads.data[0].id;
|
|
223
|
-
const thread = await shipmail.threads.get(threadId);
|
|
244
|
+
const thread = await shipmail.threads.get(threadId, { mailbox_id: "mbx_..." });
|
|
224
245
|
|
|
225
246
|
await shipmail.threads.reply(threadId, {
|
|
247
|
+
mailbox_id: "mbx_...",
|
|
248
|
+
to: ["customer@example.com"],
|
|
226
249
|
text: "Thanks for your email.",
|
|
227
250
|
});
|
|
228
251
|
```
|
|
229
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
|
+
|
|
230
268
|
## Webhooks
|
|
231
269
|
|
|
232
270
|
```ts
|
|
@@ -259,6 +297,7 @@ message.sent
|
|
|
259
297
|
message.delivered
|
|
260
298
|
message.bounced
|
|
261
299
|
message.complained
|
|
300
|
+
thread.needs_reply
|
|
262
301
|
domain.verified
|
|
263
302
|
domain.verification_failed
|
|
264
303
|
domain.degraded
|
|
@@ -356,6 +395,8 @@ Preflight responses include `url_breakdown` so you can see which links, image
|
|
|
356
395
|
URLs, and video thumbnails contribute to deliverability checks.
|
|
357
396
|
Block prose fields are plain text in API requests. Use newlines for paragraph
|
|
358
397
|
breaks, and use `body_html` or `custom_html` only when you need raw HTML.
|
|
398
|
+
Concurrent newsletter updates can throw `ConflictError` (409). Fetch the latest
|
|
399
|
+
newsletter, merge your changes, and retry the update.
|
|
359
400
|
|
|
360
401
|
## Partner beta
|
|
361
402
|
|
|
@@ -424,6 +465,10 @@ if (page.pagination.has_more) {
|
|
|
424
465
|
}
|
|
425
466
|
```
|
|
426
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
|
+
|
|
427
472
|
Auto-paginate over all pages:
|
|
428
473
|
|
|
429
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
|
-
|
|
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,45 @@ 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
|
+
}
|
|
690
|
+
replyToInboxMessage(id, messageId, params, options) {
|
|
691
|
+
return this.client.request({
|
|
692
|
+
method: "POST",
|
|
693
|
+
path: `/mailboxes/${encodeURIComponent(id)}/inbox/messages/${encodeURIComponent(messageId)}/reply`,
|
|
694
|
+
body: params,
|
|
695
|
+
methodOptions: options
|
|
696
|
+
});
|
|
697
|
+
}
|
|
698
|
+
replyToInboxThread(id, threadId, params, options) {
|
|
699
|
+
return this.client.request({
|
|
700
|
+
method: "POST",
|
|
701
|
+
path: `/mailboxes/${encodeURIComponent(id)}/inbox/threads/${encodeURIComponent(threadId)}/reply`,
|
|
702
|
+
body: params,
|
|
703
|
+
methodOptions: options
|
|
704
|
+
});
|
|
705
|
+
}
|
|
642
706
|
updateInboxMessage(id, messageId, params, options) {
|
|
643
707
|
return this.client.request({
|
|
644
708
|
method: "PATCH",
|
|
@@ -1081,6 +1145,33 @@ var Partner = class extends ApiResource {
|
|
|
1081
1145
|
}
|
|
1082
1146
|
};
|
|
1083
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
|
+
|
|
1084
1175
|
// src/resources/status.ts
|
|
1085
1176
|
var Status = class extends ApiResource {
|
|
1086
1177
|
get(options) {
|
|
@@ -1144,8 +1235,9 @@ var Threads = class extends ApiResource {
|
|
|
1144
1235
|
method: "GET",
|
|
1145
1236
|
path: `/threads/${encodeURIComponent(id)}`,
|
|
1146
1237
|
query: {
|
|
1147
|
-
|
|
1148
|
-
|
|
1238
|
+
mailbox_id: params.mailbox_id,
|
|
1239
|
+
cursor: params.cursor,
|
|
1240
|
+
limit: params.limit
|
|
1149
1241
|
},
|
|
1150
1242
|
methodOptions: options
|
|
1151
1243
|
});
|
|
@@ -1263,7 +1355,7 @@ var Webhooks = class extends ApiResource {
|
|
|
1263
1355
|
};
|
|
1264
1356
|
|
|
1265
1357
|
// src/version.ts
|
|
1266
|
-
var VERSION = "0.2.
|
|
1358
|
+
var VERSION = "0.2.3";
|
|
1267
1359
|
|
|
1268
1360
|
// src/client.ts
|
|
1269
1361
|
var DEFAULT_BASE_URL = "https://shipmail.to/api/v1";
|
|
@@ -1324,6 +1416,7 @@ var ShipMailClient = class {
|
|
|
1324
1416
|
this.messages = new Messages(this);
|
|
1325
1417
|
this.newsletters = new Newsletters(this);
|
|
1326
1418
|
this.partner = new Partner(this);
|
|
1419
|
+
this.replyScans = new ReplyScans(this);
|
|
1327
1420
|
this.suppressions = new Suppressions(this);
|
|
1328
1421
|
this.threads = new Threads(this);
|
|
1329
1422
|
this.webhooks = new Webhooks(this);
|
|
@@ -1434,6 +1527,7 @@ var WEBHOOK_EVENT_TYPES = [
|
|
|
1434
1527
|
"message.delivered",
|
|
1435
1528
|
"message.bounced",
|
|
1436
1529
|
"message.complained",
|
|
1530
|
+
"thread.needs_reply",
|
|
1437
1531
|
"mailbox.rule_matched",
|
|
1438
1532
|
"domain.verified",
|
|
1439
1533
|
"domain.verification_failed",
|
|
@@ -1456,7 +1550,14 @@ var MESSAGE_STATUSES = [
|
|
|
1456
1550
|
"suppressed",
|
|
1457
1551
|
"cancelled"
|
|
1458
1552
|
];
|
|
1459
|
-
var MESSAGE_SOURCES = [
|
|
1553
|
+
var MESSAGE_SOURCES = [
|
|
1554
|
+
"api",
|
|
1555
|
+
"newsletter",
|
|
1556
|
+
"dashboard",
|
|
1557
|
+
"inbound",
|
|
1558
|
+
"smtp",
|
|
1559
|
+
"agent"
|
|
1560
|
+
];
|
|
1460
1561
|
var WEBHOOK_DELIVERY_STATUSES = ["pending", "delivered", "failed"];
|
|
1461
1562
|
|
|
1462
1563
|
// src/webhook-verification.ts
|