zupost 0.6.0 → 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -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
@@ -9,9 +9,9 @@ type HttpMethod = 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE';
9
9
  declare class HttpClient {
10
10
  #private;
11
11
  constructor(apiKey: string, baseUrl: string, userAgent: string);
12
- request<T = unknown>(path: string, method: HttpMethod, body?: unknown): Promise<T>;
12
+ request<T = unknown>(path: string, method: HttpMethod, body?: unknown, extraHeaders?: Record<string, string>): Promise<T>;
13
13
  get<T = unknown>(path: string): Promise<T>;
14
- post<T = unknown>(path: string, body: unknown): Promise<T>;
14
+ post<T = unknown>(path: string, body: unknown, extraHeaders?: Record<string, string>): Promise<T>;
15
15
  patch<T = unknown>(path: string, body: unknown): Promise<T>;
16
16
  delete<T = unknown>(path: string, body?: unknown): Promise<T>;
17
17
  }
@@ -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
  /**
@@ -109,6 +113,12 @@ interface SendEmailOptions {
109
113
  /** The file content as a Base64-encoded string (e.g., "JVBERi0xLjQKJ..."). */
110
114
  content: string;
111
115
  }>;
116
+ /**
117
+ * zupost Platform only: a domain grant token obtained from a completed
118
+ * onboarding session. Set it to send from an end customer's domain that was
119
+ * connected through your platform. The `from` address must be on that domain.
120
+ */
121
+ domainToken?: string;
112
122
  }
113
123
  /**
114
124
  * Response from sending an email.
@@ -795,6 +805,99 @@ declare class Inbound {
795
805
  };
796
806
  }
797
807
 
808
+ /** Optional visual customization of the zupost-hosted connect page. */
809
+ interface OnboardingSessionBranding {
810
+ brandName?: string;
811
+ brandLogoUrl?: string;
812
+ brandColor?: string;
813
+ }
814
+ interface CreateOnboardingSessionOptions {
815
+ /**
816
+ * URL the end user is redirected back to after finishing the flow. Its host
817
+ * must be in your platform organization's allowed redirect hosts. zupost
818
+ * appends an `onboarding_session_id` query parameter on return.
819
+ */
820
+ returnUrl: string;
821
+ /** Optional domain to pre-fill on the connect page, e.g. `customer.com`. */
822
+ domain?: string;
823
+ /** Optional branding overrides for the hosted page. */
824
+ branding?: OnboardingSessionBranding;
825
+ }
826
+ interface CreateOnboardingSessionResponse {
827
+ /** The onboarding session id; use it with {@link OnboardingSessions.get}. */
828
+ id: string;
829
+ /** The zupost-hosted URL to redirect your end user to. */
830
+ url: string;
831
+ /** ISO timestamp after which the session can no longer be completed. */
832
+ expiresAt: string;
833
+ }
834
+ type OnboardingSessionStatus = 'OPEN' | 'COMPLETED' | 'EXPIRED';
835
+ type GrantStatus = 'PENDING' | 'ACTIVE' | 'REVOKED';
836
+ /** The grant produced once a session completes. */
837
+ interface OnboardingSessionGrant {
838
+ id: string;
839
+ /**
840
+ * The secret domain-grant token used to send from the connected domain.
841
+ * Present once the session is `COMPLETED`.
842
+ */
843
+ token: string | null;
844
+ status: GrantStatus;
845
+ domainName: string | null;
846
+ }
847
+ interface OnboardingSession {
848
+ id: string;
849
+ status: OnboardingSessionStatus;
850
+ domainName: string | null;
851
+ expiresAt: string;
852
+ /** Populated once `status` is `COMPLETED`. */
853
+ grant: OnboardingSessionGrant | null;
854
+ }
855
+
856
+ /**
857
+ * Platform API.
858
+ *
859
+ * For zupost Platform organizations that build products on top of zupost. Start
860
+ * a hosted, no-account domain-connect session for one of your end customers,
861
+ * redirect them to it, then exchange the completed session for a domain grant
862
+ * token you store and send with (via `zupost.emails.send({ ..., domainToken })`).
863
+ */
864
+ declare class Platform {
865
+ private readonly http;
866
+ constructor(http: HttpClient);
867
+ /** Hosted domain-connect onboarding sessions. */
868
+ readonly onboardingSessions: {
869
+ /**
870
+ * Start a hosted domain-connect onboarding session. Redirect your end user
871
+ * to the returned `url`; when they finish, zupost sends them back to your
872
+ * `returnUrl` with an `onboarding_session_id` query parameter that you can
873
+ * exchange via {@link get}.
874
+ *
875
+ * @example
876
+ * ```typescript
877
+ * const session = await zupost.platform.onboardingSessions.create({
878
+ * returnUrl: 'https://app.example.com/zupost/return',
879
+ * domain: 'customer.com',
880
+ * });
881
+ * // redirect the user to session.url
882
+ * ```
883
+ */
884
+ create: (options: CreateOnboardingSessionOptions) => Promise<CreateOnboardingSessionResponse>;
885
+ /**
886
+ * Fetch an onboarding session. Once its `status` is `COMPLETED`, read
887
+ * `grant.token` — the credential you persist and send with.
888
+ *
889
+ * @example
890
+ * ```typescript
891
+ * const session = await zupost.platform.onboardingSessions.get(id);
892
+ * if (session.status === 'COMPLETED') {
893
+ * await store(session.domainName, session.grant?.token);
894
+ * }
895
+ * ```
896
+ */
897
+ get: (id: string) => Promise<OnboardingSession>;
898
+ };
899
+ }
900
+
798
901
  interface ZupostOptions {
799
902
  /**
800
903
  * Custom API URL. Defaults to 'https://api.zupost.com'.
@@ -831,6 +934,12 @@ declare class Zupost {
831
934
  * your own webhook through an inbound channel.
832
935
  */
833
936
  readonly inbound: Inbound;
937
+ /**
938
+ * Platform API. For zupost Platform organizations: run hosted domain-connect
939
+ * onboarding for your end customers and obtain domain grant tokens to send
940
+ * on their behalf.
941
+ */
942
+ readonly platform: Platform;
834
943
  constructor(apiKey: string, options?: ZupostOptions);
835
944
  }
