@eusend_dev/sdk 0.19.0 → 0.21.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 +17 -3
- package/dist/index.cjs +20 -2
- package/dist/index.d.cts +74 -7
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.mts +74 -7
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +20 -2
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -58,8 +58,8 @@ console.log(data?.id) // 9a8b7c6d-5e4f-4a3b-8c1d-0e9f8a7b6c5d (UUID)
|
|
|
58
58
|
| `templateId` | `string` | ID of a saved template |
|
|
59
59
|
| `variables` | `Record<string, unknown>` | Template variable substitutions |
|
|
60
60
|
| `headers` | `Record<string, string>` | Custom email headers, written into the outbound message. Header names and values may not contain line breaks. |
|
|
61
|
-
| `trackOpens` | `boolean` | Track open events. Omit to use your organization default
|
|
62
|
-
| `trackClicks` | `boolean` | Track click events. Omit to use your organization default
|
|
61
|
+
| `trackOpens` | `boolean` | Track open events. Omit to use your organization default (off unless changed) |
|
|
62
|
+
| `trackClicks` | `boolean` | Track click events. Omit to use your organization default (off unless changed) |
|
|
63
63
|
|
|
64
64
|
At least one of `html`, `react`, `text`, or `templateId` is required.
|
|
65
65
|
|
|
@@ -496,6 +496,18 @@ const { data: csv } = await client.suppressions.export()
|
|
|
496
496
|
// "email,reason,created_at\n..."
|
|
497
497
|
```
|
|
498
498
|
|
|
499
|
+
## Reputation
|
|
500
|
+
|
|
501
|
+
Your bounce and complaint rates exactly as the sending limits judge them: what counted, what did not, and how far you are from a halved daily limit or a pause. Not available to sending-only keys.
|
|
502
|
+
|
|
503
|
+
```ts
|
|
504
|
+
const { data } = await client.reputation.get()
|
|
505
|
+
// data.state: 'healthy' | 'warning' | 'limited' | 'paused'
|
|
506
|
+
if (data?.next?.bounces != null && data.next.bounces <= 3) {
|
|
507
|
+
console.warn(`${data.next.bounces} more bounces would move this account to ${data.next.state}`)
|
|
508
|
+
}
|
|
509
|
+
```
|
|
510
|
+
|
|
499
511
|
## Templates
|
|
500
512
|
|
|
501
513
|
Templates let you define reusable email layouts with `{{variable}}` placeholders that are substituted at send time.
|
|
@@ -601,6 +613,8 @@ async function verifyWebhook(req: Request, secret: string): Promise<boolean> {
|
|
|
601
613
|
await client.webhooks.list()
|
|
602
614
|
await client.webhooks.get(webhookId) // includes recent deliveries
|
|
603
615
|
await client.webhooks.update(webhookId, { events: ['email.bounced'] })
|
|
616
|
+
await client.webhooks.update(webhookId, { enabled: true }) // re-enable a paused or auto-disabled endpoint
|
|
617
|
+
await client.webhooks.test(webhookId) // send a signed webhook.test event
|
|
604
618
|
await client.webhooks.delete(webhookId)
|
|
605
619
|
```
|
|
606
620
|
|
|
@@ -704,7 +718,7 @@ if (error) {
|
|
|
704
718
|
| `CONFLICT` | 409 | Resource already exists |
|
|
705
719
|
| `RATE_LIMITED` | 429 | Too many requests |
|
|
706
720
|
| `MONTHLY_LIMIT_EXCEEDED` | 429 | Monthly send quota reached |
|
|
707
|
-
| `DAILY_LIMIT_EXCEEDED` | 429 | Daily
|
|
721
|
+
| `DAILY_LIMIT_EXCEEDED` | 429 | Daily recipient ceiling reached — to, cc and bcc all count (resets midnight UTC) |
|
|
708
722
|
| `PLAN_LIMIT_EXCEEDED` | 403 | Feature not available on your plan |
|
|
709
723
|
| `DOMAIN_NOT_VERIFIED` | 403 | The sender domain is not verified for your organisation |
|
|
710
724
|
| `SENDING_SUSPENDED` | 403 | Sending suspended for your account (high bounce or complaint rate) |
|
package/dist/index.cjs
CHANGED
|
@@ -471,9 +471,14 @@ var Webhooks = class {
|
|
|
471
471
|
update(id, options) {
|
|
472
472
|
return this.client.patch(`/webhooks/${id}`, {
|
|
473
473
|
url: options.url,
|
|
474
|
-
events: options.events
|
|
474
|
+
events: options.events,
|
|
475
|
+
enabled: options.enabled
|
|
475
476
|
});
|
|
476
477
|
}
|
|
478
|
+
/** Send one signed `webhook.test` event to the endpoint. Works on a disabled endpoint. */
|
|
479
|
+
test(id) {
|
|
480
|
+
return this.client.post(`/webhooks/${id}/test`);
|
|
481
|
+
}
|
|
477
482
|
delete(id) {
|
|
478
483
|
return this.client.delete(`/webhooks/${id}`);
|
|
479
484
|
}
|
|
@@ -637,9 +642,21 @@ var Suppressions = class {
|
|
|
637
642
|
}
|
|
638
643
|
};
|
|
639
644
|
//#endregion
|
|
645
|
+
//#region src/reputation.ts
|
|
646
|
+
/** Your organization's sending reputation, as the sending limits judge it. */
|
|
647
|
+
var ReputationResource = class {
|
|
648
|
+
constructor(client) {
|
|
649
|
+
this.client = client;
|
|
650
|
+
}
|
|
651
|
+
/** Not available to sending-only keys. Cached by the API for up to 30 seconds. */
|
|
652
|
+
get() {
|
|
653
|
+
return this.client.get("/reputation");
|
|
654
|
+
}
|
|
655
|
+
};
|
|
656
|
+
//#endregion
|
|
640
657
|
//#region src/eusend.ts
|
|
641
658
|
const DEFAULT_BASE_URL = "https://api.eusend.dev";
|
|
642
|
-
const SDK_VERSION = "0.
|
|
659
|
+
const SDK_VERSION = "0.21.0";
|
|
643
660
|
var Eusend = class {
|
|
644
661
|
constructor(key, options) {
|
|
645
662
|
const apiKey = key ?? (typeof process !== "undefined" ? process.env["EUSEND_API_KEY"] : void 0);
|
|
@@ -657,6 +674,7 @@ var Eusend = class {
|
|
|
657
674
|
this.webhooks = new Webhooks(this);
|
|
658
675
|
this.broadcasts = new Broadcasts(this);
|
|
659
676
|
this.suppressions = new Suppressions(this);
|
|
677
|
+
this.reputation = new ReputationResource(this);
|
|
660
678
|
}
|
|
661
679
|
async fetchRequest(path, init = {}, extraHeaders = {}, parse = "json") {
|
|
662
680
|
const headers = {
|
package/dist/index.d.cts
CHANGED
|
@@ -92,7 +92,16 @@ interface SendEmailOptions {
|
|
|
92
92
|
* event for this send.
|
|
93
93
|
*/
|
|
94
94
|
tags?: EmailTags;
|
|
95
|
+
/**
|
|
96
|
+
* Embed an open-tracking pixel. Omit to use your organization's default (Settings →
|
|
97
|
+
* General → Email tracking), which is off unless you changed it.
|
|
98
|
+
*/
|
|
95
99
|
trackOpens?: boolean;
|
|
100
|
+
/**
|
|
101
|
+
* Rewrite links through eusend so clicks are recorded. Omit to use your organization's
|
|
102
|
+
* default, which is off unless you changed it. Rewritten links can hurt inbox placement,
|
|
103
|
+
* so leave this off for sign-in links and password resets.
|
|
104
|
+
*/
|
|
96
105
|
trackClicks?: boolean;
|
|
97
106
|
/** File attachments. Up to 20 per message, 10 MB combined. */
|
|
98
107
|
attachments?: Attachment[];
|
|
@@ -697,6 +706,8 @@ interface CreateWebhookOptions {
|
|
|
697
706
|
interface UpdateWebhookOptions {
|
|
698
707
|
url?: string;
|
|
699
708
|
events?: WebhookEvent[];
|
|
709
|
+
/** `false` pauses the endpoint; `true` re-enables a paused or auto-disabled one. */
|
|
710
|
+
enabled?: boolean;
|
|
700
711
|
}
|
|
701
712
|
interface WebhookDelivery {
|
|
702
713
|
id: string;
|
|
@@ -714,8 +725,16 @@ interface Webhook {
|
|
|
714
725
|
id: string;
|
|
715
726
|
url: string;
|
|
716
727
|
events: WebhookEvent[];
|
|
728
|
+
/** When the endpoint stopped receiving events; `null` while active. */
|
|
729
|
+
disabledAt: string | null;
|
|
730
|
+
/** `failing` after three days of failed deliveries, `manual` when paused. */
|
|
731
|
+
disabledReason: 'failing' | 'manual' | null;
|
|
717
732
|
createdAt: string;
|
|
718
733
|
}
|
|
734
|
+
interface WebhookTestResponse {
|
|
735
|
+
/** The id of the test delivery, as it appears in the webhook's deliveries. */
|
|
736
|
+
id: string;
|
|
737
|
+
}
|
|
719
738
|
interface WebhookWithDeliveries extends Webhook {
|
|
720
739
|
deliveries: WebhookDelivery[];
|
|
721
740
|
}
|
|
@@ -729,6 +748,8 @@ declare class Webhooks {
|
|
|
729
748
|
list(): Promise<EusendResponse<Webhook[]>>;
|
|
730
749
|
get(id: string): Promise<EusendResponse<WebhookWithDeliveries>>;
|
|
731
750
|
update(id: string, options: UpdateWebhookOptions): Promise<EusendResponse<Webhook>>;
|
|
751
|
+
/** Send one signed `webhook.test` event to the endpoint. Works on a disabled endpoint. */
|
|
752
|
+
test(id: string): Promise<EusendResponse<WebhookTestResponse>>;
|
|
732
753
|
delete(id: string): Promise<EusendResponse<Record<string, never>>>;
|
|
733
754
|
}
|
|
734
755
|
//#endregion
|
|
@@ -763,12 +784,13 @@ interface CreateBroadcastOptions {
|
|
|
763
784
|
templateVariables?: Record<string, string>;
|
|
764
785
|
/**
|
|
765
786
|
* Embed the open-tracking pixel for this broadcast. Omit to use your organization's
|
|
766
|
-
* default (Settings → General → Email tracking)
|
|
787
|
+
* default (Settings → General → Email tracking), which is off unless you changed it. An
|
|
788
|
+
* explicit value always wins over it.
|
|
767
789
|
*/
|
|
768
790
|
trackOpens?: boolean;
|
|
769
791
|
/**
|
|
770
|
-
* Rewrite links so clicks are recorded. Omit to use your organization's default
|
|
771
|
-
* `false` leaves the original URLs untouched in the delivered mail.
|
|
792
|
+
* Rewrite links so clicks are recorded. Omit to use your organization's default (off
|
|
793
|
+
* unless you changed it); `false` leaves the original URLs untouched in the delivered mail.
|
|
772
794
|
*/
|
|
773
795
|
trackClicks?: boolean;
|
|
774
796
|
}
|
|
@@ -791,12 +813,13 @@ interface UpdateBroadcastOptions {
|
|
|
791
813
|
scheduledAt?: string | null;
|
|
792
814
|
/**
|
|
793
815
|
* Embed the open-tracking pixel for this broadcast. Omit to use your organization's
|
|
794
|
-
* default (Settings → General → Email tracking)
|
|
816
|
+
* default (Settings → General → Email tracking), which is off unless you changed it. An
|
|
817
|
+
* explicit value always wins over it.
|
|
795
818
|
*/
|
|
796
819
|
trackOpens?: boolean;
|
|
797
820
|
/**
|
|
798
|
-
* Rewrite links so clicks are recorded. Omit to use your organization's default
|
|
799
|
-
* `false` leaves the original URLs untouched in the delivered mail.
|
|
821
|
+
* Rewrite links so clicks are recorded. Omit to use your organization's default (off
|
|
822
|
+
* unless you changed it); `false` leaves the original URLs untouched in the delivered mail.
|
|
800
823
|
*/
|
|
801
824
|
trackClicks?: boolean;
|
|
802
825
|
}
|
|
@@ -974,6 +997,49 @@ declare class Suppressions {
|
|
|
974
997
|
export(): Promise<EusendResponse<string>>;
|
|
975
998
|
}
|
|
976
999
|
//#endregion
|
|
1000
|
+
//#region src/reputation.d.ts
|
|
1001
|
+
type ReputationState = 'healthy' | 'warning' | 'limited' | 'paused';
|
|
1002
|
+
interface Reputation {
|
|
1003
|
+
/**
|
|
1004
|
+
* `warning`: the raw bounce rate is high but the evidence does not yet put it past the
|
|
1005
|
+
* line. `limited`: the daily sending ceiling is halved. `paused`: sending is suspended.
|
|
1006
|
+
*/
|
|
1007
|
+
state: ReputationState;
|
|
1008
|
+
/** False until at least 100 recipients have a delivery result. */
|
|
1009
|
+
measured: boolean;
|
|
1010
|
+
bounce: {
|
|
1011
|
+
/** Raw rate over the judged window. */
|
|
1012
|
+
rate: number;
|
|
1013
|
+
/** The 95% confidence lower bound compared against the lines; 0 without enough evidence. */
|
|
1014
|
+
judged_rate: number;
|
|
1015
|
+
counted: number;
|
|
1016
|
+
/** Bounces about eusend's sending infrastructure rather than the address. */
|
|
1017
|
+
not_counted: number;
|
|
1018
|
+
recipients: number;
|
|
1019
|
+
window: '7d' | '30d' | null;
|
|
1020
|
+
limited_at: number;
|
|
1021
|
+
paused_at: number;
|
|
1022
|
+
};
|
|
1023
|
+
complaint: {
|
|
1024
|
+
rate: number;
|
|
1025
|
+
complaints: number;
|
|
1026
|
+
limited_at: number;
|
|
1027
|
+
paused_at: number;
|
|
1028
|
+
};
|
|
1029
|
+
/** The next state and how many more counted bounces reach it. Null when paused. */
|
|
1030
|
+
next: {
|
|
1031
|
+
state: 'limited' | 'paused';
|
|
1032
|
+
bounces: number | null;
|
|
1033
|
+
} | null;
|
|
1034
|
+
}
|
|
1035
|
+
/** Your organization's sending reputation, as the sending limits judge it. */
|
|
1036
|
+
declare class ReputationResource {
|
|
1037
|
+
private readonly client;
|
|
1038
|
+
constructor(client: Eusend);
|
|
1039
|
+
/** Not available to sending-only keys. Cached by the API for up to 30 seconds. */
|
|
1040
|
+
get(): Promise<EusendResponse<Reputation>>;
|
|
1041
|
+
}
|
|
1042
|
+
//#endregion
|
|
977
1043
|
//#region src/eusend.d.ts
|
|
978
1044
|
interface EusendOptions {
|
|
979
1045
|
baseUrl?: string;
|
|
@@ -995,6 +1061,7 @@ declare class Eusend {
|
|
|
995
1061
|
readonly webhooks: Webhooks;
|
|
996
1062
|
readonly broadcasts: Broadcasts;
|
|
997
1063
|
readonly suppressions: Suppressions;
|
|
1064
|
+
readonly reputation: ReputationResource;
|
|
998
1065
|
constructor(key?: string, options?: EusendOptions);
|
|
999
1066
|
fetchRequest<T>(path: string, init?: RequestInit, extraHeaders?: Record<string, string>, parse?: 'json' | 'text'): Promise<EusendResponse<T>>;
|
|
1000
1067
|
get<T>(path: string, extraHeaders?: Record<string, string>): Promise<EusendResponse<T>>;
|
|
@@ -1004,5 +1071,5 @@ declare class Eusend {
|
|
|
1004
1071
|
delete<T>(path: string): Promise<EusendResponse<T>>;
|
|
1005
1072
|
}
|
|
1006
1073
|
//#endregion
|
|
1007
|
-
export { type ApiKey, type ApiKeyPermission, type Attachment, type Audience, type AudienceDetail, type AudienceListItem, type BatchContactOptions, type BatchCreateContactsOptions, type BatchItemResult, type BatchSendResponse, type Broadcast, type BroadcastDetail, type BroadcastListItem, type BroadcastStatus, type CancelEmailResponse, type ClearTopicSubscriptionResponse, type Contact, type ContactProperty, type ContactPropertyType, type ContactStatus, type CreateApiKeyOptions, type CreateApiKeyResponse, type CreateBroadcastOptions, type CreateContactOptions, type CreateContactPropertyOptions, type CreateDomainResponse, type CreateSuppressionOptions, type CreateTemplateOptions, type CreateTopicOptions, type CreateWebhookOptions, type CreateWebhookResponse, type DeleteContactPropertyResponse, type DeleteDomainResponse, type DeleteTopicResponse, type DnsRecord, type Domain, type DomainDiagnostic, type DomainListItem, type DomainStatus, type DomainVerification, type Email, type EmailEvent, type EmailEventType, type EmailListItem, type EmailStatus, Eusend, type EusendError, type EusendErrorCode, type EusendOptions, type EusendResponse, type ImportSuppressionsResponse, type ListContactsOptions, type ListContactsResponse, type ListEmailsOptions, type ListEmailsResponse, type ListSuppressionsOptions, type ListSuppressionsResponse, type SendBroadcastOptions, type SendBroadcastResponse, type SendEmailOptions, type SendEmailRequestOptions, type SendEmailResponse, type SuppressionEntry, type SuppressionImportItem, type SuppressionReason, type Template, type TemplateListItem, type TestBroadcastOptions, type TestBroadcastResponse, type Topic, type TopicDefaultSubscription, type TopicSubscriptionResponse, type TopicVisibility, type UpdateAudienceOptions, type UpdateBroadcastOptions, type UpdateContactOptions, type UpdateContactPropertyOptions, type UpdateEmailOptions, type UpdateEmailResponse, type UpdateTemplateOptions, type UpdateTopicOptions, type UpdateWebhookOptions, type Webhook, type WebhookDelivery, type WebhookEvent, type WebhookWithDeliveries };
|
|
1074
|
+
export { type ApiKey, type ApiKeyPermission, type Attachment, type Audience, type AudienceDetail, type AudienceListItem, type BatchContactOptions, type BatchCreateContactsOptions, type BatchItemResult, type BatchSendResponse, type Broadcast, type BroadcastDetail, type BroadcastListItem, type BroadcastStatus, type CancelEmailResponse, type ClearTopicSubscriptionResponse, type Contact, type ContactProperty, type ContactPropertyType, type ContactStatus, type CreateApiKeyOptions, type CreateApiKeyResponse, type CreateBroadcastOptions, type CreateContactOptions, type CreateContactPropertyOptions, type CreateDomainResponse, type CreateSuppressionOptions, type CreateTemplateOptions, type CreateTopicOptions, type CreateWebhookOptions, type CreateWebhookResponse, type DeleteContactPropertyResponse, type DeleteDomainResponse, type DeleteTopicResponse, type DnsRecord, type Domain, type DomainDiagnostic, type DomainListItem, type DomainStatus, type DomainVerification, type Email, type EmailEvent, type EmailEventType, type EmailListItem, type EmailStatus, Eusend, type EusendError, type EusendErrorCode, type EusendOptions, type EusendResponse, type ImportSuppressionsResponse, type ListContactsOptions, type ListContactsResponse, type ListEmailsOptions, type ListEmailsResponse, type ListSuppressionsOptions, type ListSuppressionsResponse, type Reputation, type ReputationState, type SendBroadcastOptions, type SendBroadcastResponse, type SendEmailOptions, type SendEmailRequestOptions, type SendEmailResponse, type SuppressionEntry, type SuppressionImportItem, type SuppressionReason, type Template, type TemplateListItem, type TestBroadcastOptions, type TestBroadcastResponse, type Topic, type TopicDefaultSubscription, type TopicSubscriptionResponse, type TopicVisibility, type UpdateAudienceOptions, type UpdateBroadcastOptions, type UpdateContactOptions, type UpdateContactPropertyOptions, type UpdateEmailOptions, type UpdateEmailResponse, type UpdateTemplateOptions, type UpdateTopicOptions, type UpdateWebhookOptions, type Webhook, type WebhookDelivery, type WebhookEvent, type WebhookTestResponse, type WebhookWithDeliveries };
|
|
1008
1075
|
//# sourceMappingURL=index.d.cts.map
|
package/dist/index.d.cts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.cts","names":[],"sources":["../src/interfaces.ts","../src/react-render.ts","../src/emails.ts","../src/batch.ts","../src/domains.ts","../src/api-keys.ts","../src/audiences.ts","../src/contact-properties.ts","../src/topics.ts","../src/templates.ts","../src/webhooks.ts","../src/broadcasts.ts","../src/suppressions.ts","../src/eusend.ts"],"mappings":";KAAY;UA2BK;EACf;EACA;EACA,MAAM;;KAGI,eAAe;EACrB,MAAM;EAAG;EAAa,SAAS;;EAC/B;EAAY,OAAO;EAAa,SAAS;;;;KChCnC;WACD;WACA;WACA;;;;KCFC;KAYA;UAEK;;EAEf;;;;;;EAMA,mBAAmB;;;;;;EAMnB;;EAEA;;;;;EAKA;;;UAIe;EACf;EACA;;;;;;;;;;;;KAaU,YAAY,yBAAyB;UAEhC;;;;;EAKf;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;;;;;EAMA,QAAQ;EACR;EACA,YAAY;EACZ,UAAU;;;;;;EAMV,OAAO
|
|
1
|
+
{"version":3,"file":"index.d.cts","names":[],"sources":["../src/interfaces.ts","../src/react-render.ts","../src/emails.ts","../src/batch.ts","../src/domains.ts","../src/api-keys.ts","../src/audiences.ts","../src/contact-properties.ts","../src/topics.ts","../src/templates.ts","../src/webhooks.ts","../src/broadcasts.ts","../src/suppressions.ts","../src/reputation.ts","../src/eusend.ts"],"mappings":"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"}
|
package/dist/index.d.mts
CHANGED
|
@@ -92,7 +92,16 @@ interface SendEmailOptions {
|
|
|
92
92
|
* event for this send.
|
|
93
93
|
*/
|
|
94
94
|
tags?: EmailTags;
|
|
95
|
+
/**
|
|
96
|
+
* Embed an open-tracking pixel. Omit to use your organization's default (Settings →
|
|
97
|
+
* General → Email tracking), which is off unless you changed it.
|
|
98
|
+
*/
|
|
95
99
|
trackOpens?: boolean;
|
|
100
|
+
/**
|
|
101
|
+
* Rewrite links through eusend so clicks are recorded. Omit to use your organization's
|
|
102
|
+
* default, which is off unless you changed it. Rewritten links can hurt inbox placement,
|
|
103
|
+
* so leave this off for sign-in links and password resets.
|
|
104
|
+
*/
|
|
96
105
|
trackClicks?: boolean;
|
|
97
106
|
/** File attachments. Up to 20 per message, 10 MB combined. */
|
|
98
107
|
attachments?: Attachment[];
|
|
@@ -697,6 +706,8 @@ interface CreateWebhookOptions {
|
|
|
697
706
|
interface UpdateWebhookOptions {
|
|
698
707
|
url?: string;
|
|
699
708
|
events?: WebhookEvent[];
|
|
709
|
+
/** `false` pauses the endpoint; `true` re-enables a paused or auto-disabled one. */
|
|
710
|
+
enabled?: boolean;
|
|
700
711
|
}
|
|
701
712
|
interface WebhookDelivery {
|
|
702
713
|
id: string;
|
|
@@ -714,8 +725,16 @@ interface Webhook {
|
|
|
714
725
|
id: string;
|
|
715
726
|
url: string;
|
|
716
727
|
events: WebhookEvent[];
|
|
728
|
+
/** When the endpoint stopped receiving events; `null` while active. */
|
|
729
|
+
disabledAt: string | null;
|
|
730
|
+
/** `failing` after three days of failed deliveries, `manual` when paused. */
|
|
731
|
+
disabledReason: 'failing' | 'manual' | null;
|
|
717
732
|
createdAt: string;
|
|
718
733
|
}
|
|
734
|
+
interface WebhookTestResponse {
|
|
735
|
+
/** The id of the test delivery, as it appears in the webhook's deliveries. */
|
|
736
|
+
id: string;
|
|
737
|
+
}
|
|
719
738
|
interface WebhookWithDeliveries extends Webhook {
|
|
720
739
|
deliveries: WebhookDelivery[];
|
|
721
740
|
}
|
|
@@ -729,6 +748,8 @@ declare class Webhooks {
|
|
|
729
748
|
list(): Promise<EusendResponse<Webhook[]>>;
|
|
730
749
|
get(id: string): Promise<EusendResponse<WebhookWithDeliveries>>;
|
|
731
750
|
update(id: string, options: UpdateWebhookOptions): Promise<EusendResponse<Webhook>>;
|
|
751
|
+
/** Send one signed `webhook.test` event to the endpoint. Works on a disabled endpoint. */
|
|
752
|
+
test(id: string): Promise<EusendResponse<WebhookTestResponse>>;
|
|
732
753
|
delete(id: string): Promise<EusendResponse<Record<string, never>>>;
|
|
733
754
|
}
|
|
734
755
|
//#endregion
|
|
@@ -763,12 +784,13 @@ interface CreateBroadcastOptions {
|
|
|
763
784
|
templateVariables?: Record<string, string>;
|
|
764
785
|
/**
|
|
765
786
|
* Embed the open-tracking pixel for this broadcast. Omit to use your organization's
|
|
766
|
-
* default (Settings → General → Email tracking)
|
|
787
|
+
* default (Settings → General → Email tracking), which is off unless you changed it. An
|
|
788
|
+
* explicit value always wins over it.
|
|
767
789
|
*/
|
|
768
790
|
trackOpens?: boolean;
|
|
769
791
|
/**
|
|
770
|
-
* Rewrite links so clicks are recorded. Omit to use your organization's default
|
|
771
|
-
* `false` leaves the original URLs untouched in the delivered mail.
|
|
792
|
+
* Rewrite links so clicks are recorded. Omit to use your organization's default (off
|
|
793
|
+
* unless you changed it); `false` leaves the original URLs untouched in the delivered mail.
|
|
772
794
|
*/
|
|
773
795
|
trackClicks?: boolean;
|
|
774
796
|
}
|
|
@@ -791,12 +813,13 @@ interface UpdateBroadcastOptions {
|
|
|
791
813
|
scheduledAt?: string | null;
|
|
792
814
|
/**
|
|
793
815
|
* Embed the open-tracking pixel for this broadcast. Omit to use your organization's
|
|
794
|
-
* default (Settings → General → Email tracking)
|
|
816
|
+
* default (Settings → General → Email tracking), which is off unless you changed it. An
|
|
817
|
+
* explicit value always wins over it.
|
|
795
818
|
*/
|
|
796
819
|
trackOpens?: boolean;
|
|
797
820
|
/**
|
|
798
|
-
* Rewrite links so clicks are recorded. Omit to use your organization's default
|
|
799
|
-
* `false` leaves the original URLs untouched in the delivered mail.
|
|
821
|
+
* Rewrite links so clicks are recorded. Omit to use your organization's default (off
|
|
822
|
+
* unless you changed it); `false` leaves the original URLs untouched in the delivered mail.
|
|
800
823
|
*/
|
|
801
824
|
trackClicks?: boolean;
|
|
802
825
|
}
|
|
@@ -974,6 +997,49 @@ declare class Suppressions {
|
|
|
974
997
|
export(): Promise<EusendResponse<string>>;
|
|
975
998
|
}
|
|
976
999
|
//#endregion
|
|
1000
|
+
//#region src/reputation.d.ts
|
|
1001
|
+
type ReputationState = 'healthy' | 'warning' | 'limited' | 'paused';
|
|
1002
|
+
interface Reputation {
|
|
1003
|
+
/**
|
|
1004
|
+
* `warning`: the raw bounce rate is high but the evidence does not yet put it past the
|
|
1005
|
+
* line. `limited`: the daily sending ceiling is halved. `paused`: sending is suspended.
|
|
1006
|
+
*/
|
|
1007
|
+
state: ReputationState;
|
|
1008
|
+
/** False until at least 100 recipients have a delivery result. */
|
|
1009
|
+
measured: boolean;
|
|
1010
|
+
bounce: {
|
|
1011
|
+
/** Raw rate over the judged window. */
|
|
1012
|
+
rate: number;
|
|
1013
|
+
/** The 95% confidence lower bound compared against the lines; 0 without enough evidence. */
|
|
1014
|
+
judged_rate: number;
|
|
1015
|
+
counted: number;
|
|
1016
|
+
/** Bounces about eusend's sending infrastructure rather than the address. */
|
|
1017
|
+
not_counted: number;
|
|
1018
|
+
recipients: number;
|
|
1019
|
+
window: '7d' | '30d' | null;
|
|
1020
|
+
limited_at: number;
|
|
1021
|
+
paused_at: number;
|
|
1022
|
+
};
|
|
1023
|
+
complaint: {
|
|
1024
|
+
rate: number;
|
|
1025
|
+
complaints: number;
|
|
1026
|
+
limited_at: number;
|
|
1027
|
+
paused_at: number;
|
|
1028
|
+
};
|
|
1029
|
+
/** The next state and how many more counted bounces reach it. Null when paused. */
|
|
1030
|
+
next: {
|
|
1031
|
+
state: 'limited' | 'paused';
|
|
1032
|
+
bounces: number | null;
|
|
1033
|
+
} | null;
|
|
1034
|
+
}
|
|
1035
|
+
/** Your organization's sending reputation, as the sending limits judge it. */
|
|
1036
|
+
declare class ReputationResource {
|
|
1037
|
+
private readonly client;
|
|
1038
|
+
constructor(client: Eusend);
|
|
1039
|
+
/** Not available to sending-only keys. Cached by the API for up to 30 seconds. */
|
|
1040
|
+
get(): Promise<EusendResponse<Reputation>>;
|
|
1041
|
+
}
|
|
1042
|
+
//#endregion
|
|
977
1043
|
//#region src/eusend.d.ts
|
|
978
1044
|
interface EusendOptions {
|
|
979
1045
|
baseUrl?: string;
|
|
@@ -995,6 +1061,7 @@ declare class Eusend {
|
|
|
995
1061
|
readonly webhooks: Webhooks;
|
|
996
1062
|
readonly broadcasts: Broadcasts;
|
|
997
1063
|
readonly suppressions: Suppressions;
|
|
1064
|
+
readonly reputation: ReputationResource;
|
|
998
1065
|
constructor(key?: string, options?: EusendOptions);
|
|
999
1066
|
fetchRequest<T>(path: string, init?: RequestInit, extraHeaders?: Record<string, string>, parse?: 'json' | 'text'): Promise<EusendResponse<T>>;
|
|
1000
1067
|
get<T>(path: string, extraHeaders?: Record<string, string>): Promise<EusendResponse<T>>;
|
|
@@ -1004,5 +1071,5 @@ declare class Eusend {
|
|
|
1004
1071
|
delete<T>(path: string): Promise<EusendResponse<T>>;
|
|
1005
1072
|
}
|
|
1006
1073
|
//#endregion
|
|
1007
|
-
export { type ApiKey, type ApiKeyPermission, type Attachment, type Audience, type AudienceDetail, type AudienceListItem, type BatchContactOptions, type BatchCreateContactsOptions, type BatchItemResult, type BatchSendResponse, type Broadcast, type BroadcastDetail, type BroadcastListItem, type BroadcastStatus, type CancelEmailResponse, type ClearTopicSubscriptionResponse, type Contact, type ContactProperty, type ContactPropertyType, type ContactStatus, type CreateApiKeyOptions, type CreateApiKeyResponse, type CreateBroadcastOptions, type CreateContactOptions, type CreateContactPropertyOptions, type CreateDomainResponse, type CreateSuppressionOptions, type CreateTemplateOptions, type CreateTopicOptions, type CreateWebhookOptions, type CreateWebhookResponse, type DeleteContactPropertyResponse, type DeleteDomainResponse, type DeleteTopicResponse, type DnsRecord, type Domain, type DomainDiagnostic, type DomainListItem, type DomainStatus, type DomainVerification, type Email, type EmailEvent, type EmailEventType, type EmailListItem, type EmailStatus, Eusend, type EusendError, type EusendErrorCode, type EusendOptions, type EusendResponse, type ImportSuppressionsResponse, type ListContactsOptions, type ListContactsResponse, type ListEmailsOptions, type ListEmailsResponse, type ListSuppressionsOptions, type ListSuppressionsResponse, type SendBroadcastOptions, type SendBroadcastResponse, type SendEmailOptions, type SendEmailRequestOptions, type SendEmailResponse, type SuppressionEntry, type SuppressionImportItem, type SuppressionReason, type Template, type TemplateListItem, type TestBroadcastOptions, type TestBroadcastResponse, type Topic, type TopicDefaultSubscription, type TopicSubscriptionResponse, type TopicVisibility, type UpdateAudienceOptions, type UpdateBroadcastOptions, type UpdateContactOptions, type UpdateContactPropertyOptions, type UpdateEmailOptions, type UpdateEmailResponse, type UpdateTemplateOptions, type UpdateTopicOptions, type UpdateWebhookOptions, type Webhook, type WebhookDelivery, type WebhookEvent, type WebhookWithDeliveries };
|
|
1074
|
+
export { type ApiKey, type ApiKeyPermission, type Attachment, type Audience, type AudienceDetail, type AudienceListItem, type BatchContactOptions, type BatchCreateContactsOptions, type BatchItemResult, type BatchSendResponse, type Broadcast, type BroadcastDetail, type BroadcastListItem, type BroadcastStatus, type CancelEmailResponse, type ClearTopicSubscriptionResponse, type Contact, type ContactProperty, type ContactPropertyType, type ContactStatus, type CreateApiKeyOptions, type CreateApiKeyResponse, type CreateBroadcastOptions, type CreateContactOptions, type CreateContactPropertyOptions, type CreateDomainResponse, type CreateSuppressionOptions, type CreateTemplateOptions, type CreateTopicOptions, type CreateWebhookOptions, type CreateWebhookResponse, type DeleteContactPropertyResponse, type DeleteDomainResponse, type DeleteTopicResponse, type DnsRecord, type Domain, type DomainDiagnostic, type DomainListItem, type DomainStatus, type DomainVerification, type Email, type EmailEvent, type EmailEventType, type EmailListItem, type EmailStatus, Eusend, type EusendError, type EusendErrorCode, type EusendOptions, type EusendResponse, type ImportSuppressionsResponse, type ListContactsOptions, type ListContactsResponse, type ListEmailsOptions, type ListEmailsResponse, type ListSuppressionsOptions, type ListSuppressionsResponse, type Reputation, type ReputationState, type SendBroadcastOptions, type SendBroadcastResponse, type SendEmailOptions, type SendEmailRequestOptions, type SendEmailResponse, type SuppressionEntry, type SuppressionImportItem, type SuppressionReason, type Template, type TemplateListItem, type TestBroadcastOptions, type TestBroadcastResponse, type Topic, type TopicDefaultSubscription, type TopicSubscriptionResponse, type TopicVisibility, type UpdateAudienceOptions, type UpdateBroadcastOptions, type UpdateContactOptions, type UpdateContactPropertyOptions, type UpdateEmailOptions, type UpdateEmailResponse, type UpdateTemplateOptions, type UpdateTopicOptions, type UpdateWebhookOptions, type Webhook, type WebhookDelivery, type WebhookEvent, type WebhookTestResponse, type WebhookWithDeliveries };
|
|
1008
1075
|
//# sourceMappingURL=index.d.mts.map
|
package/dist/index.d.mts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.mts","names":[],"sources":["../src/interfaces.ts","../src/react-render.ts","../src/emails.ts","../src/batch.ts","../src/domains.ts","../src/api-keys.ts","../src/audiences.ts","../src/contact-properties.ts","../src/topics.ts","../src/templates.ts","../src/webhooks.ts","../src/broadcasts.ts","../src/suppressions.ts","../src/eusend.ts"],"mappings":";KAAY;UA2BK;EACf;EACA;EACA,MAAM;;KAGI,eAAe;EACrB,MAAM;EAAG;EAAa,SAAS;;EAC/B;EAAY,OAAO;EAAa,SAAS;;;;KChCnC;WACD;WACA;WACA;;;;KCFC;KAYA;UAEK;;EAEf;;;;;;EAMA,mBAAmB;;;;;;EAMnB;;EAEA;;;;;EAKA;;;UAIe;EACf;EACA;;;;;;;;;;;;KAaU,YAAY,yBAAyB;UAEhC;;;;;EAKf;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;;;;;EAMA,QAAQ;EACR;EACA,YAAY;EACZ,UAAU;;;;;;EAMV,OAAO
|
|
1
|
+
{"version":3,"file":"index.d.mts","names":[],"sources":["../src/interfaces.ts","../src/react-render.ts","../src/emails.ts","../src/batch.ts","../src/domains.ts","../src/api-keys.ts","../src/audiences.ts","../src/contact-properties.ts","../src/topics.ts","../src/templates.ts","../src/webhooks.ts","../src/broadcasts.ts","../src/suppressions.ts","../src/reputation.ts","../src/eusend.ts"],"mappings":"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"}
|
package/dist/index.mjs
CHANGED
|
@@ -470,9 +470,14 @@ var Webhooks = class {
|
|
|
470
470
|
update(id, options) {
|
|
471
471
|
return this.client.patch(`/webhooks/${id}`, {
|
|
472
472
|
url: options.url,
|
|
473
|
-
events: options.events
|
|
473
|
+
events: options.events,
|
|
474
|
+
enabled: options.enabled
|
|
474
475
|
});
|
|
475
476
|
}
|
|
477
|
+
/** Send one signed `webhook.test` event to the endpoint. Works on a disabled endpoint. */
|
|
478
|
+
test(id) {
|
|
479
|
+
return this.client.post(`/webhooks/${id}/test`);
|
|
480
|
+
}
|
|
476
481
|
delete(id) {
|
|
477
482
|
return this.client.delete(`/webhooks/${id}`);
|
|
478
483
|
}
|
|
@@ -636,9 +641,21 @@ var Suppressions = class {
|
|
|
636
641
|
}
|
|
637
642
|
};
|
|
638
643
|
//#endregion
|
|
644
|
+
//#region src/reputation.ts
|
|
645
|
+
/** Your organization's sending reputation, as the sending limits judge it. */
|
|
646
|
+
var ReputationResource = class {
|
|
647
|
+
constructor(client) {
|
|
648
|
+
this.client = client;
|
|
649
|
+
}
|
|
650
|
+
/** Not available to sending-only keys. Cached by the API for up to 30 seconds. */
|
|
651
|
+
get() {
|
|
652
|
+
return this.client.get("/reputation");
|
|
653
|
+
}
|
|
654
|
+
};
|
|
655
|
+
//#endregion
|
|
639
656
|
//#region src/eusend.ts
|
|
640
657
|
const DEFAULT_BASE_URL = "https://api.eusend.dev";
|
|
641
|
-
const SDK_VERSION = "0.
|
|
658
|
+
const SDK_VERSION = "0.21.0";
|
|
642
659
|
var Eusend = class {
|
|
643
660
|
constructor(key, options) {
|
|
644
661
|
const apiKey = key ?? (typeof process !== "undefined" ? process.env["EUSEND_API_KEY"] : void 0);
|
|
@@ -656,6 +673,7 @@ var Eusend = class {
|
|
|
656
673
|
this.webhooks = new Webhooks(this);
|
|
657
674
|
this.broadcasts = new Broadcasts(this);
|
|
658
675
|
this.suppressions = new Suppressions(this);
|
|
676
|
+
this.reputation = new ReputationResource(this);
|
|
659
677
|
}
|
|
660
678
|
async fetchRequest(path, init = {}, extraHeaders = {}, parse = "json") {
|
|
661
679
|
const headers = {
|
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.mjs","names":[],"sources":["../src/react-render.ts","../src/emails.ts","../src/batch.ts","../src/domains.ts","../src/api-keys.ts","../src/audiences.ts","../src/contact-properties.ts","../src/topics.ts","../src/templates.ts","../src/webhooks.ts","../src/broadcasts.ts","../src/suppressions.ts","../src/eusend.ts"],"sourcesContent":["// Minimal structural type so the SDK doesn't take a hard dependency on `react`.\n// Real React elements assignable to this; users who pass `react:` are expected to\n// have `react` and `@react-email/render` installed (declared as optional peers).\nexport type ReactEmailElement = {\n readonly type: unknown\n readonly props: unknown\n readonly key: string | number | null\n}\n\nlet renderPromise: Promise<(element: ReactEmailElement) => Promise<string>> | null = null\n\nasync function getRender(): Promise<(element: ReactEmailElement) => Promise<string>> {\n if (!renderPromise) {\n renderPromise = (async () => {\n try {\n const mod = (await import('@react-email/render')) as {\n render: (element: unknown, options?: { plainText?: boolean }) => Promise<string> | string\n }\n return (element: ReactEmailElement) => Promise.resolve(mod.render(element))\n } catch {\n throw new Error(\n 'Passing `react:` requires `@react-email/render` and `react` to be installed. ' +\n 'Run: npm install @react-email/render react',\n )\n }\n })()\n }\n return renderPromise\n}\n\nexport async function renderReactEmail(element: ReactEmailElement): Promise<string> {\n const render = await getRender()\n return render(element)\n}\n","import type { Eusend } from './eusend'\nimport type { EusendErrorCode, EusendResponse } from './interfaces'\nimport { renderReactEmail, type ReactEmailElement } from './react-render'\n\nexport type EmailStatus =\n | 'queued'\n | 'scheduled'\n | 'canceled'\n | 'sending'\n | 'sent'\n | 'delivered'\n | 'bounced'\n | 'complained'\n | 'suppressed'\n | 'failed'\n\nexport type EmailEventType = 'sent' | 'delivered' | 'opened' | 'clicked' | 'bounced' | 'complained'\n\nexport interface Attachment {\n /** Name the recipient sees for the file, e.g. `invoice.pdf`. */\n filename: string\n /**\n * File contents. A base64-encoded string (sent as-is) or raw bytes\n * (`Uint8Array`/`Buffer`), which the SDK base64-encodes for you. Provide either\n * `content` or `path`, not both.\n */\n content?: string | Uint8Array\n /**\n * A URL the server fetches at send time to attach the file. Use instead of\n * `content` when the bytes live on a public URL. Provide either `content` or `path`,\n * not both.\n */\n path?: string\n /** MIME type, e.g. `application/pdf`. Inferred from the filename when omitted. */\n contentType?: string\n /**\n * Content-ID for an inline attachment. Set it to reference the file from your\n * HTML with `<img src=\"cid:<contentId>\">` instead of showing it as a download.\n */\n contentId?: string\n}\n\n/** A single tag in the `[{ name, value }]` form, for Resend-compatible payloads. */\nexport interface EmailTag {\n name: string\n value: string\n}\n\n/**\n * Labels attached to a send, used to filter your email log and to route webhook events.\n *\n * Accepts either a plain object (`{ category: 'password_reset' }`) or the\n * `[{ name, value }]` array form, so a payload written against Resend works unchanged.\n * Responses and webhook payloads always return the object form.\n *\n * Names and values may contain ASCII letters, numbers, underscores and dashes; up to 10\n * tags per email.\n */\nexport type EmailTags = Record<string, string> | EmailTag[]\n\nexport interface SendEmailOptions {\n /**\n * Sender address. Accepts a bare email (`onboarding@eusend.dev`) or a display-name\n * form (`Acme <onboarding@eusend.dev>`). The domain must be verified on your account.\n */\n from: string\n to: string | string[]\n cc?: string | string[]\n bcc?: string | string[]\n replyTo?: string | string[]\n subject?: string\n html?: string\n text?: string\n /**\n * A React Email component. The SDK renders it to HTML locally before sending\n * — the JSX source never travels over the wire. Requires `@react-email/render`\n * and `react` as peer dependencies. Ignored when `html` is also provided.\n */\n react?: ReactEmailElement\n templateId?: string\n variables?: Record<string, unknown>\n headers?: Record<string, string>\n /**\n * Labels for log filtering and webhook routing, e.g.\n * `{ category: 'password_reset', tier: 'pro' }`. Returned on every `email.*` webhook\n * event for this send.\n */\n tags?: EmailTags\n trackOpens?: boolean\n trackClicks?: boolean\n /** File attachments. Up to 20 per message, 10 MB combined. */\n attachments?: Attachment[]\n /**\n * Schedule the send for a future time, at most 30 days out. Accepts a `Date`, an\n * ISO 8601 string, or a natural-language time like `\"in 1 hour\"` or `\"tomorrow at\n * 9am\"` (parsed server-side, same as Resend). Relative phrasings resolve against the\n * server clock in UTC — pass an offset-qualified ISO string when you need an exact\n * instant. The email is created with status `scheduled`; reschedule it with\n * `emails.update()` or call `emails.cancel()` any time before it sends.\n */\n scheduledAt?: string | Date\n}\n\nexport interface SendEmailRequestOptions {\n idempotencyKey?: string\n}\n\nexport interface SendEmailResponse {\n id: string\n}\n\n/**\n * Per-item outcome of a batch send, positionally mapped to the input array:\n * `data[i]` describes `emails[i]`. Items that were queued carry `{ id }`; items\n * that could not be queued carry `{ error, code }` (e.g. an unverified sender\n * domain, all recipients suppressed, or an exhausted send quota). Branch on the\n * presence of `id`.\n */\nexport type BatchItemResult =\n { id: string; error?: never; code?: never } | { id?: never; error: string; code: EusendErrorCode }\n\nexport interface BatchSendResponse {\n data: BatchItemResult[]\n}\n\nexport interface EmailEvent {\n id: string\n type: EmailEventType\n metadata: Record<string, unknown>\n createdAt: string\n}\n\nexport interface Email {\n id: string\n from: string\n to: string[]\n cc: string[]\n bcc: string[]\n replyTo: string[]\n subject: string\n html: string | null\n text: string | null\n status: EmailStatus\n /** Always the object form, `{}` when the send carried no tags. */\n tags: Record<string, string>\n testMode: boolean\n templateId: string | null\n /** Set only for scheduled sends. */\n scheduledAt: string | null\n createdAt: string\n events: EmailEvent[]\n}\n\nexport interface UpdateEmailOptions {\n /** The new send time, at most 30 days out — a `Date`, an ISO 8601 string, or natural\n * language like `\"in 1 hour\"` (parsed server-side, same as `emails.send`). */\n scheduledAt: string | Date\n}\n\nexport interface UpdateEmailResponse {\n id: string\n status: 'scheduled'\n scheduledAt: string\n}\n\nexport interface CancelEmailResponse {\n id: string\n status: 'canceled'\n}\n\nexport interface EmailListItem {\n id: string\n from: string\n to: string[]\n subject: string\n status: EmailStatus\n /** Always the object form, `{}` when the send carried no tags. */\n tags: Record<string, string>\n testMode: boolean\n createdAt: string\n}\n\nexport interface ListEmailsOptions {\n limit?: number\n cursor?: string\n status?: EmailStatus\n from?: string\n to?: string\n /**\n * Filter by tag. `'category:password_reset'` matches that exact pair; a bare\n * `'category'` matches any email carrying the tag. Pass an array to require several.\n */\n tag?: string | string[]\n}\n\nexport interface ListEmailsResponse {\n data: EmailListItem[]\n nextCursor: string | null\n}\n\nasync function resolveHtml(options: SendEmailOptions): Promise<string | undefined> {\n if (options.html) return options.html\n if (options.react) return renderReactEmail(options.react)\n return undefined\n}\n\nfunction encodeAttachmentContent(content: string | Uint8Array): string {\n // A string is assumed to already be base64. Raw bytes are encoded here.\n if (typeof content === 'string') return content\n if (typeof Buffer !== 'undefined') return Buffer.from(content).toString('base64')\n let binary = ''\n for (const byte of content) binary += String.fromCharCode(byte)\n return btoa(binary)\n}\n\nfunction toIsoString(value: string | Date): string {\n return value instanceof Date ? value.toISOString() : value\n}\n\nexport async function toApiPayload(options: SendEmailOptions) {\n const html = await resolveHtml(options)\n return {\n from: options.from,\n to: options.to,\n cc: options.cc,\n bcc: options.bcc,\n reply_to: options.replyTo,\n subject: options.subject,\n html,\n text: options.text,\n template_id: options.templateId,\n variables: options.variables,\n headers: options.headers,\n tags: options.tags,\n track_opens: options.trackOpens,\n track_clicks: options.trackClicks,\n attachments: options.attachments?.map((a) => ({\n filename: a.filename,\n content: a.content === undefined ? undefined : encodeAttachmentContent(a.content),\n path: a.path,\n content_type: a.contentType,\n content_id: a.contentId,\n })),\n scheduled_at: options.scheduledAt ? toIsoString(options.scheduledAt) : undefined,\n }\n}\n\nexport class Emails {\n constructor(private readonly client: Eusend) {}\n\n async send(\n options: SendEmailOptions,\n requestOptions?: SendEmailRequestOptions,\n ): Promise<EusendResponse<SendEmailResponse>> {\n const extraHeaders: Record<string, string> = {}\n if (requestOptions?.idempotencyKey) {\n extraHeaders['Idempotency-Key'] = requestOptions.idempotencyKey\n }\n const payload = await toApiPayload(options)\n return this.client.post<SendEmailResponse>('/emails', payload, extraHeaders)\n }\n\n async list(options: ListEmailsOptions = {}): Promise<EusendResponse<ListEmailsResponse>> {\n const params = new URLSearchParams()\n if (options.limit != null) params.set('limit', String(options.limit))\n if (options.cursor) params.set('cursor', options.cursor)\n if (options.status) params.set('status', options.status)\n if (options.from) params.set('from', options.from)\n if (options.to) params.set('to', options.to)\n // Repeated `tag` params, one per filter — the API ANDs them.\n for (const tag of options.tag == null ? [] : [options.tag].flat()) {\n params.append('tag', tag)\n }\n const qs = params.toString()\n\n const res = await this.client.get<{ data: EmailListItem[]; next_cursor: string | null }>(\n qs ? `/emails?${qs}` : '/emails',\n )\n if (res.error) return res\n return {\n data: { data: res.data.data, nextCursor: res.data.next_cursor },\n error: null,\n headers: res.headers,\n }\n }\n\n get(id: string): Promise<EusendResponse<Email>> {\n return this.client.get<Email>(`/emails/${id}`)\n }\n\n /**\n * Reschedule a scheduled email. Fails once the email has started sending, and returns\n * 429 `DAILY_LIMIT_EXCEEDED` when the new day's sending quota is already used up.\n */\n async update(\n id: string,\n options: UpdateEmailOptions,\n ): Promise<EusendResponse<UpdateEmailResponse>> {\n const res = await this.client.patch<{ id: string; status: 'scheduled'; scheduled_at: string }>(\n `/emails/${id}`,\n { scheduled_at: toIsoString(options.scheduledAt) },\n )\n if (res.error) return res\n return {\n data: { id: res.data.id, status: res.data.status, scheduledAt: res.data.scheduled_at },\n error: null,\n headers: res.headers,\n }\n }\n\n /** Cancel a scheduled email. Fails once the email has started sending. */\n cancel(id: string): Promise<EusendResponse<CancelEmailResponse>> {\n return this.client.post<CancelEmailResponse>(`/emails/${id}/cancel`, undefined)\n }\n}\n","import type { Eusend } from './eusend'\nimport type { EusendResponse } from './interfaces'\nimport {\n toApiPayload,\n type SendEmailOptions,\n type SendEmailRequestOptions,\n type BatchSendResponse,\n} from './emails'\n\n/**\n * Batch sending — `eusend.batch.send([...])`. The method path mirrors Resend's\n * `resend.batch.send([...])`, so migrating is a mechanical `resend` → `eusend` rename.\n * The HTTP body is a top-level array of email objects (POST /emails/batch), up to 100\n * per request. As with Resend, attachments and `scheduledAt` are not supported on the\n * batch endpoint — send those individually via `emails.send`.\n *\n * The response maps positionally to the input: `data[i]` is `{ id }` when\n * `emails[i]` was queued, or `{ error, code }` when it was not (unverified\n * domain, suppressed recipients, exhausted quota, …) — failed items never fail\n * the whole batch, so branch on the presence of `id` per item.\n *\n * Pass `{ idempotencyKey }` to retry safely: the key is applied per item by position, so\n * a retry must keep the items in the same order or it will match the wrong emails.\n */\nexport class Batch {\n constructor(private readonly client: Eusend) {}\n\n async send(\n emails: SendEmailOptions[],\n requestOptions?: SendEmailRequestOptions,\n ): Promise<EusendResponse<BatchSendResponse>> {\n const extraHeaders: Record<string, string> = {}\n if (requestOptions?.idempotencyKey) {\n extraHeaders['Idempotency-Key'] = requestOptions.idempotencyKey\n }\n const payloads = await Promise.all(emails.map(toApiPayload))\n return this.client.post<BatchSendResponse>('/emails/batch', payloads, extraHeaders)\n }\n}\n","import type { Eusend } from './eusend'\nimport type { EusendResponse } from './interfaces'\n\nexport type DomainStatus = 'pending' | 'verified' | 'failed'\n\nexport interface DnsRecord {\n type: string\n name: string\n value: string\n /** MX records only. */\n priority?: number\n /**\n * `authentication` — required before the domain can send.\n * `policy` — recommended; absence weakens but does not block.\n * `alignment` — optional; publishing all of them enables Return-Path SPF alignment.\n */\n purpose?: string\n description?: string\n}\n\nexport interface CreateDomainResponse {\n id: string\n name: string\n /**\n * Every record to publish, in presentation order. Prefer this over the individual\n * keys below — it is the only place the optional Return-Path alignment records appear.\n */\n records: DnsRecord[]\n dkim: DnsRecord\n dmarc: DnsRecord\n}\n\nexport interface DomainListItem {\n id: string\n name: string\n status: DomainStatus\n createdAt: string\n}\n\n/** Whether a verification chain is polling DNS for this domain right now. */\nexport interface DomainVerification {\n running: boolean\n /** When the running chain started, or null when none is. */\n startedAt: string | null\n}\n\n/**\n * What the last unmatched DNS check found, when it found a mistake rather than an absence.\n *\n * `code` is the mistake: `doubled_domain` (the record sits under the domain twice, because the\n * control panel appends it to whatever you type), `truncated_key` (the value was cut at the\n * 255-character limit for a single DNS string instead of being split into two), `foreign_key`\n * (a DKIM key we did not issue is published at the selector), `quoted_value`, `multiple_records`,\n * `cname_at_selector`. New codes may be added, so treat an unknown one as generic.\n */\nexport interface DomainDiagnostic {\n code: string\n /** The name the record was actually found at, for `doubled_domain`. */\n foundAt?: string\n /** How much of the key is published, and how much there is, for `truncated_key`. */\n publishedChars?: number\n expectedChars?: number\n /** Where the CNAME points, for `cname_at_selector`. */\n target?: string\n /** The DNS host serving the zone, when its nameservers named one we recognise. */\n provider?: {\n id: string\n label: string\n /** Path to the guide for this panel on eusend.dev, or null where there is none. */\n guide: string | null\n }\n}\n\nexport interface Domain {\n id: string\n name: string\n dkimPublicKey: string\n dkimSelector: string\n status: DomainStatus\n createdAt: string\n verifiedAt: string | null\n verification: DomainVerification\n /** Null while nothing is wrong beyond the records not having propagated yet. */\n diagnostic: DomainDiagnostic | null\n}\n\nexport interface DeleteDomainResponse {\n message: string\n /** Scheduled emails from this domain that were canceled because it can no longer send. */\n canceled_scheduled_emails: number\n}\n\nexport class Domains {\n constructor(private readonly client: Eusend) {}\n\n create(name: string): Promise<EusendResponse<CreateDomainResponse>> {\n return this.client.post<CreateDomainResponse>('/domains', { name })\n }\n\n list(): Promise<EusendResponse<DomainListItem[]>> {\n return this.client.get<DomainListItem[]>('/domains')\n }\n\n get(id: string): Promise<EusendResponse<Domain>> {\n return this.client.get<Domain>(`/domains/${id}`)\n }\n\n delete(id: string): Promise<EusendResponse<DeleteDomainResponse>> {\n return this.client.delete<DeleteDomainResponse>(`/domains/${id}`)\n }\n\n verify(id: string): Promise<EusendResponse<{ message: string }>> {\n return this.client.post<{ message: string }>(`/domains/${id}/verify`)\n }\n}\n","import type { Eusend } from './eusend'\nimport type { EusendResponse } from './interfaces'\n\n/**\n * What a key may reach. `full_access` is every resource; `sending_access` is limited to\n * sending email (and rescheduling or canceling a scheduled send).\n */\nexport type ApiKeyPermission = 'full_access' | 'sending_access'\n\nexport interface CreateApiKeyOptions {\n name: string\n testMode?: boolean\n /** Defaults to `full_access`. */\n permission?: ApiKeyPermission\n /**\n * Restrict the key to sending from a single domain. Only valid together with\n * `permission: 'sending_access'`; omit for any verified domain.\n */\n domainId?: string\n}\n\nexport interface CreateApiKeyResponse {\n id: string\n name: string\n key: string\n prefix: string\n testMode: boolean\n permission: ApiKeyPermission\n domainId: string | null\n domainName: string | null\n createdAt: string\n}\n\nexport interface ApiKey {\n id: string\n name: string\n prefix: string\n testMode: boolean\n permission: ApiKeyPermission\n domainId: string | null\n domainName: string | null\n createdAt: string\n lastUsedAt: string | null\n}\n\ntype CreateApiKeyApiResponse = {\n id: string\n name: string\n key: string\n prefix: string\n test_mode: boolean\n permission: ApiKeyPermission\n domain_id: string | null\n domain_name: string | null\n created_at: string\n}\n\nexport class ApiKeys {\n constructor(private readonly client: Eusend) {}\n\n async create(options: CreateApiKeyOptions): Promise<EusendResponse<CreateApiKeyResponse>> {\n const res = await this.client.post<CreateApiKeyApiResponse>('/api-keys', {\n name: options.name,\n test_mode: options.testMode ?? false,\n permission: options.permission ?? 'full_access',\n ...(options.domainId ? { domain_id: options.domainId } : {}),\n })\n if (res.error) return res\n return {\n data: {\n id: res.data.id,\n name: res.data.name,\n key: res.data.key,\n prefix: res.data.prefix,\n testMode: res.data.test_mode,\n permission: res.data.permission,\n domainId: res.data.domain_id,\n domainName: res.data.domain_name,\n createdAt: res.data.created_at,\n },\n error: null,\n headers: res.headers,\n }\n }\n\n list(): Promise<EusendResponse<ApiKey[]>> {\n return this.client.get<ApiKey[]>('/api-keys')\n }\n\n delete(id: string): Promise<EusendResponse<{ message: string }>> {\n return this.client.delete<{ message: string }>(`/api-keys/${id}`)\n }\n}\n","import type { Eusend } from './eusend'\nimport type { EusendResponse } from './interfaces'\n\nexport type ContactStatus = 'subscribed' | 'unsubscribed'\n\nexport interface Audience {\n id: string\n name: string\n organizationId: string\n createdAt: string\n updatedAt: string\n}\n\nexport interface AudienceListItem {\n id: string\n name: string\n createdAt: string\n contactCount: number\n}\n\nexport interface AudienceDetail extends AudienceListItem {\n updatedAt: string\n}\n\nexport interface UpdateAudienceOptions {\n name: string\n}\n\nexport interface Contact {\n id: string\n audienceId: string\n email: string\n firstName: string | null\n lastName: string | null\n /** Custom properties, available as `{{key}}` in a broadcast body. */\n properties: Record<string, string>\n status: ContactStatus\n unsubscribedAt: string | null\n createdAt: string\n updatedAt: string\n}\n\nexport interface CreateContactOptions {\n email: string\n firstName?: string\n lastName?: string\n /**\n * Custom properties, merged into the `{{variable}}` map when a broadcast renders, so\n * `{ plan: 'pro' }` makes `{{plan}}` resolve to `pro`.\n *\n * Values are strings; keys are lowercase letters, digits and underscores, starting with\n * a letter (at most 40 characters, 20 properties per contact). `email`, `name`,\n * `first_name`, `last_name` and `full_name` are built in and cannot be used.\n *\n * Sending this REPLACES the contact's properties. Omitting it on `createContact` clears\n * them; omitting it on `updateContact` leaves them untouched.\n */\n properties?: Record<string, string>\n}\n\nexport interface UpdateContactOptions {\n firstName?: string\n lastName?: string\n unsubscribed?: boolean\n /** Replaces the contact's custom properties. Omit to leave them unchanged; pass `{}` to\n * clear them. See {@link CreateContactOptions.properties} for the naming rules. */\n properties?: Record<string, string>\n}\n\nexport interface ListContactsOptions {\n limit?: number\n cursor?: string\n search?: string\n subscribed?: boolean\n}\n\nexport interface ListContactsResponse {\n data: Contact[]\n nextCursor: string | null\n}\n\n/**\n * A contact in a bulk import. Extends the single-create shape with the two fields that\n * only make sense when migrating a list in from somewhere else.\n */\nexport interface BatchContactOptions extends CreateContactOptions {\n /**\n * Mark the contact as opted out, so a list moved from another provider keeps its\n * unsubscribes. An import can only ever ADD an opt-out: passing `false` will not\n * re-subscribe someone who has already unsubscribed. Use `updateContact` for that,\n * one contact at a time.\n */\n unsubscribed?: boolean\n /** Original signup time (ISO 8601). Applied on insert only — an existing contact\n * keeps the date it already has. */\n createdAt?: string\n /**\n * Unlike `createContact`, an import MERGES properties into whatever the contact already\n * has — a CSV carrying only `plan` will not drop a `company` an earlier import set. To\n * replace the whole object, use `updateContact`.\n */\n properties?: Record<string, string>\n}\n\nexport interface BatchCreateContactsOptions {\n contacts: BatchContactOptions[]\n}\n\nexport class Audiences {\n constructor(private readonly client: Eusend) {}\n\n create(name: string): Promise<EusendResponse<Audience>> {\n return this.client.post<Audience>('/audiences', { name })\n }\n\n async list(): Promise<EusendResponse<AudienceListItem[]>> {\n const res = await this.client.get<{ data: AudienceListItem[] }>('/audiences')\n if (res.error) return res\n return { data: res.data.data, error: null, headers: res.headers }\n }\n\n get(id: string): Promise<EusendResponse<AudienceDetail>> {\n return this.client.get<AudienceDetail>(`/audiences/${id}`)\n }\n\n /** Rename an audience. */\n update(id: string, options: UpdateAudienceOptions): Promise<EusendResponse<Audience>> {\n return this.client.patch<Audience>(`/audiences/${id}`, { name: options.name })\n }\n\n delete(id: string): Promise<EusendResponse<Record<string, never>>> {\n return this.client.delete<Record<string, never>>(`/audiences/${id}`)\n }\n\n createContact(\n audienceId: string,\n options: CreateContactOptions,\n ): Promise<EusendResponse<Contact>> {\n return this.client.post<Contact>(`/audiences/${audienceId}/contacts`, {\n email: options.email,\n first_name: options.firstName,\n last_name: options.lastName,\n properties: options.properties,\n })\n }\n\n async listContacts(\n audienceId: string,\n options: ListContactsOptions = {},\n ): Promise<EusendResponse<ListContactsResponse>> {\n const params = new URLSearchParams()\n if (options.limit != null) params.set('limit', String(options.limit))\n if (options.cursor) params.set('cursor', options.cursor)\n if (options.search) params.set('search', options.search)\n if (options.subscribed != null) params.set('subscribed', String(options.subscribed))\n const qs = params.toString()\n return this.client.get<ListContactsResponse>(\n qs ? `/audiences/${audienceId}/contacts?${qs}` : `/audiences/${audienceId}/contacts`,\n )\n }\n\n getContact(audienceId: string, contactId: string): Promise<EusendResponse<Contact>> {\n return this.client.get<Contact>(`/audiences/${audienceId}/contacts/${contactId}`)\n }\n\n updateContact(\n audienceId: string,\n contactId: string,\n options: UpdateContactOptions,\n ): Promise<EusendResponse<Contact>> {\n return this.client.patch<Contact>(`/audiences/${audienceId}/contacts/${contactId}`, {\n first_name: options.firstName,\n last_name: options.lastName,\n unsubscribed: options.unsubscribed,\n properties: options.properties,\n })\n }\n\n deleteContact(\n audienceId: string,\n contactId: string,\n ): Promise<EusendResponse<Record<string, never>>> {\n return this.client.delete<Record<string, never>>(\n `/audiences/${audienceId}/contacts/${contactId}`,\n )\n }\n\n /**\n * Upsert up to 1000 contacts in one call. Addresses are lowercased and\n * de-duplicated server-side; `count` is the number of rows written and\n * `duplicates` how many repeated addresses were collapsed to get there.\n */\n /**\n * Delete up to 1,000 contacts from an audience by id.\n *\n * `deleted` may be lower than the number of ids sent — an id may already be gone, or\n * may belong to another audience — so a retry after a dropped response settles at 0\n * rather than failing.\n *\n * This is not an unsubscribe. It removes them from the audience without adding them to\n * the suppression list; use `updateContact({ unsubscribed: true })` to stop mailing\n * somebody while keeping the record.\n */\n batchDeleteContacts(\n audienceId: string,\n contactIds: string[],\n ): Promise<EusendResponse<{ deleted: number }>> {\n return this.client.post<{ deleted: number }>(\n `/audiences/${audienceId}/contacts/batch-delete`,\n { contact_ids: contactIds },\n )\n }\n\n batchCreateContacts(\n audienceId: string,\n options: BatchCreateContactsOptions,\n ): Promise<EusendResponse<{ count: number; duplicates: number }>> {\n return this.client.post<{ count: number; duplicates: number }>(\n `/audiences/${audienceId}/contacts/batch`,\n {\n contacts: options.contacts.map((c) => ({\n email: c.email,\n first_name: c.firstName,\n last_name: c.lastName,\n unsubscribed: c.unsubscribed,\n created_at: c.createdAt,\n properties: c.properties,\n })),\n },\n )\n }\n}\n","import type { Eusend } from './eusend'\nimport type { EusendResponse } from './interfaces'\n\n/**\n * A declared property's type. Values are carried and rendered as strings either way —\n * `number` buys a write-time check, not arithmetic or locale formatting.\n */\nexport type ContactPropertyType = 'string' | 'number'\n\nexport interface ContactProperty {\n id: string\n key: string\n type: ContactPropertyType\n /** Substituted into `{{key}}` for contacts that carry no value of their own. `null`\n * renders empty, which is what an unset property did before the registry existed. */\n fallbackValue: string | null\n createdAt: string\n updatedAt: string\n}\n\nexport interface CreateContactPropertyOptions {\n /** Lowercase letters, digits and underscores, starting with a letter; at most 40\n * characters. `email`, `name`, `first_name`, `last_name` and `full_name` are built in\n * and cannot be declared. */\n key: string\n /** Defaults to `string`. */\n type?: ContactPropertyType\n fallbackValue?: string | null\n}\n\nexport interface UpdateContactPropertyOptions {\n /** The only mutable field. `key` and `type` are fixed at creation: a rename would have\n * to rewrite every contact and every broadcast body spelling `{{old_key}}`, so changing\n * either is a delete and a create. */\n fallbackValue: string | null\n}\n\nexport interface DeleteContactPropertyResponse {\n deleted: true\n /** How many contacts had the key stripped from them. */\n contactsUpdated: number\n}\n\n/**\n * The organization's custom contact properties — the schema behind the `properties` bag\n * each contact carries.\n *\n * Declaring a property is optional. A property arriving on a contact write that has never\n * been declared registers itself as a `string`, so an existing integration needs no\n * changes. Declaring one up front is what buys a type check and a fallback value.\n */\nexport class ContactProperties {\n constructor(private readonly client: Eusend) {}\n\n create(options: CreateContactPropertyOptions): Promise<EusendResponse<ContactProperty>> {\n return this.client.post<ContactProperty>('/contact-properties', {\n key: options.key,\n type: options.type,\n fallback_value: options.fallbackValue,\n })\n }\n\n /** Every property the organization has defined. Unpaginated — the registry is capped at\n * 100 entries, and a variable picker wants all of them. */\n async list(): Promise<EusendResponse<ContactProperty[]>> {\n const res = await this.client.get<{ data: ContactProperty[] }>('/contact-properties')\n if (res.error) return res\n return { data: res.data.data, error: null, headers: res.headers }\n }\n\n get(id: string): Promise<EusendResponse<ContactProperty>> {\n return this.client.get<ContactProperty>(`/contact-properties/${id}`)\n }\n\n update(\n id: string,\n options: UpdateContactPropertyOptions,\n ): Promise<EusendResponse<ContactProperty>> {\n return this.client.patch<ContactProperty>(`/contact-properties/${id}`, {\n fallback_value: options.fallbackValue,\n })\n }\n\n /**\n * Delete a property definition AND strip the key from every contact in the organization.\n *\n * Destructive and not undoable. Leaving the values in place was the alternative, and a\n * worse one: the property would keep rendering in broadcasts, and the next contact write\n * carrying that key would register it again.\n */\n delete(id: string): Promise<EusendResponse<DeleteContactPropertyResponse>> {\n return this.client.delete<DeleteContactPropertyResponse>(`/contact-properties/${id}`)\n }\n}\n","import type { Eusend } from './eusend'\nimport type { EusendResponse } from './interfaces'\n\n/** What a contact who has never expressed a preference receives. Fixed at creation. */\nexport type TopicDefaultSubscription = 'opt_in' | 'opt_out'\n\n/** Whether the topic is listed on the unsubscribe page to a contact who is not opted in. */\nexport type TopicVisibility = 'public' | 'private'\n\nexport interface Topic {\n id: string\n name: string\n description: string | null\n defaultSubscription: TopicDefaultSubscription\n visibility: TopicVisibility\n /** Contacts who explicitly opted in. Present on list and create, not on get. */\n subscriberCount?: number\n createdAt: string\n updatedAt: string\n}\n\nexport interface CreateTopicOptions {\n name: string\n /** `opt_in` reaches everyone until they leave; `opt_out` reaches nobody until they join.\n * Cannot be changed afterwards. */\n defaultSubscription: TopicDefaultSubscription\n description?: string | null\n /** Defaults to `private`. */\n visibility?: TopicVisibility\n}\n\n/** `defaultSubscription` is absent deliberately — it is fixed at creation. */\nexport interface UpdateTopicOptions {\n name?: string\n description?: string | null\n visibility?: TopicVisibility\n}\n\nexport interface DeleteTopicResponse {\n id: string\n deleted: true\n}\n\nexport interface TopicSubscriptionResponse {\n topicId: string\n contactId: string\n subscribed: boolean\n}\n\nexport interface ClearTopicSubscriptionResponse {\n topicId: string\n contactId: string\n deleted: true\n}\n\nexport class Topics {\n constructor(private readonly client: Eusend) {}\n\n create(options: CreateTopicOptions): Promise<EusendResponse<Topic>> {\n return this.client.post<Topic>('/topics', {\n name: options.name,\n default_subscription: options.defaultSubscription,\n description: options.description,\n visibility: options.visibility,\n })\n }\n\n /** Every topic the organization has defined. Unpaginated — the list is capped at 100,\n * and both the composer's picker and the unsubscribe page want all of it. */\n async list(): Promise<EusendResponse<Topic[]>> {\n const res = await this.client.get<{ data: Topic[] }>('/topics')\n if (res.error) return res\n return { data: res.data.data, error: null, headers: res.headers }\n }\n\n get(id: string): Promise<EusendResponse<Topic>> {\n return this.client.get<Topic>(`/topics/${id}`)\n }\n\n update(id: string, options: UpdateTopicOptions): Promise<EusendResponse<Topic>> {\n return this.client.patch<Topic>(`/topics/${id}`, {\n name: options.name,\n description: options.description,\n visibility: options.visibility,\n })\n }\n\n /** Deletes the topic and every stored preference for it. A draft broadcast scoped to it\n * widens back to its whole audience; returns 409 while a broadcast that is scheduled or\n * has not finished sending still uses the topic. */\n delete(id: string): Promise<EusendResponse<DeleteTopicResponse>> {\n return this.client.delete<DeleteTopicResponse>(`/topics/${id}`)\n }\n\n /** Record an explicit preference for one contact. */\n subscribe(\n topicId: string,\n contactId: string,\n subscribed = true,\n ): Promise<EusendResponse<TopicSubscriptionResponse>> {\n return this.client.put<TopicSubscriptionResponse>(\n `/topics/${topicId}/contacts/${contactId}`,\n { subscribed },\n )\n }\n\n /**\n * Forget the contact's explicit choice, so they fall back to the topic's default.\n *\n * Different from `subscribe(id, contactId, false)`: that records \"no thanks\", this\n * records nothing at all — so on an opt-in topic the contact starts receiving it again.\n */\n clearSubscription(\n topicId: string,\n contactId: string,\n ): Promise<EusendResponse<ClearTopicSubscriptionResponse>> {\n return this.client.delete<ClearTopicSubscriptionResponse>(\n `/topics/${topicId}/contacts/${contactId}`,\n )\n }\n}\n","import type { Eusend } from './eusend'\nimport type { EusendResponse } from './interfaces'\nimport { renderReactEmail, type ReactEmailElement } from './react-render'\n\ninterface TemplateHtmlOrReact {\n /**\n * A React Email component. The SDK renders it to HTML locally before sending.\n * Requires `@react-email/render` and `react` as peer dependencies.\n * Ignored when `html` is also provided.\n */\n react?: ReactEmailElement\n}\n\nexport interface CreateTemplateOptions extends TemplateHtmlOrReact {\n name: string\n subject: string\n html?: string\n}\n\nexport interface UpdateTemplateOptions extends TemplateHtmlOrReact {\n name?: string\n subject?: string\n html?: string\n}\n\nexport interface Template {\n id: string\n name: string\n subject: string\n html: string | null\n reactSource: string | null\n createdAt: string\n updatedAt: string\n}\n\nexport interface TemplateListItem {\n id: string\n name: string\n subject: string\n createdAt: string\n updatedAt: string\n}\n\nasync function resolveTemplateHtml(\n options: TemplateHtmlOrReact & { html?: string },\n): Promise<string | undefined> {\n if (options.html) return options.html\n if (options.react) return renderReactEmail(options.react)\n return undefined\n}\n\nexport class Templates {\n constructor(private readonly client: Eusend) {}\n\n async create(options: CreateTemplateOptions): Promise<EusendResponse<Template>> {\n const html = await resolveTemplateHtml(options)\n if (!html) {\n return {\n data: null,\n error: {\n message: 'Either html or react is required',\n statusCode: null,\n name: 'VALIDATION_ERROR',\n },\n headers: null,\n }\n }\n return this.client.post<Template>('/templates', {\n name: options.name,\n subject: options.subject,\n html,\n })\n }\n\n async list(): Promise<EusendResponse<TemplateListItem[]>> {\n const res = await this.client.get<{ data: TemplateListItem[] }>('/templates')\n if (res.error) return res\n return { data: res.data.data, error: null, headers: res.headers }\n }\n\n get(id: string): Promise<EusendResponse<Template>> {\n return this.client.get<Template>(`/templates/${id}`)\n }\n\n async update(id: string, options: UpdateTemplateOptions): Promise<EusendResponse<Template>> {\n const html = await resolveTemplateHtml(options)\n return this.client.patch<Template>(`/templates/${id}`, {\n name: options.name,\n subject: options.subject,\n html,\n })\n }\n\n delete(id: string): Promise<EusendResponse<Record<string, never>>> {\n return this.client.delete<Record<string, never>>(`/templates/${id}`)\n }\n}\n","import type { Eusend } from './eusend'\nimport type { EusendResponse } from './interfaces'\n\nexport type WebhookEvent =\n | 'email.sent'\n | 'email.delivered'\n | 'email.bounced'\n | 'email.complained'\n | 'email.opened'\n | 'email.clicked'\n | 'email.failed'\n | 'email.suppressed'\n | '*'\n\nexport interface CreateWebhookOptions {\n url: string\n events: WebhookEvent[]\n}\n\nexport interface UpdateWebhookOptions {\n url?: string\n events?: WebhookEvent[]\n}\n\nexport interface WebhookDelivery {\n id: string\n webhookId: string\n emailId: string | null\n eventType: string\n payload: Record<string, unknown>\n status: 'pending' | 'success' | 'failed'\n responseStatus: number | null\n attempts: number\n createdAt: string\n lastAttemptAt: string | null\n}\n\nexport interface Webhook {\n id: string\n url: string\n events: WebhookEvent[]\n createdAt: string\n}\n\nexport interface WebhookWithDeliveries extends Webhook {\n deliveries: WebhookDelivery[]\n}\n\nexport interface CreateWebhookResponse extends Webhook {\n secret: string\n}\n\nexport class Webhooks {\n constructor(private readonly client: Eusend) {}\n\n create(options: CreateWebhookOptions): Promise<EusendResponse<CreateWebhookResponse>> {\n return this.client.post<CreateWebhookResponse>('/webhooks', {\n url: options.url,\n events: options.events,\n })\n }\n\n async list(): Promise<EusendResponse<Webhook[]>> {\n const res = await this.client.get<{ data: Webhook[] }>('/webhooks')\n if (res.error) return res\n return { data: res.data.data, error: null, headers: res.headers }\n }\n\n get(id: string): Promise<EusendResponse<WebhookWithDeliveries>> {\n return this.client.get<WebhookWithDeliveries>(`/webhooks/${id}`)\n }\n\n update(id: string, options: UpdateWebhookOptions): Promise<EusendResponse<Webhook>> {\n return this.client.patch<Webhook>(`/webhooks/${id}`, {\n url: options.url,\n events: options.events,\n })\n }\n\n delete(id: string): Promise<EusendResponse<Record<string, never>>> {\n return this.client.delete<Record<string, never>>(`/webhooks/${id}`)\n }\n}\n","import type { Eusend } from './eusend'\nimport type { EusendResponse } from './interfaces'\nimport { renderReactEmail, type ReactEmailElement } from './react-render'\n\n/**\n * `held` is a list send stopped part-way pending review. Unlike `paused` it cannot be\n * resumed by sending again — `send()` returns BROADCAST_HELD until the review clears.\n */\nexport type BroadcastStatus =\n 'draft' | 'scheduled' | 'sending' | 'sent' | 'paused' | 'held' | 'cancelled'\n\nexport interface CreateBroadcastOptions {\n name: string\n audienceId: string\n /** Narrows the audience to the contacts subscribed to this topic. Omit to send to all\n * of it. */\n topicId?: string\n /**\n * Sender address. Accepts a bare email (`onboarding@eusend.dev`) or a display-name\n * form (`Acme <onboarding@eusend.dev>`). The domain must be verified on your account.\n */\n from: string\n /** Where replies go. Same formats as `from`; omit to have replies go to the sender. */\n replyTo?: string\n subject: string\n html?: string\n /**\n * A React Email component. The SDK renders it to HTML locally before sending —\n * the JSX source never travels over the wire. Requires `@react-email/render`\n * and `react` as peer dependencies. Ignored when `html` is also provided.\n */\n react?: ReactEmailElement\n templateId?: string\n templateVariables?: Record<string, string>\n /**\n * Embed the open-tracking pixel for this broadcast. Omit to use your organization's\n * default (Settings → General → Email tracking); `false` always wins over it.\n */\n trackOpens?: boolean\n /**\n * Rewrite links so clicks are recorded. Omit to use your organization's default;\n * `false` leaves the original URLs untouched in the delivered mail.\n */\n trackClicks?: boolean\n}\n\nexport interface UpdateBroadcastOptions {\n name?: string\n audienceId?: string\n /** Pass null to clear the topic and widen the send back to the whole audience. */\n topicId?: string | null\n from?: string\n /** Pass null to clear it, so replies go back to the sender. */\n replyTo?: string | null\n subject?: string\n html?: string\n /**\n * See `react` on CreateBroadcastOptions. Rendered to HTML locally before sending.\n */\n react?: ReactEmailElement\n templateId?: string | null\n templateVariables?: Record<string, string> | null\n scheduledAt?: string | null\n /**\n * Embed the open-tracking pixel for this broadcast. Omit to use your organization's\n * default (Settings → General → Email tracking); `false` always wins over it.\n */\n trackOpens?: boolean\n /**\n * Rewrite links so clicks are recorded. Omit to use your organization's default;\n * `false` leaves the original URLs untouched in the delivered mail.\n */\n trackClicks?: boolean\n}\n\nexport interface SendBroadcastOptions {\n scheduledAt?: string\n}\n\nexport interface Broadcast {\n id: string\n organizationId: string\n name: string\n status: BroadcastStatus\n /** Null when the associated audience has been deleted. */\n audienceId: string | null\n /** The topic this broadcast is scoped to, or null for the whole audience. */\n topicId: string | null\n fromAddress: string\n replyTo: string | null\n subject: string\n html: string | null\n reactSource: string | null\n editorJson: Record<string, unknown> | null\n templateId: string | null\n templateVariables: Record<string, string> | null\n heldReason: string | null\n scheduledAt: string | null\n startedAt: string | null\n completedAt: string | null\n recipientCount: number | null\n sentCount: number | null\n trackOpens: boolean\n trackClicks: boolean\n createdAt: string\n updatedAt: string\n}\n\nexport interface BroadcastListItem {\n id: string\n name: string\n status: BroadcastStatus\n /** Null when the associated audience has been deleted. */\n audienceId: string | null\n topicId: string | null\n topicName: string | null\n fromAddress: string\n subject: string\n recipientCount: number | null\n sentCount: number | null\n scheduledAt: string | null\n startedAt: string | null\n completedAt: string | null\n createdAt: string\n audienceName: string | null\n}\n\nexport interface BroadcastDetail extends Broadcast {\n stats: Record<string, number>\n}\n\nexport interface TestBroadcastOptions {\n /**\n * Up to 5 addresses, each on a domain verified on your account. A test send delivers\n * real mail without the paid-plan gate that `send()` carries, so it is restricted to\n * inboxes you have already proved you control; anything else returns\n * `DOMAIN_NOT_VERIFIED`.\n */\n to: string[]\n}\n\nexport interface TestBroadcastResponse {\n id: string\n /** The addresses actually mailed, lowercased and de-duplicated. */\n sentTo: string[]\n /** One email id per recipient, for looking the delivery up in the logs. */\n emailIds: string[]\n}\n\nexport interface SendBroadcastResponse {\n id: string\n status: 'sending' | 'scheduled'\n scheduledAt: string | null\n}\n\nasync function resolveBroadcastHtml(options: {\n html?: string\n react?: ReactEmailElement\n}): Promise<string | undefined> {\n if (options.html) return options.html\n if (options.react) return renderReactEmail(options.react)\n return undefined\n}\n\nexport class Broadcasts {\n constructor(private readonly client: Eusend) {}\n\n async create(options: CreateBroadcastOptions): Promise<EusendResponse<Broadcast>> {\n const html = await resolveBroadcastHtml(options)\n return this.client.post<Broadcast>('/broadcasts', {\n name: options.name,\n audience_id: options.audienceId,\n topic_id: options.topicId,\n from: options.from,\n reply_to: options.replyTo,\n subject: options.subject,\n html,\n template_id: options.templateId,\n template_variables: options.templateVariables,\n track_opens: options.trackOpens,\n track_clicks: options.trackClicks,\n })\n }\n\n async list(): Promise<EusendResponse<BroadcastListItem[]>> {\n const res = await this.client.get<{ data: BroadcastListItem[] }>('/broadcasts')\n if (res.error) return res\n return { data: res.data.data, error: null, headers: res.headers }\n }\n\n get(id: string): Promise<EusendResponse<BroadcastDetail>> {\n return this.client.get<BroadcastDetail>(`/broadcasts/${id}`)\n }\n\n /**\n * An update that leaves the broadcast scheduled — setting `scheduledAt`, or editing one\n * that already is — runs the same checks as `send()` and can return the same 403s.\n * Unscheduling with `scheduledAt: null` is always allowed.\n */\n async update(id: string, options: UpdateBroadcastOptions): Promise<EusendResponse<Broadcast>> {\n const html = await resolveBroadcastHtml(options)\n return this.client.patch<Broadcast>(`/broadcasts/${id}`, {\n name: options.name,\n audience_id: options.audienceId,\n topic_id: options.topicId,\n from: options.from,\n reply_to: options.replyTo,\n subject: options.subject,\n html,\n template_id: options.templateId,\n template_variables: options.templateVariables,\n scheduled_at: options.scheduledAt,\n track_opens: options.trackOpens,\n track_clicks: options.trackClicks,\n })\n }\n\n async send(\n id: string,\n options: SendBroadcastOptions = {},\n ): Promise<EusendResponse<SendBroadcastResponse>> {\n // This endpoint is the one broadcast response that comes back snake_cased, so\n // map it rather than exposing a `scheduledAt` that is always undefined.\n const res = await this.client.post<{\n id: string\n status: 'sending' | 'scheduled'\n scheduled_at: string | null\n }>(`/broadcasts/${id}/send`, {\n scheduled_at: options.scheduledAt,\n })\n if (res.error) return res\n return {\n data: { id: res.data.id, status: res.data.status, scheduledAt: res.data.scheduled_at },\n error: null,\n headers: res.headers,\n }\n }\n\n /**\n * Send yourself a copy before the campaign goes out — the real message through the real\n * sending path, so it shows what a recipient will see.\n *\n * Works on every plan including Free, unlike `send()`. It costs daily and monthly quota\n * like any other send, and does NOT move the broadcast's status: the campaign stays a\n * draft no matter how many tests you send.\n *\n * Requires a LIVE api key. \"Test\" here means a dress rehearsal, not a sandbox — a\n * `eu_test_` key is refused because the mail really is delivered.\n */\n async test(\n id: string,\n options: TestBroadcastOptions,\n ): Promise<EusendResponse<TestBroadcastResponse>> {\n // Snake-cased on the wire, like the send() response above.\n const res = await this.client.post<{\n id: string\n sent_to: string[]\n email_ids: string[]\n }>(`/broadcasts/${id}/test`, { to: options.to })\n if (res.error) return res\n return {\n data: { id: res.data.id, sentTo: res.data.sent_to, emailIds: res.data.email_ids },\n error: null,\n headers: res.headers,\n }\n }\n\n cancel(id: string): Promise<EusendResponse<Broadcast>> {\n return this.client.post<Broadcast>(`/broadcasts/${id}/cancel`)\n }\n\n delete(id: string): Promise<EusendResponse<Record<string, never>>> {\n return this.client.delete<Record<string, never>>(`/broadcasts/${id}`)\n }\n}\n","import type { Eusend } from './eusend'\nimport type { EusendResponse } from './interfaces'\n\nexport type SuppressionReason = 'bounce' | 'complaint' | 'manual'\n\nexport interface SuppressionEntry {\n id: string\n email: string\n reason: SuppressionReason\n created_at: string\n}\n\nexport interface ListSuppressionsOptions {\n /** Filter to addresses containing this substring. Pass a domain (\"@acme.com\") to see every suppressed address there. */\n email?: string\n reason?: SuppressionReason\n limit?: number\n cursor?: string\n}\n\nexport interface ListSuppressionsResponse {\n data: SuppressionEntry[]\n next_cursor: string | null\n}\n\nexport interface CreateSuppressionOptions {\n email: string\n /** Defaults to 'manual'. An add never overwrites the reason an address is already suppressed for. */\n reason?: SuppressionReason\n}\n\n/** An item in an import — a bare address, or an address with the reason it was suppressed. */\nexport type SuppressionImportItem = string | { email: string; reason?: SuppressionReason }\n\nexport interface ImportSuppressionsResponse {\n /** Entries written. */\n count: number\n /** Entries that were already on the list. */\n already_suppressed: number\n /** Repeated addresses in the payload, collapsed before the write. */\n duplicates: number\n}\n\n/**\n * The addresses your organization will not send to.\n *\n * Hard bounces and spam complaints are added automatically; these methods cover the\n * addresses you manage yourself. Suppression applies to live sending only — test-mode\n * keys can read the list but not modify it.\n */\nexport class Suppressions {\n constructor(private readonly client: Eusend) {}\n\n list(options: ListSuppressionsOptions = {}): Promise<EusendResponse<ListSuppressionsResponse>> {\n const params = new URLSearchParams()\n if (options.email) params.set('email', options.email)\n if (options.reason) params.set('reason', options.reason)\n if (options.limit != null) params.set('limit', String(options.limit))\n if (options.cursor) params.set('cursor', options.cursor)\n const qs = params.toString()\n return this.client.get<ListSuppressionsResponse>(qs ? `/suppressions?${qs}` : '/suppressions')\n }\n\n /**\n * Suppress an address. If it is already suppressed the existing entry is returned\n * unchanged — a manual add never rewrites a real bounce or complaint.\n */\n create(options: CreateSuppressionOptions): Promise<EusendResponse<SuppressionEntry>> {\n return this.client.post<SuppressionEntry>('/suppressions', {\n email: options.email,\n reason: options.reason,\n })\n }\n\n /**\n * Import up to 1000 addresses in one call — for carrying a suppression list over from\n * another provider before your first send. Items may be bare addresses or objects.\n */\n import(emails: SuppressionImportItem[]): Promise<EusendResponse<ImportSuppressionsResponse>> {\n return this.client.post<ImportSuppressionsResponse>('/suppressions/batch', { emails })\n }\n\n /**\n * Un-suppress by entry id or by address, making the address sendable again.\n *\n * Removing an address that hard-bounced or complained is what damages a sender's\n * reputation when done in bulk — remove an entry when the address was fixed or the\n * complaint was a mistake, not to retry a failing list.\n */\n remove(idOrEmail: string): Promise<EusendResponse<{ deleted: number }>> {\n return this.client.delete<{ deleted: number }>(`/suppressions/${encodeURIComponent(idOrEmail)}`)\n }\n\n /** The whole list as CSV (`email,reason,created_at`), for backup or migration. */\n export(): Promise<EusendResponse<string>> {\n return this.client.fetchRequest<string>('/suppressions/export', { method: 'GET' }, {}, 'text')\n }\n}\n","import type { EusendError, EusendResponse } from './interfaces'\nimport { Emails } from './emails'\nimport { Batch } from './batch'\nimport { Domains } from './domains'\nimport { ApiKeys } from './api-keys'\nimport { Audiences } from './audiences'\nimport { ContactProperties } from './contact-properties'\nimport { Topics } from './topics'\nimport { Templates } from './templates'\nimport { Webhooks } from './webhooks'\nimport { Broadcasts } from './broadcasts'\nimport { Suppressions } from './suppressions'\n\nconst DEFAULT_BASE_URL = 'https://api.eusend.dev'\nconst SDK_VERSION = '0.19.0'\n\nexport interface EusendOptions {\n baseUrl?: string\n}\n\nexport class Eusend {\n readonly baseUrl: string\n private readonly apiKey: string\n\n readonly emails: Emails\n /** Batch sending — `client.batch.send([...])`. Mirrors Resend's `resend.batch.send()`. */\n readonly batch: Batch\n readonly domains: Domains\n readonly apiKeys: ApiKeys\n readonly audiences: Audiences\n /** The org's declared contact properties — `client.contactProperties.list()`. */\n readonly contactProperties: ContactProperties\n /** Subscription topics — `client.topics.list()`. */\n readonly topics: Topics\n readonly templates: Templates\n readonly webhooks: Webhooks\n readonly broadcasts: Broadcasts\n readonly suppressions: Suppressions\n\n constructor(key?: string, options?: EusendOptions) {\n const apiKey =\n key ?? (typeof process !== 'undefined' ? process.env['EUSEND_API_KEY'] : undefined)\n if (!apiKey) {\n throw new Error(\n 'Missing Eusend API key. Pass it to the constructor or set the EUSEND_API_KEY environment variable.',\n )\n }\n this.apiKey = apiKey\n this.baseUrl = options?.baseUrl ?? DEFAULT_BASE_URL\n\n this.emails = new Emails(this)\n this.batch = new Batch(this)\n this.domains = new Domains(this)\n this.apiKeys = new ApiKeys(this)\n this.audiences = new Audiences(this)\n this.contactProperties = new ContactProperties(this)\n this.topics = new Topics(this)\n this.templates = new Templates(this)\n this.webhooks = new Webhooks(this)\n this.broadcasts = new Broadcasts(this)\n this.suppressions = new Suppressions(this)\n }\n\n async fetchRequest<T>(\n path: string,\n init: RequestInit = {},\n extraHeaders: Record<string, string> = {},\n // Not every successful endpoint answers with JSON — the suppression export returns\n // CSV. Parsing that as JSON throws inside the try below, which would surface a\n // perfectly good download as \"Network request failed\".\n parse: 'json' | 'text' = 'json',\n ): Promise<EusendResponse<T>> {\n const headers: Record<string, string> = {\n Authorization: `Bearer ${this.apiKey}`,\n 'Content-Type': 'application/json',\n 'User-Agent': `eusend-node/${SDK_VERSION}`,\n ...extraHeaders,\n }\n\n try {\n const res = await fetch(`${this.baseUrl}${path}`, { ...init, headers })\n const responseHeaders = Object.fromEntries(res.headers.entries())\n\n if (!res.ok) {\n let error: EusendError\n try {\n const json = (await res.json()) as { error?: string; code?: string }\n error = {\n message: json.error ?? 'Unknown error',\n statusCode: res.status,\n name: (json.code as EusendError['name']) ?? 'INTERNAL_ERROR',\n }\n } catch {\n error = { message: 'Request failed', statusCode: res.status, name: 'INTERNAL_ERROR' }\n }\n return { data: null, error, headers: responseHeaders }\n }\n\n if (res.status === 204 || res.headers.get('content-length') === '0') {\n return { data: {} as T, error: null, headers: responseHeaders }\n }\n\n const data = (parse === 'text' ? await res.text() : await res.json()) as T\n return { data, error: null, headers: responseHeaders }\n } catch {\n return {\n data: null,\n error: {\n message: 'Network request failed. The request could not be resolved.',\n statusCode: null,\n name: 'application_error',\n },\n headers: null,\n }\n }\n }\n\n get<T>(path: string, extraHeaders?: Record<string, string>): Promise<EusendResponse<T>> {\n return this.fetchRequest<T>(path, { method: 'GET' }, extraHeaders)\n }\n\n post<T>(\n path: string,\n body?: unknown,\n extraHeaders?: Record<string, string>,\n ): Promise<EusendResponse<T>> {\n return this.fetchRequest<T>(\n path,\n { method: 'POST', body: body != null ? JSON.stringify(body) : undefined },\n extraHeaders,\n )\n }\n\n patch<T>(path: string, body?: unknown): Promise<EusendResponse<T>> {\n return this.fetchRequest<T>(path, {\n method: 'PATCH',\n body: body != null ? JSON.stringify(body) : undefined,\n })\n }\n\n put<T>(path: string, body?: unknown): Promise<EusendResponse<T>> {\n return this.fetchRequest<T>(path, {\n method: 'PUT',\n body: body != null ? JSON.stringify(body) : undefined,\n })\n }\n\n delete<T>(path: string): Promise<EusendResponse<T>> {\n return this.fetchRequest<T>(path, { method: 'DELETE' })\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.mjs","names":[],"sources":["../src/react-render.ts","../src/emails.ts","../src/batch.ts","../src/domains.ts","../src/api-keys.ts","../src/audiences.ts","../src/contact-properties.ts","../src/topics.ts","../src/templates.ts","../src/webhooks.ts","../src/broadcasts.ts","../src/suppressions.ts","../src/reputation.ts","../src/eusend.ts"],"sourcesContent":["// Minimal structural type so the SDK doesn't take a hard dependency on `react`.\n// Real React elements assignable to this; users who pass `react:` are expected to\n// have `react` and `@react-email/render` installed (declared as optional peers).\nexport type ReactEmailElement = {\n readonly type: unknown\n readonly props: unknown\n readonly key: string | number | null\n}\n\nlet renderPromise: Promise<(element: ReactEmailElement) => Promise<string>> | null = null\n\nasync function getRender(): Promise<(element: ReactEmailElement) => Promise<string>> {\n if (!renderPromise) {\n renderPromise = (async () => {\n try {\n const mod = (await import('@react-email/render')) as {\n render: (element: unknown, options?: { plainText?: boolean }) => Promise<string> | string\n }\n return (element: ReactEmailElement) => Promise.resolve(mod.render(element))\n } catch {\n throw new Error(\n 'Passing `react:` requires `@react-email/render` and `react` to be installed. ' +\n 'Run: npm install @react-email/render react',\n )\n }\n })()\n }\n return renderPromise\n}\n\nexport async function renderReactEmail(element: ReactEmailElement): Promise<string> {\n const render = await getRender()\n return render(element)\n}\n","import type { Eusend } from './eusend'\nimport type { EusendErrorCode, EusendResponse } from './interfaces'\nimport { renderReactEmail, type ReactEmailElement } from './react-render'\n\nexport type EmailStatus =\n | 'queued'\n | 'scheduled'\n | 'canceled'\n | 'sending'\n | 'sent'\n | 'delivered'\n | 'bounced'\n | 'complained'\n | 'suppressed'\n | 'failed'\n\nexport type EmailEventType = 'sent' | 'delivered' | 'opened' | 'clicked' | 'bounced' | 'complained'\n\nexport interface Attachment {\n /** Name the recipient sees for the file, e.g. `invoice.pdf`. */\n filename: string\n /**\n * File contents. A base64-encoded string (sent as-is) or raw bytes\n * (`Uint8Array`/`Buffer`), which the SDK base64-encodes for you. Provide either\n * `content` or `path`, not both.\n */\n content?: string | Uint8Array\n /**\n * A URL the server fetches at send time to attach the file. Use instead of\n * `content` when the bytes live on a public URL. Provide either `content` or `path`,\n * not both.\n */\n path?: string\n /** MIME type, e.g. `application/pdf`. Inferred from the filename when omitted. */\n contentType?: string\n /**\n * Content-ID for an inline attachment. Set it to reference the file from your\n * HTML with `<img src=\"cid:<contentId>\">` instead of showing it as a download.\n */\n contentId?: string\n}\n\n/** A single tag in the `[{ name, value }]` form, for Resend-compatible payloads. */\nexport interface EmailTag {\n name: string\n value: string\n}\n\n/**\n * Labels attached to a send, used to filter your email log and to route webhook events.\n *\n * Accepts either a plain object (`{ category: 'password_reset' }`) or the\n * `[{ name, value }]` array form, so a payload written against Resend works unchanged.\n * Responses and webhook payloads always return the object form.\n *\n * Names and values may contain ASCII letters, numbers, underscores and dashes; up to 10\n * tags per email.\n */\nexport type EmailTags = Record<string, string> | EmailTag[]\n\nexport interface SendEmailOptions {\n /**\n * Sender address. Accepts a bare email (`onboarding@eusend.dev`) or a display-name\n * form (`Acme <onboarding@eusend.dev>`). The domain must be verified on your account.\n */\n from: string\n to: string | string[]\n cc?: string | string[]\n bcc?: string | string[]\n replyTo?: string | string[]\n subject?: string\n html?: string\n text?: string\n /**\n * A React Email component. The SDK renders it to HTML locally before sending\n * — the JSX source never travels over the wire. Requires `@react-email/render`\n * and `react` as peer dependencies. Ignored when `html` is also provided.\n */\n react?: ReactEmailElement\n templateId?: string\n variables?: Record<string, unknown>\n headers?: Record<string, string>\n /**\n * Labels for log filtering and webhook routing, e.g.\n * `{ category: 'password_reset', tier: 'pro' }`. Returned on every `email.*` webhook\n * event for this send.\n */\n tags?: EmailTags\n /**\n * Embed an open-tracking pixel. Omit to use your organization's default (Settings →\n * General → Email tracking), which is off unless you changed it.\n */\n trackOpens?: boolean\n /**\n * Rewrite links through eusend so clicks are recorded. Omit to use your organization's\n * default, which is off unless you changed it. Rewritten links can hurt inbox placement,\n * so leave this off for sign-in links and password resets.\n */\n trackClicks?: boolean\n /** File attachments. Up to 20 per message, 10 MB combined. */\n attachments?: Attachment[]\n /**\n * Schedule the send for a future time, at most 30 days out. Accepts a `Date`, an\n * ISO 8601 string, or a natural-language time like `\"in 1 hour\"` or `\"tomorrow at\n * 9am\"` (parsed server-side, same as Resend). Relative phrasings resolve against the\n * server clock in UTC — pass an offset-qualified ISO string when you need an exact\n * instant. The email is created with status `scheduled`; reschedule it with\n * `emails.update()` or call `emails.cancel()` any time before it sends.\n */\n scheduledAt?: string | Date\n}\n\nexport interface SendEmailRequestOptions {\n idempotencyKey?: string\n}\n\nexport interface SendEmailResponse {\n id: string\n}\n\n/**\n * Per-item outcome of a batch send, positionally mapped to the input array:\n * `data[i]` describes `emails[i]`. Items that were queued carry `{ id }`; items\n * that could not be queued carry `{ error, code }` (e.g. an unverified sender\n * domain, all recipients suppressed, or an exhausted send quota). Branch on the\n * presence of `id`.\n */\nexport type BatchItemResult =\n { id: string; error?: never; code?: never } | { id?: never; error: string; code: EusendErrorCode }\n\nexport interface BatchSendResponse {\n data: BatchItemResult[]\n}\n\nexport interface EmailEvent {\n id: string\n type: EmailEventType\n metadata: Record<string, unknown>\n createdAt: string\n}\n\nexport interface Email {\n id: string\n from: string\n to: string[]\n cc: string[]\n bcc: string[]\n replyTo: string[]\n subject: string\n html: string | null\n text: string | null\n status: EmailStatus\n /** Always the object form, `{}` when the send carried no tags. */\n tags: Record<string, string>\n testMode: boolean\n templateId: string | null\n /** Set only for scheduled sends. */\n scheduledAt: string | null\n createdAt: string\n events: EmailEvent[]\n}\n\nexport interface UpdateEmailOptions {\n /** The new send time, at most 30 days out — a `Date`, an ISO 8601 string, or natural\n * language like `\"in 1 hour\"` (parsed server-side, same as `emails.send`). */\n scheduledAt: string | Date\n}\n\nexport interface UpdateEmailResponse {\n id: string\n status: 'scheduled'\n scheduledAt: string\n}\n\nexport interface CancelEmailResponse {\n id: string\n status: 'canceled'\n}\n\nexport interface EmailListItem {\n id: string\n from: string\n to: string[]\n subject: string\n status: EmailStatus\n /** Always the object form, `{}` when the send carried no tags. */\n tags: Record<string, string>\n testMode: boolean\n createdAt: string\n}\n\nexport interface ListEmailsOptions {\n limit?: number\n cursor?: string\n status?: EmailStatus\n from?: string\n to?: string\n /**\n * Filter by tag. `'category:password_reset'` matches that exact pair; a bare\n * `'category'` matches any email carrying the tag. Pass an array to require several.\n */\n tag?: string | string[]\n}\n\nexport interface ListEmailsResponse {\n data: EmailListItem[]\n nextCursor: string | null\n}\n\nasync function resolveHtml(options: SendEmailOptions): Promise<string | undefined> {\n if (options.html) return options.html\n if (options.react) return renderReactEmail(options.react)\n return undefined\n}\n\nfunction encodeAttachmentContent(content: string | Uint8Array): string {\n // A string is assumed to already be base64. Raw bytes are encoded here.\n if (typeof content === 'string') return content\n if (typeof Buffer !== 'undefined') return Buffer.from(content).toString('base64')\n let binary = ''\n for (const byte of content) binary += String.fromCharCode(byte)\n return btoa(binary)\n}\n\nfunction toIsoString(value: string | Date): string {\n return value instanceof Date ? value.toISOString() : value\n}\n\nexport async function toApiPayload(options: SendEmailOptions) {\n const html = await resolveHtml(options)\n return {\n from: options.from,\n to: options.to,\n cc: options.cc,\n bcc: options.bcc,\n reply_to: options.replyTo,\n subject: options.subject,\n html,\n text: options.text,\n template_id: options.templateId,\n variables: options.variables,\n headers: options.headers,\n tags: options.tags,\n track_opens: options.trackOpens,\n track_clicks: options.trackClicks,\n attachments: options.attachments?.map((a) => ({\n filename: a.filename,\n content: a.content === undefined ? undefined : encodeAttachmentContent(a.content),\n path: a.path,\n content_type: a.contentType,\n content_id: a.contentId,\n })),\n scheduled_at: options.scheduledAt ? toIsoString(options.scheduledAt) : undefined,\n }\n}\n\nexport class Emails {\n constructor(private readonly client: Eusend) {}\n\n async send(\n options: SendEmailOptions,\n requestOptions?: SendEmailRequestOptions,\n ): Promise<EusendResponse<SendEmailResponse>> {\n const extraHeaders: Record<string, string> = {}\n if (requestOptions?.idempotencyKey) {\n extraHeaders['Idempotency-Key'] = requestOptions.idempotencyKey\n }\n const payload = await toApiPayload(options)\n return this.client.post<SendEmailResponse>('/emails', payload, extraHeaders)\n }\n\n async list(options: ListEmailsOptions = {}): Promise<EusendResponse<ListEmailsResponse>> {\n const params = new URLSearchParams()\n if (options.limit != null) params.set('limit', String(options.limit))\n if (options.cursor) params.set('cursor', options.cursor)\n if (options.status) params.set('status', options.status)\n if (options.from) params.set('from', options.from)\n if (options.to) params.set('to', options.to)\n // Repeated `tag` params, one per filter — the API ANDs them.\n for (const tag of options.tag == null ? [] : [options.tag].flat()) {\n params.append('tag', tag)\n }\n const qs = params.toString()\n\n const res = await this.client.get<{ data: EmailListItem[]; next_cursor: string | null }>(\n qs ? `/emails?${qs}` : '/emails',\n )\n if (res.error) return res\n return {\n data: { data: res.data.data, nextCursor: res.data.next_cursor },\n error: null,\n headers: res.headers,\n }\n }\n\n get(id: string): Promise<EusendResponse<Email>> {\n return this.client.get<Email>(`/emails/${id}`)\n }\n\n /**\n * Reschedule a scheduled email. Fails once the email has started sending, and returns\n * 429 `DAILY_LIMIT_EXCEEDED` when the new day's sending quota is already used up.\n */\n async update(\n id: string,\n options: UpdateEmailOptions,\n ): Promise<EusendResponse<UpdateEmailResponse>> {\n const res = await this.client.patch<{ id: string; status: 'scheduled'; scheduled_at: string }>(\n `/emails/${id}`,\n { scheduled_at: toIsoString(options.scheduledAt) },\n )\n if (res.error) return res\n return {\n data: { id: res.data.id, status: res.data.status, scheduledAt: res.data.scheduled_at },\n error: null,\n headers: res.headers,\n }\n }\n\n /** Cancel a scheduled email. Fails once the email has started sending. */\n cancel(id: string): Promise<EusendResponse<CancelEmailResponse>> {\n return this.client.post<CancelEmailResponse>(`/emails/${id}/cancel`, undefined)\n }\n}\n","import type { Eusend } from './eusend'\nimport type { EusendResponse } from './interfaces'\nimport {\n toApiPayload,\n type SendEmailOptions,\n type SendEmailRequestOptions,\n type BatchSendResponse,\n} from './emails'\n\n/**\n * Batch sending — `eusend.batch.send([...])`. The method path mirrors Resend's\n * `resend.batch.send([...])`, so migrating is a mechanical `resend` → `eusend` rename.\n * The HTTP body is a top-level array of email objects (POST /emails/batch), up to 100\n * per request. As with Resend, attachments and `scheduledAt` are not supported on the\n * batch endpoint — send those individually via `emails.send`.\n *\n * The response maps positionally to the input: `data[i]` is `{ id }` when\n * `emails[i]` was queued, or `{ error, code }` when it was not (unverified\n * domain, suppressed recipients, exhausted quota, …) — failed items never fail\n * the whole batch, so branch on the presence of `id` per item.\n *\n * Pass `{ idempotencyKey }` to retry safely: the key is applied per item by position, so\n * a retry must keep the items in the same order or it will match the wrong emails.\n */\nexport class Batch {\n constructor(private readonly client: Eusend) {}\n\n async send(\n emails: SendEmailOptions[],\n requestOptions?: SendEmailRequestOptions,\n ): Promise<EusendResponse<BatchSendResponse>> {\n const extraHeaders: Record<string, string> = {}\n if (requestOptions?.idempotencyKey) {\n extraHeaders['Idempotency-Key'] = requestOptions.idempotencyKey\n }\n const payloads = await Promise.all(emails.map(toApiPayload))\n return this.client.post<BatchSendResponse>('/emails/batch', payloads, extraHeaders)\n }\n}\n","import type { Eusend } from './eusend'\nimport type { EusendResponse } from './interfaces'\n\nexport type DomainStatus = 'pending' | 'verified' | 'failed'\n\nexport interface DnsRecord {\n type: string\n name: string\n value: string\n /** MX records only. */\n priority?: number\n /**\n * `authentication` — required before the domain can send.\n * `policy` — recommended; absence weakens but does not block.\n * `alignment` — optional; publishing all of them enables Return-Path SPF alignment.\n */\n purpose?: string\n description?: string\n}\n\nexport interface CreateDomainResponse {\n id: string\n name: string\n /**\n * Every record to publish, in presentation order. Prefer this over the individual\n * keys below — it is the only place the optional Return-Path alignment records appear.\n */\n records: DnsRecord[]\n dkim: DnsRecord\n dmarc: DnsRecord\n}\n\nexport interface DomainListItem {\n id: string\n name: string\n status: DomainStatus\n createdAt: string\n}\n\n/** Whether a verification chain is polling DNS for this domain right now. */\nexport interface DomainVerification {\n running: boolean\n /** When the running chain started, or null when none is. */\n startedAt: string | null\n}\n\n/**\n * What the last unmatched DNS check found, when it found a mistake rather than an absence.\n *\n * `code` is the mistake: `doubled_domain` (the record sits under the domain twice, because the\n * control panel appends it to whatever you type), `truncated_key` (the value was cut at the\n * 255-character limit for a single DNS string instead of being split into two), `foreign_key`\n * (a DKIM key we did not issue is published at the selector), `quoted_value`, `multiple_records`,\n * `cname_at_selector`. New codes may be added, so treat an unknown one as generic.\n */\nexport interface DomainDiagnostic {\n code: string\n /** The name the record was actually found at, for `doubled_domain`. */\n foundAt?: string\n /** How much of the key is published, and how much there is, for `truncated_key`. */\n publishedChars?: number\n expectedChars?: number\n /** Where the CNAME points, for `cname_at_selector`. */\n target?: string\n /** The DNS host serving the zone, when its nameservers named one we recognise. */\n provider?: {\n id: string\n label: string\n /** Path to the guide for this panel on eusend.dev, or null where there is none. */\n guide: string | null\n }\n}\n\nexport interface Domain {\n id: string\n name: string\n dkimPublicKey: string\n dkimSelector: string\n status: DomainStatus\n createdAt: string\n verifiedAt: string | null\n verification: DomainVerification\n /** Null while nothing is wrong beyond the records not having propagated yet. */\n diagnostic: DomainDiagnostic | null\n}\n\nexport interface DeleteDomainResponse {\n message: string\n /** Scheduled emails from this domain that were canceled because it can no longer send. */\n canceled_scheduled_emails: number\n}\n\nexport class Domains {\n constructor(private readonly client: Eusend) {}\n\n create(name: string): Promise<EusendResponse<CreateDomainResponse>> {\n return this.client.post<CreateDomainResponse>('/domains', { name })\n }\n\n list(): Promise<EusendResponse<DomainListItem[]>> {\n return this.client.get<DomainListItem[]>('/domains')\n }\n\n get(id: string): Promise<EusendResponse<Domain>> {\n return this.client.get<Domain>(`/domains/${id}`)\n }\n\n delete(id: string): Promise<EusendResponse<DeleteDomainResponse>> {\n return this.client.delete<DeleteDomainResponse>(`/domains/${id}`)\n }\n\n verify(id: string): Promise<EusendResponse<{ message: string }>> {\n return this.client.post<{ message: string }>(`/domains/${id}/verify`)\n }\n}\n","import type { Eusend } from './eusend'\nimport type { EusendResponse } from './interfaces'\n\n/**\n * What a key may reach. `full_access` is every resource; `sending_access` is limited to\n * sending email (and rescheduling or canceling a scheduled send).\n */\nexport type ApiKeyPermission = 'full_access' | 'sending_access'\n\nexport interface CreateApiKeyOptions {\n name: string\n testMode?: boolean\n /** Defaults to `full_access`. */\n permission?: ApiKeyPermission\n /**\n * Restrict the key to sending from a single domain. Only valid together with\n * `permission: 'sending_access'`; omit for any verified domain.\n */\n domainId?: string\n}\n\nexport interface CreateApiKeyResponse {\n id: string\n name: string\n key: string\n prefix: string\n testMode: boolean\n permission: ApiKeyPermission\n domainId: string | null\n domainName: string | null\n createdAt: string\n}\n\nexport interface ApiKey {\n id: string\n name: string\n prefix: string\n testMode: boolean\n permission: ApiKeyPermission\n domainId: string | null\n domainName: string | null\n createdAt: string\n lastUsedAt: string | null\n}\n\ntype CreateApiKeyApiResponse = {\n id: string\n name: string\n key: string\n prefix: string\n test_mode: boolean\n permission: ApiKeyPermission\n domain_id: string | null\n domain_name: string | null\n created_at: string\n}\n\nexport class ApiKeys {\n constructor(private readonly client: Eusend) {}\n\n async create(options: CreateApiKeyOptions): Promise<EusendResponse<CreateApiKeyResponse>> {\n const res = await this.client.post<CreateApiKeyApiResponse>('/api-keys', {\n name: options.name,\n test_mode: options.testMode ?? false,\n permission: options.permission ?? 'full_access',\n ...(options.domainId ? { domain_id: options.domainId } : {}),\n })\n if (res.error) return res\n return {\n data: {\n id: res.data.id,\n name: res.data.name,\n key: res.data.key,\n prefix: res.data.prefix,\n testMode: res.data.test_mode,\n permission: res.data.permission,\n domainId: res.data.domain_id,\n domainName: res.data.domain_name,\n createdAt: res.data.created_at,\n },\n error: null,\n headers: res.headers,\n }\n }\n\n list(): Promise<EusendResponse<ApiKey[]>> {\n return this.client.get<ApiKey[]>('/api-keys')\n }\n\n delete(id: string): Promise<EusendResponse<{ message: string }>> {\n return this.client.delete<{ message: string }>(`/api-keys/${id}`)\n }\n}\n","import type { Eusend } from './eusend'\nimport type { EusendResponse } from './interfaces'\n\nexport type ContactStatus = 'subscribed' | 'unsubscribed'\n\nexport interface Audience {\n id: string\n name: string\n organizationId: string\n createdAt: string\n updatedAt: string\n}\n\nexport interface AudienceListItem {\n id: string\n name: string\n createdAt: string\n contactCount: number\n}\n\nexport interface AudienceDetail extends AudienceListItem {\n updatedAt: string\n}\n\nexport interface UpdateAudienceOptions {\n name: string\n}\n\nexport interface Contact {\n id: string\n audienceId: string\n email: string\n firstName: string | null\n lastName: string | null\n /** Custom properties, available as `{{key}}` in a broadcast body. */\n properties: Record<string, string>\n status: ContactStatus\n unsubscribedAt: string | null\n createdAt: string\n updatedAt: string\n}\n\nexport interface CreateContactOptions {\n email: string\n firstName?: string\n lastName?: string\n /**\n * Custom properties, merged into the `{{variable}}` map when a broadcast renders, so\n * `{ plan: 'pro' }` makes `{{plan}}` resolve to `pro`.\n *\n * Values are strings; keys are lowercase letters, digits and underscores, starting with\n * a letter (at most 40 characters, 20 properties per contact). `email`, `name`,\n * `first_name`, `last_name` and `full_name` are built in and cannot be used.\n *\n * Sending this REPLACES the contact's properties. Omitting it on `createContact` clears\n * them; omitting it on `updateContact` leaves them untouched.\n */\n properties?: Record<string, string>\n}\n\nexport interface UpdateContactOptions {\n firstName?: string\n lastName?: string\n unsubscribed?: boolean\n /** Replaces the contact's custom properties. Omit to leave them unchanged; pass `{}` to\n * clear them. See {@link CreateContactOptions.properties} for the naming rules. */\n properties?: Record<string, string>\n}\n\nexport interface ListContactsOptions {\n limit?: number\n cursor?: string\n search?: string\n subscribed?: boolean\n}\n\nexport interface ListContactsResponse {\n data: Contact[]\n nextCursor: string | null\n}\n\n/**\n * A contact in a bulk import. Extends the single-create shape with the two fields that\n * only make sense when migrating a list in from somewhere else.\n */\nexport interface BatchContactOptions extends CreateContactOptions {\n /**\n * Mark the contact as opted out, so a list moved from another provider keeps its\n * unsubscribes. An import can only ever ADD an opt-out: passing `false` will not\n * re-subscribe someone who has already unsubscribed. Use `updateContact` for that,\n * one contact at a time.\n */\n unsubscribed?: boolean\n /** Original signup time (ISO 8601). Applied on insert only — an existing contact\n * keeps the date it already has. */\n createdAt?: string\n /**\n * Unlike `createContact`, an import MERGES properties into whatever the contact already\n * has — a CSV carrying only `plan` will not drop a `company` an earlier import set. To\n * replace the whole object, use `updateContact`.\n */\n properties?: Record<string, string>\n}\n\nexport interface BatchCreateContactsOptions {\n contacts: BatchContactOptions[]\n}\n\nexport class Audiences {\n constructor(private readonly client: Eusend) {}\n\n create(name: string): Promise<EusendResponse<Audience>> {\n return this.client.post<Audience>('/audiences', { name })\n }\n\n async list(): Promise<EusendResponse<AudienceListItem[]>> {\n const res = await this.client.get<{ data: AudienceListItem[] }>('/audiences')\n if (res.error) return res\n return { data: res.data.data, error: null, headers: res.headers }\n }\n\n get(id: string): Promise<EusendResponse<AudienceDetail>> {\n return this.client.get<AudienceDetail>(`/audiences/${id}`)\n }\n\n /** Rename an audience. */\n update(id: string, options: UpdateAudienceOptions): Promise<EusendResponse<Audience>> {\n return this.client.patch<Audience>(`/audiences/${id}`, { name: options.name })\n }\n\n delete(id: string): Promise<EusendResponse<Record<string, never>>> {\n return this.client.delete<Record<string, never>>(`/audiences/${id}`)\n }\n\n createContact(\n audienceId: string,\n options: CreateContactOptions,\n ): Promise<EusendResponse<Contact>> {\n return this.client.post<Contact>(`/audiences/${audienceId}/contacts`, {\n email: options.email,\n first_name: options.firstName,\n last_name: options.lastName,\n properties: options.properties,\n })\n }\n\n async listContacts(\n audienceId: string,\n options: ListContactsOptions = {},\n ): Promise<EusendResponse<ListContactsResponse>> {\n const params = new URLSearchParams()\n if (options.limit != null) params.set('limit', String(options.limit))\n if (options.cursor) params.set('cursor', options.cursor)\n if (options.search) params.set('search', options.search)\n if (options.subscribed != null) params.set('subscribed', String(options.subscribed))\n const qs = params.toString()\n return this.client.get<ListContactsResponse>(\n qs ? `/audiences/${audienceId}/contacts?${qs}` : `/audiences/${audienceId}/contacts`,\n )\n }\n\n getContact(audienceId: string, contactId: string): Promise<EusendResponse<Contact>> {\n return this.client.get<Contact>(`/audiences/${audienceId}/contacts/${contactId}`)\n }\n\n updateContact(\n audienceId: string,\n contactId: string,\n options: UpdateContactOptions,\n ): Promise<EusendResponse<Contact>> {\n return this.client.patch<Contact>(`/audiences/${audienceId}/contacts/${contactId}`, {\n first_name: options.firstName,\n last_name: options.lastName,\n unsubscribed: options.unsubscribed,\n properties: options.properties,\n })\n }\n\n deleteContact(\n audienceId: string,\n contactId: string,\n ): Promise<EusendResponse<Record<string, never>>> {\n return this.client.delete<Record<string, never>>(\n `/audiences/${audienceId}/contacts/${contactId}`,\n )\n }\n\n /**\n * Upsert up to 1000 contacts in one call. Addresses are lowercased and\n * de-duplicated server-side; `count` is the number of rows written and\n * `duplicates` how many repeated addresses were collapsed to get there.\n */\n /**\n * Delete up to 1,000 contacts from an audience by id.\n *\n * `deleted` may be lower than the number of ids sent — an id may already be gone, or\n * may belong to another audience — so a retry after a dropped response settles at 0\n * rather than failing.\n *\n * This is not an unsubscribe. It removes them from the audience without adding them to\n * the suppression list; use `updateContact({ unsubscribed: true })` to stop mailing\n * somebody while keeping the record.\n */\n batchDeleteContacts(\n audienceId: string,\n contactIds: string[],\n ): Promise<EusendResponse<{ deleted: number }>> {\n return this.client.post<{ deleted: number }>(\n `/audiences/${audienceId}/contacts/batch-delete`,\n { contact_ids: contactIds },\n )\n }\n\n batchCreateContacts(\n audienceId: string,\n options: BatchCreateContactsOptions,\n ): Promise<EusendResponse<{ count: number; duplicates: number }>> {\n return this.client.post<{ count: number; duplicates: number }>(\n `/audiences/${audienceId}/contacts/batch`,\n {\n contacts: options.contacts.map((c) => ({\n email: c.email,\n first_name: c.firstName,\n last_name: c.lastName,\n unsubscribed: c.unsubscribed,\n created_at: c.createdAt,\n properties: c.properties,\n })),\n },\n )\n }\n}\n","import type { Eusend } from './eusend'\nimport type { EusendResponse } from './interfaces'\n\n/**\n * A declared property's type. Values are carried and rendered as strings either way —\n * `number` buys a write-time check, not arithmetic or locale formatting.\n */\nexport type ContactPropertyType = 'string' | 'number'\n\nexport interface ContactProperty {\n id: string\n key: string\n type: ContactPropertyType\n /** Substituted into `{{key}}` for contacts that carry no value of their own. `null`\n * renders empty, which is what an unset property did before the registry existed. */\n fallbackValue: string | null\n createdAt: string\n updatedAt: string\n}\n\nexport interface CreateContactPropertyOptions {\n /** Lowercase letters, digits and underscores, starting with a letter; at most 40\n * characters. `email`, `name`, `first_name`, `last_name` and `full_name` are built in\n * and cannot be declared. */\n key: string\n /** Defaults to `string`. */\n type?: ContactPropertyType\n fallbackValue?: string | null\n}\n\nexport interface UpdateContactPropertyOptions {\n /** The only mutable field. `key` and `type` are fixed at creation: a rename would have\n * to rewrite every contact and every broadcast body spelling `{{old_key}}`, so changing\n * either is a delete and a create. */\n fallbackValue: string | null\n}\n\nexport interface DeleteContactPropertyResponse {\n deleted: true\n /** How many contacts had the key stripped from them. */\n contactsUpdated: number\n}\n\n/**\n * The organization's custom contact properties — the schema behind the `properties` bag\n * each contact carries.\n *\n * Declaring a property is optional. A property arriving on a contact write that has never\n * been declared registers itself as a `string`, so an existing integration needs no\n * changes. Declaring one up front is what buys a type check and a fallback value.\n */\nexport class ContactProperties {\n constructor(private readonly client: Eusend) {}\n\n create(options: CreateContactPropertyOptions): Promise<EusendResponse<ContactProperty>> {\n return this.client.post<ContactProperty>('/contact-properties', {\n key: options.key,\n type: options.type,\n fallback_value: options.fallbackValue,\n })\n }\n\n /** Every property the organization has defined. Unpaginated — the registry is capped at\n * 100 entries, and a variable picker wants all of them. */\n async list(): Promise<EusendResponse<ContactProperty[]>> {\n const res = await this.client.get<{ data: ContactProperty[] }>('/contact-properties')\n if (res.error) return res\n return { data: res.data.data, error: null, headers: res.headers }\n }\n\n get(id: string): Promise<EusendResponse<ContactProperty>> {\n return this.client.get<ContactProperty>(`/contact-properties/${id}`)\n }\n\n update(\n id: string,\n options: UpdateContactPropertyOptions,\n ): Promise<EusendResponse<ContactProperty>> {\n return this.client.patch<ContactProperty>(`/contact-properties/${id}`, {\n fallback_value: options.fallbackValue,\n })\n }\n\n /**\n * Delete a property definition AND strip the key from every contact in the organization.\n *\n * Destructive and not undoable. Leaving the values in place was the alternative, and a\n * worse one: the property would keep rendering in broadcasts, and the next contact write\n * carrying that key would register it again.\n */\n delete(id: string): Promise<EusendResponse<DeleteContactPropertyResponse>> {\n return this.client.delete<DeleteContactPropertyResponse>(`/contact-properties/${id}`)\n }\n}\n","import type { Eusend } from './eusend'\nimport type { EusendResponse } from './interfaces'\n\n/** What a contact who has never expressed a preference receives. Fixed at creation. */\nexport type TopicDefaultSubscription = 'opt_in' | 'opt_out'\n\n/** Whether the topic is listed on the unsubscribe page to a contact who is not opted in. */\nexport type TopicVisibility = 'public' | 'private'\n\nexport interface Topic {\n id: string\n name: string\n description: string | null\n defaultSubscription: TopicDefaultSubscription\n visibility: TopicVisibility\n /** Contacts who explicitly opted in. Present on list and create, not on get. */\n subscriberCount?: number\n createdAt: string\n updatedAt: string\n}\n\nexport interface CreateTopicOptions {\n name: string\n /** `opt_in` reaches everyone until they leave; `opt_out` reaches nobody until they join.\n * Cannot be changed afterwards. */\n defaultSubscription: TopicDefaultSubscription\n description?: string | null\n /** Defaults to `private`. */\n visibility?: TopicVisibility\n}\n\n/** `defaultSubscription` is absent deliberately — it is fixed at creation. */\nexport interface UpdateTopicOptions {\n name?: string\n description?: string | null\n visibility?: TopicVisibility\n}\n\nexport interface DeleteTopicResponse {\n id: string\n deleted: true\n}\n\nexport interface TopicSubscriptionResponse {\n topicId: string\n contactId: string\n subscribed: boolean\n}\n\nexport interface ClearTopicSubscriptionResponse {\n topicId: string\n contactId: string\n deleted: true\n}\n\nexport class Topics {\n constructor(private readonly client: Eusend) {}\n\n create(options: CreateTopicOptions): Promise<EusendResponse<Topic>> {\n return this.client.post<Topic>('/topics', {\n name: options.name,\n default_subscription: options.defaultSubscription,\n description: options.description,\n visibility: options.visibility,\n })\n }\n\n /** Every topic the organization has defined. Unpaginated — the list is capped at 100,\n * and both the composer's picker and the unsubscribe page want all of it. */\n async list(): Promise<EusendResponse<Topic[]>> {\n const res = await this.client.get<{ data: Topic[] }>('/topics')\n if (res.error) return res\n return { data: res.data.data, error: null, headers: res.headers }\n }\n\n get(id: string): Promise<EusendResponse<Topic>> {\n return this.client.get<Topic>(`/topics/${id}`)\n }\n\n update(id: string, options: UpdateTopicOptions): Promise<EusendResponse<Topic>> {\n return this.client.patch<Topic>(`/topics/${id}`, {\n name: options.name,\n description: options.description,\n visibility: options.visibility,\n })\n }\n\n /** Deletes the topic and every stored preference for it. A draft broadcast scoped to it\n * widens back to its whole audience; returns 409 while a broadcast that is scheduled or\n * has not finished sending still uses the topic. */\n delete(id: string): Promise<EusendResponse<DeleteTopicResponse>> {\n return this.client.delete<DeleteTopicResponse>(`/topics/${id}`)\n }\n\n /** Record an explicit preference for one contact. */\n subscribe(\n topicId: string,\n contactId: string,\n subscribed = true,\n ): Promise<EusendResponse<TopicSubscriptionResponse>> {\n return this.client.put<TopicSubscriptionResponse>(\n `/topics/${topicId}/contacts/${contactId}`,\n { subscribed },\n )\n }\n\n /**\n * Forget the contact's explicit choice, so they fall back to the topic's default.\n *\n * Different from `subscribe(id, contactId, false)`: that records \"no thanks\", this\n * records nothing at all — so on an opt-in topic the contact starts receiving it again.\n */\n clearSubscription(\n topicId: string,\n contactId: string,\n ): Promise<EusendResponse<ClearTopicSubscriptionResponse>> {\n return this.client.delete<ClearTopicSubscriptionResponse>(\n `/topics/${topicId}/contacts/${contactId}`,\n )\n }\n}\n","import type { Eusend } from './eusend'\nimport type { EusendResponse } from './interfaces'\nimport { renderReactEmail, type ReactEmailElement } from './react-render'\n\ninterface TemplateHtmlOrReact {\n /**\n * A React Email component. The SDK renders it to HTML locally before sending.\n * Requires `@react-email/render` and `react` as peer dependencies.\n * Ignored when `html` is also provided.\n */\n react?: ReactEmailElement\n}\n\nexport interface CreateTemplateOptions extends TemplateHtmlOrReact {\n name: string\n subject: string\n html?: string\n}\n\nexport interface UpdateTemplateOptions extends TemplateHtmlOrReact {\n name?: string\n subject?: string\n html?: string\n}\n\nexport interface Template {\n id: string\n name: string\n subject: string\n html: string | null\n reactSource: string | null\n createdAt: string\n updatedAt: string\n}\n\nexport interface TemplateListItem {\n id: string\n name: string\n subject: string\n createdAt: string\n updatedAt: string\n}\n\nasync function resolveTemplateHtml(\n options: TemplateHtmlOrReact & { html?: string },\n): Promise<string | undefined> {\n if (options.html) return options.html\n if (options.react) return renderReactEmail(options.react)\n return undefined\n}\n\nexport class Templates {\n constructor(private readonly client: Eusend) {}\n\n async create(options: CreateTemplateOptions): Promise<EusendResponse<Template>> {\n const html = await resolveTemplateHtml(options)\n if (!html) {\n return {\n data: null,\n error: {\n message: 'Either html or react is required',\n statusCode: null,\n name: 'VALIDATION_ERROR',\n },\n headers: null,\n }\n }\n return this.client.post<Template>('/templates', {\n name: options.name,\n subject: options.subject,\n html,\n })\n }\n\n async list(): Promise<EusendResponse<TemplateListItem[]>> {\n const res = await this.client.get<{ data: TemplateListItem[] }>('/templates')\n if (res.error) return res\n return { data: res.data.data, error: null, headers: res.headers }\n }\n\n get(id: string): Promise<EusendResponse<Template>> {\n return this.client.get<Template>(`/templates/${id}`)\n }\n\n async update(id: string, options: UpdateTemplateOptions): Promise<EusendResponse<Template>> {\n const html = await resolveTemplateHtml(options)\n return this.client.patch<Template>(`/templates/${id}`, {\n name: options.name,\n subject: options.subject,\n html,\n })\n }\n\n delete(id: string): Promise<EusendResponse<Record<string, never>>> {\n return this.client.delete<Record<string, never>>(`/templates/${id}`)\n }\n}\n","import type { Eusend } from './eusend'\nimport type { EusendResponse } from './interfaces'\n\nexport type WebhookEvent =\n | 'email.sent'\n | 'email.delivered'\n | 'email.bounced'\n | 'email.complained'\n | 'email.opened'\n | 'email.clicked'\n | 'email.failed'\n | 'email.suppressed'\n | '*'\n\nexport interface CreateWebhookOptions {\n url: string\n events: WebhookEvent[]\n}\n\nexport interface UpdateWebhookOptions {\n url?: string\n events?: WebhookEvent[]\n /** `false` pauses the endpoint; `true` re-enables a paused or auto-disabled one. */\n enabled?: boolean\n}\n\nexport interface WebhookDelivery {\n id: string\n webhookId: string\n emailId: string | null\n eventType: string\n payload: Record<string, unknown>\n status: 'pending' | 'success' | 'failed'\n responseStatus: number | null\n attempts: number\n createdAt: string\n lastAttemptAt: string | null\n}\n\nexport interface Webhook {\n id: string\n url: string\n events: WebhookEvent[]\n /** When the endpoint stopped receiving events; `null` while active. */\n disabledAt: string | null\n /** `failing` after three days of failed deliveries, `manual` when paused. */\n disabledReason: 'failing' | 'manual' | null\n createdAt: string\n}\n\nexport interface WebhookTestResponse {\n /** The id of the test delivery, as it appears in the webhook's deliveries. */\n id: string\n}\n\nexport interface WebhookWithDeliveries extends Webhook {\n deliveries: WebhookDelivery[]\n}\n\nexport interface CreateWebhookResponse extends Webhook {\n secret: string\n}\n\nexport class Webhooks {\n constructor(private readonly client: Eusend) {}\n\n create(options: CreateWebhookOptions): Promise<EusendResponse<CreateWebhookResponse>> {\n return this.client.post<CreateWebhookResponse>('/webhooks', {\n url: options.url,\n events: options.events,\n })\n }\n\n async list(): Promise<EusendResponse<Webhook[]>> {\n const res = await this.client.get<{ data: Webhook[] }>('/webhooks')\n if (res.error) return res\n return { data: res.data.data, error: null, headers: res.headers }\n }\n\n get(id: string): Promise<EusendResponse<WebhookWithDeliveries>> {\n return this.client.get<WebhookWithDeliveries>(`/webhooks/${id}`)\n }\n\n update(id: string, options: UpdateWebhookOptions): Promise<EusendResponse<Webhook>> {\n return this.client.patch<Webhook>(`/webhooks/${id}`, {\n url: options.url,\n events: options.events,\n enabled: options.enabled,\n })\n }\n\n /** Send one signed `webhook.test` event to the endpoint. Works on a disabled endpoint. */\n test(id: string): Promise<EusendResponse<WebhookTestResponse>> {\n return this.client.post<WebhookTestResponse>(`/webhooks/${id}/test`)\n }\n\n delete(id: string): Promise<EusendResponse<Record<string, never>>> {\n return this.client.delete<Record<string, never>>(`/webhooks/${id}`)\n }\n}\n","import type { Eusend } from './eusend'\nimport type { EusendResponse } from './interfaces'\nimport { renderReactEmail, type ReactEmailElement } from './react-render'\n\n/**\n * `held` is a list send stopped part-way pending review. Unlike `paused` it cannot be\n * resumed by sending again — `send()` returns BROADCAST_HELD until the review clears.\n */\nexport type BroadcastStatus =\n 'draft' | 'scheduled' | 'sending' | 'sent' | 'paused' | 'held' | 'cancelled'\n\nexport interface CreateBroadcastOptions {\n name: string\n audienceId: string\n /** Narrows the audience to the contacts subscribed to this topic. Omit to send to all\n * of it. */\n topicId?: string\n /**\n * Sender address. Accepts a bare email (`onboarding@eusend.dev`) or a display-name\n * form (`Acme <onboarding@eusend.dev>`). The domain must be verified on your account.\n */\n from: string\n /** Where replies go. Same formats as `from`; omit to have replies go to the sender. */\n replyTo?: string\n subject: string\n html?: string\n /**\n * A React Email component. The SDK renders it to HTML locally before sending —\n * the JSX source never travels over the wire. Requires `@react-email/render`\n * and `react` as peer dependencies. Ignored when `html` is also provided.\n */\n react?: ReactEmailElement\n templateId?: string\n templateVariables?: Record<string, string>\n /**\n * Embed the open-tracking pixel for this broadcast. Omit to use your organization's\n * default (Settings → General → Email tracking), which is off unless you changed it. An\n * explicit value always wins over it.\n */\n trackOpens?: boolean\n /**\n * Rewrite links so clicks are recorded. Omit to use your organization's default (off\n * unless you changed it); `false` leaves the original URLs untouched in the delivered mail.\n */\n trackClicks?: boolean\n}\n\nexport interface UpdateBroadcastOptions {\n name?: string\n audienceId?: string\n /** Pass null to clear the topic and widen the send back to the whole audience. */\n topicId?: string | null\n from?: string\n /** Pass null to clear it, so replies go back to the sender. */\n replyTo?: string | null\n subject?: string\n html?: string\n /**\n * See `react` on CreateBroadcastOptions. Rendered to HTML locally before sending.\n */\n react?: ReactEmailElement\n templateId?: string | null\n templateVariables?: Record<string, string> | null\n scheduledAt?: string | null\n /**\n * Embed the open-tracking pixel for this broadcast. Omit to use your organization's\n * default (Settings → General → Email tracking), which is off unless you changed it. An\n * explicit value always wins over it.\n */\n trackOpens?: boolean\n /**\n * Rewrite links so clicks are recorded. Omit to use your organization's default (off\n * unless you changed it); `false` leaves the original URLs untouched in the delivered mail.\n */\n trackClicks?: boolean\n}\n\nexport interface SendBroadcastOptions {\n scheduledAt?: string\n}\n\nexport interface Broadcast {\n id: string\n organizationId: string\n name: string\n status: BroadcastStatus\n /** Null when the associated audience has been deleted. */\n audienceId: string | null\n /** The topic this broadcast is scoped to, or null for the whole audience. */\n topicId: string | null\n fromAddress: string\n replyTo: string | null\n subject: string\n html: string | null\n reactSource: string | null\n editorJson: Record<string, unknown> | null\n templateId: string | null\n templateVariables: Record<string, string> | null\n heldReason: string | null\n scheduledAt: string | null\n startedAt: string | null\n completedAt: string | null\n recipientCount: number | null\n sentCount: number | null\n trackOpens: boolean\n trackClicks: boolean\n createdAt: string\n updatedAt: string\n}\n\nexport interface BroadcastListItem {\n id: string\n name: string\n status: BroadcastStatus\n /** Null when the associated audience has been deleted. */\n audienceId: string | null\n topicId: string | null\n topicName: string | null\n fromAddress: string\n subject: string\n recipientCount: number | null\n sentCount: number | null\n scheduledAt: string | null\n startedAt: string | null\n completedAt: string | null\n createdAt: string\n audienceName: string | null\n}\n\nexport interface BroadcastDetail extends Broadcast {\n stats: Record<string, number>\n}\n\nexport interface TestBroadcastOptions {\n /**\n * Up to 5 addresses, each on a domain verified on your account. A test send delivers\n * real mail without the paid-plan gate that `send()` carries, so it is restricted to\n * inboxes you have already proved you control; anything else returns\n * `DOMAIN_NOT_VERIFIED`.\n */\n to: string[]\n}\n\nexport interface TestBroadcastResponse {\n id: string\n /** The addresses actually mailed, lowercased and de-duplicated. */\n sentTo: string[]\n /** One email id per recipient, for looking the delivery up in the logs. */\n emailIds: string[]\n}\n\nexport interface SendBroadcastResponse {\n id: string\n status: 'sending' | 'scheduled'\n scheduledAt: string | null\n}\n\nasync function resolveBroadcastHtml(options: {\n html?: string\n react?: ReactEmailElement\n}): Promise<string | undefined> {\n if (options.html) return options.html\n if (options.react) return renderReactEmail(options.react)\n return undefined\n}\n\nexport class Broadcasts {\n constructor(private readonly client: Eusend) {}\n\n async create(options: CreateBroadcastOptions): Promise<EusendResponse<Broadcast>> {\n const html = await resolveBroadcastHtml(options)\n return this.client.post<Broadcast>('/broadcasts', {\n name: options.name,\n audience_id: options.audienceId,\n topic_id: options.topicId,\n from: options.from,\n reply_to: options.replyTo,\n subject: options.subject,\n html,\n template_id: options.templateId,\n template_variables: options.templateVariables,\n track_opens: options.trackOpens,\n track_clicks: options.trackClicks,\n })\n }\n\n async list(): Promise<EusendResponse<BroadcastListItem[]>> {\n const res = await this.client.get<{ data: BroadcastListItem[] }>('/broadcasts')\n if (res.error) return res\n return { data: res.data.data, error: null, headers: res.headers }\n }\n\n get(id: string): Promise<EusendResponse<BroadcastDetail>> {\n return this.client.get<BroadcastDetail>(`/broadcasts/${id}`)\n }\n\n /**\n * An update that leaves the broadcast scheduled — setting `scheduledAt`, or editing one\n * that already is — runs the same checks as `send()` and can return the same 403s.\n * Unscheduling with `scheduledAt: null` is always allowed.\n */\n async update(id: string, options: UpdateBroadcastOptions): Promise<EusendResponse<Broadcast>> {\n const html = await resolveBroadcastHtml(options)\n return this.client.patch<Broadcast>(`/broadcasts/${id}`, {\n name: options.name,\n audience_id: options.audienceId,\n topic_id: options.topicId,\n from: options.from,\n reply_to: options.replyTo,\n subject: options.subject,\n html,\n template_id: options.templateId,\n template_variables: options.templateVariables,\n scheduled_at: options.scheduledAt,\n track_opens: options.trackOpens,\n track_clicks: options.trackClicks,\n })\n }\n\n async send(\n id: string,\n options: SendBroadcastOptions = {},\n ): Promise<EusendResponse<SendBroadcastResponse>> {\n // This endpoint is the one broadcast response that comes back snake_cased, so\n // map it rather than exposing a `scheduledAt` that is always undefined.\n const res = await this.client.post<{\n id: string\n status: 'sending' | 'scheduled'\n scheduled_at: string | null\n }>(`/broadcasts/${id}/send`, {\n scheduled_at: options.scheduledAt,\n })\n if (res.error) return res\n return {\n data: { id: res.data.id, status: res.data.status, scheduledAt: res.data.scheduled_at },\n error: null,\n headers: res.headers,\n }\n }\n\n /**\n * Send yourself a copy before the campaign goes out — the real message through the real\n * sending path, so it shows what a recipient will see.\n *\n * Works on every plan including Free, unlike `send()`. It costs daily and monthly quota\n * like any other send, and does NOT move the broadcast's status: the campaign stays a\n * draft no matter how many tests you send.\n *\n * Requires a LIVE api key. \"Test\" here means a dress rehearsal, not a sandbox — a\n * `eu_test_` key is refused because the mail really is delivered.\n */\n async test(\n id: string,\n options: TestBroadcastOptions,\n ): Promise<EusendResponse<TestBroadcastResponse>> {\n // Snake-cased on the wire, like the send() response above.\n const res = await this.client.post<{\n id: string\n sent_to: string[]\n email_ids: string[]\n }>(`/broadcasts/${id}/test`, { to: options.to })\n if (res.error) return res\n return {\n data: { id: res.data.id, sentTo: res.data.sent_to, emailIds: res.data.email_ids },\n error: null,\n headers: res.headers,\n }\n }\n\n cancel(id: string): Promise<EusendResponse<Broadcast>> {\n return this.client.post<Broadcast>(`/broadcasts/${id}/cancel`)\n }\n\n delete(id: string): Promise<EusendResponse<Record<string, never>>> {\n return this.client.delete<Record<string, never>>(`/broadcasts/${id}`)\n }\n}\n","import type { Eusend } from './eusend'\nimport type { EusendResponse } from './interfaces'\n\nexport type SuppressionReason = 'bounce' | 'complaint' | 'manual'\n\nexport interface SuppressionEntry {\n id: string\n email: string\n reason: SuppressionReason\n created_at: string\n}\n\nexport interface ListSuppressionsOptions {\n /** Filter to addresses containing this substring. Pass a domain (\"@acme.com\") to see every suppressed address there. */\n email?: string\n reason?: SuppressionReason\n limit?: number\n cursor?: string\n}\n\nexport interface ListSuppressionsResponse {\n data: SuppressionEntry[]\n next_cursor: string | null\n}\n\nexport interface CreateSuppressionOptions {\n email: string\n /** Defaults to 'manual'. An add never overwrites the reason an address is already suppressed for. */\n reason?: SuppressionReason\n}\n\n/** An item in an import — a bare address, or an address with the reason it was suppressed. */\nexport type SuppressionImportItem = string | { email: string; reason?: SuppressionReason }\n\nexport interface ImportSuppressionsResponse {\n /** Entries written. */\n count: number\n /** Entries that were already on the list. */\n already_suppressed: number\n /** Repeated addresses in the payload, collapsed before the write. */\n duplicates: number\n}\n\n/**\n * The addresses your organization will not send to.\n *\n * Hard bounces and spam complaints are added automatically; these methods cover the\n * addresses you manage yourself. Suppression applies to live sending only — test-mode\n * keys can read the list but not modify it.\n */\nexport class Suppressions {\n constructor(private readonly client: Eusend) {}\n\n list(options: ListSuppressionsOptions = {}): Promise<EusendResponse<ListSuppressionsResponse>> {\n const params = new URLSearchParams()\n if (options.email) params.set('email', options.email)\n if (options.reason) params.set('reason', options.reason)\n if (options.limit != null) params.set('limit', String(options.limit))\n if (options.cursor) params.set('cursor', options.cursor)\n const qs = params.toString()\n return this.client.get<ListSuppressionsResponse>(qs ? `/suppressions?${qs}` : '/suppressions')\n }\n\n /**\n * Suppress an address. If it is already suppressed the existing entry is returned\n * unchanged — a manual add never rewrites a real bounce or complaint.\n */\n create(options: CreateSuppressionOptions): Promise<EusendResponse<SuppressionEntry>> {\n return this.client.post<SuppressionEntry>('/suppressions', {\n email: options.email,\n reason: options.reason,\n })\n }\n\n /**\n * Import up to 1000 addresses in one call — for carrying a suppression list over from\n * another provider before your first send. Items may be bare addresses or objects.\n */\n import(emails: SuppressionImportItem[]): Promise<EusendResponse<ImportSuppressionsResponse>> {\n return this.client.post<ImportSuppressionsResponse>('/suppressions/batch', { emails })\n }\n\n /**\n * Un-suppress by entry id or by address, making the address sendable again.\n *\n * Removing an address that hard-bounced or complained is what damages a sender's\n * reputation when done in bulk — remove an entry when the address was fixed or the\n * complaint was a mistake, not to retry a failing list.\n */\n remove(idOrEmail: string): Promise<EusendResponse<{ deleted: number }>> {\n return this.client.delete<{ deleted: number }>(`/suppressions/${encodeURIComponent(idOrEmail)}`)\n }\n\n /** The whole list as CSV (`email,reason,created_at`), for backup or migration. */\n export(): Promise<EusendResponse<string>> {\n return this.client.fetchRequest<string>('/suppressions/export', { method: 'GET' }, {}, 'text')\n }\n}\n","import type { Eusend } from './eusend'\nimport type { EusendResponse } from './interfaces'\n\nexport type ReputationState = 'healthy' | 'warning' | 'limited' | 'paused'\n\nexport interface Reputation {\n /**\n * `warning`: the raw bounce rate is high but the evidence does not yet put it past the\n * line. `limited`: the daily sending ceiling is halved. `paused`: sending is suspended.\n */\n state: ReputationState\n /** False until at least 100 recipients have a delivery result. */\n measured: boolean\n bounce: {\n /** Raw rate over the judged window. */\n rate: number\n /** The 95% confidence lower bound compared against the lines; 0 without enough evidence. */\n judged_rate: number\n counted: number\n /** Bounces about eusend's sending infrastructure rather than the address. */\n not_counted: number\n recipients: number\n window: '7d' | '30d' | null\n limited_at: number\n paused_at: number\n }\n complaint: {\n rate: number\n complaints: number\n limited_at: number\n paused_at: number\n }\n /** The next state and how many more counted bounces reach it. Null when paused. */\n next: { state: 'limited' | 'paused'; bounces: number | null } | null\n}\n\n/** Your organization's sending reputation, as the sending limits judge it. */\nexport class ReputationResource {\n constructor(private readonly client: Eusend) {}\n\n /** Not available to sending-only keys. Cached by the API for up to 30 seconds. */\n get(): Promise<EusendResponse<Reputation>> {\n return this.client.get<Reputation>('/reputation')\n }\n}\n","import type { EusendError, EusendResponse } from './interfaces'\nimport { Emails } from './emails'\nimport { Batch } from './batch'\nimport { Domains } from './domains'\nimport { ApiKeys } from './api-keys'\nimport { Audiences } from './audiences'\nimport { ContactProperties } from './contact-properties'\nimport { Topics } from './topics'\nimport { Templates } from './templates'\nimport { Webhooks } from './webhooks'\nimport { Broadcasts } from './broadcasts'\nimport { Suppressions } from './suppressions'\nimport { ReputationResource } from './reputation'\n\nconst DEFAULT_BASE_URL = 'https://api.eusend.dev'\nconst SDK_VERSION = '0.21.0'\n\nexport interface EusendOptions {\n baseUrl?: string\n}\n\nexport class Eusend {\n readonly baseUrl: string\n private readonly apiKey: string\n\n readonly emails: Emails\n /** Batch sending — `client.batch.send([...])`. Mirrors Resend's `resend.batch.send()`. */\n readonly batch: Batch\n readonly domains: Domains\n readonly apiKeys: ApiKeys\n readonly audiences: Audiences\n /** The org's declared contact properties — `client.contactProperties.list()`. */\n readonly contactProperties: ContactProperties\n /** Subscription topics — `client.topics.list()`. */\n readonly topics: Topics\n readonly templates: Templates\n readonly webhooks: Webhooks\n readonly broadcasts: Broadcasts\n readonly suppressions: Suppressions\n readonly reputation: ReputationResource\n\n constructor(key?: string, options?: EusendOptions) {\n const apiKey =\n key ?? (typeof process !== 'undefined' ? process.env['EUSEND_API_KEY'] : undefined)\n if (!apiKey) {\n throw new Error(\n 'Missing Eusend API key. Pass it to the constructor or set the EUSEND_API_KEY environment variable.',\n )\n }\n this.apiKey = apiKey\n this.baseUrl = options?.baseUrl ?? DEFAULT_BASE_URL\n\n this.emails = new Emails(this)\n this.batch = new Batch(this)\n this.domains = new Domains(this)\n this.apiKeys = new ApiKeys(this)\n this.audiences = new Audiences(this)\n this.contactProperties = new ContactProperties(this)\n this.topics = new Topics(this)\n this.templates = new Templates(this)\n this.webhooks = new Webhooks(this)\n this.broadcasts = new Broadcasts(this)\n this.suppressions = new Suppressions(this)\n this.reputation = new ReputationResource(this)\n }\n\n async fetchRequest<T>(\n path: string,\n init: RequestInit = {},\n extraHeaders: Record<string, string> = {},\n // Not every successful endpoint answers with JSON — the suppression export returns\n // CSV. Parsing that as JSON throws inside the try below, which would surface a\n // perfectly good download as \"Network request failed\".\n parse: 'json' | 'text' = 'json',\n ): Promise<EusendResponse<T>> {\n const headers: Record<string, string> = {\n Authorization: `Bearer ${this.apiKey}`,\n 'Content-Type': 'application/json',\n 'User-Agent': `eusend-node/${SDK_VERSION}`,\n ...extraHeaders,\n }\n\n try {\n const res = await fetch(`${this.baseUrl}${path}`, { ...init, headers })\n const responseHeaders = Object.fromEntries(res.headers.entries())\n\n if (!res.ok) {\n let error: EusendError\n try {\n const json = (await res.json()) as { error?: string; code?: string }\n error = {\n message: json.error ?? 'Unknown error',\n statusCode: res.status,\n name: (json.code as EusendError['name']) ?? 'INTERNAL_ERROR',\n }\n } catch {\n error = { message: 'Request failed', statusCode: res.status, name: 'INTERNAL_ERROR' }\n }\n return { data: null, error, headers: responseHeaders }\n }\n\n if (res.status === 204 || res.headers.get('content-length') === '0') {\n return { data: {} as T, error: null, headers: responseHeaders }\n }\n\n const data = (parse === 'text' ? await res.text() : await res.json()) as T\n return { data, error: null, headers: responseHeaders }\n } catch {\n return {\n data: null,\n error: {\n message: 'Network request failed. The request could not be resolved.',\n statusCode: null,\n name: 'application_error',\n },\n headers: null,\n }\n }\n }\n\n get<T>(path: string, extraHeaders?: Record<string, string>): Promise<EusendResponse<T>> {\n return this.fetchRequest<T>(path, { method: 'GET' }, extraHeaders)\n }\n\n post<T>(\n path: string,\n body?: unknown,\n extraHeaders?: Record<string, string>,\n ): Promise<EusendResponse<T>> {\n return this.fetchRequest<T>(\n path,\n { method: 'POST', body: body != null ? JSON.stringify(body) : undefined },\n extraHeaders,\n )\n }\n\n patch<T>(path: string, body?: unknown): Promise<EusendResponse<T>> {\n return this.fetchRequest<T>(path, {\n method: 'PATCH',\n body: body != null ? JSON.stringify(body) : undefined,\n })\n }\n\n put<T>(path: string, body?: unknown): Promise<EusendResponse<T>> {\n return this.fetchRequest<T>(path, {\n method: 'PUT',\n body: body != null ? JSON.stringify(body) : undefined,\n })\n }\n\n delete<T>(path: string): Promise<EusendResponse<T>> {\n return this.fetchRequest<T>(path, { method: 'DELETE' })\n }\n}\n"],"mappings":"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"}
|