retransmit.dev 0.3.0 → 0.5.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/LICENSE +21 -661
- package/README.md +108 -4
- package/dist/index.cjs +72 -16
- package/dist/index.d.cts +99 -6
- package/dist/index.d.ts +99 -6
- package/dist/index.js +72 -16
- package/package.json +9 -5
package/README.md
CHANGED
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
# retransmit.dev
|
|
2
2
|
|
|
3
|
+
[](https://github.com/retransmit-dev/retransmit-node/actions/workflows/ci.yml)
|
|
4
|
+
[](https://www.npmjs.com/package/retransmit.dev)
|
|
5
|
+
[](https://github.com/retransmit-dev/retransmit-node/blob/main/LICENSE)
|
|
6
|
+
|
|
3
7
|
Node.js SDK for the [Retransmit](https://retransmit.dev) messaging API. Send email, SMS, and WhatsApp through one typed client. Zero dependencies, works on Node 18+ and edge runtimes with `fetch`.
|
|
4
8
|
|
|
5
9
|
| Channel | SDK namespace | Availability |
|
|
@@ -74,6 +78,103 @@ Names and values allow letters, digits, underscores and dashes, up to 256
|
|
|
74
78
|
characters each. Names must be unique within one email. Batch emails accept
|
|
75
79
|
the same `tags` field.
|
|
76
80
|
|
|
81
|
+
### Custom headers
|
|
82
|
+
|
|
83
|
+
Add your own message headers with `headers`. The common case is a unique
|
|
84
|
+
`X-Entity-Ref-ID` per email so Gmail does not thread related messages, such as
|
|
85
|
+
order updates with the same subject, into one conversation.
|
|
86
|
+
|
|
87
|
+
```ts
|
|
88
|
+
await retransmit.emails.send({
|
|
89
|
+
from: "Acme <hello@yourdomain.com>",
|
|
90
|
+
to: "user@example.com",
|
|
91
|
+
subject: "Your order shipped",
|
|
92
|
+
html: "<p>Order #4821 is on its way.</p>",
|
|
93
|
+
headers: { "X-Entity-Ref-ID": "order_4821" },
|
|
94
|
+
});
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
Up to 20 headers per email. Names are printable ASCII without `:` and may
|
|
98
|
+
only appear once; values are a single line. Headers Retransmit sets itself,
|
|
99
|
+
like `From`, `To`, `Subject`, `Date` or `Message-ID`, are rejected with a
|
|
100
|
+
`validation_error`. Marketing emails keep the hosted `List-Unsubscribe`
|
|
101
|
+
headers even if you pass your own. Headers come back on `emails.get`, and
|
|
102
|
+
batch emails accept the same field.
|
|
103
|
+
|
|
104
|
+
### Attachments
|
|
105
|
+
|
|
106
|
+
Attach up to 20 files, 30 MB in total. Pass the bytes as `content` (a
|
|
107
|
+
`Buffer`, `Uint8Array` or base64 string), or a public URL as `path` and
|
|
108
|
+
Retransmit fetches it while the request runs. Either way the file travels
|
|
109
|
+
inside the email.
|
|
110
|
+
|
|
111
|
+
```ts
|
|
112
|
+
import { readFile } from "node:fs/promises";
|
|
113
|
+
|
|
114
|
+
await retransmit.emails.send({
|
|
115
|
+
from: "Acme <billing@yourdomain.com>",
|
|
116
|
+
to: "user@example.com",
|
|
117
|
+
subject: "Your invoice",
|
|
118
|
+
html: "<p>Your invoice is attached.</p>",
|
|
119
|
+
attachments: [
|
|
120
|
+
{ filename: "invoice.pdf", content: await readFile("./invoice.pdf") },
|
|
121
|
+
{ filename: "terms.pdf", path: "https://yourdomain.com/terms.pdf" },
|
|
122
|
+
],
|
|
123
|
+
});
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
To embed an image in the HTML, give it a `contentId` and reference it as
|
|
127
|
+
`cid:`:
|
|
128
|
+
|
|
129
|
+
```ts
|
|
130
|
+
await retransmit.emails.send({
|
|
131
|
+
from: "Acme <hello@yourdomain.com>",
|
|
132
|
+
to: "user@example.com",
|
|
133
|
+
subject: "Welcome",
|
|
134
|
+
html: '<p><img src="cid:logo" alt="Acme" /> Glad to have you.</p>',
|
|
135
|
+
attachments: [{ filename: "logo.png", path: "https://yourdomain.com/logo.png", contentId: "logo" }],
|
|
136
|
+
});
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
Executables, scripts and installers are rejected with `invalid_attachment`,
|
|
140
|
+
and `batch.send` does not accept attachments. Files are kept for 30 days so
|
|
141
|
+
you can see what went out:
|
|
142
|
+
|
|
143
|
+
```ts
|
|
144
|
+
const { data } = await retransmit.emails.attachments("em_xxxxxxxxxxxx");
|
|
145
|
+
// data.attachments: [{ id, filename, content_type, size, download_url, expires_at, ... }]
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
`download_url` is signed and valid for one hour; it is `null` once the file
|
|
149
|
+
has expired.
|
|
150
|
+
|
|
151
|
+
### Idempotency
|
|
152
|
+
|
|
153
|
+
A send can succeed on the server and still fail on your side, through a
|
|
154
|
+
timeout or a dropped connection. Retrying it blindly sends the email twice.
|
|
155
|
+
Pass an `idempotencyKey` and retries become safe: for 24 hours the same key
|
|
156
|
+
with the same payload returns the original response, `id` included, and
|
|
157
|
+
nothing is queued again.
|
|
158
|
+
|
|
159
|
+
```ts
|
|
160
|
+
await retransmit.emails.send(
|
|
161
|
+
{
|
|
162
|
+
from: "Acme <hello@yourdomain.com>",
|
|
163
|
+
to: "user@example.com",
|
|
164
|
+
subject: "Welcome to Acme",
|
|
165
|
+
html: "<p>Glad to have you.</p>",
|
|
166
|
+
},
|
|
167
|
+
{ idempotencyKey: "welcome-user/123" },
|
|
168
|
+
);
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
Use a value that identifies that exact email, such as a UUID or
|
|
172
|
+
`<event>/<entity-id>`. Keys are 1 to 256 characters and are shared by every
|
|
173
|
+
API key in your organization. The same key with a different payload returns
|
|
174
|
+
`invalid_idempotent_request`; a retry that overlaps the first request returns
|
|
175
|
+
`concurrent_idempotent_requests`, so wait a moment and try again. Batches
|
|
176
|
+
accept the same option with one key for the whole batch.
|
|
177
|
+
|
|
77
178
|
### List and filter emails
|
|
78
179
|
|
|
79
180
|
`emails.list` returns your emails newest first. Every tag you pass must match.
|
|
@@ -133,10 +234,13 @@ console.log(data?.status); // "sent" | "delivered" | "undelivered" | ...
|
|
|
133
234
|
Send up to 10,000 emails in one request:
|
|
134
235
|
|
|
135
236
|
```ts
|
|
136
|
-
const { data: batch } = await retransmit.batch.send(
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
237
|
+
const { data: batch } = await retransmit.batch.send(
|
|
238
|
+
[
|
|
239
|
+
{ from: "Acme <hello@yourdomain.com>", to: "a@example.com", subject: "Hi", text: "Hello A" },
|
|
240
|
+
{ from: "Acme <hello@yourdomain.com>", to: "b@example.com", subject: "Hi", text: "Hello B" },
|
|
241
|
+
],
|
|
242
|
+
{ idempotencyKey: "weekly-digest/2026-09-07" },
|
|
243
|
+
);
|
|
140
244
|
|
|
141
245
|
const { data: progress } = await retransmit.batch.get(batch!.id);
|
|
142
246
|
console.log(progress?.processed, "/", progress?.total, progress?.counts);
|
package/dist/index.cjs
CHANGED
|
@@ -32,6 +32,24 @@ __export(index_exports, {
|
|
|
32
32
|
module.exports = __toCommonJS(index_exports);
|
|
33
33
|
|
|
34
34
|
// src/emails.ts
|
|
35
|
+
function toBase64(bytes) {
|
|
36
|
+
if (typeof Buffer !== "undefined") return Buffer.from(bytes).toString("base64");
|
|
37
|
+
let binary = "";
|
|
38
|
+
const CHUNK = 32768;
|
|
39
|
+
for (let i = 0; i < bytes.length; i += CHUNK) {
|
|
40
|
+
binary += String.fromCharCode(...bytes.subarray(i, i + CHUNK));
|
|
41
|
+
}
|
|
42
|
+
return btoa(binary);
|
|
43
|
+
}
|
|
44
|
+
function toWireAttachment(attachment) {
|
|
45
|
+
return {
|
|
46
|
+
filename: attachment.filename,
|
|
47
|
+
content: attachment.content === void 0 || typeof attachment.content === "string" ? attachment.content : toBase64(attachment.content),
|
|
48
|
+
path: attachment.path,
|
|
49
|
+
content_type: attachment.contentType,
|
|
50
|
+
content_id: attachment.contentId
|
|
51
|
+
};
|
|
52
|
+
}
|
|
35
53
|
function toWirePayload(options) {
|
|
36
54
|
return {
|
|
37
55
|
from: options.from,
|
|
@@ -43,7 +61,9 @@ function toWirePayload(options) {
|
|
|
43
61
|
html: options.html,
|
|
44
62
|
text: options.text,
|
|
45
63
|
marketing: options.marketing,
|
|
46
|
-
tags: options.tags
|
|
64
|
+
tags: options.tags,
|
|
65
|
+
headers: options.headers,
|
|
66
|
+
attachments: options.attachments?.map(toWireAttachment)
|
|
47
67
|
};
|
|
48
68
|
}
|
|
49
69
|
var Emails = class {
|
|
@@ -51,9 +71,18 @@ var Emails = class {
|
|
|
51
71
|
this.client = client;
|
|
52
72
|
}
|
|
53
73
|
client;
|
|
54
|
-
/**
|
|
55
|
-
|
|
56
|
-
|
|
74
|
+
/**
|
|
75
|
+
* Queues a single email. Poll `get(id)` or subscribe to webhooks for the
|
|
76
|
+
* outcome. Pass `{ idempotencyKey }` to make the call safe to retry.
|
|
77
|
+
*/
|
|
78
|
+
send(options, requestOptions) {
|
|
79
|
+
return this.client.request(
|
|
80
|
+
"POST",
|
|
81
|
+
"/v1/emails",
|
|
82
|
+
toWirePayload(options),
|
|
83
|
+
void 0,
|
|
84
|
+
requestOptions
|
|
85
|
+
);
|
|
57
86
|
}
|
|
58
87
|
/** Retrieves an email with its current status and event history. */
|
|
59
88
|
get(id) {
|
|
@@ -76,6 +105,21 @@ var Emails = class {
|
|
|
76
105
|
tags() {
|
|
77
106
|
return this.client.request("GET", "/v1/emails/tags");
|
|
78
107
|
}
|
|
108
|
+
/**
|
|
109
|
+
* The attachments of an email, each with a signed `download_url` valid for
|
|
110
|
+
* one hour. Files are kept for 30 days after the send; after that the link
|
|
111
|
+
* is `null` and only the metadata remains.
|
|
112
|
+
*/
|
|
113
|
+
attachments(emailId) {
|
|
114
|
+
return this.client.request("GET", `/v1/emails/${encodeURIComponent(emailId)}/attachments`);
|
|
115
|
+
}
|
|
116
|
+
/** One attachment of an email with a signed download link. */
|
|
117
|
+
getAttachment(emailId, attachmentId) {
|
|
118
|
+
return this.client.request(
|
|
119
|
+
"GET",
|
|
120
|
+
`/v1/emails/${encodeURIComponent(emailId)}/attachments/${encodeURIComponent(attachmentId)}`
|
|
121
|
+
);
|
|
122
|
+
}
|
|
79
123
|
};
|
|
80
124
|
|
|
81
125
|
// src/batch.ts
|
|
@@ -84,11 +128,19 @@ var Batch = class {
|
|
|
84
128
|
this.client = client;
|
|
85
129
|
}
|
|
86
130
|
client;
|
|
87
|
-
/**
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
131
|
+
/**
|
|
132
|
+
* Queues up to 10,000 emails in one request. Track progress with `get(id)`.
|
|
133
|
+
* Pass `{ idempotencyKey }` covering the whole batch to make the call safe
|
|
134
|
+
* to retry.
|
|
135
|
+
*/
|
|
136
|
+
send(emails, requestOptions) {
|
|
137
|
+
return this.client.request(
|
|
138
|
+
"POST",
|
|
139
|
+
"/v1/emails/batch",
|
|
140
|
+
{ emails: emails.map(toWirePayload) },
|
|
141
|
+
void 0,
|
|
142
|
+
requestOptions
|
|
143
|
+
);
|
|
92
144
|
}
|
|
93
145
|
/** Batch progress: how many emails are in each status so far. */
|
|
94
146
|
get(id) {
|
|
@@ -147,7 +199,7 @@ var Whatsapp = class {
|
|
|
147
199
|
|
|
148
200
|
// src/retransmit.ts
|
|
149
201
|
var DEFAULT_BASE_URL = "https://api.retransmit.dev";
|
|
150
|
-
var USER_AGENT = "retransmit.dev-node/0.
|
|
202
|
+
var USER_AGENT = "retransmit.dev-node/0.5.0";
|
|
151
203
|
function readEnv(name) {
|
|
152
204
|
return typeof process !== "undefined" ? process.env?.[name] : void 0;
|
|
153
205
|
}
|
|
@@ -172,7 +224,7 @@ var Retransmit = class {
|
|
|
172
224
|
);
|
|
173
225
|
}
|
|
174
226
|
/** Internal transport shared by the resource classes. API failures are returned, never thrown. */
|
|
175
|
-
async request(method, path, body, query) {
|
|
227
|
+
async request(method, path, body, query, options = {}) {
|
|
176
228
|
const params = new URLSearchParams();
|
|
177
229
|
for (const [key, value] of Object.entries(query ?? {})) {
|
|
178
230
|
if (value === void 0) continue;
|
|
@@ -180,15 +232,19 @@ var Retransmit = class {
|
|
|
180
232
|
}
|
|
181
233
|
const encoded = params.toString();
|
|
182
234
|
const search = encoded ? `?${encoded}` : "";
|
|
235
|
+
const headers = {
|
|
236
|
+
Authorization: `Bearer ${this.apiKey}`,
|
|
237
|
+
"Content-Type": "application/json",
|
|
238
|
+
"User-Agent": USER_AGENT
|
|
239
|
+
};
|
|
240
|
+
if (options.idempotencyKey !== void 0) {
|
|
241
|
+
headers["Idempotency-Key"] = options.idempotencyKey;
|
|
242
|
+
}
|
|
183
243
|
let response;
|
|
184
244
|
try {
|
|
185
245
|
response = await fetch(`${this.baseUrl}${path}${search}`, {
|
|
186
246
|
method,
|
|
187
|
-
headers
|
|
188
|
-
Authorization: `Bearer ${this.apiKey}`,
|
|
189
|
-
"Content-Type": "application/json",
|
|
190
|
-
"User-Agent": USER_AGENT
|
|
191
|
-
},
|
|
247
|
+
headers,
|
|
192
248
|
body: body === void 0 ? void 0 : JSON.stringify(body)
|
|
193
249
|
});
|
|
194
250
|
} catch (cause) {
|
package/dist/index.d.cts
CHANGED
|
@@ -20,6 +20,18 @@ interface RetransmitOptions {
|
|
|
20
20
|
/** Override the API origin. Defaults to `https://api.retransmit.dev` (or `RETRANSMIT_BASE_URL`). */
|
|
21
21
|
baseUrl?: string;
|
|
22
22
|
}
|
|
23
|
+
/** Per-request options, passed as the second argument of `emails.send` and `batch.send`. */
|
|
24
|
+
interface RequestOptions {
|
|
25
|
+
/**
|
|
26
|
+
* Makes the request safe to retry. Sent as the `Idempotency-Key` header.
|
|
27
|
+
* For 24 hours, a retry with the same key and payload returns the original
|
|
28
|
+
* response instead of queuing the email again. 1 to 256 characters; a UUID
|
|
29
|
+
* or `<event>/<entity-id>` such as `welcome-user/123` works well. A retry
|
|
30
|
+
* with a different payload fails with `invalid_idempotent_request`, and one
|
|
31
|
+
* that overlaps the first request fails with `concurrent_idempotent_requests`.
|
|
32
|
+
*/
|
|
33
|
+
idempotencyKey?: string;
|
|
34
|
+
}
|
|
23
35
|
interface SendEmailOptions {
|
|
24
36
|
/** Sender, as `address@domain.com` or `Name <address@domain.com>`. The domain must be verified on your account. */
|
|
25
37
|
from: string;
|
|
@@ -47,6 +59,68 @@ interface SendEmailOptions {
|
|
|
47
59
|
* and are never sent to the recipient.
|
|
48
60
|
*/
|
|
49
61
|
tags?: EmailTag[];
|
|
62
|
+
/**
|
|
63
|
+
* Custom message headers, keyed by header name, for example
|
|
64
|
+
* `{ "X-Entity-Ref-ID": "order_4821" }` to stop Gmail threading related
|
|
65
|
+
* emails together. Up to 20 headers. Names are printable ASCII without `:`
|
|
66
|
+
* (up to 126 characters); values are single-line, up to 870 characters.
|
|
67
|
+
* Headers Retransmit sets itself (From, To, Cc, Bcc, Reply-To, Subject,
|
|
68
|
+
* Date, Message-ID, Return-Path, MIME/Content-* and DKIM-Signature) are
|
|
69
|
+
* rejected with a `validation_error`. On marketing emails the hosted
|
|
70
|
+
* List-Unsubscribe headers take precedence over yours.
|
|
71
|
+
*/
|
|
72
|
+
headers?: EmailHeaders;
|
|
73
|
+
/**
|
|
74
|
+
* Files to attach, up to 20 per email and 30 MB in total. Each needs a
|
|
75
|
+
* `filename` and either `content` (the bytes) or `path` (a public URL
|
|
76
|
+
* fetched when you call `send`). Add `contentId` to embed an image inline.
|
|
77
|
+
* Not accepted by `batch.send`.
|
|
78
|
+
*/
|
|
79
|
+
attachments?: Attachment[];
|
|
80
|
+
}
|
|
81
|
+
type EmailHeaders = Record<string, string>;
|
|
82
|
+
/** A file to attach. Provide exactly one of `content` and `path`. */
|
|
83
|
+
interface Attachment {
|
|
84
|
+
/**
|
|
85
|
+
* Name the recipient sees, up to 255 characters, no path separators. Its
|
|
86
|
+
* extension sets the content type when `contentType` is omitted.
|
|
87
|
+
*/
|
|
88
|
+
filename: string;
|
|
89
|
+
/** The file: a `Buffer`, a `Uint8Array`, or an already base64 encoded string. */
|
|
90
|
+
content?: string | Uint8Array;
|
|
91
|
+
/**
|
|
92
|
+
* Public http(s) URL the file is fetched from while the request runs, with
|
|
93
|
+
* a 15 second budget. Private and internal hosts are refused.
|
|
94
|
+
*/
|
|
95
|
+
path?: string;
|
|
96
|
+
/** MIME type such as `application/pdf`. Inferred from the filename when omitted. */
|
|
97
|
+
contentType?: string;
|
|
98
|
+
/**
|
|
99
|
+
* Embeds the file inline and sets its Content-ID. Reference it in `html`
|
|
100
|
+
* as `<img src="cid:the-id">`. Letters, digits, `.`, `_`, `@` and `-`, up
|
|
101
|
+
* to 128 characters, unique per email.
|
|
102
|
+
*/
|
|
103
|
+
contentId?: string;
|
|
104
|
+
}
|
|
105
|
+
/** An attachment as it was sent, without a download link. */
|
|
106
|
+
interface EmailAttachment {
|
|
107
|
+
id: string;
|
|
108
|
+
filename: string;
|
|
109
|
+
content_type: string;
|
|
110
|
+
/** Size in bytes of the decoded file. */
|
|
111
|
+
size: number;
|
|
112
|
+
content_id: string | null;
|
|
113
|
+
/** True for images embedded via `contentId`. */
|
|
114
|
+
inline: boolean;
|
|
115
|
+
}
|
|
116
|
+
interface EmailAttachmentWithDownload extends EmailAttachment {
|
|
117
|
+
/** When the stored file is deleted, 30 days after the send. */
|
|
118
|
+
expires_at: string;
|
|
119
|
+
/** Signed link to download the file, valid for one hour. `null` once the file has expired. */
|
|
120
|
+
download_url: string | null;
|
|
121
|
+
}
|
|
122
|
+
interface ListEmailAttachmentsResponse {
|
|
123
|
+
attachments: EmailAttachmentWithDownload[];
|
|
50
124
|
}
|
|
51
125
|
interface EmailTag {
|
|
52
126
|
name: string;
|
|
@@ -72,11 +146,15 @@ interface GetEmailResponse {
|
|
|
72
146
|
subject: string;
|
|
73
147
|
marketing: boolean;
|
|
74
148
|
tags: EmailTag[];
|
|
149
|
+
/** Custom headers given at send time, or null. */
|
|
150
|
+
headers: EmailHeaders | null;
|
|
75
151
|
status: EmailStatus;
|
|
76
152
|
error: string | null;
|
|
77
153
|
created_at: string;
|
|
78
154
|
last_event_at: string | null;
|
|
79
155
|
events: EmailEvent[];
|
|
156
|
+
/** Attachments given at send time, without download links. See `emails.attachments`. */
|
|
157
|
+
attachments: EmailAttachment[];
|
|
80
158
|
}
|
|
81
159
|
interface ListEmailsOptions {
|
|
82
160
|
/**
|
|
@@ -255,8 +333,12 @@ interface GetBatchResponse {
|
|
|
255
333
|
declare class Batch {
|
|
256
334
|
private readonly client;
|
|
257
335
|
constructor(client: Retransmit);
|
|
258
|
-
/**
|
|
259
|
-
|
|
336
|
+
/**
|
|
337
|
+
* Queues up to 10,000 emails in one request. Track progress with `get(id)`.
|
|
338
|
+
* Pass `{ idempotencyKey }` covering the whole batch to make the call safe
|
|
339
|
+
* to retry.
|
|
340
|
+
*/
|
|
341
|
+
send(emails: SendEmailOptions[], requestOptions?: RequestOptions): Promise<Result<SendBatchResponse>>;
|
|
260
342
|
/** Batch progress: how many emails are in each status so far. */
|
|
261
343
|
get(id: string): Promise<Result<GetBatchResponse>>;
|
|
262
344
|
}
|
|
@@ -264,8 +346,11 @@ declare class Batch {
|
|
|
264
346
|
declare class Emails {
|
|
265
347
|
private readonly client;
|
|
266
348
|
constructor(client: Retransmit);
|
|
267
|
-
/**
|
|
268
|
-
|
|
349
|
+
/**
|
|
350
|
+
* Queues a single email. Poll `get(id)` or subscribe to webhooks for the
|
|
351
|
+
* outcome. Pass `{ idempotencyKey }` to make the call safe to retry.
|
|
352
|
+
*/
|
|
353
|
+
send(options: SendEmailOptions, requestOptions?: RequestOptions): Promise<Result<SendEmailResponse>>;
|
|
269
354
|
/** Retrieves an email with its current status and event history. */
|
|
270
355
|
get(id: string): Promise<Result<GetEmailResponse>>;
|
|
271
356
|
/**
|
|
@@ -275,6 +360,14 @@ declare class Emails {
|
|
|
275
360
|
list(options?: ListEmailsOptions): Promise<Result<ListEmailsResponse>>;
|
|
276
361
|
/** Every distinct tag on your emails, with a count of emails carrying it. */
|
|
277
362
|
tags(): Promise<Result<ListEmailTagsResponse>>;
|
|
363
|
+
/**
|
|
364
|
+
* The attachments of an email, each with a signed `download_url` valid for
|
|
365
|
+
* one hour. Files are kept for 30 days after the send; after that the link
|
|
366
|
+
* is `null` and only the metadata remains.
|
|
367
|
+
*/
|
|
368
|
+
attachments(emailId: string): Promise<Result<ListEmailAttachmentsResponse>>;
|
|
369
|
+
/** One attachment of an email with a signed download link. */
|
|
370
|
+
getAttachment(emailId: string, attachmentId: string): Promise<Result<EmailAttachmentWithDownload>>;
|
|
278
371
|
}
|
|
279
372
|
|
|
280
373
|
declare class Sms {
|
|
@@ -308,7 +401,7 @@ declare class Retransmit {
|
|
|
308
401
|
private readonly baseUrl;
|
|
309
402
|
constructor(apiKey?: string, options?: RetransmitOptions);
|
|
310
403
|
/** Internal transport shared by the resource classes. API failures are returned, never thrown. */
|
|
311
|
-
request<T>(method: "GET" | "POST", path: string, body?: unknown, query?: Record<string, string | number | string[] | undefined
|
|
404
|
+
request<T>(method: "GET" | "POST", path: string, body?: unknown, query?: Record<string, string | number | string[] | undefined>, options?: RequestOptions): Promise<Result<T>>;
|
|
312
405
|
}
|
|
313
406
|
|
|
314
|
-
export { Batch, EMAIL_STATUSES, type EmailEvent, type EmailStatus, type EmailSummary, type EmailTag, type EmailTagCount, Emails, type GetBatchResponse, type GetEmailResponse, type GetSmsResponse, type GetWhatsappResponse, type ListEmailTagsResponse, type ListEmailsOptions, type ListEmailsResponse, type Result, Retransmit, type RetransmitError, type RetransmitOptions, SMS_STATUSES, type SendBatchResponse, type SendEmailOptions, type SendEmailResponse, type SendSmsOptions, type SendSmsResponse, type SendWhatsappOptions, type SendWhatsappResponse, Sms, type SmsEvent, type SmsStatus, WHATSAPP_STATUSES, Whatsapp, type WhatsappDocument, type WhatsappEvent, type WhatsappMedia, type WhatsappMessageType, type WhatsappStatus, type WhatsappTemplate };
|
|
407
|
+
export { type Attachment, Batch, EMAIL_STATUSES, type EmailAttachment, type EmailAttachmentWithDownload, type EmailEvent, type EmailStatus, type EmailSummary, type EmailTag, type EmailTagCount, Emails, type GetBatchResponse, type GetEmailResponse, type GetSmsResponse, type GetWhatsappResponse, type ListEmailAttachmentsResponse, type ListEmailTagsResponse, type ListEmailsOptions, type ListEmailsResponse, type RequestOptions, type Result, Retransmit, type RetransmitError, type RetransmitOptions, SMS_STATUSES, type SendBatchResponse, type SendEmailOptions, type SendEmailResponse, type SendSmsOptions, type SendSmsResponse, type SendWhatsappOptions, type SendWhatsappResponse, Sms, type SmsEvent, type SmsStatus, WHATSAPP_STATUSES, Whatsapp, type WhatsappDocument, type WhatsappEvent, type WhatsappMedia, type WhatsappMessageType, type WhatsappStatus, type WhatsappTemplate };
|
package/dist/index.d.ts
CHANGED
|
@@ -20,6 +20,18 @@ interface RetransmitOptions {
|
|
|
20
20
|
/** Override the API origin. Defaults to `https://api.retransmit.dev` (or `RETRANSMIT_BASE_URL`). */
|
|
21
21
|
baseUrl?: string;
|
|
22
22
|
}
|
|
23
|
+
/** Per-request options, passed as the second argument of `emails.send` and `batch.send`. */
|
|
24
|
+
interface RequestOptions {
|
|
25
|
+
/**
|
|
26
|
+
* Makes the request safe to retry. Sent as the `Idempotency-Key` header.
|
|
27
|
+
* For 24 hours, a retry with the same key and payload returns the original
|
|
28
|
+
* response instead of queuing the email again. 1 to 256 characters; a UUID
|
|
29
|
+
* or `<event>/<entity-id>` such as `welcome-user/123` works well. A retry
|
|
30
|
+
* with a different payload fails with `invalid_idempotent_request`, and one
|
|
31
|
+
* that overlaps the first request fails with `concurrent_idempotent_requests`.
|
|
32
|
+
*/
|
|
33
|
+
idempotencyKey?: string;
|
|
34
|
+
}
|
|
23
35
|
interface SendEmailOptions {
|
|
24
36
|
/** Sender, as `address@domain.com` or `Name <address@domain.com>`. The domain must be verified on your account. */
|
|
25
37
|
from: string;
|
|
@@ -47,6 +59,68 @@ interface SendEmailOptions {
|
|
|
47
59
|
* and are never sent to the recipient.
|
|
48
60
|
*/
|
|
49
61
|
tags?: EmailTag[];
|
|
62
|
+
/**
|
|
63
|
+
* Custom message headers, keyed by header name, for example
|
|
64
|
+
* `{ "X-Entity-Ref-ID": "order_4821" }` to stop Gmail threading related
|
|
65
|
+
* emails together. Up to 20 headers. Names are printable ASCII without `:`
|
|
66
|
+
* (up to 126 characters); values are single-line, up to 870 characters.
|
|
67
|
+
* Headers Retransmit sets itself (From, To, Cc, Bcc, Reply-To, Subject,
|
|
68
|
+
* Date, Message-ID, Return-Path, MIME/Content-* and DKIM-Signature) are
|
|
69
|
+
* rejected with a `validation_error`. On marketing emails the hosted
|
|
70
|
+
* List-Unsubscribe headers take precedence over yours.
|
|
71
|
+
*/
|
|
72
|
+
headers?: EmailHeaders;
|
|
73
|
+
/**
|
|
74
|
+
* Files to attach, up to 20 per email and 30 MB in total. Each needs a
|
|
75
|
+
* `filename` and either `content` (the bytes) or `path` (a public URL
|
|
76
|
+
* fetched when you call `send`). Add `contentId` to embed an image inline.
|
|
77
|
+
* Not accepted by `batch.send`.
|
|
78
|
+
*/
|
|
79
|
+
attachments?: Attachment[];
|
|
80
|
+
}
|
|
81
|
+
type EmailHeaders = Record<string, string>;
|
|
82
|
+
/** A file to attach. Provide exactly one of `content` and `path`. */
|
|
83
|
+
interface Attachment {
|
|
84
|
+
/**
|
|
85
|
+
* Name the recipient sees, up to 255 characters, no path separators. Its
|
|
86
|
+
* extension sets the content type when `contentType` is omitted.
|
|
87
|
+
*/
|
|
88
|
+
filename: string;
|
|
89
|
+
/** The file: a `Buffer`, a `Uint8Array`, or an already base64 encoded string. */
|
|
90
|
+
content?: string | Uint8Array;
|
|
91
|
+
/**
|
|
92
|
+
* Public http(s) URL the file is fetched from while the request runs, with
|
|
93
|
+
* a 15 second budget. Private and internal hosts are refused.
|
|
94
|
+
*/
|
|
95
|
+
path?: string;
|
|
96
|
+
/** MIME type such as `application/pdf`. Inferred from the filename when omitted. */
|
|
97
|
+
contentType?: string;
|
|
98
|
+
/**
|
|
99
|
+
* Embeds the file inline and sets its Content-ID. Reference it in `html`
|
|
100
|
+
* as `<img src="cid:the-id">`. Letters, digits, `.`, `_`, `@` and `-`, up
|
|
101
|
+
* to 128 characters, unique per email.
|
|
102
|
+
*/
|
|
103
|
+
contentId?: string;
|
|
104
|
+
}
|
|
105
|
+
/** An attachment as it was sent, without a download link. */
|
|
106
|
+
interface EmailAttachment {
|
|
107
|
+
id: string;
|
|
108
|
+
filename: string;
|
|
109
|
+
content_type: string;
|
|
110
|
+
/** Size in bytes of the decoded file. */
|
|
111
|
+
size: number;
|
|
112
|
+
content_id: string | null;
|
|
113
|
+
/** True for images embedded via `contentId`. */
|
|
114
|
+
inline: boolean;
|
|
115
|
+
}
|
|
116
|
+
interface EmailAttachmentWithDownload extends EmailAttachment {
|
|
117
|
+
/** When the stored file is deleted, 30 days after the send. */
|
|
118
|
+
expires_at: string;
|
|
119
|
+
/** Signed link to download the file, valid for one hour. `null` once the file has expired. */
|
|
120
|
+
download_url: string | null;
|
|
121
|
+
}
|
|
122
|
+
interface ListEmailAttachmentsResponse {
|
|
123
|
+
attachments: EmailAttachmentWithDownload[];
|
|
50
124
|
}
|
|
51
125
|
interface EmailTag {
|
|
52
126
|
name: string;
|
|
@@ -72,11 +146,15 @@ interface GetEmailResponse {
|
|
|
72
146
|
subject: string;
|
|
73
147
|
marketing: boolean;
|
|
74
148
|
tags: EmailTag[];
|
|
149
|
+
/** Custom headers given at send time, or null. */
|
|
150
|
+
headers: EmailHeaders | null;
|
|
75
151
|
status: EmailStatus;
|
|
76
152
|
error: string | null;
|
|
77
153
|
created_at: string;
|
|
78
154
|
last_event_at: string | null;
|
|
79
155
|
events: EmailEvent[];
|
|
156
|
+
/** Attachments given at send time, without download links. See `emails.attachments`. */
|
|
157
|
+
attachments: EmailAttachment[];
|
|
80
158
|
}
|
|
81
159
|
interface ListEmailsOptions {
|
|
82
160
|
/**
|
|
@@ -255,8 +333,12 @@ interface GetBatchResponse {
|
|
|
255
333
|
declare class Batch {
|
|
256
334
|
private readonly client;
|
|
257
335
|
constructor(client: Retransmit);
|
|
258
|
-
/**
|
|
259
|
-
|
|
336
|
+
/**
|
|
337
|
+
* Queues up to 10,000 emails in one request. Track progress with `get(id)`.
|
|
338
|
+
* Pass `{ idempotencyKey }` covering the whole batch to make the call safe
|
|
339
|
+
* to retry.
|
|
340
|
+
*/
|
|
341
|
+
send(emails: SendEmailOptions[], requestOptions?: RequestOptions): Promise<Result<SendBatchResponse>>;
|
|
260
342
|
/** Batch progress: how many emails are in each status so far. */
|
|
261
343
|
get(id: string): Promise<Result<GetBatchResponse>>;
|
|
262
344
|
}
|
|
@@ -264,8 +346,11 @@ declare class Batch {
|
|
|
264
346
|
declare class Emails {
|
|
265
347
|
private readonly client;
|
|
266
348
|
constructor(client: Retransmit);
|
|
267
|
-
/**
|
|
268
|
-
|
|
349
|
+
/**
|
|
350
|
+
* Queues a single email. Poll `get(id)` or subscribe to webhooks for the
|
|
351
|
+
* outcome. Pass `{ idempotencyKey }` to make the call safe to retry.
|
|
352
|
+
*/
|
|
353
|
+
send(options: SendEmailOptions, requestOptions?: RequestOptions): Promise<Result<SendEmailResponse>>;
|
|
269
354
|
/** Retrieves an email with its current status and event history. */
|
|
270
355
|
get(id: string): Promise<Result<GetEmailResponse>>;
|
|
271
356
|
/**
|
|
@@ -275,6 +360,14 @@ declare class Emails {
|
|
|
275
360
|
list(options?: ListEmailsOptions): Promise<Result<ListEmailsResponse>>;
|
|
276
361
|
/** Every distinct tag on your emails, with a count of emails carrying it. */
|
|
277
362
|
tags(): Promise<Result<ListEmailTagsResponse>>;
|
|
363
|
+
/**
|
|
364
|
+
* The attachments of an email, each with a signed `download_url` valid for
|
|
365
|
+
* one hour. Files are kept for 30 days after the send; after that the link
|
|
366
|
+
* is `null` and only the metadata remains.
|
|
367
|
+
*/
|
|
368
|
+
attachments(emailId: string): Promise<Result<ListEmailAttachmentsResponse>>;
|
|
369
|
+
/** One attachment of an email with a signed download link. */
|
|
370
|
+
getAttachment(emailId: string, attachmentId: string): Promise<Result<EmailAttachmentWithDownload>>;
|
|
278
371
|
}
|
|
279
372
|
|
|
280
373
|
declare class Sms {
|
|
@@ -308,7 +401,7 @@ declare class Retransmit {
|
|
|
308
401
|
private readonly baseUrl;
|
|
309
402
|
constructor(apiKey?: string, options?: RetransmitOptions);
|
|
310
403
|
/** Internal transport shared by the resource classes. API failures are returned, never thrown. */
|
|
311
|
-
request<T>(method: "GET" | "POST", path: string, body?: unknown, query?: Record<string, string | number | string[] | undefined
|
|
404
|
+
request<T>(method: "GET" | "POST", path: string, body?: unknown, query?: Record<string, string | number | string[] | undefined>, options?: RequestOptions): Promise<Result<T>>;
|
|
312
405
|
}
|
|
313
406
|
|
|
314
|
-
export { Batch, EMAIL_STATUSES, type EmailEvent, type EmailStatus, type EmailSummary, type EmailTag, type EmailTagCount, Emails, type GetBatchResponse, type GetEmailResponse, type GetSmsResponse, type GetWhatsappResponse, type ListEmailTagsResponse, type ListEmailsOptions, type ListEmailsResponse, type Result, Retransmit, type RetransmitError, type RetransmitOptions, SMS_STATUSES, type SendBatchResponse, type SendEmailOptions, type SendEmailResponse, type SendSmsOptions, type SendSmsResponse, type SendWhatsappOptions, type SendWhatsappResponse, Sms, type SmsEvent, type SmsStatus, WHATSAPP_STATUSES, Whatsapp, type WhatsappDocument, type WhatsappEvent, type WhatsappMedia, type WhatsappMessageType, type WhatsappStatus, type WhatsappTemplate };
|
|
407
|
+
export { type Attachment, Batch, EMAIL_STATUSES, type EmailAttachment, type EmailAttachmentWithDownload, type EmailEvent, type EmailStatus, type EmailSummary, type EmailTag, type EmailTagCount, Emails, type GetBatchResponse, type GetEmailResponse, type GetSmsResponse, type GetWhatsappResponse, type ListEmailAttachmentsResponse, type ListEmailTagsResponse, type ListEmailsOptions, type ListEmailsResponse, type RequestOptions, type Result, Retransmit, type RetransmitError, type RetransmitOptions, SMS_STATUSES, type SendBatchResponse, type SendEmailOptions, type SendEmailResponse, type SendSmsOptions, type SendSmsResponse, type SendWhatsappOptions, type SendWhatsappResponse, Sms, type SmsEvent, type SmsStatus, WHATSAPP_STATUSES, Whatsapp, type WhatsappDocument, type WhatsappEvent, type WhatsappMedia, type WhatsappMessageType, type WhatsappStatus, type WhatsappTemplate };
|