@zyphr-dev/node-sdk 0.1.53 → 0.1.55

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zyphr-dev/node-sdk",
3
- "version": "0.1.53",
3
+ "version": "0.1.55",
4
4
  "description": "Official Zyphr SDK for Node.js, React, and React Native",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",
@@ -318,6 +318,7 @@ src/models/RenderTemplateRequest.ts
318
318
  src/models/ReorderWorkflowStepsRequest.ts
319
319
  src/models/ReplayWebhookEventsRequest.ts
320
320
  src/models/RequestMeta.ts
321
+ src/models/ResendEmailVerificationRequest.ts
321
322
  src/models/ResetPasswordRequest.ts
322
323
  src/models/ResetPasswordResponse.ts
323
324
  src/models/ResubscribeRequest.ts
@@ -522,9 +523,6 @@ src/models/WebhookIpsResponseData.ts
522
523
  src/models/WebhookJobResponse.ts
523
524
  src/models/WebhookListResponse.ts
524
525
  src/models/WebhookMetricsResponse.ts
525
- src/models/WebhookRegion.ts
526
- src/models/WebhookRegionsResponse.ts
527
- src/models/WebhookRegionsResponseData.ts
528
526
  src/models/WebhookReplayResponse.ts
529
527
  src/models/WebhookResponse.ts
530
528
  src/models/WebhookSecretRotateResponse.ts
