groundmail 0.17.0 → 0.20.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/README.md CHANGED
@@ -46,6 +46,49 @@ await tx.emails.send({
46
46
  Outcomes: `delivered`, `bounce`, `block`, `complaint`, `suppressed`, `delayed`. Details:
47
47
  https://docs.groundmail.dev/testing
48
48
 
49
+ ## Tenants
50
+
51
+ If you send email for your own customers, create one tenant per customer. Each tenant has its
52
+ own domains, suppression list, stats, pause switch and daily limit, so one customer's bounces
53
+ or complaints never affect the others. Tenants are included on the Scale and Dedicated plans.
54
+
55
+ ```ts
56
+ await tx.tenants.create({ external_id: 'cus_123', name: 'Acme', daily_limit: 5000 })
57
+ await tx.tenants.domains.assign('cus_123', 'mail.acme.com')
58
+
59
+ await tx.emails.send({
60
+ from: 'billing@mail.acme.com',
61
+ to: 'user@example.com',
62
+ subject: 'Your invoice',
63
+ html: '<p>Thanks!</p>',
64
+ tenant: 'cus_123',
65
+ })
66
+
67
+ const { stats } = await tx.tenants.stats('cus_123', { days: 7 })
68
+ await tx.tenants.pause('cus_123', 'Unpaid invoice')
69
+ await tx.tenants.resume('cus_123')
70
+ ```
71
+
72
+ `tenant` (your external id or the Groundmail id) also works on `emails.list`, `domains.create` and
73
+ `domains.list`, `suppressions`, `apiKeys.create` (a key limited to one tenant) and
74
+ `emails.testWebhook`. Webhook endpoints take `tenants: ['cus_123']` to receive only those
75
+ tenants' email events. Details: https://docs.groundmail.dev/tenants
76
+
77
+ ## DMARC monitoring
78
+
79
+ Free for every domain. Turn it on, publish the record it returns, and read sources, pass rates
80
+ and whether it's safe to enforce once the daily reports arrive:
81
+
82
+ ```ts
83
+ const { dmarc } = await tx.dmarc.enable('yourdomain.com') // or { apply: 'cloudflare' }
84
+ console.log(dmarc.dns.suggested_record) // your record with our report address in rua=
85
+
86
+ const report = await tx.dmarc.get('yourdomain.com')
87
+ if (report.dmarc.enabled) console.log(report.dmarc.readiness.label, report.dmarc.sources)
88
+ ```
89
+
90
+ Details: https://docs.groundmail.dev/dmarc
91
+
49
92
  ## Adapters
50
93
 
51
94
  Optional entry points (install peer deps as needed):
@@ -63,6 +106,7 @@ Optional entry points (install peer deps as needed):
63
106
  - Quickstart: https://docs.groundmail.dev/quickstart
64
107
  - Node / Nodemailer: https://docs.groundmail.dev/frameworks/node
65
108
  - Testing (test keys, simulator): https://docs.groundmail.dev/testing
109
+ - DMARC monitoring: https://docs.groundmail.dev/dmarc
66
110
  - API reference: https://docs.groundmail.dev/api/emails
67
111
  - Product: https://groundmail.dev
68
112
 
package/dist/authjs.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { G as Groundmail } from './client-DLz4rpD9.js';
1
+ import { G as Groundmail } from './client-DfOr7H56.js';
2
2
 
3
3
  /** Subset of Auth.js theme used for the default magic-link email. */
4
4
  type AuthjsTheme = {
package/dist/authjs.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  DEFAULT_API_BASE_URL,
3
3
  Groundmail
4
- } from "./chunk-MJKAVFFN.js";
4
+ } from "./chunk-2RKWN4OE.js";
5
5
 
6
6
  // src/authjs.ts
7
7
  function escapeHtml(value) {
@@ -1,4 +1,4 @@
1
- import { S as SendEmailResult, G as Groundmail } from './client-DLz4rpD9.js';
1
+ import { S as SendEmailResult, G as Groundmail } from './client-DfOr7H56.js';
2
2
 
3
3
  type BetterAuthEmailUser = {
4
4
  email: string;
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  DEFAULT_API_BASE_URL,
3
3
  Groundmail
4
- } from "./chunk-MJKAVFFN.js";
4
+ } from "./chunk-2RKWN4OE.js";
5
5
 
6
6
  // src/better-auth.ts
7
7
  function linkHtml(label, url) {
@@ -895,6 +895,32 @@ var AutomationsResource = class {
895
895
  }
896
896
  };
897
897
 
898
+ // src/dmarc.ts
899
+ var DmarcResource = class {
900
+ constructor(client) {
901
+ this.client = client;
902
+ }
903
+ path(domain) {
904
+ return `/domains/${encodeURIComponent(domain)}/dmarc`;
905
+ }
906
+ /** Monitoring status and the last 30 days of reports. `domain` is the domain id or name. */
907
+ async get(domain) {
908
+ return this.client.request(this.path(domain), { method: "GET" });
909
+ }
910
+ /** Turn monitoring on. Returns the report address and the DMARC record to publish. */
911
+ async enable(domain, params = {}) {
912
+ return this.client.request(this.path(domain), { method: "POST", body: JSON.stringify(params) });
913
+ }
914
+ /** Turn the weekly digest email on or off. */
915
+ async update(domain, params) {
916
+ return this.client.request(this.path(domain), { method: "PATCH", body: JSON.stringify(params) });
917
+ }
918
+ /** Stop monitoring. Remove the address from your DMARC record's rua= tag too. */
919
+ async disable(domain) {
920
+ return this.client.request(this.path(domain), { method: "DELETE" });
921
+ }
922
+ };
923
+
898
924
  // src/domains.ts
899
925
  var DomainsResource = class {
900
926
  constructor(client) {
@@ -906,6 +932,7 @@ var DomainsResource = class {
906
932
  if (params.cursor) search.set("cursor", params.cursor);
907
933
  const inboundEnabled = params.inbound_enabled ?? params.inboundEnabled;
908
934
  if (inboundEnabled !== void 0) search.set("inbound_enabled", String(inboundEnabled));
935
+ if (params.tenant) search.set("tenant", params.tenant);
909
936
  const query = search.toString();
910
937
  return this.client.request(`/domains${query ? `?${query}` : ""}`, { method: "GET" });
911
938
  }
@@ -918,7 +945,8 @@ var DomainsResource = class {
918
945
  method: "POST",
919
946
  body: JSON.stringify({
920
947
  name: params.name,
921
- ...inboundEnabled !== void 0 ? { inbound_enabled: inboundEnabled } : {}
948
+ ...inboundEnabled !== void 0 ? { inbound_enabled: inboundEnabled } : {},
949
+ ...params.tenant ? { tenant: params.tenant } : {}
922
950
  })
923
951
  });
924
952
  }
@@ -1009,6 +1037,7 @@ var EmailsResource = class {
1009
1037
  if (params.limit != null) search.set("limit", String(params.limit));
1010
1038
  if (params.cursor) search.set("cursor", params.cursor);
1011
1039
  if (params.test != null) search.set("test", String(params.test));
1040
+ if (params.tenant) search.set("tenant", params.tenant);
1012
1041
  const query = search.toString();
1013
1042
  return this.client.request(`/emails${query ? `?${query}` : ""}`, {
1014
1043
  method: "GET"
@@ -1074,7 +1103,8 @@ var EmailsResource = class {
1074
1103
  ...params.email_id !== void 0 ? { email_id: params.email_id } : {},
1075
1104
  ...params.webhook_id !== void 0 ? { webhook_id: params.webhook_id } : {},
1076
1105
  ...params.sync !== void 0 ? { sync: params.sync } : {},
1077
- ...params.deliver !== void 0 ? { deliver: params.deliver } : {}
1106
+ ...params.deliver !== void 0 ? { deliver: params.deliver } : {},
1107
+ ...params.tenant !== void 0 ? { tenant: params.tenant } : {}
1078
1108
  })
1079
1109
  });
1080
1110
  }
