zupost 0.5.1 → 0.6.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -53,7 +53,7 @@ await zupost.emails.send({
53
53
 
54
54
  #### Fallback: inline content
55
55
 
56
- When a template is not a good fit, you can pass raw content instead. Exactly one of `html`, `markdown`, or `react` is required in that case.
56
+ When a template is not a good fit, you can pass raw content instead. At least one of `html`, `markdown`, `react`, or `text` is required in that case. `html`, `markdown`, and `react` are mutually exclusive, while `text` can be sent on its own or added alongside one of them as a plain text alternative.
57
57
 
58
58
  ```typescript
59
59
  // Inline HTML
@@ -71,6 +71,14 @@ await zupost.emails.send({
71
71
  subject: 'Team Update',
72
72
  markdown: '# Hello Team\n\nThis is a **markdown** email.',
73
73
  });
74
+
75
+ // Plain text only
76
+ await zupost.emails.send({
77
+ from: 'sender@example.com',
78
+ to: 'recipient@example.com',
79
+ subject: 'Hello World',
80
+ text: 'Hello! This is a plain text email.',
81
+ });
74
82
  ```
75
83
 
76
84
  ### Send with React Email (fallback)
package/dist/index.d.mts CHANGED
@@ -21,8 +21,10 @@ declare class HttpClient {
21
21
  *
22
22
  * Zupost is template first: the recommended way to send is by providing a
23
23
  * `templateId` (managed in the Zupost dashboard) together with `variables`.
24
- * `html`, `markdown`, and `react` are supported as fallbacks for ad-hoc or
25
- * dynamically generated content. Exactly one content source is required.
24
+ * `html`, `markdown`, `react`, and `text` are supported as fallbacks for
25
+ * ad-hoc or dynamically generated content. At least one content source is
26
+ * required. `html`, `markdown`, and `react` are mutually exclusive, while
27
+ * `text` may be sent on its own or alongside one of them.
26
28
  */
27
29
  interface SendEmailOptions {
28
30
  /**
@@ -82,7 +84,9 @@ interface SendEmailOptions {
82
84
  */
83
85
  reactOptions?: Options;
84
86
  /**
85
- * Plain text content for the email.
87
+ * Plain text content for the email. Can be sent on its own as the only
88
+ * content source, or alongside `html`, `markdown`, or `react` to provide a
89
+ * plain text alternative.
86
90
  */
87
91
  text?: string;
88
92
  /**
@@ -618,6 +622,183 @@ declare class Sequences {
618
622
  trigger(id: string, options: TriggerRunOptions): Promise<SequenceRun>;
619
623
  }
620
624
 
625
+ /**
626
+ * Verification status shared by a domain and its individual DNS records.
627
+ */
628
+ type DomainVerificationStatus = 'NOT_STARTED' | 'PENDING' | 'SUCCESS' | 'FAILED' | 'TEMPORARY_FAILURE';
629
+ type DomainDnsRecordType = 'MX' | 'TXT' | 'CNAME';
630
+ /**
631
+ * A single DNS record you need to add at your DNS provider for the domain to
632
+ * verify (DKIM, SPF, the verification TXT record, optional DMARC, …).
633
+ */
634
+ interface DomainDnsRecord {
635
+ type: DomainDnsRecordType;
636
+ /** Record name/host, e.g. `mail` or `@`. */
637
+ name: string;
638
+ /** Record value, e.g. the SPF or DKIM string. */
639
+ value: string;
640
+ /** Recommended TTL, e.g. `Auto`. */
641
+ ttl: string;
642
+ /** Priority for MX records. */
643
+ priority?: string | null;
644
+ /** Verification status of this specific record. */
645
+ status?: DomainVerificationStatus | null;
646
+ /** Whether adding this record is recommended (e.g. DMARC). */
647
+ recommended?: boolean;
648
+ }
649
+ /**
650
+ * A sending domain with its DNS records and verification state.
651
+ */
652
+ interface Domain {
653
+ id: string;
654
+ /** The domain name, e.g. `example.com`. */
655
+ name: string;
656
+ projectId: string;
657
+ /** Primary sending region, e.g. `eu-central-1`. */
658
+ mainRegion: string;
659
+ /** All regions the domain is provisioned in. */
660
+ regions: string[];
661
+ clickTracking: boolean;
662
+ openTracking: boolean;
663
+ dkimTokens: string[];
664
+ dkimStatus?: DomainVerificationStatus | null;
665
+ /** Overall verification status of the domain. */
666
+ status?: DomainVerificationStatus | null;
667
+ spfStatus?: DomainVerificationStatus | null;
668
+ createdAt: string;
669
+ updatedAt: string;
670
+ dmarcAdded: boolean;
671
+ verificationInProcess: boolean;
672
+ errorMessage?: string | null;
673
+ subdomain?: string | null;
674
+ verificationError?: string | null;
675
+ lastCheckedTime?: string | null;
676
+ scheduledForDeletion: boolean;
677
+ /** DNS records to add at your DNS provider to verify the domain. */
678
+ dnsRecords: DomainDnsRecord[];
679
+ }
680
+ interface CreateDomainOptions {
681
+ /** The domain name to register, e.g. `example.com`. */
682
+ name: string;
683
+ /**
684
+ * Sending region for the domain. Defaults to `eu-central-1`.
685
+ */
686
+ region?: string;
687
+ }
688
+ interface DeleteDomainResponse {
689
+ success: boolean;
690
+ message: string;
691
+ }
692
+ interface VerifyDomainResponse {
693
+ message: string;
694
+ }
695
+
696
+ /**
697
+ * Domains API.
698
+ *
699
+ * A Domain is a sending domain you own (e.g. `example.com`). After creating it
700
+ * you add the returned `dnsRecords` (DKIM, SPF, verification TXT) at your DNS
701
+ * provider and then `verify` it. Only verified domains can send email and
702
+ * receive inbound mail.
703
+ */
704
+ declare class Domains {
705
+ private readonly http;
706
+ constructor(http: HttpClient);
707
+ /**
708
+ * Register a new sending domain. The response contains the `dnsRecords` you
709
+ * need to add at your DNS provider before calling {@link verify}.
710
+ *
711
+ * @example
712
+ * ```typescript
713
+ * const domain = await zupost.domains.create({ name: 'example.com' });
714
+ * for (const record of domain.dnsRecords) {
715
+ * console.log(record.type, record.name, record.value);
716
+ * }
717
+ * ```
718
+ */
719
+ create(options: CreateDomainOptions): Promise<Domain>;
720
+ /**
721
+ * Get a domain by ID, including its current verification status and DNS
722
+ * records.
723
+ */
724
+ get(id: string): Promise<Domain>;
725
+ /**
726
+ * List all domains in the project.
727
+ */
728
+ list(): Promise<Domain[]>;
729
+ /**
730
+ * Start the verification process for a domain. Add the DNS records returned
731
+ * by {@link create} or {@link get} first; Zupost then checks them and
732
+ * updates the domain's `status`.
733
+ */
734
+ verify(id: string): Promise<VerifyDomainResponse>;
735
+ /**
736
+ * Schedule a domain for deletion.
737
+ */
738
+ delete(id: string): Promise<DeleteDomainResponse>;
739
+ }
740
+
741
+ interface CreateInboundChannelOptions {
742
+ /** Human-readable name for the channel (1-100 characters). */
743
+ name: string;
744
+ /** ID of a verified domain that should receive inbound email. */
745
+ domainId: string;
746
+ /**
747
+ * HTTPS URL parsed inbound emails are delivered to. Must resolve to a
748
+ * public address.
749
+ */
750
+ webhookUrl: string;
751
+ /**
752
+ * Shared secret (32-512 characters) used to sign webhook deliveries so you
753
+ * can verify they originate from Zupost.
754
+ */
755
+ webhookSecret: string;
756
+ }
757
+ /**
758
+ * An inbound email channel: it routes mail received on a domain to your
759
+ * `webhookUrl`.
760
+ */
761
+ interface InboundChannel {
762
+ id: string;
763
+ name: string;
764
+ projectId: string;
765
+ domainId: string;
766
+ webhookUrl: string;
767
+ createdAt: string;
768
+ updatedAt: string;
769
+ }
770
+
771
+ /**
772
+ * Inbound API.
773
+ *
774
+ * Receive email sent to a verified domain by routing it through an inbound
775
+ * channel to your own HTTPS webhook. Deliveries are signed with the
776
+ * `webhookSecret` you provide so you can verify their authenticity.
777
+ */
778
+ declare class Inbound {
779
+ private readonly http;
780
+ constructor(http: HttpClient);
781
+ /**
782
+ * Inbound channels route mail received on a domain to a webhook.
783
+ */
784
+ readonly channels: {
785
+ /**
786
+ * Create an inbound channel for a verified domain.
787
+ *
788
+ * @example
789
+ * ```typescript
790
+ * const channel = await zupost.inbound.channels.create({
791
+ * name: 'Support inbox',
792
+ * domainId: 'dom_123',
793
+ * webhookUrl: 'https://example.com/zupost/inbound',
794
+ * webhookSecret: process.env.ZUPOST_INBOUND_SECRET!,
795
+ * });
796
+ * ```
797
+ */
798
+ create: (options: CreateInboundChannelOptions) => Promise<InboundChannel>;
799
+ };
800
+ }
801
+
621
802
  interface ZupostOptions {
622
803
  /**
623
804
  * Custom API URL. Defaults to 'https://api.zupost.com'.
@@ -644,6 +825,16 @@ declare class Zupost {
644
825
  * transactional) with branches, waits, tags and webhooks.
645
826
  */
646
827
  readonly sequences: Sequences;
828
+ /**
829
+ * Domains API. A Domain is a sending domain you own, with DNS records and
830
+ * verification state. Only verified domains can send and receive email.
831
+ */
832
+ readonly domains: Domains;
833
+ /**
834
+ * Inbound API. Receive email on a verified domain and have it delivered to
835
+ * your own webhook through an inbound channel.
836
+ */
837
+ readonly inbound: Inbound;
647
838
  constructor(apiKey: string, options?: ZupostOptions);
648
839
  }
649
840
 
@@ -713,4 +904,4 @@ declare function defineSequence<TSteps extends Record<string, SequenceStep>>(def
713
904
  steps: TSteps;
714
905
  }): SequenceDefinition;
715
906
 
716
- export { type BranchCondition, type Contact, type ContactEvent, type ContactEventType, type ContactExport, type ContactTag, type CreateContactOptions, type CreateSequenceOptions, type EmailRecipientType, type ForgetContactResponse, type ListContactsOptions, type ListContactsResponse, type ListEventsOptions, type ListEventsResponse, type ListRunsOptions, type ListRunsResponse, type ListSequencesOptions, type ListSequencesResponse, type SaveVersionOptions, type SendCampaignOptions, type SendCampaignResponse, type SendEmailOptions, type SendEmailResponse, type Sequence, type SequenceDefinition, type SequenceRun, type SequenceRunStatus, type SequenceStatus, type SequenceStep, type SequenceTriggerType, type SequenceType, type SequenceVersion, type TriggerRunOptions, type UpdateContactOptions, type WaitDuration, Zupost, ZupostError, type ZupostOptions, defineSequence };
907
+ export { type BranchCondition, type Contact, type ContactEvent, type ContactEventType, type ContactExport, type ContactTag, type CreateContactOptions, type CreateDomainOptions, type CreateInboundChannelOptions, type CreateSequenceOptions, type DeleteDomainResponse, type Domain, type DomainDnsRecord, type DomainDnsRecordType, type DomainVerificationStatus, type EmailRecipientType, type ForgetContactResponse, type InboundChannel, type ListContactsOptions, type ListContactsResponse, type ListEventsOptions, type ListEventsResponse, type ListRunsOptions, type ListRunsResponse, type ListSequencesOptions, type ListSequencesResponse, type SaveVersionOptions, type SendCampaignOptions, type SendCampaignResponse, type SendEmailOptions, type SendEmailResponse, type Sequence, type SequenceDefinition, type SequenceRun, type SequenceRunStatus, type SequenceStatus, type SequenceStep, type SequenceTriggerType, type SequenceType, type SequenceVersion, type TriggerRunOptions, type UpdateContactOptions, type VerifyDomainResponse, type WaitDuration, Zupost, ZupostError, type ZupostOptions, defineSequence };
package/dist/index.d.ts CHANGED
@@ -21,8 +21,10 @@ declare class HttpClient {
21
21
  *
22
22
  * Zupost is template first: the recommended way to send is by providing a
23
23
  * `templateId` (managed in the Zupost dashboard) together with `variables`.
24
- * `html`, `markdown`, and `react` are supported as fallbacks for ad-hoc or
25
- * dynamically generated content. Exactly one content source is required.
24
+ * `html`, `markdown`, `react`, and `text` are supported as fallbacks for
25
+ * ad-hoc or dynamically generated content. At least one content source is
26
+ * required. `html`, `markdown`, and `react` are mutually exclusive, while
27
+ * `text` may be sent on its own or alongside one of them.
26
28
  */
27
29
  interface SendEmailOptions {
28
30
  /**
@@ -82,7 +84,9 @@ interface SendEmailOptions {
82
84
  */
83
85
  reactOptions?: Options;
84
86
  /**
85
- * Plain text content for the email.
87
+ * Plain text content for the email. Can be sent on its own as the only
88
+ * content source, or alongside `html`, `markdown`, or `react` to provide a
89
+ * plain text alternative.
86
90
  */
87
91
  text?: string;
88
92
  /**
@@ -618,6 +622,183 @@ declare class Sequences {
618
622
  trigger(id: string, options: TriggerRunOptions): Promise<SequenceRun>;
619
623
  }
620
624
 
625
+ /**
626
+ * Verification status shared by a domain and its individual DNS records.
627
+ */
628
+ type DomainVerificationStatus = 'NOT_STARTED' | 'PENDING' | 'SUCCESS' | 'FAILED' | 'TEMPORARY_FAILURE';
629
+ type DomainDnsRecordType = 'MX' | 'TXT' | 'CNAME';
630
+ /**
631
+ * A single DNS record you need to add at your DNS provider for the domain to
632
+ * verify (DKIM, SPF, the verification TXT record, optional DMARC, …).
633
+ */
634
+ interface DomainDnsRecord {
635
+ type: DomainDnsRecordType;
636
+ /** Record name/host, e.g. `mail` or `@`. */
637
+ name: string;
638
+ /** Record value, e.g. the SPF or DKIM string. */
639
+ value: string;
640
+ /** Recommended TTL, e.g. `Auto`. */
641
+ ttl: string;
642
+ /** Priority for MX records. */
643
+ priority?: string | null;
644
+ /** Verification status of this specific record. */
645
+ status?: DomainVerificationStatus | null;
646
+ /** Whether adding this record is recommended (e.g. DMARC). */
647
+ recommended?: boolean;
648
+ }
649
+ /**
650
+ * A sending domain with its DNS records and verification state.
651
+ */
652
+ interface Domain {
653
+ id: string;
654
+ /** The domain name, e.g. `example.com`. */
655
+ name: string;
656
+ projectId: string;
657
+ /** Primary sending region, e.g. `eu-central-1`. */
658
+ mainRegion: string;
659
+ /** All regions the domain is provisioned in. */
660
+ regions: string[];
661
+ clickTracking: boolean;
662
+ openTracking: boolean;
663
+ dkimTokens: string[];
664
+ dkimStatus?: DomainVerificationStatus | null;
665
+ /** Overall verification status of the domain. */
666
+ status?: DomainVerificationStatus | null;
667
+ spfStatus?: DomainVerificationStatus | null;
668
+ createdAt: string;
669
+ updatedAt: string;
670
+ dmarcAdded: boolean;
671
+ verificationInProcess: boolean;
672
+ errorMessage?: string | null;
673
+ subdomain?: string | null;
674
+ verificationError?: string | null;
675
+ lastCheckedTime?: string | null;
676
+ scheduledForDeletion: boolean;
677
+ /** DNS records to add at your DNS provider to verify the domain. */
678
+ dnsRecords: DomainDnsRecord[];
679
+ }
680
+ interface CreateDomainOptions {
681
+ /** The domain name to register, e.g. `example.com`. */
682
+ name: string;
683
+ /**
684
+ * Sending region for the domain. Defaults to `eu-central-1`.
685
+ */
686
+ region?: string;
687
+ }
688
+ interface DeleteDomainResponse {
689
+ success: boolean;
690
+ message: string;
691
+ }
692
+ interface VerifyDomainResponse {
693
+ message: string;
694
+ }
695
+
696
+ /**
697
+ * Domains API.
698
+ *
699
+ * A Domain is a sending domain you own (e.g. `example.com`). After creating it
700
+ * you add the returned `dnsRecords` (DKIM, SPF, verification TXT) at your DNS
701
+ * provider and then `verify` it. Only verified domains can send email and
702
+ * receive inbound mail.
703
+ */
704
+ declare class Domains {
705
+ private readonly http;
706
+ constructor(http: HttpClient);
707
+ /**
708
+ * Register a new sending domain. The response contains the `dnsRecords` you
709
+ * need to add at your DNS provider before calling {@link verify}.
710
+ *
711
+ * @example
712
+ * ```typescript
713
+ * const domain = await zupost.domains.create({ name: 'example.com' });
714
+ * for (const record of domain.dnsRecords) {
715
+ * console.log(record.type, record.name, record.value);
716
+ * }
717
+ * ```
718
+ */
719
+ create(options: CreateDomainOptions): Promise<Domain>;
720
+ /**
721
+ * Get a domain by ID, including its current verification status and DNS
722
+ * records.
723
+ */
724
+ get(id: string): Promise<Domain>;
725
+ /**
726
+ * List all domains in the project.
727
+ */
728
+ list(): Promise<Domain[]>;
729
+ /**
730
+ * Start the verification process for a domain. Add the DNS records returned
731
+ * by {@link create} or {@link get} first; Zupost then checks them and
732
+ * updates the domain's `status`.
733
+ */
734
+ verify(id: string): Promise<VerifyDomainResponse>;
735
+ /**
736
+ * Schedule a domain for deletion.
737
+ */
738
+ delete(id: string): Promise<DeleteDomainResponse>;
739
+ }
740
+
741
+ interface CreateInboundChannelOptions {
742
+ /** Human-readable name for the channel (1-100 characters). */
743
+ name: string;
744
+ /** ID of a verified domain that should receive inbound email. */
745
+ domainId: string;
746
+ /**
747
+ * HTTPS URL parsed inbound emails are delivered to. Must resolve to a
748
+ * public address.
749
+ */
750
+ webhookUrl: string;
751
+ /**
752
+ * Shared secret (32-512 characters) used to sign webhook deliveries so you
753
+ * can verify they originate from Zupost.
754
+ */
755
+ webhookSecret: string;
756
+ }
757
+ /**
758
+ * An inbound email channel: it routes mail received on a domain to your
759
+ * `webhookUrl`.
760
+ */
761
+ interface InboundChannel {
762
+ id: string;
763
+ name: string;
764
+ projectId: string;
765
+ domainId: string;
766
+ webhookUrl: string;
767
+ createdAt: string;
768
+ updatedAt: string;
769
+ }
770
+
771
+ /**
772
+ * Inbound API.
773
+ *
774
+ * Receive email sent to a verified domain by routing it through an inbound
775
+ * channel to your own HTTPS webhook. Deliveries are signed with the
776
+ * `webhookSecret` you provide so you can verify their authenticity.
777
+ */
778
+ declare class Inbound {
779
+ private readonly http;
780
+ constructor(http: HttpClient);
781
+ /**
782
+ * Inbound channels route mail received on a domain to a webhook.
783
+ */
784
+ readonly channels: {
785
+ /**
786
+ * Create an inbound channel for a verified domain.
787
+ *
788
+ * @example
789
+ * ```typescript
790
+ * const channel = await zupost.inbound.channels.create({
791
+ * name: 'Support inbox',
792
+ * domainId: 'dom_123',
793
+ * webhookUrl: 'https://example.com/zupost/inbound',
794
+ * webhookSecret: process.env.ZUPOST_INBOUND_SECRET!,
795
+ * });
796
+ * ```
797
+ */
798
+ create: (options: CreateInboundChannelOptions) => Promise<InboundChannel>;
799
+ };
800
+ }
801
+
621
802
  interface ZupostOptions {
622
803
  /**
623
804
  * Custom API URL. Defaults to 'https://api.zupost.com'.
@@ -644,6 +825,16 @@ declare class Zupost {
644
825
  * transactional) with branches, waits, tags and webhooks.
645
826
  */
646
827
  readonly sequences: Sequences;
828
+ /**
829
+ * Domains API. A Domain is a sending domain you own, with DNS records and
830
+ * verification state. Only verified domains can send and receive email.
831
+ */
832
+ readonly domains: Domains;
833
+ /**
834
+ * Inbound API. Receive email on a verified domain and have it delivered to
835
+ * your own webhook through an inbound channel.
836
+ */
837
+ readonly inbound: Inbound;
647
838
  constructor(apiKey: string, options?: ZupostOptions);
648
839
  }
649
840
 
@@ -713,4 +904,4 @@ declare function defineSequence<TSteps extends Record<string, SequenceStep>>(def
713
904
  steps: TSteps;
714
905
  }): SequenceDefinition;
715
906
 
716
- export { type BranchCondition, type Contact, type ContactEvent, type ContactEventType, type ContactExport, type ContactTag, type CreateContactOptions, type CreateSequenceOptions, type EmailRecipientType, type ForgetContactResponse, type ListContactsOptions, type ListContactsResponse, type ListEventsOptions, type ListEventsResponse, type ListRunsOptions, type ListRunsResponse, type ListSequencesOptions, type ListSequencesResponse, type SaveVersionOptions, type SendCampaignOptions, type SendCampaignResponse, type SendEmailOptions, type SendEmailResponse, type Sequence, type SequenceDefinition, type SequenceRun, type SequenceRunStatus, type SequenceStatus, type SequenceStep, type SequenceTriggerType, type SequenceType, type SequenceVersion, type TriggerRunOptions, type UpdateContactOptions, type WaitDuration, Zupost, ZupostError, type ZupostOptions, defineSequence };
907
+ export { type BranchCondition, type Contact, type ContactEvent, type ContactEventType, type ContactExport, type ContactTag, type CreateContactOptions, type CreateDomainOptions, type CreateInboundChannelOptions, type CreateSequenceOptions, type DeleteDomainResponse, type Domain, type DomainDnsRecord, type DomainDnsRecordType, type DomainVerificationStatus, type EmailRecipientType, type ForgetContactResponse, type InboundChannel, type ListContactsOptions, type ListContactsResponse, type ListEventsOptions, type ListEventsResponse, type ListRunsOptions, type ListRunsResponse, type ListSequencesOptions, type ListSequencesResponse, type SaveVersionOptions, type SendCampaignOptions, type SendCampaignResponse, type SendEmailOptions, type SendEmailResponse, type Sequence, type SequenceDefinition, type SequenceRun, type SequenceRunStatus, type SequenceStatus, type SequenceStep, type SequenceTriggerType, type SequenceType, type SequenceVersion, type TriggerRunOptions, type UpdateContactOptions, type VerifyDomainResponse, type WaitDuration, Zupost, ZupostError, type ZupostOptions, defineSequence };
package/dist/index.js CHANGED
@@ -79,7 +79,7 @@ __export(index_exports, {
79
79
  module.exports = __toCommonJS(index_exports);
80
80
 
81
81
  // package.json
82
- var version = "0.5.1";
82
+ var version = "0.6.1";
83
83
 
84
84
  // src/errors.ts
85
85
  var ZupostError = class _ZupostError extends Error {
@@ -267,8 +267,10 @@ var Emails = class {
267
267
  if (inlineCount > 1) {
268
268
  throw new Error("Provide only one of html, markdown, or react");
269
269
  }
270
- if (inlineCount === 0 && !options.templateId) {
271
- throw new Error("Provide one of html, markdown, react, or templateId");
270
+ if (inlineCount === 0 && !options.templateId && !options.text) {
271
+ throw new Error(
272
+ "Provide one of html, markdown, react, text, or templateId"
273
+ );
272
274
  }
273
275
  const payload = __spreadValues({}, options);
274
276
  if (options.react) {
@@ -536,6 +538,101 @@ var Sequences = class {
536
538
  }
537
539
  };
538
540
 
541
+ // src/domain/domains.ts
542
+ var DEFAULT_REGION = "eu-central-1";
543
+ var Domains = class {
544
+ constructor(http) {
545
+ this.http = http;
546
+ }
547
+ /**
548
+ * Register a new sending domain. The response contains the `dnsRecords` you
549
+ * need to add at your DNS provider before calling {@link verify}.
550
+ *
551
+ * @example
552
+ * ```typescript
553
+ * const domain = await zupost.domains.create({ name: 'example.com' });
554
+ * for (const record of domain.dnsRecords) {
555
+ * console.log(record.type, record.name, record.value);
556
+ * }
557
+ * ```
558
+ */
559
+ create(options) {
560
+ return __async(this, null, function* () {
561
+ var _a;
562
+ return this.http.post("/domain", {
563
+ name: options.name,
564
+ region: (_a = options.region) != null ? _a : DEFAULT_REGION
565
+ });
566
+ });
567
+ }
568
+ /**
569
+ * Get a domain by ID, including its current verification status and DNS
570
+ * records.
571
+ */
572
+ get(id) {
573
+ return __async(this, null, function* () {
574
+ return this.http.get(`/domain/${encodeURIComponent(id)}`);
575
+ });
576
+ }
577
+ /**
578
+ * List all domains in the project.
579
+ */
580
+ list() {
581
+ return __async(this, null, function* () {
582
+ return this.http.get("/domain");
583
+ });
584
+ }
585
+ /**
586
+ * Start the verification process for a domain. Add the DNS records returned
587
+ * by {@link create} or {@link get} first; Zupost then checks them and
588
+ * updates the domain's `status`.
589
+ */
590
+ verify(id) {
591
+ return __async(this, null, function* () {
592
+ return this.http.post(
593
+ `/domain/${encodeURIComponent(id)}/verify`,
594
+ void 0
595
+ );
596
+ });
597
+ }
598
+ /**
599
+ * Schedule a domain for deletion.
600
+ */
601
+ delete(id) {
602
+ return __async(this, null, function* () {
603
+ return this.http.delete(`/domain/${encodeURIComponent(id)}`);
604
+ });
605
+ }
606
+ };
607
+
608
+ // src/inbound/inbound.ts
609
+ var Inbound = class {
610
+ constructor(http) {
611
+ this.http = http;
612
+ /**
613
+ * Inbound channels route mail received on a domain to a webhook.
614
+ */
615
+ this.channels = {
616
+ /**
617
+ * Create an inbound channel for a verified domain.
618
+ *
619
+ * @example
620
+ * ```typescript
621
+ * const channel = await zupost.inbound.channels.create({
622
+ * name: 'Support inbox',
623
+ * domainId: 'dom_123',
624
+ * webhookUrl: 'https://example.com/zupost/inbound',
625
+ * webhookSecret: process.env.ZUPOST_INBOUND_SECRET!,
626
+ * });
627
+ * ```
628
+ */
629
+ create: (options) => __async(this, null, function* () {
630
+ return this.http.post("/inbound-channel", options);
631
+ })
632
+ };
633
+ }
634
+ };
635
+
539
636
  // src/zupost.ts
540
637
  var _client;
541
638
  var Zupost = class {
@@ -551,6 +648,8 @@ var Zupost = class {
551
648
  this.campaigns = new Campaigns(__privateGet(this, _client));
552
649
  this.contacts = new Contacts(__privateGet(this, _client));
553
650
  this.sequences = new Sequences(__privateGet(this, _client));
651
+ this.domains = new Domains(__privateGet(this, _client));
652
+ this.inbound = new Inbound(__privateGet(this, _client));
554
653
  }
555
654
  };
556
655
  _client = new WeakMap();
package/dist/index.mjs CHANGED
@@ -44,7 +44,7 @@ var __async = (__this, __arguments, generator) => {
44
44
  };
45
45
 
46
46
  // package.json
47
- var version = "0.5.1";
47
+ var version = "0.6.1";
48
48
 
49
49
  // src/errors.ts
50
50
  var ZupostError = class _ZupostError extends Error {
@@ -232,8 +232,10 @@ var Emails = class {
232
232
  if (inlineCount > 1) {
233
233
  throw new Error("Provide only one of html, markdown, or react");
234
234
  }
235
- if (inlineCount === 0 && !options.templateId) {
236
- throw new Error("Provide one of html, markdown, react, or templateId");
235
+ if (inlineCount === 0 && !options.templateId && !options.text) {
236
+ throw new Error(
237
+ "Provide one of html, markdown, react, text, or templateId"
238
+ );
237
239
  }
238
240
  const payload = __spreadValues({}, options);
239
241
  if (options.react) {
@@ -501,6 +503,101 @@ var Sequences = class {
501
503
  }
502
504
  };
503
505
 
506
+ // src/domain/domains.ts
507
+ var DEFAULT_REGION = "eu-central-1";
508
+ var Domains = class {
509
+ constructor(http) {
510
+ this.http = http;
511
+ }
512
+ /**
513
+ * Register a new sending domain. The response contains the `dnsRecords` you
514
+ * need to add at your DNS provider before calling {@link verify}.
515
+ *
516
+ * @example
517
+ * ```typescript
518
+ * const domain = await zupost.domains.create({ name: 'example.com' });
519
+ * for (const record of domain.dnsRecords) {
520
+ * console.log(record.type, record.name, record.value);
521
+ * }
522
+ * ```
523
+ */
524
+ create(options) {
525
+ return __async(this, null, function* () {
526
+ var _a;
527
+ return this.http.post("/domain", {
528
+ name: options.name,
529
+ region: (_a = options.region) != null ? _a : DEFAULT_REGION
530
+ });
531
+ });
532
+ }
533
+ /**
534
+ * Get a domain by ID, including its current verification status and DNS
535
+ * records.
536
+ */
537
+ get(id) {
538
+ return __async(this, null, function* () {
539
+ return this.http.get(`/domain/${encodeURIComponent(id)}`);
540
+ });
541
+ }
542
+ /**
543
+ * List all domains in the project.
544
+ */
545
+ list() {
546
+ return __async(this, null, function* () {
547
+ return this.http.get("/domain");
548
+ });
549
+ }
550
+ /**
551
+ * Start the verification process for a domain. Add the DNS records returned
552
+ * by {@link create} or {@link get} first; Zupost then checks them and
553
+ * updates the domain's `status`.
554
+ */
555
+ verify(id) {
556
+ return __async(this, null, function* () {
557
+ return this.http.post(
558
+ `/domain/${encodeURIComponent(id)}/verify`,
559
+ void 0
560
+ );
561
+ });
562
+ }
563
+ /**
564
+ * Schedule a domain for deletion.
565
+ */
566
+ delete(id) {
567
+ return __async(this, null, function* () {
568
+ return this.http.delete(`/domain/${encodeURIComponent(id)}`);
569
+ });
570
+ }
571
+ };
572
+
573
+ // src/inbound/inbound.ts
574
+ var Inbound = class {
575
+ constructor(http) {
576
+ this.http = http;
577
+ /**
578
+ * Inbound channels route mail received on a domain to a webhook.
579
+ */
580
+ this.channels = {
581
+ /**
582
+ * Create an inbound channel for a verified domain.
583
+ *
584
+ * @example
585
+ * ```typescript
586
+ * const channel = await zupost.inbound.channels.create({
587
+ * name: 'Support inbox',
588
+ * domainId: 'dom_123',
589
+ * webhookUrl: 'https://example.com/zupost/inbound',
590
+ * webhookSecret: process.env.ZUPOST_INBOUND_SECRET!,
591
+ * });
592
+ * ```
593
+ */
594
+ create: (options) => __async(this, null, function* () {
595
+ return this.http.post("/inbound-channel", options);
596
+ })
597
+ };
598
+ }
599
+ };
600
+
504
601
  // src/zupost.ts
505
602
  var _client;
506
603
  var Zupost = class {
@@ -516,6 +613,8 @@ var Zupost = class {
516
613
  this.campaigns = new Campaigns(__privateGet(this, _client));
517
614
  this.contacts = new Contacts(__privateGet(this, _client));
518
615
  this.sequences = new Sequences(__privateGet(this, _client));
616
+ this.domains = new Domains(__privateGet(this, _client));
617
+ this.inbound = new Inbound(__privateGet(this, _client));
519
618
  }
520
619
  };
521
620
  _client = new WeakMap();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "zupost",
3
- "version": "0.5.1",
3
+ "version": "0.6.1",
4
4
  "description": "Node.js SDK for Zupost",
5
5
  "engines": {
6
6
  "node": ">=20"