delivrie 0.0.0-stage → 0.1.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 ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 South Circle
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,3 +1,122 @@
1
- # Temporary Holding Version
1
+ # Delivrie for Node.js
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ The official TypeScript SDK for the [Delivrie](https://delivrie.io) email API. It uses only web-standard APIs (`fetch`, Web Crypto), so the same package runs on Node.js 18+, Bun, Deno, Cloudflare Workers and Vercel Edge. No dependencies.
4
+
5
+ ```bash
6
+ npm install delivrie
7
+ ```
8
+
9
+ ## Send an email
10
+
11
+ ```ts
12
+ import { Delivrie } from "delivrie";
13
+
14
+ const delivrie = new Delivrie(process.env.DELIVRIE_API_KEY);
15
+
16
+ const { data, error } = await delivrie.emails.send({
17
+ from: "Kora <orders@mail.kora.ng>",
18
+ to: "ada@example.com",
19
+ subject: "Your order is on its way",
20
+ html: "<p>Thanks for your order!</p>",
21
+ });
22
+
23
+ if (error) console.error(error.name, error.message);
24
+ else console.log("Sent", data.id);
25
+ ```
26
+
27
+ Create an API key at [delivrie.io/api-keys](https://delivrie.io/api-keys). If you leave out the key, the SDK reads `DELIVRIE_API_KEY` from the environment. Never use your key in browser code: call Delivrie from your server or an edge function.
28
+
29
+ CommonJS works too:
30
+
31
+ ```js
32
+ const Delivrie = require("delivrie");
33
+ const delivrie = new Delivrie("dlv_...");
34
+ ```
35
+
36
+ ## Results and errors
37
+
38
+ Every call resolves to `{ data, error }`, and exactly one of them is `null`. API errors never throw, so you don't need `try`/`catch`:
39
+
40
+ ```ts
41
+ const { error } = await delivrie.domains.get("dom_123");
42
+ if (error?.name === "not_found") { /* ... */ }
43
+ ```
44
+
45
+ `error` has `statusCode`, `name` and `message`, matching the [API's errors](https://delivrie.io/docs/errors). Network problems and timeouts come back with `statusCode: 0` and the name `network_error` or `timeout`.
46
+
47
+ ## Retries and idempotency
48
+
49
+ Reads and deletes are retried up to twice on server errors and network failures, with backoff. Sends are only retried when you pass an idempotency key, so a retry can never send the same email twice:
50
+
51
+ ```ts
52
+ await delivrie.emails.send(email, { idempotencyKey: `order-${order.id}` });
53
+ ```
54
+
55
+ Change the defaults with `new Delivrie(key, { maxRetries: 0, timeout: 10_000 })`.
56
+
57
+ ## More examples
58
+
59
+ ```ts
60
+ // Attachments: pass a base64 string, a Buffer or a Uint8Array
61
+ await delivrie.emails.send({
62
+ from: "billing@mail.kora.ng",
63
+ to: ["ada@example.com"],
64
+ subject: "Invoice",
65
+ text: "Your invoice is attached.",
66
+ attachments: [{ filename: "invoice.pdf", content: await readFile("invoice.pdf") }],
67
+ });
68
+
69
+ // A published template, scheduled for later
70
+ await delivrie.emails.send({
71
+ from: "hello@mail.kora.ng",
72
+ to: "ada@example.com",
73
+ template: { id: "welcome", variables: { first_name: "Ada" } },
74
+ scheduledAt: "tomorrow at 9am",
75
+ });
76
+
77
+ // Up to 100 emails in one request
78
+ await delivrie.emails.batch([{ ... }, { ... }]);
79
+
80
+ // Domains, contacts, broadcasts
81
+ await delivrie.domains.create({ name: "mail.kora.ng" });
82
+ await delivrie.contacts.create({ email: "ada@example.com", first_name: "Ada" });
83
+ await delivrie.broadcasts.send("bc_123", { scheduled_at: "in 1 hour" });
84
+
85
+ // Start automations listening for an event
86
+ await delivrie.events.send({ event: "user.signed_up", email: "ada@example.com", data: { plan: "starter" } });
87
+ ```
88
+
89
+ The client covers `emails`, `domains`, `apiKeys`, `webhooks`, `contacts`, `segments`, `topics`, `contactProperties`, `broadcasts`, `templates`, `suppressions`, `events`, `automations`, `inbox`, `metrics`, `logs` and `usage`. For anything else, `delivrie.request(method, path, body)` calls the API directly.
90
+
91
+ ## Verify webhooks
92
+
93
+ Delivrie signs webhooks with the [Standard Webhooks](https://www.standardwebhooks.com) scheme. Check the signature against the raw body, before parsing it:
94
+
95
+ ```ts
96
+ import { verifyWebhook } from "delivrie";
97
+
98
+ // Next.js route handler, Hono, Workers, etc.
99
+ export async function POST(req: Request) {
100
+ try {
101
+ const event = await verifyWebhook({
102
+ payload: await req.text(),
103
+ headers: req.headers,
104
+ secret: process.env.DELIVRIE_WEBHOOK_SECRET!, // whsec_...
105
+ });
106
+ if (event.type === "email.bounced") { /* ... */ }
107
+ return new Response("ok");
108
+ } catch {
109
+ return new Response("invalid signature", { status: 400 });
110
+ }
111
+ }
112
+ ```
113
+
114
+ With Express, use `express.raw({ type: "application/json" })` on the route and pass `req.body` and `req.headers`.
115
+
116
+ ## Links
117
+
118
+ - [Docs](https://delivrie.io/docs)
119
+ - [API reference](https://delivrie.io/docs/api)
120
+ - [Changelog](https://delivrie.io/docs/changelog)
121
+
122
+ MIT licensed.
@@ -0,0 +1,242 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Delivrie = exports.VERSION = void 0;
4
+ const webhooks_js_1 = require("./webhooks.cjs");
5
+ exports.VERSION = "0.1.0";
6
+ const DEFAULT_BASE_URL = "https://delivrie.io/api";
7
+ const sleep = (ms) => new Promise((r) => setTimeout(r, ms));
8
+ const enc = encodeURIComponent;
9
+ function toBase64(bytes) {
10
+ let s = "";
11
+ for (let i = 0; i < bytes.length; i += 0x8000)
12
+ s += String.fromCharCode.apply(null, Array.from(bytes.subarray(i, i + 0x8000)));
13
+ return btoa(s);
14
+ }
15
+ function normalizeEmail(e) {
16
+ const { replyTo, scheduledAt, attachments, ...rest } = e;
17
+ const out = { ...rest };
18
+ if (out.reply_to === undefined && replyTo !== undefined)
19
+ out.reply_to = replyTo;
20
+ const when = rest.scheduled_at ?? scheduledAt;
21
+ if (when !== undefined)
22
+ out.scheduled_at = when instanceof Date ? when.toISOString() : when;
23
+ if (attachments)
24
+ out.attachments = attachments.map((a) => ({ ...a, content: typeof a.content === "string" ? a.content : toBase64(a.content) }));
25
+ return out;
26
+ }
27
+ /**
28
+ * The Delivrie client.
29
+ *
30
+ * ```ts
31
+ * import { Delivrie } from "delivrie";
32
+ * const delivrie = new Delivrie(process.env.DELIVRIE_API_KEY);
33
+ * const { data, error } = await delivrie.emails.send({ from: "Kora <hi@kora.ng>", to: "ada@example.com", subject: "Hi", html: "<p>Hello</p>" });
34
+ * ```
35
+ */
36
+ class Delivrie {
37
+ constructor(apiKey, options = {}) {
38
+ // ---------------------------------------------------------------- resources
39
+ this.emails = {
40
+ /** Send one email. Returns its id straight away; delivery events arrive through webhooks. */
41
+ send: (email, opts) => this.request("POST", "/emails", normalizeEmail(email), opts),
42
+ /** Send up to 100 emails in one request (no attachments or scheduling). */
43
+ batch: (emails, opts) => this.request("POST", "/emails/batch", emails.map(normalizeEmail), opts),
44
+ get: (id) => this.request("GET", `/emails/${enc(id)}`),
45
+ list: (params = {}) => this.request("GET", "/emails", undefined, { query: { ...params } }),
46
+ /** Received (inbound) emails. */
47
+ listReceived: (params = {}) => this.request("GET", "/emails/received", undefined, { query: { ...params } }),
48
+ /** Move a scheduled email. */
49
+ update: (id, params) => this.request("PATCH", `/emails/${enc(id)}`, { scheduled_at: params.scheduled_at instanceof Date ? params.scheduled_at.toISOString() : params.scheduled_at }),
50
+ /** Cancel a scheduled email. */
51
+ cancel: (id) => this.request("POST", `/emails/${enc(id)}/cancel`),
52
+ forward: (id, params) => this.request("POST", `/emails/${enc(id)}/forward`, params),
53
+ };
54
+ this.domains = {
55
+ create: (params) => this.request("POST", "/domains", params),
56
+ get: (id) => this.request("GET", `/domains/${enc(id)}`),
57
+ /** Check DNS now and update the domain's status. */
58
+ verify: (id) => this.request("POST", `/domains/${enc(id)}/verify`),
59
+ update: (id, params) => this.request("PATCH", `/domains/${enc(id)}`, params),
60
+ list: () => this.request("GET", "/domains"),
61
+ remove: (id) => this.request("DELETE", `/domains/${enc(id)}`),
62
+ };
63
+ this.apiKeys = {
64
+ create: (params) => this.request("POST", "/api-keys", params),
65
+ list: () => this.request("GET", "/api-keys"),
66
+ remove: (id) => this.request("DELETE", `/api-keys/${enc(id)}`),
67
+ };
68
+ this.webhooks = {
69
+ create: (params) => this.request("POST", "/webhooks", params),
70
+ list: () => this.request("GET", "/webhooks"),
71
+ /** Recent delivery attempts for a webhook. */
72
+ deliveries: (id) => this.request("GET", `/webhooks/${enc(id)}/events`),
73
+ /** Send a test event to the endpoint. */
74
+ test: (id) => this.request("POST", `/webhooks/${enc(id)}/test`),
75
+ /** Send a past delivery again. */
76
+ replay: (deliveryId) => this.request("POST", `/webhook-deliveries/${enc(deliveryId)}/replay`),
77
+ /** Check a webhook request's signature and return the parsed event. Rejects with `WebhookVerificationError` if it isn't from Delivrie. */
78
+ verify: (opts) => (0, webhooks_js_1.verifyWebhook)(opts),
79
+ };
80
+ this.contacts = {
81
+ create: (params) => this.request("POST", "/contacts", params),
82
+ /** By id or email address. */
83
+ get: (idOrEmail) => this.request("GET", `/contacts/${enc(idOrEmail)}`),
84
+ update: (idOrEmail, params) => this.request("PATCH", `/contacts/${enc(idOrEmail)}`, params),
85
+ list: (params = {}) => this.request("GET", "/contacts", undefined, { query: { ...params } }),
86
+ remove: (idOrEmail) => this.request("DELETE", `/contacts/${enc(idOrEmail)}`),
87
+ };
88
+ this.segments = {
89
+ create: (params) => this.request("POST", "/segments", params),
90
+ list: () => this.request("GET", "/segments"),
91
+ remove: (id) => this.request("DELETE", `/segments/${enc(id)}`),
92
+ /** Add contacts by email (they're created if needed). */
93
+ addContacts: (id, contacts) => this.request("POST", `/segments/${enc(id)}/contacts`, { contacts: contacts.map((c) => (typeof c === "string" ? { email: c } : c)) }),
94
+ };
95
+ this.topics = { list: () => this.request("GET", "/topics") };
96
+ this.contactProperties = { list: () => this.request("GET", "/contact-properties") };
97
+ this.broadcasts = {
98
+ create: (params) => this.request("POST", "/broadcasts", params),
99
+ get: (id) => this.request("GET", `/broadcasts/${enc(id)}`),
100
+ list: () => this.request("GET", "/broadcasts"),
101
+ /** Send now, or schedule with `scheduled_at`. */
102
+ send: (id, params = {}) => this.request("POST", `/broadcasts/${enc(id)}/send`, params.scheduled_at === undefined ? {} : { scheduled_at: params.scheduled_at instanceof Date ? params.scheduled_at.toISOString() : params.scheduled_at }),
103
+ cancel: (id) => this.request("POST", `/broadcasts/${enc(id)}/cancel`),
104
+ recipients: (id) => this.request("GET", `/broadcasts/${enc(id)}/recipients`),
105
+ remove: (id) => this.request("DELETE", `/broadcasts/${enc(id)}`),
106
+ };
107
+ this.templates = {
108
+ create: (params) => this.request("POST", "/templates", params),
109
+ /** By id or alias. */
110
+ get: (idOrAlias) => this.request("GET", `/templates/${enc(idOrAlias)}`),
111
+ list: () => this.request("GET", "/templates"),
112
+ /** Publish the current draft so sends use it. */
113
+ publish: (id) => this.request("POST", `/templates/${enc(id)}/publish`),
114
+ };
115
+ this.suppressions = {
116
+ /** Stop sending to one or more addresses. */
117
+ add: (email) => this.request("POST", "/suppressions", Array.isArray(email) ? { emails: email } : { email }),
118
+ list: () => this.request("GET", "/suppressions"),
119
+ remove: (email) => this.request("DELETE", `/suppressions/${enc(email)}`),
120
+ };
121
+ this.events = {
122
+ /** Record an event for a contact; live automations listening for it start. */
123
+ send: (params) => this.request("POST", "/events", params),
124
+ list: () => this.request("GET", "/events"),
125
+ };
126
+ this.automations = {
127
+ list: () => this.request("GET", "/automations"),
128
+ get: (id) => this.request("GET", `/automations/${enc(id)}`),
129
+ create: (params) => this.request("POST", "/automations", params),
130
+ runs: (id) => this.request("GET", `/automations/${enc(id)}/runs`),
131
+ publish: (id) => this.request("POST", `/automations/${enc(id)}/publish`),
132
+ pause: (id) => this.request("POST", `/automations/${enc(id)}/pause`),
133
+ resume: (id) => this.request("POST", `/automations/${enc(id)}/resume`),
134
+ };
135
+ this.inbox = {
136
+ threads: {
137
+ list: (params = {}) => this.request("GET", "/inbox/threads", undefined, { query: params }),
138
+ get: (id) => this.request("GET", `/inbox/threads/${enc(id)}`),
139
+ update: (id, params) => this.request("PATCH", `/inbox/threads/${enc(id)}`, params),
140
+ reply: (id, params) => this.request("POST", `/inbox/threads/${enc(id)}/reply`, params),
141
+ },
142
+ labels: { list: () => this.request("GET", "/inbox/labels") },
143
+ };
144
+ this.metrics = {
145
+ get: (params = {}) => this.request("GET", "/metrics", undefined, { query: params }),
146
+ };
147
+ this.logs = {
148
+ list: (params = {}) => this.request("GET", "/logs", undefined, { query: { ...params } }),
149
+ get: (id) => this.request("GET", `/logs/${enc(id)}`),
150
+ };
151
+ this.usage = { get: () => this.request("GET", "/usage") };
152
+ // process.env on Node, Bun and Deno (with --allow-env); absent on edge runtimes, where you pass the key directly.
153
+ const env = globalThis.process?.env ?? {};
154
+ const key = apiKey ?? env.DELIVRIE_API_KEY;
155
+ if (!key)
156
+ throw new Error("Missing API key. Pass it to new Delivrie(key) or set DELIVRIE_API_KEY. Create one at https://delivrie.io/api-keys");
157
+ this.key = key;
158
+ this.baseUrl = (options.baseUrl ?? env.DELIVRIE_BASE_URL ?? DEFAULT_BASE_URL).replace(/\/+$/, "");
159
+ this.timeout = options.timeout ?? 30000;
160
+ this.maxRetries = Math.max(0, options.maxRetries ?? 2);
161
+ const f = options.fetch ?? (typeof fetch !== "undefined" ? fetch : undefined);
162
+ if (!f)
163
+ throw new Error("No fetch available. Use Node.js 18 or later, or pass options.fetch.");
164
+ this.fetchImpl = f;
165
+ this.extraHeaders = options.headers ?? {};
166
+ }
167
+ /** Low-level request for endpoints the SDK doesn't wrap yet. Paths are relative to the API base, e.g. `/emails`. */
168
+ async request(method, path, body, opts = {}) {
169
+ let url = this.baseUrl + path;
170
+ if (opts.query) {
171
+ const q = Object.entries(opts.query).filter(([, v]) => v !== undefined && v !== null).map(([k, v]) => `${enc(k)}=${enc(String(v))}`).join("&");
172
+ if (q)
173
+ url += (url.includes("?") ? "&" : "?") + q;
174
+ }
175
+ const headers = {
176
+ authorization: `Bearer ${this.key}`,
177
+ accept: "application/json",
178
+ "user-agent": `delivrie-node/${exports.VERSION}`,
179
+ ...this.extraHeaders,
180
+ };
181
+ if (body !== undefined)
182
+ headers["content-type"] = "application/json";
183
+ if (opts.idempotencyKey)
184
+ headers["idempotency-key"] = opts.idempotencyKey;
185
+ // GET/DELETE are safe to repeat; POST/PATCH only with an idempotency key, so a retry never sends an email twice.
186
+ const retryable = method === "GET" || method === "DELETE" || !!opts.idempotencyKey;
187
+ for (let attempt = 0;; attempt++) {
188
+ const ctrl = new AbortController();
189
+ const timer = setTimeout(() => ctrl.abort(new Error("timeout")), this.timeout);
190
+ const onAbort = () => ctrl.abort(opts.signal?.reason);
191
+ opts.signal?.addEventListener("abort", onAbort, { once: true });
192
+ let res;
193
+ try {
194
+ res = await this.fetchImpl(url, { method, headers, body: body === undefined ? undefined : JSON.stringify(body), signal: ctrl.signal });
195
+ }
196
+ catch (e) {
197
+ clearTimeout(timer);
198
+ opts.signal?.removeEventListener("abort", onAbort);
199
+ if (opts.signal?.aborted)
200
+ return { data: null, error: { statusCode: 0, name: "aborted", message: "The request was aborted" } };
201
+ if (retryable && attempt < this.maxRetries) {
202
+ await sleep(backoff(attempt));
203
+ continue;
204
+ }
205
+ const timedOut = ctrl.signal.aborted;
206
+ return { data: null, error: { statusCode: 0, name: timedOut ? "timeout" : "network_error", message: timedOut ? `No response within ${this.timeout} ms` : e?.message || "Network error" } };
207
+ }
208
+ clearTimeout(timer);
209
+ opts.signal?.removeEventListener("abort", onAbort);
210
+ const text = await res.text();
211
+ let json = null;
212
+ try {
213
+ json = text ? JSON.parse(text) : null;
214
+ }
215
+ catch {
216
+ json = null;
217
+ }
218
+ if (res.ok)
219
+ return { data: json, error: null };
220
+ const err = toError(res.status, json, text);
221
+ const rateLimited = res.status === 429 && err.name === "rate_limit_exceeded";
222
+ if ((rateLimited || res.status >= 500) && retryable && attempt < this.maxRetries) {
223
+ const after = Number(res.headers.get("retry-after"));
224
+ await sleep(Number.isFinite(after) && after > 0 ? Math.min(after, 30) * 1000 : backoff(attempt));
225
+ continue;
226
+ }
227
+ return { data: null, error: err };
228
+ }
229
+ }
230
+ }
231
+ exports.Delivrie = Delivrie;
232
+ function backoff(attempt) {
233
+ return Math.min(8000, 500 * 2 ** attempt) + Math.floor(Math.random() * 250);
234
+ }
235
+ function toError(status, json, text) {
236
+ const j = (json && typeof json === "object" ? json : {});
237
+ return {
238
+ statusCode: typeof j.statusCode === "number" ? j.statusCode : status,
239
+ name: typeof j.name === "string" ? j.name : status === 401 ? "invalid_api_key" : status === 404 ? "not_found" : status === 429 ? "rate_limit_exceeded" : "application_error",
240
+ message: typeof j.message === "string" ? j.message : text.slice(0, 300) || `Request failed with status ${status}`,
241
+ };
242
+ }
@@ -0,0 +1,190 @@
1
+ import type { ApiKey, Automation, Broadcast, Contact, CreateApiKeyRequest, CreateApiKeyResponse, CreateBroadcastRequest, CreateContactRequest, CreateDomainRequest, CreateEmailResponse, CreateTemplateRequest, CreateWebhookRequest, CreateWebhookResponse, Domain, Email, EmailSummary, ForwardEmailRequest, InboxThread, List, ListContactsParams, ListEmailsParams, Log, LogSummary, Metrics, Pagination, ReplyToThreadRequest, RequestOptions, Result, Segment, SendEmailRequest, SendEventRequest, Suppression, Template, Topic, UpdateContactRequest, UpdateDomainRequest, Usage, Webhook, WebhookDelivery, Deleted } from "./types.cjs";
2
+ import { type VerifyWebhookOptions } from "./webhooks.cjs";
3
+ export declare const VERSION = "0.1.0";
4
+ export interface DelivrieOptions {
5
+ /** Defaults to `https://delivrie.io/api`. */
6
+ baseUrl?: string;
7
+ /** Per-request timeout in milliseconds. Default 30000. */
8
+ timeout?: number;
9
+ /** Retries for rate limits, server errors and network errors. Default 2. Sends are only retried with an idempotency key. */
10
+ maxRetries?: number;
11
+ /** A custom fetch, for example in tests or older runtimes. Defaults to the global fetch. */
12
+ fetch?: typeof fetch;
13
+ /** Extra headers sent with every request. */
14
+ headers?: Record<string, string>;
15
+ }
16
+ type Method = "GET" | "POST" | "PATCH" | "DELETE";
17
+ type Query = Record<string, string | number | boolean | undefined | null>;
18
+ /**
19
+ * The Delivrie client.
20
+ *
21
+ * ```ts
22
+ * import { Delivrie } from "delivrie";
23
+ * const delivrie = new Delivrie(process.env.DELIVRIE_API_KEY);
24
+ * const { data, error } = await delivrie.emails.send({ from: "Kora <hi@kora.ng>", to: "ada@example.com", subject: "Hi", html: "<p>Hello</p>" });
25
+ * ```
26
+ */
27
+ export declare class Delivrie {
28
+ readonly baseUrl: string;
29
+ private readonly key;
30
+ private readonly timeout;
31
+ private readonly maxRetries;
32
+ private readonly fetchImpl;
33
+ private readonly extraHeaders;
34
+ constructor(apiKey?: string, options?: DelivrieOptions);
35
+ /** Low-level request for endpoints the SDK doesn't wrap yet. Paths are relative to the API base, e.g. `/emails`. */
36
+ request<T>(method: Method, path: string, body?: unknown, opts?: RequestOptions & {
37
+ query?: Query;
38
+ }): Promise<Result<T>>;
39
+ readonly emails: {
40
+ /** Send one email. Returns its id straight away; delivery events arrive through webhooks. */
41
+ send: (email: SendEmailRequest, opts?: RequestOptions) => Promise<Result<CreateEmailResponse>>;
42
+ /** Send up to 100 emails in one request (no attachments or scheduling). */
43
+ batch: (emails: SendEmailRequest[], opts?: RequestOptions) => Promise<Result<{
44
+ data: CreateEmailResponse[];
45
+ }>>;
46
+ get: (id: string) => Promise<Result<Email>>;
47
+ list: (params?: ListEmailsParams) => Promise<Result<List<EmailSummary>>>;
48
+ /** Received (inbound) emails. */
49
+ listReceived: (params?: Pagination) => Promise<Result<List<EmailSummary>>>;
50
+ /** Move a scheduled email. */
51
+ update: (id: string, params: {
52
+ scheduled_at: string | Date;
53
+ }) => Promise<Result<{
54
+ object: "email";
55
+ id: string;
56
+ }>>;
57
+ /** Cancel a scheduled email. */
58
+ cancel: (id: string) => Promise<Result<{
59
+ object: "email";
60
+ id: string;
61
+ }>>;
62
+ forward: (id: string, params: ForwardEmailRequest) => Promise<Result<CreateEmailResponse>>;
63
+ };
64
+ readonly domains: {
65
+ create: (params: CreateDomainRequest) => Promise<Result<Domain>>;
66
+ get: (id: string) => Promise<Result<Domain>>;
67
+ /** Check DNS now and update the domain's status. */
68
+ verify: (id: string) => Promise<Result<Domain>>;
69
+ update: (id: string, params: UpdateDomainRequest) => Promise<Result<Domain>>;
70
+ list: () => Promise<Result<List<Domain>>>;
71
+ remove: (id: string) => Promise<Result<Deleted>>;
72
+ };
73
+ readonly apiKeys: {
74
+ create: (params: CreateApiKeyRequest) => Promise<Result<CreateApiKeyResponse>>;
75
+ list: () => Promise<Result<List<ApiKey>>>;
76
+ remove: (id: string) => Promise<Result<Deleted>>;
77
+ };
78
+ readonly webhooks: {
79
+ create: (params: CreateWebhookRequest) => Promise<Result<CreateWebhookResponse>>;
80
+ list: () => Promise<Result<List<Webhook>>>;
81
+ /** Recent delivery attempts for a webhook. */
82
+ deliveries: (id: string) => Promise<Result<List<WebhookDelivery>>>;
83
+ /** Send a test event to the endpoint. */
84
+ test: (id: string) => Promise<Result<Record<string, unknown>>>;
85
+ /** Send a past delivery again. */
86
+ replay: (deliveryId: string) => Promise<Result<Record<string, unknown>>>;
87
+ /** Check a webhook request's signature and return the parsed event. Rejects with `WebhookVerificationError` if it isn't from Delivrie. */
88
+ verify: <T = Record<string, unknown>>(opts: VerifyWebhookOptions) => Promise<import("./types.cjs").WebhookEvent<T>>;
89
+ };
90
+ readonly contacts: {
91
+ create: (params: CreateContactRequest) => Promise<Result<{
92
+ object: "contact";
93
+ id: string;
94
+ }>>;
95
+ /** By id or email address. */
96
+ get: (idOrEmail: string) => Promise<Result<Contact>>;
97
+ update: (idOrEmail: string, params: UpdateContactRequest) => Promise<Result<Contact>>;
98
+ list: (params?: ListContactsParams) => Promise<Result<List<Contact>>>;
99
+ remove: (idOrEmail: string) => Promise<Result<Deleted>>;
100
+ };
101
+ readonly segments: {
102
+ create: (params: {
103
+ name: string;
104
+ }) => Promise<Result<{
105
+ object: "segment";
106
+ id: string;
107
+ }>>;
108
+ list: () => Promise<Result<List<Segment>>>;
109
+ remove: (id: string) => Promise<Result<Deleted>>;
110
+ /** Add contacts by email (they're created if needed). */
111
+ addContacts: (id: string, contacts: Array<string | CreateContactRequest>) => Promise<Result<Record<string, unknown>>>;
112
+ };
113
+ readonly topics: {
114
+ list: () => Promise<Result<List<Topic>>>;
115
+ };
116
+ readonly contactProperties: {
117
+ list: () => Promise<Result<List<Record<string, unknown>>>>;
118
+ };
119
+ readonly broadcasts: {
120
+ create: (params: CreateBroadcastRequest) => Promise<Result<{
121
+ object: "broadcast";
122
+ id: string;
123
+ }>>;
124
+ get: (id: string) => Promise<Result<Broadcast>>;
125
+ list: () => Promise<Result<List<Broadcast>>>;
126
+ /** Send now, or schedule with `scheduled_at`. */
127
+ send: (id: string, params?: {
128
+ scheduled_at?: string | Date;
129
+ }) => Promise<Result<Broadcast>>;
130
+ cancel: (id: string) => Promise<Result<Broadcast>>;
131
+ recipients: (id: string) => Promise<Result<List<Record<string, unknown>>>>;
132
+ remove: (id: string) => Promise<Result<Deleted>>;
133
+ };
134
+ readonly templates: {
135
+ create: (params: CreateTemplateRequest) => Promise<Result<{
136
+ object: "template";
137
+ id: string;
138
+ }>>;
139
+ /** By id or alias. */
140
+ get: (idOrAlias: string) => Promise<Result<Template>>;
141
+ list: () => Promise<Result<List<Template>>>;
142
+ /** Publish the current draft so sends use it. */
143
+ publish: (id: string) => Promise<Result<Template>>;
144
+ };
145
+ readonly suppressions: {
146
+ /** Stop sending to one or more addresses. */
147
+ add: (email: string | string[]) => Promise<Result<Record<string, unknown>>>;
148
+ list: () => Promise<Result<List<Suppression>>>;
149
+ remove: (email: string) => Promise<Result<Deleted>>;
150
+ };
151
+ readonly events: {
152
+ /** Record an event for a contact; live automations listening for it start. */
153
+ send: (params: SendEventRequest) => Promise<Result<Record<string, unknown>>>;
154
+ list: () => Promise<Result<List<Record<string, unknown>>>>;
155
+ };
156
+ readonly automations: {
157
+ list: () => Promise<Result<List<Automation>>>;
158
+ get: (id: string) => Promise<Result<Automation>>;
159
+ create: (params: Record<string, unknown>) => Promise<Result<Automation>>;
160
+ runs: (id: string) => Promise<Result<List<Record<string, unknown>>>>;
161
+ publish: (id: string) => Promise<Result<Automation>>;
162
+ pause: (id: string) => Promise<Result<Automation>>;
163
+ resume: (id: string) => Promise<Result<Automation>>;
164
+ };
165
+ readonly inbox: {
166
+ threads: {
167
+ list: (params?: Pagination & Query) => Promise<Result<List<InboxThread>>>;
168
+ get: (id: string) => Promise<Result<InboxThread>>;
169
+ update: (id: string, params: Record<string, unknown>) => Promise<Result<InboxThread>>;
170
+ reply: (id: string, params: ReplyToThreadRequest) => Promise<Result<CreateEmailResponse>>;
171
+ };
172
+ labels: {
173
+ list: () => Promise<Result<List<Record<string, unknown>>>>;
174
+ };
175
+ };
176
+ readonly metrics: {
177
+ get: (params?: {
178
+ days?: number;
179
+ domain_id?: string;
180
+ }) => Promise<Result<Metrics>>;
181
+ };
182
+ readonly logs: {
183
+ list: (params?: Pagination) => Promise<Result<List<LogSummary>>>;
184
+ get: (id: string) => Promise<Result<Log>>;
185
+ };
186
+ readonly usage: {
187
+ get: () => Promise<Result<Usage>>;
188
+ };
189
+ }
190
+ export {};
@@ -0,0 +1,13 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.default = exports.WebhookVerificationError = exports.verifyWebhook = exports.VERSION = exports.Delivrie = void 0;
4
+ var client_js_1 = require("./client.cjs");
5
+ Object.defineProperty(exports, "Delivrie", { enumerable: true, get: function () { return client_js_1.Delivrie; } });
6
+ Object.defineProperty(exports, "VERSION", { enumerable: true, get: function () { return client_js_1.VERSION; } });
7
+ var webhooks_js_1 = require("./webhooks.cjs");
8
+ Object.defineProperty(exports, "verifyWebhook", { enumerable: true, get: function () { return webhooks_js_1.verifyWebhook; } });
9
+ Object.defineProperty(exports, "WebhookVerificationError", { enumerable: true, get: function () { return webhooks_js_1.WebhookVerificationError; } });
10
+ var client_js_2 = require("./client.cjs");
11
+ Object.defineProperty(exports, "default", { enumerable: true, get: function () { return client_js_2.Delivrie; } });
12
+
13
+ module.exports = Object.assign(exports.Delivrie, exports);
@@ -0,0 +1,4 @@
1
+ export { Delivrie, VERSION, type DelivrieOptions } from "./client.cjs";
2
+ export { verifyWebhook, WebhookVerificationError, type VerifyWebhookOptions } from "./webhooks.cjs";
3
+ export type * from "./types.cjs";
4
+ export { Delivrie as default } from "./client.cjs";
@@ -0,0 +1,4 @@
1
+ "use strict";
2
+ // Request and response types for the Delivrie API (https://delivrie.io/docs/api).
3
+ // Field names match the API exactly (snake_case), so the API reference and these types read the same.
4
+ Object.defineProperty(exports, "__esModule", { value: true });