836
945
 
@@ -900,4 +1009,4 @@ declare function defineSequence<TSteps extends Record<string, SequenceStep>>(def
900
1009
  steps: TSteps;
901
1010
  }): SequenceDefinition;
902
1011
 
903
- 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 };
1012
+ export { type BranchCondition, type Contact, type ContactEvent, type ContactEventType, type ContactExport, type ContactTag, type CreateContactOptions, type CreateDomainOptions, type CreateInboundChannelOptions, type CreateOnboardingSessionOptions, type CreateOnboardingSessionResponse, type CreateSequenceOptions, type DeleteDomainResponse, type Domain, type DomainDnsRecord, type DomainDnsRecordType, type DomainVerificationStatus, type EmailRecipientType, type ForgetContactResponse, type GrantStatus, type InboundChannel, type ListContactsOptions, type ListContactsResponse, type ListEventsOptions, type ListEventsResponse, type ListRunsOptions, type ListRunsResponse, type ListSequencesOptions, type ListSequencesResponse, type OnboardingSession, type OnboardingSessionBranding, type OnboardingSessionGrant, type OnboardingSessionStatus, 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
@@ -9,9 +9,9 @@ type HttpMethod = 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE';
9
9
  declare class HttpClient {
10
10
  #private;
11
11
  constructor(apiKey: string, baseUrl: string, userAgent: string);
12
- request<T = unknown>(path: string, method: HttpMethod, body?: unknown): Promise<T>;
12
+ request<T = unknown>(path: string, method: HttpMethod, body?: unknown, extraHeaders?: Record<string, string>): Promise<T>;
13
13
  get<T = unknown>(path: string): Promise<T>;
14
- post<T = unknown>(path: string, body: unknown): Promise<T>;
14
+ post<T = unknown>(path: string, body: unknown, extraHeaders?: Record<string, string>): Promise<T>;
15
15
  patch<T = unknown>(path: string, body: unknown): Promise<T>;
16
16
  delete<T = unknown>(path: string, body?: unknown): Promise<T>;
17
17
  }
@@ -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
  /**
@@ -109,6 +113,12 @@ interface SendEmailOptions {
109
113
  /** The file content as a Base64-encoded string (e.g., "JVBERi0xLjQKJ..."). */
110
114
  content: string;
111
115
  }>;