package/src/client.ts CHANGED
@@ -34,6 +34,7 @@ import {
34
34
  DevicesApi,
35
35
  DomainsApi,
36
36
  UtilityApi,
37
+ WorkflowsApi,
37
38
  EmailsApi,
38
39
  InboundEmailApi,
39
40
  InboxApi,
@@ -103,6 +104,15 @@ export class Zyphr {
103
104
  /** Publishable-key-safe utilities: password policy + pre-submit strength check. */
104
105
  readonly utility: UtilityApi;
105
106
  readonly domains: DomainsApi;
107
+ /**
108
+ * Multi-step workflow definitions and triggering (sc-7926).
109
+ *
110
+ * All 12 operations are API-key authenticated with dedicated
111
+ * `workflows:read` / `workflows:write` / `workflows:execute` scopes, so this
112
+ * is deliberate public surface. It was generated but never wired onto the
113
+ * facade, which made the documented `zyphr.workflows.*` calls throw.
114
+ */
115
+ readonly workflows: WorkflowsApi;
106
116
  /** Inbound (received) email — read access. Requires the `email:read` scope. */
107
117
  readonly inbound: InboundEmailApi;
108
118
 
@@ -162,6 +172,7 @@ export class Zyphr {
162
172
  this.devices = new DevicesApi(config);
163
173
  this.utility = new UtilityApi(config);
164
174
  this.domains = new DomainsApi(config);
175
+ this.workflows = new WorkflowsApi(config);
165
176
  this.inbound = new InboundEmailApi(config);
166
177
 
167
178
  this.waas = {
@@ -28,6 +28,11 @@ import {
28
28
  SetSelfApplicationTestRecipientsRequestToJSON,
29
29
  } from '../models/index';
30
30
 
31
+ export interface AuthApplicationApiExportEndUserDataRequest {
32
+ id: string;
33
+ userId: string;
34
+ }
35
+
31
36
  export interface AuthApplicationApiSetSelfApplicationTestRecipientsOperationRequest {
32
37
  setSelfApplicationTestRecipientsRequest: SetSelfApplicationTestRecipientsRequest;
33
38
  }
@@ -39,6 +44,23 @@ export interface AuthApplicationApiSetSelfApplicationTestRecipientsOperationRequ
39
44
  * @interface AuthApplicationApiInterface
40
45
  */
41
46
  export interface AuthApplicationApiInterface {
47
+ /**
48
+ * Returns a machine-readable JSON bundle of everything stored about one end user, for answering a GDPR Art. 15 (access) or Art. 20 (portability) request. Zyphr is a **processor**: we do not answer data subjects directly. This endpoint gives you, the controller, the data needed to respond to your own end user. **Credentials are deliberately excluded** and are listed in `export_metadata.excluded`: password hashes, session refresh-token hashes, MFA secrets, OAuth access/refresh tokens and WebAuthn public keys. These are authentication artifacts rather than personal data about the subject, and including them would turn this endpoint into a credential-exfiltration path. Message history is capped at the 1,000 most recent messages; `export_metadata.message_history_truncated` reports whether the cap was hit.
49
+ * @summary Export all data held about an end user
50
+ * @param {string} id Application ID
51
+ * @param {string} userId End user ID
52
+ * @param {*} [options] Override http request option.
53
+ * @throws {RequiredError}
54
+ * @memberof AuthApplicationApiInterface
55
+ */
56
+ exportEndUserDataRaw(requestParameters: AuthApplicationApiExportEndUserDataRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<runtime.ApiResponse<void>>;
57
+
58
+ /**
59
+ * Returns a machine-readable JSON bundle of everything stored about one end user, for answering a GDPR Art. 15 (access) or Art. 20 (portability) request. Zyphr is a **processor**: we do not answer data subjects directly. This endpoint gives you, the controller, the data needed to respond to your own end user. **Credentials are deliberately excluded** and are listed in `export_metadata.excluded`: password hashes, session refresh-token hashes, MFA secrets, OAuth access/refresh tokens and WebAuthn public keys. These are authentication artifacts rather than personal data about the subject, and including them would turn this endpoint into a credential-exfiltration path. Message history is capped at the 1,000 most recent messages; `export_metadata.message_history_truncated` reports whether the cap was hit.
60
+ * Export all data held about an end user
61
+ */
62
+ exportEndUserData(id: string, userId: string, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<void>;
63
+
42
64
  /**
43
65
  * Return non-sensitive metadata about the application whose credentials authenticated this request. Lets an integrator read their own application_id (the sole tenant discriminator embedded in every end-user token) directly from the API, rather than only from the dashboard UI or by decoding a token. Returns only id, name, the calling environment\'s mode, and the JWT signing algorithm — never secrets, signing keys, or account-internal fields.
44
66
  * @summary Get the authenticating application
@@ -77,6 +99,47 @@ export interface AuthApplicationApiInterface {
77
99
  */
78
100
  export class AuthApplicationApi extends runtime.BaseAPI implements AuthApplicationApiInterface {
79
101
 
102
+ /**
103
+ * Returns a machine-readable JSON bundle of everything stored about one end user, for answering a GDPR Art. 15 (access) or Art. 20 (portability) request. Zyphr is a **processor**: we do not answer data subjects directly. This endpoint gives you, the controller, the data needed to respond to your own end user. **Credentials are deliberately excluded** and are listed in `export_metadata.excluded`: password hashes, session refresh-token hashes, MFA secrets, OAuth access/refresh tokens and WebAuthn public keys. These are authentication artifacts rather than personal data about the subject, and including them would turn this endpoint into a credential-exfiltration path. Message history is capped at the 1,000 most recent messages; `export_metadata.message_history_truncated` reports whether the cap was hit.
104
+ * Export all data held about an end user
105
+ */
106
+ async exportEndUserDataRaw(requestParameters: AuthApplicationApiExportEndUserDataRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<runtime.ApiResponse<void>> {
107
+ if (requestParameters['id'] == null) {
108
+ throw new runtime.RequiredError(
109
+ 'id',
110
+ 'Required parameter "id" was null or undefined when calling exportEndUserData().'
111
+ );
112
+ }
113
+
114
+ if (requestParameters['userId'] == null) {
115
+ throw new runtime.RequiredError(
116
+ 'userId',
117
+ 'Required parameter "userId" was null or undefined when calling exportEndUserData().'
118
+ );
119
+ }
120
+
121
+ const queryParameters: any = {};
122
+
123
+ const headerParameters: runtime.HTTPHeaders = {};
124
+
125
+ const response = await this.request({
126
+ path: `/v1/applications/{id}/users/{userId}/export`.replace(`{${"id"}}`, encodeURIComponent(String(requestParameters['id']))).replace(`{${"userId"}}`, encodeURIComponent(String(requestParameters['userId']))),
127
+ method: 'GET',
128
+ headers: headerParameters,
129
+ query: queryParameters,
130
+ }, initOverrides);
131
+
132
+ return new runtime.VoidApiResponse(response);
133
+ }
134
+
135
+ /**
136
+ * Returns a machine-readable JSON bundle of everything stored about one end user, for answering a GDPR Art. 15 (access) or Art. 20 (portability) request. Zyphr is a **processor**: we do not answer data subjects directly. This endpoint gives you, the controller, the data needed to respond to your own end user. **Credentials are deliberately excluded** and are listed in `export_metadata.excluded`: password hashes, session refresh-token hashes, MFA secrets, OAuth access/refresh tokens and WebAuthn public keys. These are authentication artifacts rather than personal data about the subject, and including them would turn this endpoint into a credential-exfiltration path. Message history is capped at the 1,000 most recent messages; `export_metadata.message_history_truncated` reports whether the cap was hit.
137
+ * Export all data held about an end user
138
+ */
139
+ async exportEndUserData(id: string, userId: string, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<void> {
140
+ await this.exportEndUserDataRaw({ id: id, userId: userId }, initOverrides);
141
+ }
142
+
80
143
  /**
81
144
  * Return non-sensitive metadata about the application whose credentials authenticated this request. Lets an integrator read their own application_id (the sole tenant discriminator embedded in every end-user token) directly from the API, rather than only from the dashboard UI or by decoding a token. Returns only id, name, the calling environment\'s mode, and the JWT signing algorithm — never secrets, signing keys, or account-internal fields.
82
145
  * Get the authenticating application
@@ -18,6 +18,7 @@ import type {
18
18
  ApiError,
19
19
  ConfirmEmailVerificationRequest,
20
20
  ConfirmEmailVerificationResponse,
21
+ ResendEmailVerificationRequest,
21
22
  SendEmailVerificationRequest,
22
23
  SuccessResult,
23
24
  } from '../models/index';
@@ -28,6 +29,8 @@ import {
28
29
  ConfirmEmailVerificationRequestToJSON,
29
30
  ConfirmEmailVerificationResponseFromJSON,
30
31
  ConfirmEmailVerificationResponseToJSON,
32
+ ResendEmailVerificationRequestFromJSON,
33
+ ResendEmailVerificationRequestToJSON,
31
34
  SendEmailVerificationRequestFromJSON,
32
35
  SendEmailVerificationRequestToJSON,
33
36
  SuccessResultFromJSON,
@@ -38,8 +41,8 @@ export interface AuthEmailVerificationApiConfirmEmailVerificationOperationReques
38
41
  confirmEmailVerificationRequest: ConfirmEmailVerificationRequest;
39
42
  }
40
43
 
41
- export interface AuthEmailVerificationApiResendEmailVerificationRequest {
42
- sendEmailVerificationRequest?: SendEmailVerificationRequest;
44
+ export interface AuthEmailVerificationApiResendEmailVerificationOperationRequest {
45
+ resendEmailVerificationRequest?: ResendEmailVerificationRequest;
43
46
  }
44
47
 
45
48
  export interface AuthEmailVerificationApiSendEmailVerificationOperationRequest {
@@ -54,7 +57,7 @@ export interface AuthEmailVerificationApiSendEmailVerificationOperationRequest {
54
57
  */
55
58
  export interface AuthEmailVerificationApiInterface {
56
59
  /**
57
- * Verify the user\'s email using the token from the verification email.
60
+ * Verify the user\'s email using a token you collected yourself. IMPORTANT: the emailed verification LINK verifies the address server-side **on click** and then redirects to `redirect_url`. So if you take the token off that redirect and post it here, it is already redeemed — and this endpoint treats that as an idempotent **success** (`200` with `already_verified: true`), not an error. Only a genuinely invalid / expired / unknown token returns `400`. `send` / `confirm` / `resend` are NOT a mandatory matched set — `confirm` is for flows where you collect the token directly rather than landing the hosted redirect. Recommended pattern for the redirect landing: call `confirm`, ignore its result, then read the user\'s verified state back and report that — correct whether or not the link already consumed the token.
58
61
  * @summary Confirm email verification
59
62
  * @param {ConfirmEmailVerificationRequest} confirmEmailVerificationRequest
60
63
  * @param {*} [options] Override http request option.
@@ -64,7 +67,7 @@ export interface AuthEmailVerificationApiInterface {
64
67
  confirmEmailVerificationRaw(requestParameters: AuthEmailVerificationApiConfirmEmailVerificationOperationRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<runtime.ApiResponse<ConfirmEmailVerificationResponse>>;
65
68
 
66
69
  /**
67
- * Verify the user\'s email using the token from the verification email.
70
+ * Verify the user\'s email using a token you collected yourself. IMPORTANT: the emailed verification LINK verifies the address server-side **on click** and then redirects to `redirect_url`. So if you take the token off that redirect and post it here, it is already redeemed — and this endpoint treats that as an idempotent **success** (`200` with `already_verified: true`), not an error. Only a genuinely invalid / expired / unknown token returns `400`. `send` / `confirm` / `resend` are NOT a mandatory matched set — `confirm` is for flows where you collect the token directly rather than landing the hosted redirect. Recommended pattern for the redirect landing: call `confirm`, ignore its result, then read the user\'s verified state back and report that — correct whether or not the link already consumed the token.
68
71
  * Confirm email verification
69
72
  */
70
73
  confirmEmailVerification(confirmEmailVerificationRequest: ConfirmEmailVerificationRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<ConfirmEmailVerificationResponse>;
@@ -72,21 +75,21 @@ export interface AuthEmailVerificationApiInterface {
72
75
  /**
73
76
  * Resend the verification email to the authenticated user. Rate limited to once per 60 seconds.
74
77
  * @summary Resend email verification
75
- * @param {SendEmailVerificationRequest} [sendEmailVerificationRequest]
78
+ * @param {ResendEmailVerificationRequest} [resendEmailVerificationRequest]
76
79
  * @param {*} [options] Override http request option.
77
80
  * @throws {RequiredError}
78
81
  * @memberof AuthEmailVerificationApiInterface
79
82
  */
80
- resendEmailVerificationRaw(requestParameters: AuthEmailVerificationApiResendEmailVerificationRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<runtime.ApiResponse<SuccessResult>>;
83
+ resendEmailVerificationRaw(requestParameters: AuthEmailVerificationApiResendEmailVerificationOperationRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<runtime.ApiResponse<SuccessResult>>;
81
84
 
82
85
  /**
83
86
  * Resend the verification email to the authenticated user. Rate limited to once per 60 seconds.
84
87
  * Resend email verification
85
88
  */
86
- resendEmailVerification(sendEmailVerificationRequest?: SendEmailVerificationRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<SuccessResult>;
89
+ resendEmailVerification(resendEmailVerificationRequest?: ResendEmailVerificationRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<SuccessResult>;
87
90
 
88
91
  /**
89
- * Send an email verification link to the authenticated user.
92
+ * Send an email verification link to the authenticated user. Requires all three credentials simultaneously: the application key (`X-Application-Key`), the application secret (`X-Application-Secret`), and the end user\'s `Authorization: Bearer` token. If the recipient is blocked by the application\'s `auth_email_mode=allowlist` gate, the request is still **accepted with 200** (mirroring `POST /auth/forgot-password`): no email is sent, and the suppression is recorded as a `messages` row (`status=suppressed`, `status_reason=recipient_not_allowlisted`) and an `email.suppressed` webhook. It is NOT a 500.
90
93
  * @summary Send email verification
91
94
  * @param {SendEmailVerificationRequest} [sendEmailVerificationRequest]
92
95
  * @param {*} [options] Override http request option.
@@ -96,7 +99,7 @@ export interface AuthEmailVerificationApiInterface {
96
99
  sendEmailVerificationRaw(requestParameters: AuthEmailVerificationApiSendEmailVerificationOperationRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<runtime.ApiResponse<SuccessResult>>;
97
100
 
98
101
  /**
99
- * Send an email verification link to the authenticated user.
102
+ * Send an email verification link to the authenticated user. Requires all three credentials simultaneously: the application key (`X-Application-Key`), the application secret (`X-Application-Secret`), and the end user\'s `Authorization: Bearer` token. If the recipient is blocked by the application\'s `auth_email_mode=allowlist` gate, the request is still **accepted with 200** (mirroring `POST /auth/forgot-password`): no email is sent, and the suppression is recorded as a `messages` row (`status=suppressed`, `status_reason=recipient_not_allowlisted`) and an `email.suppressed` webhook. It is NOT a 500.
100
103
  * Send email verification
101
104
  */
102
105
  sendEmailVerification(sendEmailVerificationRequest?: SendEmailVerificationRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<SuccessResult>;
@@ -109,7 +112,7 @@ export interface AuthEmailVerificationApiInterface {
109
112
  export class AuthEmailVerificationApi extends runtime.BaseAPI implements AuthEmailVerificationApiInterface {
110
113
 
111
114
  /**
112
- * Verify the user\'s email using the token from the verification email.
115
+ * Verify the user\'s email using a token you collected yourself. IMPORTANT: the emailed verification LINK verifies the address server-side **on click** and then redirects to `redirect_url`. So if you take the token off that redirect and post it here, it is already redeemed — and this endpoint treats that as an idempotent **success** (`200` with `already_verified: true`), not an error. Only a genuinely invalid / expired / unknown token returns `400`. `send` / `confirm` / `resend` are NOT a mandatory matched set — `confirm` is for flows where you collect the token directly rather than landing the hosted redirect. Recommended pattern for the redirect landing: call `confirm`, ignore its result, then read the user\'s verified state back and report that — correct whether or not the link already consumed the token.
113
116
  * Confirm email verification
114
117
  */
115
118
  async confirmEmailVerificationRaw(requestParameters: AuthEmailVerificationApiConfirmEmailVerificationOperationRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<runtime.ApiResponse<ConfirmEmailVerificationResponse>> {
@@ -146,7 +149,7 @@ export class AuthEmailVerificationApi extends runtime.BaseAPI implements AuthEma
146
149
  }
147
150
 
148
151
  /**
149
- * Verify the user\'s email using the token from the verification email.
152
+ * Verify the user\'s email using a token you collected yourself. IMPORTANT: the emailed verification LINK verifies the address server-side **on click** and then redirects to `redirect_url`. So if you take the token off that redirect and post it here, it is already redeemed — and this endpoint treats that as an idempotent **success** (`200` with `already_verified: true`), not an error. Only a genuinely invalid / expired / unknown token returns `400`. `send` / `confirm` / `resend` are NOT a mandatory matched set — `confirm` is for flows where you collect the token directly rather than landing the hosted redirect. Recommended pattern for the redirect landing: call `confirm`, ignore its result, then read the user\'s verified state back and report that — correct whether or not the link already consumed the token.
150
153
  * Confirm email verification
151
154
  */
152
155
  async confirmEmailVerification(confirmEmailVerificationRequest: ConfirmEmailVerificationRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<ConfirmEmailVerificationResponse> {
@@ -158,7 +161,7 @@ export class AuthEmailVerificationApi extends runtime.BaseAPI implements AuthEma
158
161
  * Resend the verification email to the authenticated user. Rate limited to once per 60 seconds.
159
162
  * Resend email verification
160
163
  */
161
- async resendEmailVerificationRaw(requestParameters: AuthEmailVerificationApiResendEmailVerificationRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<runtime.ApiResponse<SuccessResult>> {
164
+ async resendEmailVerificationRaw(requestParameters: AuthEmailVerificationApiResendEmailVerificationOperationRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<runtime.ApiResponse<SuccessResult>> {
162
165
  const queryParameters: any = {};
163
166
 
164
167
  const headerParameters: runtime.HTTPHeaders = {};
@@ -186,7 +189,7 @@ export class AuthEmailVerificationApi extends runtime.BaseAPI implements AuthEma
186
189
  method: 'POST',
187
190
  headers: headerParameters,
188
191
  query: queryParameters,
189
- body: SendEmailVerificationRequestToJSON(requestParameters['sendEmailVerificationRequest']),
192
+ body: ResendEmailVerificationRequestToJSON(requestParameters['resendEmailVerificationRequest']),
190
193
  }, initOverrides);
191
194
 
192
195
  return new runtime.JSONApiResponse(response, (jsonValue) => SuccessResultFromJSON(jsonValue));
@@ -196,13 +199,13 @@ export class AuthEmailVerificationApi extends runtime.BaseAPI implements AuthEma
196
199
  * Resend the verification email to the authenticated user. Rate limited to once per 60 seconds.
197
200
  * Resend email verification
198
201
  */
199
- async resendEmailVerification(sendEmailVerificationRequest?: SendEmailVerificationRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<SuccessResult> {
200
- const response = await this.resendEmailVerificationRaw({ sendEmailVerificationRequest: sendEmailVerificationRequest }, initOverrides);
202
+ async resendEmailVerification(resendEmailVerificationRequest?: ResendEmailVerificationRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<SuccessResult> {
203
+ const response = await this.resendEmailVerificationRaw({ resendEmailVerificationRequest: resendEmailVerificationRequest }, initOverrides);
201
204
  return await response.value();
202
205
  }
203
206
 
204
207
  /**
205
- * Send an email verification link to the authenticated user.
208
+ * Send an email verification link to the authenticated user. Requires all three credentials simultaneously: the application key (`X-Application-Key`), the application secret (`X-Application-Secret`), and the end user\'s `Authorization: Bearer` token. If the recipient is blocked by the application\'s `auth_email_mode=allowlist` gate, the request is still **accepted with 200** (mirroring `POST /auth/forgot-password`): no email is sent, and the suppression is recorded as a `messages` row (`status=suppressed`, `status_reason=recipient_not_allowlisted`) and an `email.suppressed` webhook. It is NOT a 500.
206
209
  * Send email verification
207
210
  */
208
211
  async sendEmailVerificationRaw(requestParameters: AuthEmailVerificationApiSendEmailVerificationOperationRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<runtime.ApiResponse<SuccessResult>> {
@@ -240,7 +243,7 @@ export class AuthEmailVerificationApi extends runtime.BaseAPI implements AuthEma
240
243
  }
241
244
 
242
245
  /**
243
- * Send an email verification link to the authenticated user.
246
+ * Send an email verification link to the authenticated user. Requires all three credentials simultaneously: the application key (`X-Application-Key`), the application secret (`X-Application-Secret`), and the end user\'s `Authorization: Bearer` token. If the recipient is blocked by the application\'s `auth_email_mode=allowlist` gate, the request is still **accepted with 200** (mirroring `POST /auth/forgot-password`): no email is sent, and the suppression is recorded as a `messages` row (`status=suppressed`, `status_reason=recipient_not_allowlisted`) and an `email.suppressed` webhook. It is NOT a 500.
244
247
  * Send email verification
245
248
  */
246
249
  async sendEmailVerification(sendEmailVerificationRequest?: SendEmailVerificationRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<SuccessResult> {
@@ -167,7 +167,7 @@ export interface EmailsApiInterface {
167
167
  sendBatchEmail(sendBatchEmailRequest: SendBatchEmailRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<SendBatchEmailResponse>;
168
168
 
169
169
  /**
170
- * Queue an email for delivery. The email is processed asynchronously and you\'ll receive a message ID to track its status. You can provide content directly via `html`/`text` fields, or use a template by specifying `template_id` and `template_data`.
170
+ * Queue an email for delivery. The email is processed asynchronously and you\'ll receive a message ID to track its status. You can provide content directly via `html`/`text` fields, or use a template by specifying `template_id` and `template_data`. **CAN-SPAM compliance — actions required from you:** - **Set `classification`** to `transactional` or `marketing`. Unclassified is treated as marketing, the stricter reading. Transactional mail (password resets, receipts) is exempt from the opt-out and postal-address requirements. - **Set your postal address** in project settings. Commercial email must carry a valid physical postal address — the most commonly missed CAN-SPAM element. Marketing sends without one are flagged. - **Include an unsubscribe mechanism** on commercial email. Zyphr enforces suppression automatically once someone opts out, but the link itself is yours to include. See [Compliance Requirements](https://zyphr.dev/guides/compliance-requirements).
171
171
  * @summary Send an email
172
172
  * @param {SendEmailRequest} sendEmailRequest
173
173
  * @param {*} [options] Override http request option.
@@ -177,7 +177,7 @@ export interface EmailsApiInterface {
177
177
  sendEmailRaw(requestParameters: EmailsApiSendEmailOperationRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<runtime.ApiResponse<SendEmailResponse>>;
178
178
 
179
179
  /**
180
- * Queue an email for delivery. The email is processed asynchronously and you\'ll receive a message ID to track its status. You can provide content directly via `html`/`text` fields, or use a template by specifying `template_id` and `template_data`.
180
+ * Queue an email for delivery. The email is processed asynchronously and you\'ll receive a message ID to track its status. You can provide content directly via `html`/`text` fields, or use a template by specifying `template_id` and `template_data`. **CAN-SPAM compliance — actions required from you:** - **Set `classification`** to `transactional` or `marketing`. Unclassified is treated as marketing, the stricter reading. Transactional mail (password resets, receipts) is exempt from the opt-out and postal-address requirements. - **Set your postal address** in project settings. Commercial email must carry a valid physical postal address — the most commonly missed CAN-SPAM element. Marketing sends without one are flagged. - **Include an unsubscribe mechanism** on commercial email. Zyphr enforces suppression automatically once someone opts out, but the link itself is yours to include. See [Compliance Requirements](https://zyphr.dev/guides/compliance-requirements).
181
181
  * Send an email
182
182
  */
183
183
  sendEmail(sendEmailRequest: SendEmailRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<SendEmailResponse>;
@@ -397,7 +397,7 @@ export class EmailsApi extends runtime.BaseAPI implements EmailsApiInterface {
397
397
  }
398
398
 
399
399
  /**
400
- * Queue an email for delivery. The email is processed asynchronously and you\'ll receive a message ID to track its status. You can provide content directly via `html`/`text` fields, or use a template by specifying `template_id` and `template_data`.
400
+ * Queue an email for delivery. The email is processed asynchronously and you\'ll receive a message ID to track its status. You can provide content directly via `html`/`text` fields, or use a template by specifying `template_id` and `template_data`. **CAN-SPAM compliance — actions required from you:** - **Set `classification`** to `transactional` or `marketing`. Unclassified is treated as marketing, the stricter reading. Transactional mail (password resets, receipts) is exempt from the opt-out and postal-address requirements. - **Set your postal address** in project settings. Commercial email must carry a valid physical postal address — the most commonly missed CAN-SPAM element. Marketing sends without one are flagged. - **Include an unsubscribe mechanism** on commercial email. Zyphr enforces suppression automatically once someone opts out, but the link itself is yours to include. See [Compliance Requirements](https://zyphr.dev/guides/compliance-requirements).
401
401
  * Send an email
402
402
  */
403
403
  async sendEmailRaw(requestParameters: EmailsApiSendEmailOperationRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<runtime.ApiResponse<SendEmailResponse>> {
@@ -430,7 +430,7 @@ export class EmailsApi extends runtime.BaseAPI implements EmailsApiInterface {
430
430
  }
431
431
 
432
432
  /**
433
- * Queue an email for delivery. The email is processed asynchronously and you\'ll receive a message ID to track its status. You can provide content directly via `html`/`text` fields, or use a template by specifying `template_id` and `template_data`.
433
+ * Queue an email for delivery. The email is processed asynchronously and you\'ll receive a message ID to track its status. You can provide content directly via `html`/`text` fields, or use a template by specifying `template_id` and `template_data`. **CAN-SPAM compliance — actions required from you:** - **Set `classification`** to `transactional` or `marketing`. Unclassified is treated as marketing, the stricter reading. Transactional mail (password resets, receipts) is exempt from the opt-out and postal-address requirements. - **Set your postal address** in project settings. Commercial email must carry a valid physical postal address — the most commonly missed CAN-SPAM element. Marketing sends without one are flagged. - **Include an unsubscribe mechanism** on commercial email. Zyphr enforces suppression automatically once someone opts out, but the link itself is yours to include. See [Compliance Requirements](https://zyphr.dev/guides/compliance-requirements).
434
434
  * Send an email
435
435
  */
436
436
  async sendEmail(sendEmailRequest: SendEmailRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<SendEmailResponse> {
@@ -141,6 +141,21 @@ export interface SMSApiInterface {
141
141
  */
142
142
  getSmsConfig(initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<SmsConfigResponse>;
143
143
 
144
+ /**
145
+ * Returns the URL to configure in your SMS provider so STOP/opt-out replies reach Zyphr. The token is generated on first request and is stable thereafter. **This is required for TCPA compliance.** Until your provider is pointed at this URL, opt-out replies stop at the provider and never reach us — from Zyphr\'s side the recipient never opted out, and sends continue. See [Compliance Requirements](https://zyphr.dev/guides/compliance-requirements).
146
+ * @summary Get the inbound SMS webhook URL
147
+ * @param {*} [options] Override http request option.
148
+ * @throws {RequiredError}
149
+ * @memberof SMSApiInterface
150
+ */
151
+ getSmsInboundWebhookRaw(initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<runtime.ApiResponse<void>>;
152
+
153
+ /**
154
+ * Returns the URL to configure in your SMS provider so STOP/opt-out replies reach Zyphr. The token is generated on first request and is stable thereafter. **This is required for TCPA compliance.** Until your provider is pointed at this URL, opt-out replies stop at the provider and never reach us — from Zyphr\'s side the recipient never opted out, and sends continue. See [Compliance Requirements](https://zyphr.dev/guides/compliance-requirements).
155
+ * Get the inbound SMS webhook URL
156
+ */
157
+ getSmsInboundWebhook(initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<void>;
158
+
144
159
  /**
145
160
  * List SMS messages for the account with optional filtering and pagination.
146
161
  * @summary List SMS messages
@@ -177,7 +192,7 @@ export interface SMSApiInterface {
177
192
  sendBatchSms(sendBatchSmsRequest: SendBatchSmsRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<SendBatchSmsResponse>;
178
193
 
179
194
  /**
180
- * Send a single SMS text message. Supports subscriber preference checks and scheduling.
195
+ * Send a single SMS text message. Supports subscriber preference checks and scheduling. **TCPA compliance — actions required from you:** - **Configure the inbound webhook.** Zyphr only processes STOP/opt-out replies if your SMS provider is pointed at our inbound endpoint. Until you do this, opt-outs never reach us and we will keep delivering. See [Compliance Requirements](https://zyphr.dev/guides/compliance-requirements). - **Pass `recipient_timezone`** (IANA, e.g. `America/New_York`) so quiet hours (8am-9pm recipient-local) can be enforced. Without it we send and record that quiet hours could not be evaluated. We deliberately do not infer a timezone from the area code — people keep numbers when they move. - **Record consent** for marketing sends. Marketing requires prior express *written* consent; `express` consent covers transactional only. With no record on file we deliver and flag it, which is a gap in your evidence, not permission. - **Set `classification`.** Unclassified messages are treated as marketing, the stricter reading.
181
196
  * @summary Send an SMS message
182
197
  * @param {SendSmsRequest} sendSmsRequest
183
198
  * @param {*} [options] Override http request option.
@@ -187,7 +202,7 @@ export interface SMSApiInterface {
187
202
  sendSmsRaw(requestParameters: SMSApiSendSmsOperationRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<runtime.ApiResponse<SendSmsResponse>>;
188
203
 
189
204
  /**
190
- * Send a single SMS text message. Supports subscriber preference checks and scheduling.
205
+ * Send a single SMS text message. Supports subscriber preference checks and scheduling. **TCPA compliance — actions required from you:** - **Configure the inbound webhook.** Zyphr only processes STOP/opt-out replies if your SMS provider is pointed at our inbound endpoint. Until you do this, opt-outs never reach us and we will keep delivering. See [Compliance Requirements](https://zyphr.dev/guides/compliance-requirements). - **Pass `recipient_timezone`** (IANA, e.g. `America/New_York`) so quiet hours (8am-9pm recipient-local) can be enforced. Without it we send and record that quiet hours could not be evaluated. We deliberately do not infer a timezone from the area code — people keep numbers when they move. - **Record consent** for marketing sends. Marketing requires prior express *written* consent; `express` consent covers transactional only. With no record on file we deliver and flag it, which is a gap in your evidence, not permission. - **Set `classification`.** Unclassified messages are treated as marketing, the stricter reading.
191
206
  * Send an SMS message
192
207
  */
193
208
  sendSms(sendSmsRequest: SendSmsRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<SendSmsResponse>;
@@ -349,6 +364,37 @@ export class SMSApi extends runtime.BaseAPI implements SMSApiInterface {
349
364
  return await response.value();
350
365
  }
351
366
 
367
+ /**
368
+ * Returns the URL to configure in your SMS provider so STOP/opt-out replies reach Zyphr. The token is generated on first request and is stable thereafter. **This is required for TCPA compliance.** Until your provider is pointed at this URL, opt-out replies stop at the provider and never reach us — from Zyphr\'s side the recipient never opted out, and sends continue. See [Compliance Requirements](https://zyphr.dev/guides/compliance-requirements).
369
+ * Get the inbound SMS webhook URL
370
+ */
371
+ async getSmsInboundWebhookRaw(initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<runtime.ApiResponse<void>> {
372
+ const queryParameters: any = {};
373
+
374
+ const headerParameters: runtime.HTTPHeaders = {};
375
+
376
+ if (this.configuration && this.configuration.apiKey) {
377
+ headerParameters["X-API-Key"] = await this.configuration.apiKey("X-API-Key"); // ApiKeyAuth authentication
378
+ }
379
+
380
+ const response = await this.request({
381
+ path: `/sms/inbound-webhook`,
382
+ method: 'GET',
383
+ headers: headerParameters,
384
+ query: queryParameters,
385
+ }, initOverrides);
386
+
387
+ return new runtime.VoidApiResponse(response);
388
+ }
389
+
390
+ /**
391
+ * Returns the URL to configure in your SMS provider so STOP/opt-out replies reach Zyphr. The token is generated on first request and is stable thereafter. **This is required for TCPA compliance.** Until your provider is pointed at this URL, opt-out replies stop at the provider and never reach us — from Zyphr\'s side the recipient never opted out, and sends continue. See [Compliance Requirements](https://zyphr.dev/guides/compliance-requirements).
392
+ * Get the inbound SMS webhook URL
393
+ */
394
+ async getSmsInboundWebhook(initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<void> {
395
+ await this.getSmsInboundWebhookRaw(initOverrides);
396
+ }
397
+
352
398
  /**
353
399
  * List SMS messages for the account with optional filtering and pagination.
354
400
  * List SMS messages
@@ -440,7 +486,7 @@ export class SMSApi extends runtime.BaseAPI implements SMSApiInterface {
440
486
  }
441
487
 
442
488
  /**
443
- * Send a single SMS text message. Supports subscriber preference checks and scheduling.
489
+ * Send a single SMS text message. Supports subscriber preference checks and scheduling. **TCPA compliance — actions required from you:** - **Configure the inbound webhook.** Zyphr only processes STOP/opt-out replies if your SMS provider is pointed at our inbound endpoint. Until you do this, opt-outs never reach us and we will keep delivering. See [Compliance Requirements](https://zyphr.dev/guides/compliance-requirements). - **Pass `recipient_timezone`** (IANA, e.g. `America/New_York`) so quiet hours (8am-9pm recipient-local) can be enforced. Without it we send and record that quiet hours could not be evaluated. We deliberately do not infer a timezone from the area code — people keep numbers when they move. - **Record consent** for marketing sends. Marketing requires prior express *written* consent; `express` consent covers transactional only. With no record on file we deliver and flag it, which is a gap in your evidence, not permission. - **Set `classification`.** Unclassified messages are treated as marketing, the stricter reading.
444
490
  * Send an SMS message
445
491
  */
446
492
  async sendSmsRaw(requestParameters: SMSApiSendSmsOperationRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<runtime.ApiResponse<SendSmsResponse>> {
@@ -473,7 +519,7 @@ export class SMSApi extends runtime.BaseAPI implements SMSApiInterface {
473
519
  }
474
520
 
475
521
  /**
476
- * Send a single SMS text message. Supports subscriber preference checks and scheduling.
522
+ * Send a single SMS text message. Supports subscriber preference checks and scheduling. **TCPA compliance — actions required from you:** - **Configure the inbound webhook.** Zyphr only processes STOP/opt-out replies if your SMS provider is pointed at our inbound endpoint. Until you do this, opt-outs never reach us and we will keep delivering. See [Compliance Requirements](https://zyphr.dev/guides/compliance-requirements). - **Pass `recipient_timezone`** (IANA, e.g. `America/New_York`) so quiet hours (8am-9pm recipient-local) can be enforced. Without it we send and record that quiet hours could not be evaluated. We deliberately do not infer a timezone from the area code — people keep numbers when they move. - **Record consent** for marketing sends. Marketing requires prior express *written* consent; `express` consent covers transactional only. With no record on file we deliver and flag it, which is a gap in your evidence, not permission. - **Set `classification`.** Unclassified messages are treated as marketing, the stricter reading.
477
523
  * Send an SMS message
478
524
  */
479
525
  async sendSms(sendSmsRequest: SendSmsRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<SendSmsResponse> {
@@ -35,7 +35,6 @@ import type {
35
35
  WebhookJobResponse,
36
36
  WebhookListResponse,
37
37
  WebhookMetricsResponse,
38
- WebhookRegionsResponse,
39
38
  WebhookReplayResponse,
40
39
  WebhookResponse,
41
40
  WebhookSecretRotateResponse,
@@ -85,8 +84,6 @@ import {
85
84
  WebhookListResponseToJSON,
86
85
  WebhookMetricsResponseFromJSON,
87
86
  WebhookMetricsResponseToJSON,
88
- WebhookRegionsResponseFromJSON,
89
- WebhookRegionsResponseToJSON,
90
87
  WebhookReplayResponseFromJSON,
91
88
  WebhookReplayResponseToJSON,
92
89
  WebhookResponseFromJSON,
@@ -373,21 +370,6 @@ export interface WebhooksApiInterface {
373
370
  */
374
371
  getWebhookMetrics(id: string, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<WebhookMetricsResponse>;
375
372
 
376
- /**
377
- * Get available webhook delivery regions. Requires multi_region plan feature (Enterprise only).
378
- * @summary Get available webhook regions
379
- * @param {*} [options] Override http request option.
380
- * @throws {RequiredError}
381
- * @memberof WebhooksApiInterface
382
- */
383
- getWebhookRegionsRaw(initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<runtime.ApiResponse<WebhookRegionsResponse>>;
384
-
385
- /**
386
- * Get available webhook delivery regions. Requires multi_region plan feature (Enterprise only).
387
- * Get available webhook regions
388
- */
389
- getWebhookRegions(initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<WebhookRegionsResponse>;
390
-
391
373
  /**
392
374
  * Get webhook delivery usage statistics for the current billing period.
393
375
  * @summary Get webhook usage metrics
@@ -1010,38 +992,6 @@ export class WebhooksApi extends runtime.BaseAPI implements WebhooksApiInterface
1010
992
  return await response.value();
1011
993
  }
1012
994
 
1013
- /**
1014
- * Get available webhook delivery regions. Requires multi_region plan feature (Enterprise only).
1015
- * Get available webhook regions
1016
- */
1017
- async getWebhookRegionsRaw(initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<runtime.ApiResponse<WebhookRegionsResponse>> {
1018
- const queryParameters: any = {};
1019
-
1020
- const headerParameters: runtime.HTTPHeaders = {};
1021
-
1022
- if (this.configuration && this.configuration.apiKey) {
1023
- headerParameters["X-API-Key"] = await this.configuration.apiKey("X-API-Key"); // ApiKeyAuth authentication
1024
- }
1025
-
1026
- const response = await this.request({
1027
- path: `/v1/webhooks/regions`,
1028
- method: 'GET',
1029
- headers: headerParameters,
1030
- query: queryParameters,
1031
- }, initOverrides);
1032
-
1033
- return new runtime.JSONApiResponse(response, (jsonValue) => WebhookRegionsResponseFromJSON(jsonValue));
1034
- }
1035
-
1036
- /**
1037
- * Get available webhook delivery regions. Requires multi_region plan feature (Enterprise only).
1038
- * Get available webhook regions
1039
- */
1040
- async getWebhookRegions(initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<WebhookRegionsResponse> {
1041
- const response = await this.getWebhookRegionsRaw(initOverrides);
1042
- return await response.value();
1043
- }
1044
-
1045
995
  /**
1046
996
  * Get webhook delivery usage statistics for the current billing period.
1047
997
  * Get webhook usage metrics
@@ -31,6 +31,12 @@ export interface ConfirmEmailVerificationResponseData {
31
31
  * @memberof ConfirmEmailVerificationResponseData
32
32
  */
33
33
  email?: string;
34
+ /**
35
+ * True when the address was already verified (the emailed link consumed the token on click). Still a 200 — an idempotent success, not an error (sc-7721).
36
+ * @type {boolean}
37
+ * @memberof ConfirmEmailVerificationResponseData
38
+ */
39
+ alreadyVerified?: boolean;
34
40
  }
35
41
 
36
42
  /**
@@ -52,6 +58,7 @@ export function ConfirmEmailVerificationResponseDataFromJSONTyped(json: any, ign
52
58
 
53
59
  'success': json['success'] == null ? undefined : json['success'],
54
60
  'email': json['email'] == null ? undefined : json['email'],
61
+ 'alreadyVerified': json['already_verified'] == null ? undefined : json['already_verified'],
55
62
  };
56
63
  }
57
64
 
@@ -68,6 +75,7 @@ export function ConfirmEmailVerificationResponseDataToJSONTyped(value?: ConfirmE
68
75
 
69
76
  'success': value['success'],
70
77
  'email': value['email'],
78
+ 'already_verified': value['alreadyVerified'],
71
79
  };
72
80
  }
73
81
 
@@ -16,66 +16,50 @@ import { mapValues } from '../runtime';
16
16
  /**
17
17
  *
18
18
  * @export
19
- * @interface WebhookRegion
19
+ * @interface ResendEmailVerificationRequest
20
20
  */
21
- export interface WebhookRegion {
21
+ export interface ResendEmailVerificationRequest {
22
22
  /**
23
- *
23
+ * URL to redirect to after verification
24
24
  * @type {string}
25
- * @memberof WebhookRegion
25
+ * @memberof ResendEmailVerificationRequest
26
26
  */
27
- code?: string;
28
- /**
29
- *
30
- * @type {string}
31
- * @memberof WebhookRegion
32
- */
33
- name?: string;
34
- /**
35
- *
36
- * @type {Array<string>}
37
- * @memberof WebhookRegion
38
- */
39
- staticIps?: Array<string>;
27
+ redirectUrl?: string;
40
28
  }
41
29
 
42
30
  /**
43
- * Check if a given object implements the WebhookRegion interface.
31
+ * Check if a given object implements the ResendEmailVerificationRequest interface.
44
32
  */
45
- export function instanceOfWebhookRegion(value: object): value is WebhookRegion {
33
+ export function instanceOfResendEmailVerificationRequest(value: object): value is ResendEmailVerificationRequest {
46
34
  return true;
47
35
  }
48
36
 
49
- export function WebhookRegionFromJSON(json: any): WebhookRegion {
50
- return WebhookRegionFromJSONTyped(json, false);
37
+ export function ResendEmailVerificationRequestFromJSON(json: any): ResendEmailVerificationRequest {
38
+ return ResendEmailVerificationRequestFromJSONTyped(json, false);
51
39
  }
52
40
 
53
- export function WebhookRegionFromJSONTyped(json: any, ignoreDiscriminator: boolean): WebhookRegion {
41
+ export function ResendEmailVerificationRequestFromJSONTyped(json: any, ignoreDiscriminator: boolean): ResendEmailVerificationRequest {
54
42
  if (json == null) {
55
43
  return json;
56
44
  }
57
45
  return {
58
46
 
59
- 'code': json['code'] == null ? undefined : json['code'],
60
- 'name': json['name'] == null ? undefined : json['name'],
61
- 'staticIps': json['static_ips'] == null ? undefined : json['static_ips'],
47
+ 'redirectUrl': json['redirect_url'] == null ? undefined : json['redirect_url'],
62
48
  };
63
49
  }
64
50
 
65
- export function WebhookRegionToJSON(json: any): WebhookRegion {
66
- return WebhookRegionToJSONTyped(json, false);
51
+ export function ResendEmailVerificationRequestToJSON(json: any): ResendEmailVerificationRequest {
52
+ return ResendEmailVerificationRequestToJSONTyped(json, false);
67
53
  }
68
54
 
69
- export function WebhookRegionToJSONTyped(value?: WebhookRegion | null, ignoreDiscriminator: boolean = false): any {
55
+ export function ResendEmailVerificationRequestToJSONTyped(value?: ResendEmailVerificationRequest | null, ignoreDiscriminator: boolean = false): any {
70
56
  if (value == null) {
71
57
  return value;
72
58
  }
73
59
 
74
60
  return {
75
61
 
76
- 'code': value['code'],
77
- 'name': value['name'],
78
- 'static_ips': value['staticIps'],
62
+ 'redirect_url': value['redirectUrl'],
79
63
  };
80
64
  }
81
65
 
@@ -20,7 +20,7 @@ import { mapValues } from '../runtime';
20
20
  */
21
21
  export interface SendEmailVerificationRequest {
22
22
  /**
23
- * URL to redirect to after verification
23
+ * URL to redirect to after verification (snake_case `redirect_url` — a camelCase `redirectUrl` is ignored and the hosted verification page is used instead). Must match one of the application's configured redirect URIs.
24
24
  * @type {string}
25
25
  * @memberof SendEmailVerificationRequest
26
26
  */