@@ -1126,6 +1156,7 @@ var EmailsResource = class {
1126
1156
  }
1127
1157
  if (params.unsubscribe !== void 0) payload.unsubscribe = params.unsubscribe;
1128
1158
  if (params.category !== void 0) payload.category = params.category;
1159
+ if (params.tenant !== void 0) payload.tenant = params.tenant;
1129
1160
  return payload;
1130
1161
  }
1131
1162
  };
@@ -1196,7 +1227,8 @@ var KeysResource = class {
1196
1227
  ...params.scope && !params.scopes?.length ? { scope: params.scope } : {},
1197
1228
  ...params.scopes?.length ? { scopes: params.scopes } : {},
1198
1229
  ...params.allowedDomains?.length ? { allowed_domains: params.allowedDomains } : {},
1199
- ...params.test ? { test: true } : {}
1230
+ ...params.test ? { test: true } : {},
1231
+ ...params.tenant ? { tenant: params.tenant } : {}
1200
1232
  })
1201
1233
  });
1202
1234
  }
@@ -1275,6 +1307,7 @@ var SuppressionsResource = class {
1275
1307
  if (params.limit != null) search.set("limit", String(params.limit));
1276
1308
  if (params.cursor) search.set("cursor", params.cursor);
1277
1309
  if (params.email) search.set("email", params.email);
1310
+ if (params.tenant) search.set("tenant", params.tenant);
1278
1311
  const query = search.toString();
1279
1312
  return this.client.request(`/suppressions${query ? `?${query}` : ""}`, { method: "GET" });
1280
1313
  }
@@ -1284,10 +1317,15 @@ var SuppressionsResource = class {
1284
1317
  body: JSON.stringify(params)
1285
1318
  });
1286
1319
  }