116
+ /**
117
+ * zupost Platform only: a domain grant token obtained from a completed
118
+ * onboarding session. Set it to send from an end customer's domain that was
119
+ * connected through your platform. The `from` address must be on that domain.
120
+ */
121
+ domainToken?: string;
112
122
  }
113
123
  /**
114
124
  * Response from sending an email.
@@ -795,6 +805,99 @@ declare class Inbound {
795
805
  };
796
806
  }
797
807
 
808
+ /** Optional visual customization of the zupost-hosted connect page. */
809
+ interface OnboardingSessionBranding {
810
+ brandName?: string;
811
+ brandLogoUrl?: string;
812
+ brandColor?: string;
813
+ }
814
+ interface CreateOnboardingSessionOptions {
815
+ /**
816
+ * URL the end user is redirected back to after finishing the flow. Its host
817
+ * must be in your platform organization's allowed redirect hosts. zupost
818
+ * appends an `onboarding_session_id` query parameter on return.
819
+ */
820
+ returnUrl: string;
821
+ /** Optional domain to pre-fill on the connect page, e.g. `customer.com`. */
822
+ domain?: string;
823
+ /** Optional branding overrides for the hosted page. */
824
+ branding?: OnboardingSessionBranding;
825
+ }
826
+ interface CreateOnboardingSessionResponse {
827
+ /** The onboarding session id; use it with {@link OnboardingSessions.get}. */
828
+ id: string;
829
+ /** The zupost-hosted URL to redirect your end user to. */
830
+ url: string;
831
+ /** ISO timestamp after which the session can no longer be completed. */
832
+ expiresAt: string;
833
+ }
834
+ type OnboardingSessionStatus = 'OPEN' | 'COMPLETED' | 'EXPIRED';
835
+ type GrantStatus = 'PENDING' | 'ACTIVE' | 'REVOKED';
836
+ /** The grant produced once a session completes. */
837
+ interface OnboardingSessionGrant {
838
+ id: string;
839
+ /**
840
+ * The secret domain-grant token used to send from the connected domain.
841
+ * Present once the session is `COMPLETED`.
842
+ */
843
+ token: string | null;
844
+ status: GrantStatus;
845
+ domainName: string | null;
846
+ }
847
+ interface OnboardingSession {
848
+ id: string;
849
+ status: OnboardingSessionStatus;
850
+ domainName: string | null;
851
+ expiresAt: string;
852
+ /** Populated once `status` is `COMPLETED`. */
853
+ grant: OnboardingSessionGrant | null;
854
+ }
855
+
856
+ /**
857
+ * Platform API.
858
+ *
859
+ * For zupost Platform organizations that build products on top of zupost. Start
860
+ * a hosted, no-account domain-connect session for one of your end customers,
861
+ * redirect them to it, then exchange the completed session for a domain grant
862
+ * token you store and send with (via `zupost.emails.send({ ..., domainToken })`).
863
+ */
864
+ declare class Platform {
865
+ private readonly http;
866
+ constructor(http: HttpClient);
867
+ /** Hosted domain-connect onboarding sessions. */
868
+ readonly onboardingSessions: {
869
+ /**
870
+ * Start a hosted domain-connect onboarding session. Redirect your end user
871
+ * to the returned `url`; when they finish, zupost sends them back to your
872
+ * `returnUrl` with an `onboarding_session_id` query parameter that you can
873
+ * exchange via {@link get}.
874
+ *
875
+ * @example
876
+ * ```typescript
877
+ * const session = await zupost.platform.onboardingSessions.create({
878
+ * returnUrl: 'https://app.example.com/zupost/return',
879
+ * domain: 'customer.com',
880
+ * });
881
+ * // redirect the user to session.url
882
+ * ```
883
+ */
884
+ create: (options: CreateOnboardingSessionOptions) => Promise<CreateOnboardingSessionResponse>;
885
+ /**
886
+ * Fetch an onboarding session. Once its `status` is `COMPLETED`, read
887
+ * `grant.token` — the credential you persist and send with.
888
+ *
889
+ * @example
890
+ * ```typescript
891
+ * const session = await zupost.platform.onboardingSessions.get(id);
892
+ * if (session.status === 'COMPLETED') {
893
+ * await store(session.domainName, session.grant?.token);
894
+ * }
895
+ * ```
896
+ */
897
+ get: (id: string) => Promise<OnboardingSession>;
898
+ };
899
+ }
900
+
798
901
  interface ZupostOptions {
799
902
  /**
800
903
  * Custom API URL. Defaults to 'https://api.zupost.com'.
@@ -831,6 +934,12 @@ declare class Zupost {
831
934
  * your own webhook through an inbound channel.
832
935
  */
833
936
  readonly inbound: Inbound;
937
+ /**
938
+ * Platform API. For zupost Platform organizations: run hosted domain-connect
939
+ * onboarding for your end customers and obtain domain grant tokens to send
940
+ * on their behalf.
941
+ */
942
+ readonly platform: Platform;
834
943
  constructor(apiKey: string, options?: ZupostOptions);
835
944
  }
