@masters-union/outbound-sdk 0.0.10

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 ADDED
@@ -0,0 +1,180 @@
1
+ # outbound-sdk
2
+
3
+ Official Node.js SDK for the [Outbound](https://github.com/AdarshChakrworty/outbound) email platform.
4
+
5
+
6
+ ## Installation
7
+
8
+ ::: code-group
9
+ ```bash [npm]
10
+ npm install @masters-union/outbound-sdk
11
+ ```
12
+ ```bash [yarn]
13
+ yarn add @masters-union/outbound-sdk
14
+ ```
15
+ ```bash [pnpm]
16
+ pnpm add @masters-union/outbound-sdk
17
+ ```
18
+ :::
19
+
20
+ **Requirements:** Node.js 18+ (uses native `fetch`)
21
+
22
+ ## Quick Setup
23
+
24
+ ### 1. Get your API key
25
+
26
+ Your Outbound admin will provide you with an API key. It looks like:
27
+
28
+ ```
29
+ mu_outbound_a1b2c3d4e5f6...
30
+ ```
31
+
32
+ ### 2. Initialize the client
33
+
34
+ ::: code-group
35
+ ```ts [ESM]
36
+ import { Outbound } from '@masters-union/outbound-sdk';
37
+
38
+ const outbound = new Outbound({ apiKey: 'mu_outbound_...' });
39
+ ```
40
+ ```js [CommonJS]
41
+ const { Outbound } = require('@masters-union/outbound-sdk');
42
+
43
+ const outbound = new Outbound({ apiKey: 'mu_outbound_...' });
44
+ ```
45
+ :::
46
+
47
+ Once you set the API key in the constructor, every method uses it automatically. No need to pass it on every call.
48
+
49
+ ### 3. Send your first email
50
+
51
+ ```ts
52
+ const { jobId, messageId } = await outbound.email.send({
53
+ toEmail: 'user@example.com',
54
+ fromEmail: 'noreply@yourcompany.com', // must be a verified domain
55
+ emailSubject: 'Welcome!',
56
+ htmlBody: '<h1>Hello World</h1>',
57
+ });
58
+
59
+ console.log(`Email queued: ${jobId}`);
60
+ ```
61
+
62
+ ::: warning Verified Domains Only
63
+ The `fromEmail` must use a domain that has been verified and assigned to your tenant account by the admin. Sending from an unverified domain will return a `403 Forbidden` error.
64
+ :::
65
+
66
+ ### 4. Check delivery status
67
+
68
+ ```ts
69
+ const status = await outbound.email.status(jobId);
70
+
71
+ for (const recipient of status.recipients) {
72
+ console.log(`${recipient.recipient_email}: ${recipient.status}`);
73
+ // "sent" → "delivered" → "opened" → "clicked"
74
+ }
75
+ ```
76
+
77
+ ### 5. Send with a template
78
+
79
+ ```ts
80
+ // Create a reusable template
81
+ const { template } = await outbound.templates.create({
82
+ name: 'welcome-email',
83
+ subject: 'Welcome {{firstName}}!',
84
+ htmlBody: '<h1>Hello {{firstName}}</h1><p>Welcome to {{company}}.</p>',
85
+ variables: ['firstName', 'company'],
86
+ });
87
+
88
+ // Send to one person
89
+ await outbound.templates.send({
90
+ templateId: template.id,
91
+ toEmail: 'user@example.com',
92
+ fromEmail: 'noreply@yourcompany.com',
93
+ variables: { firstName: 'John', company: 'Acme' },
94
+ });
95
+
96
+ // Send to many people
97
+ await outbound.templates.bulkSend({
98
+ templateId: template.id,
99
+ fromEmail: 'noreply@yourcompany.com',
100
+ recipients: [
101
+ { toEmail: 'alice@example.com', variables: { firstName: 'Alice', company: 'Acme' } },
102
+ { toEmail: 'bob@example.com', variables: { firstName: 'Bob', company: 'Acme' } },
103
+ ],
104
+ });
105
+ ```
106
+
107
+ ### 6. Multi-tenant usage
108
+
109
+ The SDK supports multi-tenant applications. You can override the API key on any individual call using the optional last argument:
110
+
111
+ ```ts
112
+ const outbound = new Outbound(); // no default apiKey
113
+
114
+ const tenantAKey = 'mu_outbound_tenant_a_...';
115
+ const tenantBKey = 'mu_outbound_tenant_b_...';
116
+
117
+ // Pass { apiKey } as the last argument to override per call
118
+ await outbound.email.send({ /* ... */ }, { apiKey: tenantAKey });
119
+ await outbound.email.send({ /* ... */ }, { apiKey: tenantBKey });
120
+ ```
121
+
122
+ You can also set a default in the constructor and override only when needed:
123
+
124
+ ```ts
125
+ const outbound = new Outbound({ apiKey: tenantAKey }); // default
126
+
127
+ await outbound.email.send({ /* ... */ }); // uses tenantAKey
128
+ await outbound.email.send({ /* ... */ }, { apiKey: tenantBKey }); // uses tenantBKey
129
+ ```
130
+
131
+ ## Key Concepts
132
+
133
+ ### Email Lifecycle
134
+
135
+ Every email goes through these statuses:
136
+
137
+ ```
138
+ queued → processing → sent → delivered
139
+ ↘ bounced
140
+ ↘ complained
141
+ delivered → opened → clicked
142
+ ```
143
+
144
+ | Status | Meaning |
145
+ |--------|---------|
146
+ | `queued` | Email is in the queue, waiting to be processed |
147
+ | `processing` | Email is being sent to AWS SES |
148
+ | `sent` | SES accepted the email |
149
+ | `delivered` | Email landed in recipient's inbox |
150
+ | `bounced` | Email bounced (bad address or mailbox full) |
151
+ | `complained` | Recipient marked it as spam |
152
+ | `opened` | Recipient opened the email (requires tracking) |
153
+ | `clicked` | Recipient clicked a link (requires tracking) |
154
+ | `failed` | Failed to send (SES rejection or error) |
155
+
156
+ ### Suppression List
157
+
158
+ The platform automatically suppresses emails that bounce or receive complaints. You can also manually suppress emails. Any future send to a suppressed address is **silently filtered out** — it won't count against your quota.
159
+
160
+ ### Quotas
161
+
162
+ Your tenant account has:
163
+ - **Daily limit** — Max emails per day
164
+ - **Monthly limit** — Max emails per month
165
+ - **Rate limit** — Max emails per second
166
+ - **Template limit** — Max number of templates
167
+
168
+ Check your quota anytime with `outbound.dashboard.quota()`.
169
+
170
+ ## What's Next?
171
+
172
+ - [Configuration](/guide/configuration) — Customize timeouts, retries, and more
173
+ - [Error Handling](/guide/error-handling) — Handle every error type
174
+ - [Email API](/api/email) — Single and bulk sending reference
175
+ - [Templates API](/api/templates) — Full template lifecycle
176
+ - [Webhooks API](/api/webhooks) — Real-time event notifications
177
+
178
+ ## License
179
+
180
+ MIT
@@ -0,0 +1,473 @@
1
+ interface OutboundConfig {
2
+ apiKey?: string;
3
+ baseUrl?: string;
4
+ timeout?: number;
5
+ maxRetries?: number;
6
+ retryDelay?: number;
7
+ }
8
+ interface ResolvedConfig {
9
+ apiKey?: string;
10
+ baseUrl: string;
11
+ timeout: number;
12
+ maxRetries: number;
13
+ retryDelay: number;
14
+ }
15
+ interface RequestOverrides {
16
+ apiKey?: string;
17
+ }
18
+ interface SendEmailParams {
19
+ toEmail: string;
20
+ fromEmail: string;
21
+ emailSubject: string;
22
+ htmlBody: string;
23
+ ccEmail?: string;
24
+ bccEmail?: string;
25
+ senderName?: string;
26
+ replyTo?: string;
27
+ textBody?: string;
28
+ priority?: 'low' | 'normal' | 'high';
29
+ idempotencyKey?: string;
30
+ campaignId?: string;
31
+ metadata?: Record<string, unknown>;
32
+ headers?: Record<string, string>;
33
+ tracking?: Record<string, unknown>;
34
+ attachments?: Attachment[];
35
+ }
36
+ interface Attachment {
37
+ filename: string;
38
+ content: string;
39
+ contentType: string;
40
+ }
41
+ interface SendEmailResponse {
42
+ message: string;
43
+ jobId: string;
44
+ messageId: string;
45
+ duplicate?: boolean;
46
+ }
47
+ interface BulkEmailParams {
48
+ fromEmail: string;
49
+ emailSubject: string;
50
+ emails: BulkEmailRecipient[];
51
+ senderName?: string;
52
+ replyTo?: string;
53
+ idempotencyKey?: string;
54
+ campaignId?: string;
55
+ }
56
+ interface BulkEmailRecipient {
57
+ toEmail: string;
58
+ htmlBody: string;
59
+ subject?: string;
60
+ textBody?: string;
61
+ ccEmail?: string;
62
+ bccEmail?: string;
63
+ metadata?: Record<string, unknown>;
64
+ attachments?: Attachment[];
65
+ }
66
+ interface BulkEmailResponse {
67
+ message: string;
68
+ jobId: string;
69
+ recipientCount: number;
70
+ suppressedCount: number;
71
+ /**
72
+ * List of email addresses that were filtered out due to suppression.
73
+ * Present on the first (live) response only.
74
+ * Absent when `duplicate: true` — use `suppressedCount` instead.
75
+ */
76
+ suppressedEmails?: string[];
77
+ duplicatesRemoved?: number;
78
+ duplicate?: boolean;
79
+ }
80
+ interface EmailJob {
81
+ job_id: string;
82
+ tenant_id: string;
83
+ status: 'queued' | 'processing' | 'completed' | 'failed' | 'partial' | 'retrying' | 'cancelled';
84
+ campaign_id?: string;
85
+ recipient_count: number;
86
+ sent_count: number;
87
+ failed_count: number;
88
+ metadata?: Record<string, unknown>;
89
+ created_at: string;
90
+ updated_at: string;
91
+ }
92
+ interface JobStatusResponse {
93
+ lookupType: 'jobId' | 'sesMessageId';
94
+ job?: EmailJob;
95
+ recipients?: EmailRecipientStatus[];
96
+ }
97
+ interface EmailRecipientStatus {
98
+ message_id: string;
99
+ recipient_email: string;
100
+ status: EmailStatus;
101
+ ses_message_id?: string;
102
+ error_message?: string;
103
+ created_at: string;
104
+ }
105
+ type EmailStatus = 'queued' | 'processing' | 'sent' | 'delivered' | 'bounced' | 'complained' | 'opened' | 'clicked' | 'failed' | 'cancelled';
106
+ interface CancelEmailParams {
107
+ /** Cancel all jobs belonging to this campaign. */
108
+ campaignId?: string;
109
+ /** Cancel a specific job by its ID. */
110
+ jobId?: string;
111
+ }
112
+ interface CancelEmailResponse {
113
+ message: string;
114
+ /** Number of jobs that were cancelled. */
115
+ cancelledJobs: number;
116
+ /** Number of individual recipient records set to cancelled. */
117
+ cancelledRecipients: number;
118
+ /** Number of jobs successfully removed from the queue before processing started. */
119
+ removedFromQueue: number;
120
+ }
121
+ interface CreateTemplateParams {
122
+ name: string;
123
+ subject: string;
124
+ htmlBody: string;
125
+ textBody?: string;
126
+ variables?: string[];
127
+ metadata?: Record<string, unknown>;
128
+ }
129
+ interface UpdateTemplateParams {
130
+ name?: string;
131
+ subject?: string;
132
+ htmlBody?: string;
133
+ textBody?: string;
134
+ variables?: string[];
135
+ metadata?: Record<string, unknown>;
136
+ status?: 'active' | 'archived';
137
+ }
138
+ interface ListTemplatesParams {
139
+ status?: 'active' | 'archived';
140
+ search?: string;
141
+ sortBy?: 'name' | 'createdAt' | 'use_count' | 'last_sent_at';
142
+ sortOrder?: 'ASC' | 'DESC';
143
+ page?: number;
144
+ limit?: number;
145
+ }
146
+ interface ListTemplatesResponse {
147
+ templates: Template[];
148
+ total: number;
149
+ page: number;
150
+ limit: number;
151
+ quota: {
152
+ used: number;
153
+ allocated: number;
154
+ remaining: number;
155
+ };
156
+ }
157
+ interface Template {
158
+ id: string;
159
+ tenant_id: string;
160
+ name: string;
161
+ subject: string;
162
+ html_body: string;
163
+ text_body?: string;
164
+ variables: string[];
165
+ use_count: number;
166
+ last_sent_at?: string;
167
+ ses_template_name?: string;
168
+ status: 'active' | 'archived';
169
+ metadata?: Record<string, unknown>;
170
+ created_at: string;
171
+ updated_at: string;
172
+ }
173
+ interface TemplateResponse {
174
+ message?: string;
175
+ template: Template;
176
+ }
177
+ interface TemplateSendParams {
178
+ templateId: string;
179
+ toEmail: string;
180
+ fromEmail: string;
181
+ senderName?: string;
182
+ replyTo?: string;
183
+ ccEmail?: string;
184
+ bccEmail?: string;
185
+ variables?: Record<string, string>;
186
+ priority?: 'low' | 'normal' | 'high';
187
+ idempotencyKey?: string;
188
+ campaignId?: string;
189
+ metadata?: Record<string, unknown>;
190
+ headers?: Record<string, string>;
191
+ tracking?: Record<string, unknown>;
192
+ }
193
+ interface TemplateBulkSendParams {
194
+ templateId: string;
195
+ fromEmail: string;
196
+ senderName?: string;
197
+ replyTo?: string;
198
+ idempotencyKey?: string;
199
+ campaignId?: string;
200
+ recipients: TemplateBulkRecipient[];
201
+ }
202
+ interface TemplateBulkRecipient {
203
+ toEmail: string;
204
+ variables?: Record<string, string>;
205
+ ccEmail?: string;
206
+ bccEmail?: string;
207
+ metadata?: Record<string, unknown>;
208
+ }
209
+ interface TemplateBulkSendResponse {
210
+ message: string;
211
+ jobId: string;
212
+ recipientCount: number;
213
+ suppressedCount: number;
214
+ /**
215
+ * List of email addresses filtered out due to suppression.
216
+ * Present on the first (live) response only.
217
+ * Absent when `duplicate: true` — use `suppressedCount` instead.
218
+ */
219
+ suppressedEmails?: string[];
220
+ duplicatesRemoved?: number;
221
+ usingSesTemplate?: boolean;
222
+ duplicate?: boolean;
223
+ }
224
+ interface TemplatePreviewParams {
225
+ variables?: Record<string, string>;
226
+ }
227
+ interface TemplatePreviewResponse {
228
+ subject: string;
229
+ htmlBody: string;
230
+ textBody?: string;
231
+ missingVariables?: string[];
232
+ }
233
+ interface TemplateStatsResponse {
234
+ quota: {
235
+ used: number;
236
+ allocated: number;
237
+ remaining: number;
238
+ };
239
+ counts: {
240
+ total: number;
241
+ active: number;
242
+ archived: number;
243
+ neverUsed: number;
244
+ };
245
+ totalEmailsSentViaTemplates: number;
246
+ mostUsed: Template[];
247
+ leastUsed: Template[];
248
+ recentlyUsed: Template[];
249
+ }
250
+ interface ListSuppressionsParams {
251
+ page?: number;
252
+ limit?: number;
253
+ reason?: 'bounce' | 'complaint' | 'manual' | 'unsubscribe';
254
+ }
255
+ interface ListSuppressionsResponse {
256
+ suppressions: Suppression[];
257
+ pagination: {
258
+ page: number;
259
+ limit: number;
260
+ total: number;
261
+ };
262
+ }
263
+ interface Suppression {
264
+ id: string;
265
+ tenant_id: string;
266
+ email: string;
267
+ reason: string;
268
+ created_at: string;
269
+ }
270
+ interface AddSuppressionParams {
271
+ email: string;
272
+ reason?: 'bounce' | 'complaint' | 'manual' | 'unsubscribe';
273
+ }
274
+ interface SuppressionResponse {
275
+ suppression: Suppression;
276
+ }
277
+ type WebhookEvent = 'send' | 'delivery' | 'bounce' | 'complaint' | 'open' | 'click' | 'reject' | 'rendering_failure';
278
+ interface CreateWebhookParams {
279
+ url: string;
280
+ events: WebhookEvent[];
281
+ retryInterval?: number;
282
+ maxRetries?: number;
283
+ }
284
+ interface UpdateWebhookParams {
285
+ url?: string;
286
+ events?: WebhookEvent[];
287
+ active?: boolean;
288
+ retryInterval?: number;
289
+ maxRetries?: number;
290
+ }
291
+ interface Webhook {
292
+ id: string;
293
+ tenant_id: string;
294
+ url: string;
295
+ events: WebhookEvent[];
296
+ retry_interval: number;
297
+ max_retries: number;
298
+ active: boolean;
299
+ status: 'active' | 'defective';
300
+ created_at: string;
301
+ }
302
+ interface CreateWebhookResponse {
303
+ webhook: Webhook;
304
+ secret: string;
305
+ warning: string;
306
+ }
307
+ interface UpdateWebhookResponse {
308
+ message: string;
309
+ webhook: Webhook;
310
+ }
311
+ interface ListWebhooksResponse {
312
+ webhooks: Webhook[];
313
+ }
314
+ interface DashboardResponse {
315
+ quota: Record<string, unknown>;
316
+ templates: {
317
+ used: number;
318
+ active: number;
319
+ allocated: number;
320
+ remaining: number;
321
+ };
322
+ last30Days: {
323
+ sent: number;
324
+ delivered: number;
325
+ bounced: number;
326
+ complained: number;
327
+ opened: number;
328
+ clicked: number;
329
+ failed: number;
330
+ };
331
+ recentJobs: Record<string, unknown>[];
332
+ }
333
+ interface QuotaResponse {
334
+ used: number;
335
+ allocated: number;
336
+ remaining: number;
337
+ dailyUsed: number;
338
+ dailyLimit: number;
339
+ monthlyUsed: number;
340
+ monthlyLimit: number;
341
+ percentageUsed: number;
342
+ resetDate: string;
343
+ }
344
+
345
+ declare class HttpClient {
346
+ private config;
347
+ constructor(config: ResolvedConfig);
348
+ get<T>(path: string, params?: Record<string, unknown>, apiKey?: string): Promise<T>;
349
+ post<T>(path: string, body?: unknown, apiKey?: string): Promise<T>;
350
+ patch<T>(path: string, body?: unknown, apiKey?: string): Promise<T>;
351
+ delete<T>(path: string, apiKey?: string): Promise<T>;
352
+ private resolveApiKey;
353
+ private request;
354
+ private buildUrl;
355
+ private parseError;
356
+ private sleep;
357
+ }
358
+
359
+ declare class EmailResource {
360
+ private http;
361
+ constructor(http: HttpClient);
362
+ send(params: SendEmailParams, overrides?: RequestOverrides): Promise<SendEmailResponse>;
363
+ bulk(params: BulkEmailParams, overrides?: RequestOverrides): Promise<BulkEmailResponse>;
364
+ status(jobId: string, overrides?: RequestOverrides): Promise<JobStatusResponse>;
365
+ /**
366
+ * Cancel all queued/processing emails for a campaign or job.
367
+ * Provide either `campaignId` (cancels all jobs in that campaign) or `jobId` (cancels one job).
368
+ * Already-sent emails cannot be recalled — only recipients still in `queued` or `processing` state are cancelled.
369
+ */
370
+ cancel(params: CancelEmailParams, overrides?: RequestOverrides): Promise<CancelEmailResponse>;
371
+ }
372
+
373
+ declare class TemplatesResource {
374
+ private http;
375
+ constructor(http: HttpClient);
376
+ create(params: CreateTemplateParams, overrides?: RequestOverrides): Promise<TemplateResponse>;
377
+ list(params?: ListTemplatesParams, overrides?: RequestOverrides): Promise<ListTemplatesResponse>;
378
+ listAll(params?: Omit<ListTemplatesParams, 'page'>, overrides?: RequestOverrides): AsyncGenerator<Template>;
379
+ get(id: string, overrides?: RequestOverrides): Promise<TemplateResponse>;
380
+ update(id: string, params: UpdateTemplateParams, overrides?: RequestOverrides): Promise<TemplateResponse>;
381
+ delete(id: string, overrides?: RequestOverrides): Promise<{
382
+ message: string;
383
+ id: string;
384
+ }>;
385
+ duplicate(id: string, params?: {
386
+ name?: string;
387
+ }, overrides?: RequestOverrides): Promise<TemplateResponse>;
388
+ preview(id: string, params?: TemplatePreviewParams, overrides?: RequestOverrides): Promise<TemplatePreviewResponse>;
389
+ send(params: TemplateSendParams, overrides?: RequestOverrides): Promise<SendEmailResponse>;
390
+ bulkSend(params: TemplateBulkSendParams, overrides?: RequestOverrides): Promise<TemplateBulkSendResponse>;
391
+ stats(overrides?: RequestOverrides): Promise<TemplateStatsResponse>;
392
+ }
393
+
394
+ declare class SuppressionsResource {
395
+ private http;
396
+ constructor(http: HttpClient);
397
+ list(params?: ListSuppressionsParams, overrides?: RequestOverrides): Promise<ListSuppressionsResponse>;
398
+ listAll(params?: Omit<ListSuppressionsParams, 'page'>, overrides?: RequestOverrides): AsyncGenerator<Suppression>;
399
+ add(params: AddSuppressionParams, overrides?: RequestOverrides): Promise<SuppressionResponse>;
400
+ remove(email: string, overrides?: RequestOverrides): Promise<{
401
+ message: string;
402
+ }>;
403
+ }
404
+
405
+ declare class WebhooksResource {
406
+ private http;
407
+ constructor(http: HttpClient);
408
+ create(params: CreateWebhookParams, overrides?: RequestOverrides): Promise<CreateWebhookResponse>;
409
+ list(overrides?: RequestOverrides): Promise<ListWebhooksResponse>;
410
+ update(id: string, params: UpdateWebhookParams, overrides?: RequestOverrides): Promise<UpdateWebhookResponse>;
411
+ delete(id: string, overrides?: RequestOverrides): Promise<{
412
+ message: string;
413
+ id: string;
414
+ }>;
415
+ }
416
+
417
+ declare class DashboardResource {
418
+ private http;
419
+ constructor(http: HttpClient);
420
+ get(overrides?: RequestOverrides): Promise<DashboardResponse>;
421
+ quota(overrides?: RequestOverrides): Promise<QuotaResponse>;
422
+ }
423
+
424
+ declare class Outbound {
425
+ readonly email: EmailResource;
426
+ readonly templates: TemplatesResource;
427
+ readonly suppressions: SuppressionsResource;
428
+ readonly webhooks: WebhooksResource;
429
+ readonly dashboard: DashboardResource;
430
+ constructor(config?: OutboundConfig);
431
+ /**
432
+ * Verify a webhook signature using HMAC-SHA256.
433
+ * Use this in your webhook handler to validate incoming requests.
434
+ */
435
+ static verifyWebhookSignature(payload: string | Buffer, signature: string, secret: string): boolean;
436
+ }
437
+
438
+ declare class OutboundError extends Error {
439
+ readonly statusCode: number;
440
+ readonly details?: unknown | undefined;
441
+ readonly requestId?: string | undefined;
442
+ constructor(message: string, statusCode: number, details?: unknown | undefined, requestId?: string | undefined);
443
+ }
444
+ declare class BadRequestError extends OutboundError {
445
+ constructor(message: string, details?: unknown, requestId?: string);
446
+ }
447
+ declare class AuthenticationError extends OutboundError {
448
+ constructor(message: string, details?: unknown, requestId?: string);
449
+ }
450
+ declare class ForbiddenError extends OutboundError {
451
+ constructor(message: string, details?: unknown, requestId?: string);
452
+ }
453
+ declare class NotFoundError extends OutboundError {
454
+ constructor(message: string, details?: unknown, requestId?: string);
455
+ }
456
+ declare class ConflictError extends OutboundError {
457
+ constructor(message: string, details?: unknown, requestId?: string);
458
+ }
459
+ declare class RateLimitError extends OutboundError {
460
+ readonly retryAfter?: number;
461
+ constructor(message: string, retryAfter?: number, details?: unknown, requestId?: string);
462
+ }
463
+ declare class ServerError extends OutboundError {
464
+ constructor(message: string, statusCode?: number, details?: unknown, requestId?: string);
465
+ }
466
+ declare class TimeoutError extends OutboundError {
467
+ constructor(message?: string);
468
+ }
469
+ declare class NetworkError extends OutboundError {
470
+ constructor(message?: string);
471
+ }
472
+
473
+ export { type AddSuppressionParams, type Attachment, AuthenticationError, BadRequestError, type BulkEmailParams, type BulkEmailRecipient, type BulkEmailResponse, type CancelEmailParams, type CancelEmailResponse, ConflictError, type CreateTemplateParams, type CreateWebhookParams, type CreateWebhookResponse, type DashboardResponse, type EmailJob, type EmailRecipientStatus, type EmailStatus, ForbiddenError, type JobStatusResponse, type ListSuppressionsParams, type ListSuppressionsResponse, type ListTemplatesParams, type ListTemplatesResponse, type ListWebhooksResponse, NetworkError, NotFoundError, Outbound, type OutboundConfig, OutboundError, type QuotaResponse, RateLimitError, type RequestOverrides, type ResolvedConfig, type SendEmailParams, type SendEmailResponse, ServerError, type Suppression, type SuppressionResponse, type Template, type TemplateBulkRecipient, type TemplateBulkSendParams, type TemplateBulkSendResponse, type TemplatePreviewParams, type TemplatePreviewResponse, type TemplateResponse, type TemplateSendParams, type TemplateStatsResponse, TimeoutError, type UpdateTemplateParams, type UpdateWebhookParams, type UpdateWebhookResponse, type Webhook, type WebhookEvent };