1287
- /** Remove by suppression id or email address. */
1288
- async remove(idOrEmail) {
1289
- if (idOrEmail.includes("@")) {
1290
- return this.client.request(`/suppressions?email=${encodeURIComponent(idOrEmail)}`, {
1320
+ /**
1321
+ * Remove by suppression id or email address. Pass `tenant` to remove an address
1322
+ * from that tenant's own list (by email address).
1323
+ */
1324
+ async remove(idOrEmail, options = {}) {
1325
+ if (idOrEmail.includes("@") || options.tenant) {
1326
+ const search = new URLSearchParams({ email: idOrEmail });
1327
+ if (options.tenant) search.set("tenant", options.tenant);
1328
+ return this.client.request(`/suppressions?${search.toString()}`, {
1291
1329
  method: "DELETE"
1292
1330
  });
1293
1331
  }
@@ -1373,6 +1411,84 @@ var TemplatesResource = class {
1373
1411
  }
1374
1412
  };
1375
1413
 
1414
+ // src/tenants.ts
1415
+ var TenantsResource = class {
1416
+ constructor(client) {
1417
+ this.client = client;
1418
+ this.domains = new TenantDomainsResource(client);
1419
+ }
1420
+ async list(params = {}) {
1421
+ const search = new URLSearchParams();
1422
+ if (params.limit != null) search.set("limit", String(params.limit));
1423
+ if (params.cursor) search.set("cursor", params.cursor);
1424
+ if (params.status) search.set("status", params.status);
1425
+ const query = search.toString();
1426
+ return this.client.request(`/tenants${query ? `?${query}` : ""}`, { method: "GET" });
1427
+ }
1428
+ async create(params) {
1429
+ return this.client.request("/tenants", {
1430
+ method: "POST",
1431
+ body: JSON.stringify(params)
1432
+ });
1433
+ }
1434
+ async get(tenant) {
1435
+ return this.client.request(`/tenants/${encodeURIComponent(tenant)}`, { method: "GET" });
1436
+ }
1437
+ async update(tenant, params) {
1438
+ return this.client.request(`/tenants/${encodeURIComponent(tenant)}`, {
1439
+ method: "PATCH",
1440
+ body: JSON.stringify(params)
1441
+ });
1442
+ }
1443
+ /** Stop the tenant's new sends until you resume it. */
1444
+ async pause(tenant, reason) {
1445
+ return this.update(tenant, { status: "paused", ...reason ? { reason } : {} });
1446
+ }
1447
+ /**
1448
+ * Let a tenant you paused send again. A tenant Groundmail paused (`pause_source`
1449
+ * `automated` or `admin`) cannot be resumed this way: contact support.
1450
+ */
1451
+ async resume(tenant) {
1452
+ return this.update(tenant, { status: "active" });
1453
+ }
1454
+ /**
1455
+ * Delete a tenant and its suppression list. Its domains go back to the account,
1456
+ * its emails keep their history, and API keys limited to it stop working.
1457
+ */
1458
+ async delete(tenant) {
1459
+ return this.client.request(`/tenants/${encodeURIComponent(tenant)}`, { method: "DELETE" });
1460
+ }
1461
+ /** Email counts and rates over the last `days` (1–90, default 7), plus the tenant's ramp today. */
1462
+ async stats(tenant, params = {}) {
1463
+ const query = params.days != null ? `?days=${encodeURIComponent(String(params.days))}` : "";
1464
+ return this.client.request(`/tenants/${encodeURIComponent(tenant)}/stats${query}`, {
1465
+ method: "GET"
1466
+ });
1467
+ }
1468
+ };
1469
+ var TenantDomainsResource = class {
1470
+ constructor(client) {
1471
+ this.client = client;
1472
+ }
1473
+ async list(tenant) {
1474
+ return this.client.request(`/tenants/${encodeURIComponent(tenant)}/domains`, { method: "GET" });
1475
+ }
1476
+ /** Give an existing domain of the account (name or id) to the tenant. Only that tenant can then send from it. */
1477
+ async assign(tenant, domain) {
1478
+ return this.client.request(`/tenants/${encodeURIComponent(tenant)}/domains`, {
1479
+ method: "POST",
1480
+ body: JSON.stringify({ domain })
1481
+ });
1482
+ }
1483
+ /** Give the tenant's domain (name or id) back to the whole account. The domain itself stays. */
1484
+ async unassign(tenant, domain) {
1485
+ return this.client.request(
1486
+ `/tenants/${encodeURIComponent(tenant)}/domains/${encodeURIComponent(domain)}`,
1487
+ { method: "DELETE" }
1488
+ );
1489
+ }
1490
+ };
1491
+
1376
1492
  // src/webhooks/index.ts
1377
1493
  var WebhooksResource = class {
1378
1494
  constructor(client) {
@@ -1429,7 +1545,9 @@ var Groundmail = class {
1429
1545
  this.smtpCredentials = new SmtpCredentialsResource(this);
1430
1546
  this.suppressions = new SuppressionsResource(this);
1431
1547
  this.templates = new TemplatesResource(this);
1548
+ this.tenants = new TenantsResource(this);
1432
1549
  this.migrations = new MigrationsResource(this);
1550
+ this.dmarc = new DmarcResource(this);
1433
1551
  }
1434
1552
  /**
1435
1553
  * Check one address with Groundmail validation before you accept it (for
package/dist/clerk.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { G as Groundmail, S as SendEmailResult } from './client-DLz4rpD9.js';
1
+ import { G as Groundmail, S as SendEmailResult } from './client-DfOr7H56.js';
2
2
 
3
3
  /**
4
4
  * Subset of Clerk `email.created` webhook `data` used for delivery.
package/dist/clerk.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  DEFAULT_API_BASE_URL,
3
3
  Groundmail
4
- } from "./chunk-MJKAVFFN.js";
4
+ } from "./chunk-2RKWN4OE.js";
5
5
 
6
6
  // src/clerk.ts
7
7
  function resolveApiKey(options) {
@@ -1,6 +1,8 @@
1
1
  type ApiErrorCode = 'validation_error' | 'unauthorized' | 'forbidden' | 'not_found' | 'conflict' | 'plan_limit'
2
2
  /** 429: the send would go over a new account's daily ramp-up limit; see `details.resets_at`. */
3
- | 'daily_ramp_limit' | 'domain_limit' | 'idempotency_conflict' | 'rate_limited' | 'upstream_error' | 'not_configured' | 'internal_error';
3
+ | 'daily_ramp_limit'
4
+ /** 403: the request names a tenant, but tenants are not enabled for this account (Scale and Dedicated plans). */
5
+ | 'tenants_not_enabled' | 'domain_limit' | 'idempotency_conflict' | 'rate_limited' | 'upstream_error' | 'not_configured' | 'internal_error';
4
6
  type SendEmailParams = {
5
7
  from: string | {
6
8
  email: string;
@@ -59,6 +61,12 @@ type SendEmailParams = {
59
61
  * is not accepted: Groundmail is for transactional and product email.
60
62
  */
61
63
  category?: 'transactional' | 'product';
64
+ /**
65
+ * Send as one of your tenants (its external id or Groundmail id). The send uses that
66
+ * tenant's domains, suppression list, pause switch and daily limit. Omit to send from
67
+ * the account as a whole, or from a tenant's own domain to use that tenant automatically.
68
+ */
69
+ tenant?: string;
62
70
  };
63
71
  /**
64
72
  * Why Groundmail validation held a recipient back before sending:
@@ -167,6 +175,8 @@ type EmailListItem = {
167
175
  opened_at: string | null;
168
176
  /** First tracked-link click; requires click tracking on the sending domain. */
169
177
  clicked_at: string | null;
178
+ /** The tenant's external id. Present only when the email was sent as a tenant. */
179
+ tenant?: string | null;
170
180
  };
171
181
  type ReceivedEmailAttachmentMeta = {
172
182
  filename: string;
@@ -188,7 +198,10 @@ type ReceivedEmail = {
188
198
  to: string[];
189
199
  cc: string[];
190
200
  subject: string;
191
- spam_status: string | null;
201
+ /** Content scanning verdict; null when the message was not scanned. */
202
+ spam_status: 'clean' | 'suspicious' | 'spam' | null;
203
+ /** Content scanning score (most clean mail is under 5); null when not scanned. */
204
+ spam_score: number | null;
192
205
  bounced: boolean;
193
206
  received_with_ssl: boolean | null;
194
207
  message_id: string | null;
@@ -217,6 +230,8 @@ type ListEmailsParams = {
217
230
  cursor?: string;
218
231
  /** `true`: only test emails; `false`: only live ones. Omit for both. */
219
232
  test?: boolean;
233
+ /** Only this tenant's emails (external id or Groundmail id). */
234
+ tenant?: string;
220
235
  };
221
236
  type ListEmailsResult = {
222
237
  emails: EmailListItem[];
@@ -277,6 +292,8 @@ type ApiKey = {
277
292
  allowed_domains?: string[];
278
293
  /** A test key (`gm_test_…`): its sends are simulated and never delivered. */
279
294
  test?: boolean;
295
+ /** The tenant this key is limited to (external id). Absent or null for an account-wide key. */
296
+ tenant?: string | null;
280
297
  prefix: string;
281
298
  created_at: string;
282
299
  last_used_at: string | null;
@@ -302,6 +319,11 @@ type CreateApiKeyParams = {
302
319
  * never delivered. They get simulated events and webhooks and count toward nothing.
303
320
  */
304
321
  test?: boolean;
322
+ /**
323
+ * Limit the key to one tenant (external id or Groundmail id): it sends only as that
324
+ * tenant and sees only that tenant's emails, domains and suppressions.
325
+ */
326
+ tenant?: string;
305
327
  };
306
328
  type CreateApiKeyResult = {
307
329
  id: string;
@@ -311,6 +333,8 @@ type CreateApiKeyResult = {
311
333
  allowed_domains?: string[];
312
334
  /** A test key (`gm_test_…`). */
313
335
  test?: boolean;
336
+ /** The tenant this key is limited to (external id), when it is. */
337
+ tenant?: string;
314
338
  prefix: string;
315
339
  token: string;
316
340
  created_at: string;
@@ -341,7 +365,7 @@ type CreateSmtpCredentialParams = {
341
365
  type CreateSmtpCredentialResult = SmtpCredential & {
342
366
  password: string;
343
367
  };
344
- type WebhookEventType = 'email.received' | 'email.sent' | 'email.delivered' | 'email.delivery_delayed' | 'email.bounced' | 'email.complained' | 'email.opened' | 'email.clicked' | 'email.failed' | 'email.suppressed' | 'email.scheduled' | 'contact.unsubscribed' | 'automation.started' | 'automation.step_completed' | 'automation.completed' | 'automation.failed';
368
+ type WebhookEventType = 'email.received' | 'email.sent' | 'email.delivered' | 'email.delivery_delayed' | 'email.held' | 'email.bounced' | 'email.complained' | 'email.opened' | 'email.clicked' | 'email.failed' | 'email.suppressed' | 'email.scheduled' | 'contact.unsubscribed' | 'automation.started' | 'automation.step_completed' | 'automation.completed' | 'automation.failed';
345
369
  /** Outbound `email.*` webhook payload (everything except `email.received`). */
346
370
  type EmailWebhookEventPayload = {
347
371
  type: Exclude<EmailWebhookEventType, 'email.received'>;
@@ -357,6 +381,12 @@ type EmailWebhookEventPayload = {
357
381
  bounce_type?: BounceType | null;
358
382
  /** `true` on simulated events (test keys, simulator addresses, `POST /emails/test`). Absent on real mail. */
359
383
  test?: true;
384
+ /** The tenant's external id, when the email was sent as a tenant. */
385
+ tenant?: string;
386
+ /** On `email.held`: why the email was held before sending. */
387
+ held_reason?: string;
388
+ /** On `email.held` when content scanning held it: the score. */
389
+ spam_score?: number;
360
390
  };
361
391
  };
362
392
  /** `contact.unsubscribed` webhook payload (`scope` distinguishes global vs category opt-out). */
@@ -387,10 +417,14 @@ type SuppressedErrorDetails = {
387
417
  };
388
418
  /**
389
419
  * `details` on a 429 `daily_ramp_limit`: the send would go over a new account's
390
- * daily ramp-up limit for its stream. Send the rest after `resets_at`.
420
+ * daily ramp-up limit for its stream, or over a tenant's own daily limit (then
421
+ * `tenant` is set). Send the rest after `resets_at`.
391
422
  */
392
423
  type DailyRampLimitErrorDetails = {
393
- stream: 'transactional' | 'product';
424
+ /** Set when a tenant's own daily limit or ramp refused the send: the tenant's external id. */
425
+ tenant?: string;
426
+ /** The stream whose limit was reached. Absent when a tenant's fixed `daily_limit` was reached. */
427
+ stream?: 'transactional' | 'product';
394
428
  /** Today's recipient limit for this stream. */
395
429
  daily_limit: number;
396
430
  /** Recipients already sent today on this stream. */
@@ -398,12 +432,12 @@ type DailyRampLimitErrorDetails = {
398
432
  /** Recipients (to + cc + bcc) in the refused send. */
399
433
  recipients: number;
400
434
  /** Ramp-up stage, 1-based; null with a fixed limit set by support. */
401
- ramp_stage: number | null;
435
+ ramp_stage?: number | null;
402
436
  /** The next 00:00 UTC, ISO 8601. */
403
437
  resets_at: string;
404
438
  };
405
439
  /** Event types accepted by `POST /emails/test`. */
406
- type EmailWebhookEventType = 'email.received' | 'email.sent' | 'email.delivered' | 'email.delivery_delayed' | 'email.bounced' | 'email.complained' | 'email.opened' | 'email.clicked' | 'email.failed' | 'email.suppressed' | 'email.scheduled';
440
+ type EmailWebhookEventType = 'email.received' | 'email.sent' | 'email.delivered' | 'email.delivery_delayed' | 'email.held' | 'email.bounced' | 'email.complained' | 'email.opened' | 'email.clicked' | 'email.failed' | 'email.suppressed' | 'email.scheduled';
407
441
  type TestEmailWebhookParams = {
408
442
  event: EmailWebhookEventType;
409
443
  email_id?: string;
@@ -412,6 +446,8 @@ type TestEmailWebhookParams = {
412
446
  sync?: boolean;
413
447
  /** When true (default), enqueue delivery to account webhooks. */
414
448
  deliver?: boolean;
449
+ /** Put this tenant (external id or Groundmail id) on the test payload, to test tenant-filtered webhooks. */
450
+ tenant?: string;
415
451
  };
416
452
  type WebhookTestDelivery = {
417
453
  endpoint_id: string;
@@ -563,17 +599,23 @@ type WebhookEndpoint = {
563
599
  url: string;
564
600
  events: string[];
565
601
  enabled: boolean;
602
+ /** Present only when the endpoint receives email events for some tenants only (their external ids). */
603
+ tenants?: string[];
566
604
  created_at: string;
567
605
  updated_at: string;
568
606
  };
569
607
  type CreateWebhookParams = {
570
608
  url: string;
571
609
  events?: WebhookEventType[];
610
+ /** Only these tenants' email events (external ids or Groundmail ids). Omit, `[]` or `null` for all. */
611
+ tenants?: string[] | null;
572
612
  };
573
613
  type UpdateWebhookParams = {
574
614
  url?: string;
575
615
  events?: WebhookEventType[];
576
616
  enabled?: boolean;
617
+ /** Only these tenants' email events. `[]` or `null` removes the filter. */
618
+ tenants?: string[] | null;
577
619
  };
578
620
  type WebhookEndpointWithSecret = {
579
621
  webhook: WebhookEndpoint;
@@ -584,6 +626,8 @@ type Suppression = {
584
626
  email: string;
585
627
  reason: string | null;
586
628
  source: string;
629
+ /** The tenant's external id, on an entry of a tenant's own list. */
630
+ tenant?: string;
587
631
  created_at: string;
588
632
  updated_at: string;
589
633
  };
@@ -591,6 +635,8 @@ type ListSuppressionsParams = {
591
635
  limit?: number;
592
636
  cursor?: string;
593
637
  email?: string;
638
+ /** List this tenant's own suppression list instead of the account's. */
639
+ tenant?: string;
594
640
  };
595
641
  type ListSuppressionsResult = {
596
642
  data: Suppression[];
@@ -600,6 +646,8 @@ type ListSuppressionsResult = {
600
646
  type CreateSuppressionParams = {
601
647
  email: string;
602
648
  reason?: string;
649
+ /** Add to this tenant's own list (external id or Groundmail id) instead of the account's. */
650
+ tenant?: string;
603
651
  };
604
652
  type TemplateStatus = 'draft' | 'published';
605
653
  type TemplateFormat = 'html' | 'blocks';
@@ -755,6 +803,12 @@ type Domain = {
755
803
  inbound_enabled: boolean;
756
804
  inbound_status: 'disabled' | 'pending' | 'active' | 'error' | string;
757
805
  inbound_error: string | null;
806
+ /** Received mail at or above this score is `spam`; null uses the default (10). */
807
+ inbound_spam_threshold?: number | null;
808
+ /** `flag` keeps spam with `spam_status: 'spam'`; `drop` discards it. */
809
+ inbound_spam_action?: 'flag' | 'drop';
810
+ /** The tenant that owns this domain (external id). Absent for an account-wide domain. */
811
+ tenant?: string | null;
758
812
  };
759
813
  type DnsRecord = {
760
814
  type: string;
@@ -768,12 +822,16 @@ type CreateDomainParams = {
768
822
  name: string;
769
823
  inbound_enabled?: boolean;
770
824
  inboundEnabled?: boolean;
825
+ /** Give the new domain to this tenant (external id or Groundmail id). Only that tenant can send from it. */
826
+ tenant?: string;
771
827
  };
772
828
  type ListDomainsParams = {
773
829
  limit?: number;
774
830
  cursor?: string;
775
831
  inbound_enabled?: boolean;
776
832
  inboundEnabled?: boolean;
833
+ /** Only this tenant's domains. */
834
+ tenant?: string;
777
835
  };
778
836
  type ListDomainsResult = {
779
837
  domains: Domain[];
@@ -836,6 +894,10 @@ type UpdateDomainParams = {
836
894
  tlsMode?: DomainTlsMode;
837
895
  inbound_enabled?: boolean;
838
896
  inboundEnabled?: boolean;
897
+ /** Spam threshold for received mail (1–100); null resets to the default. */
898
+ inbound_spam_threshold?: number | null;
899
+ /** What to do with received mail at or above the threshold. */
900
+ inbound_spam_action?: 'flag' | 'drop';
839
901
  };
840
902
  type DnsProviderName = 'cloudflare' | 'godaddy' | 'vercel';
841
903
  type RemoteApplyDnsCredentials = {
@@ -1039,6 +1101,117 @@ type RunMigrationOptions = {
1039
1101
  /** Waits for `retry_after_seconds` (tests can pass a no-op). */
1040
1102
  sleep?: (ms: number) => Promise<void>;
1041
1103
  };
1104
+ type TenantStatus = 'active' | 'paused';
1105
+ /** `all` (default) or `transactional_only` (product email is refused for this tenant). */
1106
+ type TenantStreamPolicy = 'all' | 'transactional_only';
1107
+ /** Who paused a tenant: you over the API, Groundmail support, or Groundmail's automatic checks. */
1108
+ type TenantPauseSource = 'api' | 'admin' | 'automated';
1109
+ /**
1110
+ * One of your customers, inside your Groundmail account. Each tenant has its own
1111
+ * domains, suppression list, stats, pause switch and daily limit.
1112
+ */
1113
+ type Tenant = {
1114
+ id: string;
1115
+ object: 'tenant';
1116
+ /** Your id for this customer. Unique in your account; cannot be changed. */
1117
+ external_id: string;
1118
+ name: string | null;
1119
+ status: TenantStatus;
1120
+ paused_reason: string | null;
1121
+ paused_at: string | null;
1122
+ pause_source: TenantPauseSource | null;
1123
+ /** Completes a bare `from` (`"billing"` → `billing@<domain>`) on sends that name this tenant. */
1124
+ default_from_domain: string | null;
1125
+ stream_policy: TenantStreamPolicy;
1126
+ /** Most recipients per UTC day for this tenant; null for no tenant limit. */
1127
+ daily_limit: number | null;
1128
+ metadata: Record<string, unknown> | null;
1129
+ created_at: string;
1130
+ updated_at: string;
1131
+ };
1132
+ type ListTenantsParams = {
1133
+ limit?: number;
1134
+ cursor?: string;
1135
+ status?: TenantStatus;
1136
+ };
1137
+ type ListTenantsResult = {
1138
+ data: Tenant[];
1139
+ has_more: boolean;
1140
+ next_cursor: string | null;
1141
+ };
1142
+ type CreateTenantParams = {
1143
+ /** Your id for this customer: 1–128 characters of `A-Z a-z 0-9 . _ : @ -`. */
1144
+ external_id: string;
1145
+ name?: string;
1146
+ default_from_domain?: string | null;
1147
+ stream_policy?: TenantStreamPolicy;
1148
+ daily_limit?: number | null;
1149
+ metadata?: Record<string, unknown> | null;
1150
+ };
1151
+ type UpdateTenantParams = {
1152
+ name?: string | null;
1153
+ default_from_domain?: string | null;
1154
+ stream_policy?: TenantStreamPolicy;
1155
+ daily_limit?: number | null;
1156
+ metadata?: Record<string, unknown> | null;
1157
+ /** `paused` stops this tenant's new sends; `active` resumes them. */
1158
+ status?: TenantStatus;
1159
+ /** Why you paused the tenant (with `status: 'paused'`). */
1160
+ reason?: string;
1161
+ };
1162
+ type DeleteTenantResult = {
1163
+ ok: boolean;
1164
+ id: string;
1165
+ external_id: string;
1166
+ deleted: true;
1167
+ };
1168
+ /** A tenant's email counts over the last `days`. Rates are 0–1. */
1169
+ type TenantStats = {
1170
+ object: 'tenant_stats';
1171
+ days: number;
1172
+ /** Start of the window, ISO 8601. */
1173
+ from: string;
1174
+ total: number;
1175
+ queued: number;
1176
+ scheduled: number;
1177
+ sent: number;
1178
+ delivered: number;
1179
+ bounced: number;
1180
+ complained: number;
1181
+ failed: number;
1182
+ suppressed: number;
1183
+ opened: number;
1184
+ clicked: number;
1185
+ bounce_rate: number;
1186
+ complaint_rate: number;
1187
+ };
1188
+ /** A tenant's sending ramp today. `active` is false when no ramp limit applies. */
1189
+ type TenantRamp = {
1190
+ object: 'tenant_ramp';
1191
+ active: boolean;
1192
+ /** 1-based stage; null when the ramp does not apply. */
1193
+ stage: number | null;
1194
+ daily_limit: {
1195
+ transactional: number | null;
1196
+ product: number | null;
1197
+ } | null;
1198
+ used_today: {
1199
+ transactional: number;
1200
+ product: number;
1201
+ };
1202
+ completed: boolean;
1203
+ /** The next 00:00 UTC, ISO 8601. */
1204
+ resets_at: string;
1205
+ };
1206
+ type TenantStatsResult = {
1207
+ /** The tenant's external id. */
1208
+ tenant: string;
1209
+ stats: TenantStats;
1210
+ ramp?: TenantRamp;
1211
+ };
1212
+ type ListTenantDomainsResult = {
1213
+ data: Domain[];
1214
+ };
1042
1215
 
1043
1216
  declare class AutomationsResource {
1044
1217
  private readonly client;
@@ -1064,6 +1237,121 @@ declare class AutomationsResource {
1064
1237
  retryRun(id: string): Promise<AutomationRunResponse>;
1065
1238
  }
1066
1239
 
1240
+ /** Status of one sending source in the DMARC reports. `unknown`: an unrecognised server failing DMARC (possible spoofing). */
1241
+ type DmarcSourceStatus = 'passing' | 'failing' | 'unknown';
1242
+ type DmarcSource = {
1243
+ /** Provider id (`google`, `microsoft`, `groundmail`, `sendgrid`…) or `unknown:<reverse DNS domain>`. */
1244
+ key: string;
1245
+ provider: string;
1246
+ name: string;
1247
+ status: DmarcSourceStatus;
1248
+ messages: number;
1249
+ dmarc_pass: number;
1250
+ /** 0–1. */
1251
+ pass_rate: number;
1252
+ spf_aligned_rate: number;
1253
+ dkim_aligned_rate: number;
1254
+ /** Up to five source IPs, busiest first. */
1255
+ ips: string[];
1256
+ ip_count: number;
1257
+ first_seen: string;
1258
+ last_seen: string;
1259
+ };
1260
+ type DmarcReadinessVerdict = 'no_data' | 'collecting' | 'fix_sources' | 'ready_quarantine' | 'ready_reject' | 'enforced';
1261
+ type DmarcReadiness = {
1262
+ verdict: DmarcReadinessVerdict;
1263
+ label: string;
1264
+ detail: string;
1265
+ days_of_data: number;
1266
+ blocking_sources: string[];
1267
+ };
1268
+ type DmarcDailyPoint = {
1269
+ date: string;
1270
+ messages: number;
1271
+ dmarc_pass: number;
1272
+ pass_rate: number;
1273
+ };
1274
+ type DmarcMonitoring = {
1275
+ domain: string;
1276
+ enabled: true;
1277
+ /** `waiting` until the first report arrives. */
1278
+ status: 'waiting' | 'receiving';
1279
+ /** Where receivers send the domain's reports. */
1280
+ report_address: string;
1281
+ /** The `rua=` value: `mailto:<report_address>`. */
1282
+ rua: string;
1283
+ dns: {
1284
+ host: string;
1285
+ record: string | null;
1286
+ rua_present: boolean;
1287
+ policy: string | null;
1288
+ /** The current record with our address added to rua=. Publish this. */
1289
+ suggested_record: string;
1290
+ };
1291
+ digest_enabled: boolean;
1292
+ created_at: string;
1293
+ last_report_at: string | null;
1294
+ window_days: number;
1295
+ summary: {
1296
+ messages: number;
1297
+ dmarc_pass: number;
1298
+ dmarc_fail: number;
1299
+ pass_rate: number;
1300
+ reports: number;
1301
+ reporters: string[];
1302
+ };
1303
+ sources: DmarcSource[];
1304
+ daily: DmarcDailyPoint[];
1305
+ readiness: DmarcReadiness;
1306
+ };
1307
+ type DmarcMonitoringDisabled = {
1308
+ domain: string;
1309
+ enabled: false;
1310
+ status: 'disabled';
1311
+ dns: {
1312
+ host: string;
1313
+ record: string | null;
1314
+ policy: string | null;
1315
+ };
1316
+ };
1317
+ type DmarcStatus = DmarcMonitoring | DmarcMonitoringDisabled;
1318
+ type EnableDmarcParams = {
1319
+ /** Also write the record through a DNS provider connected under Settings → Integrations. */
1320
+ apply?: 'cloudflare' | 'vercel' | 'godaddy';
1321
+ digest_enabled?: boolean;
1322
+ };
1323
+ type EnableDmarcResult = {
1324
+ dmarc: DmarcMonitoring;
1325
+ applied: {
1326
+ provider: string;
1327
+ results: unknown;
1328
+ } | null;
1329
+ apply_error?: string;
1330
+ };
1331
+ /** DMARC monitoring for a sending domain: reports, sources, pass rates and enforcement readiness. */
1332
+ declare class DmarcResource {
1333
+ private readonly client;
1334
+ constructor(client: Groundmail);
1335
+ private path;
1336
+ /** Monitoring status and the last 30 days of reports. `domain` is the domain id or name. */
1337
+ get(domain: string): Promise<{
1338
+ dmarc: DmarcStatus;
1339
+ }>;
1340
+ /** Turn monitoring on. Returns the report address and the DMARC record to publish. */
1341
+ enable(domain: string, params?: EnableDmarcParams): Promise<EnableDmarcResult>;
1342
+ /** Turn the weekly digest email on or off. */
1343
+ update(domain: string, params: {
1344
+ digest_enabled: boolean;
1345
+ }): Promise<{
1346
+ dmarc: DmarcStatus;
1347
+ }>;
1348
+ /** Stop monitoring. Remove the address from your DMARC record's rua= tag too. */
1349
+ disable(domain: string): Promise<{
1350
+ dmarc: DmarcStatus;
1351
+ disabled: boolean;
1352
+ }>;
1353
+ }
1354
+
1067
1355
  declare class DomainsResource {
1068
1356
  private readonly client;
1069
1357
  constructor(client: Groundmail);
@@ -1188,8 +1476,13 @@ declare class SuppressionsResource {
1188
1476
  create(params: CreateSuppressionParams): Promise<{
1189
1477
  suppression: Suppression;
1190
1478
  }>;
1191
- /** Remove by suppression id or email address. */
1192
- remove(idOrEmail: string): Promise<{
1479
+ /**
1480
+ * Remove by suppression id or email address. Pass `tenant` to remove an address
1481
+ * from that tenant's own list (by email address).
1482
+ */
1483
+ remove(idOrEmail: string, options?: {
1484
+ tenant?: string;
1485
+ }): Promise<{
1193
1486
  ok: boolean;
1194
1487
  }>;
1195
1488
  }
@@ -1238,6 +1531,61 @@ declare class TemplatesResource {
1238
1531
  }): Promise<unknown>;
1239
1532
  }
1240
1533
 
1534
+ /**
1535
+ * Tenants: one per customer of your platform, each with its own domains,
1536
+ * suppression list, stats, pause switch and daily limit. Every method takes the
1537
+ * tenant's external id (your id for the customer) or its Groundmail id.
1538
+ */
1539
+ declare class TenantsResource {
1540
+ private readonly client;
1541
+ /** The domains a tenant owns. */
1542
+ readonly domains: TenantDomainsResource;
1543
+ constructor(client: Groundmail);
1544
+ list(params?: ListTenantsParams): Promise<ListTenantsResult>;
1545
+ create(params: CreateTenantParams): Promise<{
1546
+ tenant: Tenant;
1547
+ }>;
1548
+ get(tenant: string): Promise<{
1549
+ tenant: Tenant;
1550
+ }>;
1551
+ update(tenant: string, params: UpdateTenantParams): Promise<{
1552
+ tenant: Tenant;
1553
+ }>;
1554
+ /** Stop the tenant's new sends until you resume it. */
1555
+ pause(tenant: string, reason?: string): Promise<{
1556
+ tenant: Tenant;
1557
+ }>;
1558
+ /**
1559
+ * Let a tenant you paused send again. A tenant Groundmail paused (`pause_source`
1560
+ * `automated` or `admin`) cannot be resumed this way: contact support.
1561
+ */
1562
+ resume(tenant: string): Promise<{
1563
+ tenant: Tenant;
1564
+ }>;
1565
+ /**
1566
+ * Delete a tenant and its suppression list. Its domains go back to the account,
1567
+ * its emails keep their history, and API keys limited to it stop working.
1568
+ */
1569
+ delete(tenant: string): Promise<DeleteTenantResult>;
1570
+ /** Email counts and rates over the last `days` (1–90, default 7), plus the tenant's ramp today. */
1571
+ stats(tenant: string, params?: {
1572
+ days?: number;
1573
+ }): Promise<TenantStatsResult>;
1574
+ }
1575
+ declare class TenantDomainsResource {
1576
+ private readonly client;
1577
+ constructor(client: Groundmail);
1578
+ list(tenant: string): Promise<ListTenantDomainsResult>;
1579
+ /** Give an existing domain of the account (name or id) to the tenant. Only that tenant can then send from it. */
1580
+ assign(tenant: string, domain: string): Promise<{
1581
+ domain: Domain;
1582
+ }>;
1583
+ /** Give the tenant's domain (name or id) back to the whole account. The domain itself stays. */
1584
+ unassign(tenant: string, domain: string): Promise<{
1585
+ domain: Domain;
1586
+ }>;
1587
+ }
1588
+
1241
1589
  declare class WebhooksResource {
1242
1590
  private readonly client;
1243
1591
  constructor(client: Groundmail);
@@ -1278,8 +1626,12 @@ declare class Groundmail {
1278
1626
  readonly smtpCredentials: SmtpCredentialsResource;
1279
1627
  readonly suppressions: SuppressionsResource;
1280
1628
  readonly templates: TemplatesResource;
1629
+ /** Your platform's customers, each with its own domains, suppressions, stats and limits. */
1630
+ readonly tenants: TenantsResource;
1281
1631
  /** Import from SendGrid, Postmark or Mailgun (Beta). */
1282
1632
  readonly migrations: MigrationsResource;
1633
+ /** DMARC monitoring per domain: report address, sources, pass rates and readiness. */
1634
+ readonly dmarc: DmarcResource;
1283
1635
  constructor(apiKey: string, options?: GroundmailOptions);
1284
1636
  /**
1285
1637
  * Check one address with Groundmail validation before you accept it (for
@@ -1294,4 +1646,4 @@ declare class Groundmail {
1294
1646
  request<T>(path: string, init: RequestInit): Promise<T>;
1295
1647
  }
1296
1648
 
1297
- export { type EmailWebhookEventPayload as $, type ApiErrorBody as A, type BatchSendEmailResult as B, type CategoryUnsubscribedErrorDetails as C, type DnsRecord as D, type CreateSuppressionParams as E, type CreateTemplateParams as F, Groundmail as G, type CreateWebhookParams as H, DEFAULT_API_BASE_URL as I, type DailyRampLimitErrorDetails as J, type DeliverabilityBucket as K, type DeliverabilityDomainInsight as L, type DeliverabilityInsightsResult as M, type DeliverabilityMailServerRelay as N, type DeliverabilityWindow as O, type DnsProviderName as P, type Domain as Q, type DomainBimiAnalysis as R, type SendEmailResult as S, type DomainDetailResult as T, type DomainDmarcAnalysis as U, type DomainDnsAnalysis as V, type DomainStatus as W, type DomainTlsMode as X, type DomainTrackingDns as Y, type DomainTrackingStatus as Z, type EmailListItem as _, type ApiErrorCode as a, type WebhookEndpoint as a$, type EmailWebhookEventType as a0, type EnrollmentSkip as a1, type EventRecord as a2, type GroundmailOptions as a3, type HeldBackErrorDetails as a4, type HeldBackReason as a5, type HeldBackRecipient as a6, type ListApiKeysParams as a7, type ListApiKeysResult as a8, type ListAutomationRunsParams as a9, type ReceivedEmailAttachmentMeta as aA, type RemoteApplyDnsCredentials as aB, type RunMigrationOptions as aC, type SendEmailParams as aD, type SuppressedErrorDetails as aE, type Suppression as aF, type Template as aG, type TemplateFormat as aH, type TemplateLintWarning as aI, type TemplateStarter as aJ, type TemplateStatus as aK, type TemplateVersion as aL, type TestEmailWebhookParams as aM, type TestEmailWebhookResult as aN, type TriggerEventParams as aO, type TriggerEventResult as aP, type TwilioIntegrationResponse as aQ, type TwilioIntegrationStatus as aR, type UpdateAutomationParams as aS, type UpdateDomainParams as aT, type UpdateEmailParams as aU, type UpdateTemplateParams as aV, type UpdateWebhookParams as aW, type ValidateEmailResult as aX, type ValidationReason as aY, type ValidationVerdict as aZ, type VerifyDomainResult as a_, type ListAutomationRunsResult as aa, type ListAutomationsResult as ab, type ListDomainsParams as ac, type ListDomainsResult as ad, type ListEmailsParams as ae, type ListEmailsResult as af, type ListReceivedEmailsParams as ag, type ListReceivedEmailsResult as ah, type ListSuppressionsParams as ai, type ListSuppressionsResult as aj, type ListTemplatesParams as ak, type ListTemplatesResult as al, type MailServerSigningStatus as am, type Migration as an, type MigrationDnsChange as ao, type MigrationDnsPlan as ap, type MigrationDomainItem as aq, type MigrationItemStatus as ar, type MigrationProvider as as, type MigrationResource as at, type MigrationSummary as au, type MigrationTemplateItem as av, type MigrationTotals as aw, type MigrationWebhookItem as ax, type ReceivedEmail as ay, type ReceivedEmailAttachment as az, type ApiKey as b, type WebhookEndpointWithSecret as b0, type WebhookEventType as b1, mergeMigrations as b2, type ApiKeyScope as c, type ApplyDnsParams as d, type ApplyDnsRecordResult as e, type ApplyDnsResult as f, type Asset as g, type Automation as h, type AutomationResult as i, type AutomationRun as j, type AutomationRunResponse as k, type AutomationRunStatus as l, type AutomationRunStep as m, type AutomationRunStepStatus as n, type AutomationStatus as o, type AutomationStep as p, type AutomationTrigger as q, type BounceType as r, type ConnectTwilioParams as s, type ContactWebhookEventPayload as t, type CreateApiKeyParams as u, type CreateApiKeyResult as v, type CreateAutomationParams as w, type CreateDomainParams as x, type CreateDomainResult as y, type CreateMigrationParams as z };
1649
+ export { type Domain as $, type ApiErrorBody as A, type BatchSendEmailResult as B, type CategoryUnsubscribedErrorDetails as C, type DnsRecord as D, type CreateSuppressionParams as E, type CreateTemplateParams as F, Groundmail as G, type CreateTenantParams as H, type CreateWebhookParams as I, DEFAULT_API_BASE_URL as J, type DailyRampLimitErrorDetails as K, type DeleteTenantResult as L, type DeliverabilityBucket as M, type DeliverabilityDomainInsight as N, type DeliverabilityInsightsResult as O, type DeliverabilityMailServerRelay as P, type DeliverabilityWindow as Q, type DmarcDailyPoint as R, type SendEmailResult as S, type DmarcMonitoring as T, type DmarcMonitoringDisabled as U, type DmarcReadiness as V, type DmarcReadinessVerdict as W, type DmarcSource as X, type DmarcSourceStatus as Y, type DmarcStatus as Z, type DnsProviderName as _, type ApiErrorCode as a, type Tenant as a$, type DomainBimiAnalysis as a0, type DomainDetailResult as a1, type DomainDmarcAnalysis as a2, type DomainDnsAnalysis as a3, type DomainStatus as a4, type DomainTlsMode as a5, type DomainTrackingDns as a6, type DomainTrackingStatus as a7, type EmailListItem as a8, type EmailWebhookEventPayload as a9, type ListTenantsResult as aA, type MailServerSigningStatus as aB, type Migration as aC, type MigrationDnsChange as aD, type MigrationDnsPlan as aE, type MigrationDomainItem as aF, type MigrationItemStatus as aG, type MigrationProvider as aH, type MigrationResource as aI, type MigrationSummary as aJ, type MigrationTemplateItem as aK, type MigrationTotals as aL, type MigrationWebhookItem as aM, type ReceivedEmail as aN, type ReceivedEmailAttachment as aO, type ReceivedEmailAttachmentMeta as aP, type RemoteApplyDnsCredentials as aQ, type RunMigrationOptions as aR, type SendEmailParams as aS, type SuppressedErrorDetails as aT, type Suppression as aU, type Template as aV, type TemplateFormat as aW, type TemplateLintWarning as aX, type TemplateStarter as aY, type TemplateStatus as aZ, type TemplateVersion as a_, type EmailWebhookEventType as aa, type EnableDmarcParams as ab, type EnableDmarcResult as ac, type EnrollmentSkip as ad, type EventRecord as ae, type GroundmailOptions as af, type HeldBackErrorDetails as ag, type HeldBackReason as ah, type HeldBackRecipient as ai, type ListApiKeysParams as aj, type ListApiKeysResult as ak, type ListAutomationRunsParams as al, type ListAutomationRunsResult as am, type ListAutomationsResult as an, type ListDomainsParams as ao, type ListDomainsResult as ap, type ListEmailsParams as aq, type ListEmailsResult as ar, type ListReceivedEmailsParams as as, type ListReceivedEmailsResult as at, type ListSuppressionsParams as au, type ListSuppressionsResult as av, type ListTemplatesParams as aw, type ListTemplatesResult as ax, type ListTenantDomainsResult as ay, type ListTenantsParams as az, type ApiKey as b, type TenantPauseSource as b0, type TenantRamp as b1, type TenantStats as b2, type TenantStatsResult as b3, type TenantStatus as b4, type TenantStreamPolicy as b5, type TestEmailWebhookParams as b6, type TestEmailWebhookResult as b7, type TriggerEventParams as b8, type TriggerEventResult as b9, type TwilioIntegrationResponse as ba, type TwilioIntegrationStatus as bb, type UpdateAutomationParams as bc, type UpdateDomainParams as bd, type UpdateEmailParams as be, type UpdateTemplateParams as bf, type UpdateTenantParams as bg, type UpdateWebhookParams as bh, type ValidateEmailResult as bi, type ValidationReason as bj, type ValidationVerdict as bk, type VerifyDomainResult as bl, type WebhookEndpoint as bm, type WebhookEndpointWithSecret as bn, type WebhookEventType as bo, mergeMigrations as bp, type ApiKeyScope as c, type ApplyDnsParams as d, type ApplyDnsRecordResult as e, type ApplyDnsResult as f, type Asset as g, type Automation as h, type AutomationResult as i, type AutomationRun as j, type AutomationRunResponse as k, type AutomationRunStatus as l, type AutomationRunStep as m, type AutomationRunStepStatus as n, type AutomationStatus as o, type AutomationStep as p, type AutomationTrigger as q, type BounceType as r, type ConnectTwilioParams as s, type ContactWebhookEventPayload as t, type CreateApiKeyParams as u, type CreateApiKeyResult as v, type CreateAutomationParams as w, type CreateDomainParams as x, type CreateDomainResult as y, type CreateMigrationParams as z };
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { A as ApiErrorBody, D as DnsRecord } from './client-DLz4rpD9.js';
2
- export { a as ApiErrorCode, b as ApiKey, c as ApiKeyScope, d as ApplyDnsParams, e as ApplyDnsRecordResult, f as ApplyDnsResult, g as Asset, h as Automation, i as AutomationResult, j as AutomationRun, k as AutomationRunResponse, l as AutomationRunStatus, m as AutomationRunStep, n as AutomationRunStepStatus, o as AutomationStatus, p as AutomationStep, q as AutomationTrigger, B as BatchSendEmailResult, r as BounceType, C as CategoryUnsubscribedErrorDetails, s as ConnectTwilioParams, t as ContactWebhookEventPayload, u as CreateApiKeyParams, v as CreateApiKeyResult, w as CreateAutomationParams, x as CreateDomainParams, y as CreateDomainResult, z as CreateMigrationParams, E as CreateSuppressionParams, F as CreateTemplateParams, H as CreateWebhookParams, I as DEFAULT_API_BASE_URL, J as DailyRampLimitErrorDetails, K as DeliverabilityBucket, L as DeliverabilityDomainInsight, M as DeliverabilityInsightsResult, N as DeliverabilityMailServerRelay, O as DeliverabilityWindow, P as DnsProviderName, Q as Domain, R as DomainBimiAnalysis, T as DomainDetailResult, U as DomainDmarcAnalysis, V as DomainDnsAnalysis, W as DomainStatus, X as DomainTlsMode, Y as DomainTrackingDns, Z as DomainTrackingStatus, _ as EmailListItem, $ as EmailWebhookEventPayload, a0 as EmailWebhookEventType, a1 as EnrollmentSkip, a2 as EventRecord, G as Groundmail, a3 as GroundmailOptions, a4 as HeldBackErrorDetails, a5 as HeldBackReason, a6 as HeldBackRecipient, a7 as ListApiKeysParams, a8 as ListApiKeysResult, a9 as ListAutomationRunsParams, aa as ListAutomationRunsResult, ab as ListAutomationsResult, ac as ListDomainsParams, ad as ListDomainsResult, ae as ListEmailsParams, af as ListEmailsResult, ag as ListReceivedEmailsParams, ah as ListReceivedEmailsResult, ai as ListSuppressionsParams, aj as ListSuppressionsResult, ak as ListTemplatesParams, al as ListTemplatesResult, am as MailServerSigningStatus, an as Migration, ao as MigrationDnsChange, ap as MigrationDnsPlan, aq as MigrationDomainItem, ar as MigrationItemStatus, as as MigrationProvider, at as MigrationResource, au as MigrationSummary, av as MigrationTemplateItem, aw as MigrationTotals, ax as MigrationWebhookItem, ay as ReceivedEmail, az as ReceivedEmailAttachment, aA as ReceivedEmailAttachmentMeta, aB as RemoteApplyDnsCredentials, aC as RunMigrationOptions, aD as SendEmailParams, S as SendEmailResult, aE as SuppressedErrorDetails, aF as Suppression, aG as Template, aH as TemplateFormat, aI as TemplateLintWarning, aJ as TemplateStarter, aK as TemplateStatus, aL as TemplateVersion, aM as TestEmailWebhookParams, aN as TestEmailWebhookResult, aO as TriggerEventParams, aP as TriggerEventResult, aQ as TwilioIntegrationResponse, aR as TwilioIntegrationStatus, aS as UpdateAutomationParams, aT as UpdateDomainParams, aU as UpdateEmailParams, aV as UpdateTemplateParams, aW as UpdateWebhookParams, aX as ValidateEmailResult, aY as ValidationReason, aZ as ValidationVerdict, a_ as VerifyDomainResult, a$ as WebhookEndpoint, b0 as WebhookEndpointWithSecret, b1 as WebhookEventType, b2 as mergeMigrations } from './client-DLz4rpD9.js';
1
+ import { A as ApiErrorBody, D as DnsRecord } from './client-DfOr7H56.js';
2
+ export { a as ApiErrorCode, b as ApiKey, c as ApiKeyScope, d as ApplyDnsParams, e as ApplyDnsRecordResult, f as ApplyDnsResult, g as Asset, h as Automation, i as AutomationResult, j as AutomationRun, k as AutomationRunResponse, l as AutomationRunStatus, m as AutomationRunStep, n as AutomationRunStepStatus, o as AutomationStatus, p as AutomationStep, q as AutomationTrigger, B as BatchSendEmailResult, r as BounceType, C as CategoryUnsubscribedErrorDetails, s as ConnectTwilioParams, t as ContactWebhookEventPayload, u as CreateApiKeyParams, v as CreateApiKeyResult, w as CreateAutomationParams, x as CreateDomainParams, y as CreateDomainResult, z as CreateMigrationParams, E as CreateSuppressionParams, F as CreateTemplateParams, H as CreateTenantParams, I as CreateWebhookParams, J as DEFAULT_API_BASE_URL, K as DailyRampLimitErrorDetails, L as DeleteTenantResult, M as DeliverabilityBucket, N as DeliverabilityDomainInsight, O as DeliverabilityInsightsResult, P as DeliverabilityMailServerRelay, Q as DeliverabilityWindow, R as DmarcDailyPoint, T as DmarcMonitoring, U as DmarcMonitoringDisabled, V as DmarcReadiness, W as DmarcReadinessVerdict, X as DmarcSource, Y as DmarcSourceStatus, Z as DmarcStatus, _ as DnsProviderName, $ as Domain, a0 as DomainBimiAnalysis, a1 as DomainDetailResult, a2 as DomainDmarcAnalysis, a3 as DomainDnsAnalysis, a4 as DomainStatus, a5 as DomainTlsMode, a6 as DomainTrackingDns, a7 as DomainTrackingStatus, a8 as EmailListItem, a9 as EmailWebhookEventPayload, aa as EmailWebhookEventType, ab as EnableDmarcParams, ac as EnableDmarcResult, ad as EnrollmentSkip, ae as EventRecord, G as Groundmail, af as GroundmailOptions, ag as HeldBackErrorDetails, ah as HeldBackReason, ai as HeldBackRecipient, aj as ListApiKeysParams, ak as ListApiKeysResult, al as ListAutomationRunsParams, am as ListAutomationRunsResult, an as ListAutomationsResult, ao as ListDomainsParams, ap as ListDomainsResult, aq as ListEmailsParams, ar as ListEmailsResult, as as ListReceivedEmailsParams, at as ListReceivedEmailsResult, au as ListSuppressionsParams, av as ListSuppressionsResult, aw as ListTemplatesParams, ax as ListTemplatesResult, ay as ListTenantDomainsResult, az as ListTenantsParams, aA as ListTenantsResult, aB as MailServerSigningStatus, aC as Migration, aD as MigrationDnsChange, aE as MigrationDnsPlan, aF as MigrationDomainItem, aG as MigrationItemStatus, aH as MigrationProvider, aI as MigrationResource, aJ as MigrationSummary, aK as MigrationTemplateItem, aL as MigrationTotals, aM as MigrationWebhookItem, aN as ReceivedEmail, aO as ReceivedEmailAttachment, aP as ReceivedEmailAttachmentMeta, aQ as RemoteApplyDnsCredentials, aR as RunMigrationOptions, aS as SendEmailParams, S as SendEmailResult, aT as SuppressedErrorDetails, aU as Suppression, aV as Template, aW as TemplateFormat, aX as TemplateLintWarning, aY as TemplateStarter, aZ as TemplateStatus, a_ as TemplateVersion, a$ as Tenant, b0 as TenantPauseSource, b1 as TenantRamp, b2 as TenantStats, b3 as TenantStatsResult, b4 as TenantStatus, b5 as TenantStreamPolicy, b6 as TestEmailWebhookParams, b7 as TestEmailWebhookResult, b8 as TriggerEventParams, b9 as TriggerEventResult, ba as TwilioIntegrationResponse, bb as TwilioIntegrationStatus, bc as UpdateAutomationParams, bd as UpdateDomainParams, be as UpdateEmailParams, bf as UpdateTemplateParams, bg as UpdateTenantParams, bh as UpdateWebhookParams, bi as ValidateEmailResult, bj as ValidationReason, bk as ValidationVerdict, bl as VerifyDomainResult, bm as WebhookEndpoint, bn as WebhookEndpointWithSecret, bo as WebhookEventType, bp as mergeMigrations } from './client-DfOr7H56.js';
3
3
 
4
4
  type GroundmailErrorOptions = {
5
5
  code?: string;
package/dist/index.js CHANGED
@@ -8,7 +8,7 @@ import {
8
8
  mergeSpfInclude,
9
9
  signWebhookPayload,
10
10
  verifyWebhookSignature
11
- } from "./chunk-MJKAVFFN.js";
11
+ } from "./chunk-2RKWN4OE.js";
12
12
 
13
13
  // src/simulator.ts
14
14
  var SIMULATOR_DOMAIN = "simulator.groundmail.dev";
package/dist/payload.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { G as Groundmail } from './client-DLz4rpD9.js';
1
+ import { G as Groundmail } from './client-DfOr7H56.js';
2
2
 
3
3
  /**
4
4
  * Minimal Payload `SendEmailOptions` / address shapes used by this adapter.
package/dist/payload.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  DEFAULT_API_BASE_URL,
3
3
  Groundmail
4
- } from "./chunk-MJKAVFFN.js";
4
+ } from "./chunk-2RKWN4OE.js";
5
5
 
6
6
  // src/payload.ts
7
7
  function resolveApiKey(args) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "groundmail",
3
- "version": "0.17.0",
3
+ "version": "0.20.0",
4
4
  "description": "Groundmail transactional email API client",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -89,7 +89,7 @@
89
89
  "prepublishOnly": "npm run build && npm run build:nodemailer-bridge"
90
90
  },
91
91
  "dependencies": {
92
- "groundmail-nodemailer": "0.15.3"
92
+ "groundmail-nodemailer": "0.15.6"
93
93
  },
94
94
  "devDependencies": {
95
95
  "@types/nodemailer": "^8.0.1",