836
945
 
@@ -900,4 +1009,4 @@ declare function defineSequence<TSteps extends Record<string, SequenceStep>>(def
900
1009
  steps: TSteps;
901
1010
  }): SequenceDefinition;
902
1011
 
903
- 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 };
1012
+ export { type BranchCondition, type Contact, type ContactEvent, type ContactEventType, type ContactExport, type ContactTag, type CreateContactOptions, type CreateDomainOptions, type CreateInboundChannelOptions, type CreateOnboardingSessionOptions, type CreateOnboardingSessionResponse, type CreateSequenceOptions, type DeleteDomainResponse, type Domain, type DomainDnsRecord, type DomainDnsRecordType, type DomainVerificationStatus, type EmailRecipientType, type ForgetContactResponse, type GrantStatus, type InboundChannel, type ListContactsOptions, type ListContactsResponse, type ListEventsOptions, type ListEventsResponse, type ListRunsOptions, type ListRunsResponse, type ListSequencesOptions, type ListSequencesResponse, type OnboardingSession, type OnboardingSessionBranding, type OnboardingSessionGrant, type OnboardingSessionStatus, 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.6.0";
82
+ var version = "0.7.0";
83
83
 
84
84
  // src/errors.ts
85
85
  var ZupostError = class _ZupostError extends Error {
@@ -145,13 +145,18 @@ var HttpClient = class {
145
145
  "User-Agent": userAgent
146
146
  });
147
147
  }
148
- request(path, method, body) {
148
+ request(path, method, body, extraHeaders) {
149
149
  return __async(this, null, function* () {
150
150
  const url = `${__privateGet(this, _baseUrl)}/${path.replace(/^\//, "")}`;
151
151
  const headers = new Headers(__privateGet(this, _defaultHeaders));
152
152
  if (method !== "GET") {
153
153
  headers.set("Idempotency-Key", crypto.randomUUID());
154
154
  }
155
+ if (extraHeaders) {
156
+ for (const [key, value] of Object.entries(extraHeaders)) {
157
+ headers.set(key, value);
158
+ }
159
+ }
155
160
  const init = { method, headers };
156
161
  if (body !== void 0) {
157
162
  init.body = JSON.stringify(body);
@@ -183,9 +188,9 @@ var HttpClient = class {
183
188
  return this.request(path, "GET");
184
189
  });
185
190
  }
186
- post(path, body) {
191
+ post(path, body, extraHeaders) {
187
192
  return __async(this, null, function* () {
188
- return this.request(path, "POST", body);
193
+ return this.request(path, "POST", body, extraHeaders);
189
194
  });
190
195
  }
191
196
  patch(path, body) {
@@ -267,8 +272,8 @@ var Emails = class {
267
272
  if (inlineCount > 1) {
268
273
  throw new Error("Provide only one of html, markdown, or react");
269
274
  }
270
- if (inlineCount === 0 && !options.templateId) {
271
- throw new Error("Provide one of html, markdown, react, or templateId");
275
+ if (inlineCount === 0 && !options.templateId && !options.text) {
276
+ throw new Error("Provide one of html, markdown, react, text, or templateId");
272
277
  }
273
278
  const payload = __spreadValues({}, options);
274
279
  if (options.react) {
@@ -277,6 +282,13 @@ var Emails = class {
277
282
  delete payload.react;
278
283
  delete payload.reactOptions;
279
284
  }
285
+ const { domainToken } = options;
286
+ delete payload.domainToken;
287
+ if (domainToken) {
288
+ return this.http.post("email/send", payload, {
289
+ "X-Zupost-Domain-Token": domainToken
290
+ });
291
+ }
280
292
  return this.http.post("email/send", payload);
281
293
  });
282
294
  }
@@ -631,6 +643,54 @@ var Inbound = class {
631
643
  }
632
644
  };
633
645
 
646
+ // src/platform/platform.ts
647
+ var Platform = class {
648
+ constructor(http) {
649
+ this.http = http;
650
+ /** Hosted domain-connect onboarding sessions. */
651
+ this.onboardingSessions = {
652
+ /**
653
+ * Start a hosted domain-connect onboarding session. Redirect your end user
654
+ * to the returned `url`; when they finish, zupost sends them back to your
655
+ * `returnUrl` with an `onboarding_session_id` query parameter that you can
656
+ * exchange via {@link get}.
657
+ *
658
+ * @example
659
+ * ```typescript
660
+ * const session = await zupost.platform.onboardingSessions.create({
661
+ * returnUrl: 'https://app.example.com/zupost/return',
662
+ * domain: 'customer.com',
663
+ * });
664
+ * // redirect the user to session.url
665
+ * ```
666
+ */
667
+ create: (options) => __async(this, null, function* () {
668
+ return this.http.post(
669
+ "/platform/onboarding-sessions",
670
+ options
671
+ );
672
+ }),
673
+ /**
674
+ * Fetch an onboarding session. Once its `status` is `COMPLETED`, read
675
+ * `grant.token` — the credential you persist and send with.
676
+ *
677
+ * @example
678
+ * ```typescript
679
+ * const session = await zupost.platform.onboardingSessions.get(id);
680
+ * if (session.status === 'COMPLETED') {
681
+ * await store(session.domainName, session.grant?.token);
682
+ * }
683
+ * ```
684
+ */
685
+ get: (id) => __async(this, null, function* () {
686
+ return this.http.get(
687
+ `/platform/onboarding-sessions/${encodeURIComponent(id)}`
688
+ );
689
+ })
690
+ };
691
+ }
692
+ };
693
+
634
694
  // src/zupost.ts
635
695
  var _client;
636
696
  var Zupost = class {
@@ -648,6 +708,7 @@ var Zupost = class {
648
708
  this.sequences = new Sequences(__privateGet(this, _client));
649
709
  this.domains = new Domains(__privateGet(this, _client));
650
710
  this.inbound = new Inbound(__privateGet(this, _client));
711
+ this.platform = new Platform(__privateGet(this, _client));
651
712
  }
652
713
  };
653
714
  _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.6.0";
47
+ var version = "0.7.0";
48
48
 
49
49
  // src/errors.ts
50
50
  var ZupostError = class _ZupostError extends Error {
@@ -110,13 +110,18 @@ var HttpClient = class {
110
110
  "User-Agent": userAgent
111
111
  });
112
112
  }
113
- request(path, method, body) {
113
+ request(path, method, body, extraHeaders) {
114
114
  return __async(this, null, function* () {
115
115
  const url = `${__privateGet(this, _baseUrl)}/${path.replace(/^\//, "")}`;
116
116
  const headers = new Headers(__privateGet(this, _defaultHeaders));
117
117
  if (method !== "GET") {
118
118
  headers.set("Idempotency-Key", crypto.randomUUID());
119
119
  }
120
+ if (extraHeaders) {
121
+ for (const [key, value] of Object.entries(extraHeaders)) {
122
+ headers.set(key, value);
123
+ }
124
+ }
120
125
  const init = { method, headers };
121
126
  if (body !== void 0) {
122
127
  init.body = JSON.stringify(body);
@@ -148,9 +153,9 @@ var HttpClient = class {
148
153
  return this.request(path, "GET");
149
154
  });
150
155
  }
151
- post(path, body) {
156
+ post(path, body, extraHeaders) {
152
157
  return __async(this, null, function* () {
153
- return this.request(path, "POST", body);
158
+ return this.request(path, "POST", body, extraHeaders);
154
159
  });
155
160
  }
156
161
  patch(path, body) {
@@ -232,8 +237,8 @@ var Emails = class {
232
237
  if (inlineCount > 1) {
233
238
  throw new Error("Provide only one of html, markdown, or react");
234
239
  }
235
- if (inlineCount === 0 && !options.templateId) {
236
- throw new Error("Provide one of html, markdown, react, or templateId");
240
+ if (inlineCount === 0 && !options.templateId && !options.text) {
241
+ throw new Error("Provide one of html, markdown, react, text, or templateId");
237
242
  }
238
243
  const payload = __spreadValues({}, options);
239
244
  if (options.react) {
@@ -242,6 +247,13 @@ var Emails = class {
242
247
  delete payload.react;
243
248
  delete payload.reactOptions;
244
249
  }
250
+ const { domainToken } = options;
251
+ delete payload.domainToken;
252
+ if (domainToken) {
253
+ return this.http.post("email/send", payload, {
254
+ "X-Zupost-Domain-Token": domainToken
255
+ });
256
+ }
245
257
  return this.http.post("email/send", payload);
246
258
  });
247
259
  }
@@ -596,6 +608,54 @@ var Inbound = class {
596
608
  }
597
609
  };
598
610
 
611
+ // src/platform/platform.ts
612
+ var Platform = class {
613
+ constructor(http) {
614
+ this.http = http;
615
+ /** Hosted domain-connect onboarding sessions. */
616
+ this.onboardingSessions = {
617
+ /**
618
+ * Start a hosted domain-connect onboarding session. Redirect your end user
619
+ * to the returned `url`; when they finish, zupost sends them back to your
620
+ * `returnUrl` with an `onboarding_session_id` query parameter that you can
621
+ * exchange via {@link get}.
622
+ *
623
+ * @example
624
+ * ```typescript
625
+ * const session = await zupost.platform.onboardingSessions.create({
626
+ * returnUrl: 'https://app.example.com/zupost/return',
627
+ * domain: 'customer.com',
628
+ * });
629
+ * // redirect the user to session.url
630
+ * ```
631
+ */
632
+ create: (options) => __async(this, null, function* () {
633
+ return this.http.post(
634
+ "/platform/onboarding-sessions",
635
+ options
636
+ );
637
+ }),
638
+ /**
639
+ * Fetch an onboarding session. Once its `status` is `COMPLETED`, read
640
+ * `grant.token` — the credential you persist and send with.
641
+ *
642
+ * @example
643
+ * ```typescript
644
+ * const session = await zupost.platform.onboardingSessions.get(id);
645
+ * if (session.status === 'COMPLETED') {
646
+ * await store(session.domainName, session.grant?.token);
647
+ * }
648
+ * ```
649
+ */
650
+ get: (id) => __async(this, null, function* () {
651
+ return this.http.get(
652
+ `/platform/onboarding-sessions/${encodeURIComponent(id)}`
653
+ );
654
+ })
655
+ };
656
+ }
657
+ };
658
+
599
659
  // src/zupost.ts
600
660
  var _client;
601
661
  var Zupost = class {
@@ -613,6 +673,7 @@ var Zupost = class {
613
673
  this.sequences = new Sequences(__privateGet(this, _client));
614
674
  this.domains = new Domains(__privateGet(this, _client));
615
675
  this.inbound = new Inbound(__privateGet(this, _client));
676
+ this.platform = new Platform(__privateGet(this, _client));
616
677
  }
617
678
  };
618
679
  _client = new WeakMap();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "zupost",
3
- "version": "0.6.0",
3
+ "version": "0.7.0",
4
4
  "description": "Node.js SDK for Zupost",
5
5
  "engines": {
6
6
  "node": ">=20"