@sendora/sdk 1.1.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.
Files changed (93) hide show
  1. package/README.md +364 -0
  2. package/dist/base64.d.ts +3 -0
  3. package/dist/base64.d.ts.map +1 -0
  4. package/dist/base64.js +17 -0
  5. package/dist/base64.js.map +1 -0
  6. package/dist/broadcasts.d.ts +60 -0
  7. package/dist/broadcasts.d.ts.map +1 -0
  8. package/dist/broadcasts.js +98 -0
  9. package/dist/broadcasts.js.map +1 -0
  10. package/dist/client.d.ts +51 -0
  11. package/dist/client.d.ts.map +1 -0
  12. package/dist/client.js +69 -0
  13. package/dist/client.js.map +1 -0
  14. package/dist/domains.d.ts +34 -0
  15. package/dist/domains.d.ts.map +1 -0
  16. package/dist/domains.js +70 -0
  17. package/dist/domains.js.map +1 -0
  18. package/dist/email.d.ts +40 -0
  19. package/dist/email.d.ts.map +1 -0
  20. package/dist/email.js +68 -0
  21. package/dist/email.js.map +1 -0
  22. package/dist/error.d.ts +67 -0
  23. package/dist/error.d.ts.map +1 -0
  24. package/dist/error.js +173 -0
  25. package/dist/error.js.map +1 -0
  26. package/dist/index.d.ts +17 -0
  27. package/dist/index.d.ts.map +1 -0
  28. package/dist/index.js +5 -0
  29. package/dist/index.js.map +1 -0
  30. package/dist/messages.d.ts +37 -0
  31. package/dist/messages.d.ts.map +1 -0
  32. package/dist/messages.js +68 -0
  33. package/dist/messages.js.map +1 -0
  34. package/dist/pagination.d.ts +3 -0
  35. package/dist/pagination.d.ts.map +1 -0
  36. package/dist/pagination.js +14 -0
  37. package/dist/pagination.js.map +1 -0
  38. package/dist/retry.d.ts +6 -0
  39. package/dist/retry.d.ts.map +1 -0
  40. package/dist/retry.js +14 -0
  41. package/dist/retry.js.map +1 -0
  42. package/dist/streams.d.ts +45 -0
  43. package/dist/streams.d.ts.map +1 -0
  44. package/dist/streams.js +82 -0
  45. package/dist/streams.js.map +1 -0
  46. package/dist/suppressions.d.ts +37 -0
  47. package/dist/suppressions.d.ts.map +1 -0
  48. package/dist/suppressions.js +56 -0
  49. package/dist/suppressions.js.map +1 -0
  50. package/dist/tokens.d.ts +28 -0
  51. package/dist/tokens.d.ts.map +1 -0
  52. package/dist/tokens.js +57 -0
  53. package/dist/tokens.js.map +1 -0
  54. package/dist/transport.d.ts +34 -0
  55. package/dist/transport.d.ts.map +1 -0
  56. package/dist/transport.js +146 -0
  57. package/dist/transport.js.map +1 -0
  58. package/dist/types.d.ts +802 -0
  59. package/dist/types.d.ts.map +1 -0
  60. package/dist/types.js +2 -0
  61. package/dist/types.js.map +1 -0
  62. package/dist/version.d.ts +3 -0
  63. package/dist/version.d.ts.map +1 -0
  64. package/dist/version.js +3 -0
  65. package/dist/version.js.map +1 -0
  66. package/dist/webhook-verify.d.ts +33 -0
  67. package/dist/webhook-verify.d.ts.map +1 -0
  68. package/dist/webhook-verify.js +115 -0
  69. package/dist/webhook-verify.js.map +1 -0
  70. package/dist/webhooks.d.ts +63 -0
  71. package/dist/webhooks.d.ts.map +1 -0
  72. package/dist/webhooks.js +118 -0
  73. package/dist/webhooks.js.map +1 -0
  74. package/package.json +49 -0
  75. package/skills/sendora/SKILL.md +86 -0
  76. package/src/base64.ts +17 -0
  77. package/src/broadcasts.ts +115 -0
  78. package/src/client.ts +88 -0
  79. package/src/domains.ts +84 -0
  80. package/src/email.ts +83 -0
  81. package/src/error.ts +252 -0
  82. package/src/index.ts +16 -0
  83. package/src/messages.ts +88 -0
  84. package/src/pagination.ts +18 -0
  85. package/src/retry.ts +20 -0
  86. package/src/streams.ts +100 -0
  87. package/src/suppressions.ts +73 -0
  88. package/src/tokens.ts +70 -0
  89. package/src/transport.ts +179 -0
  90. package/src/types.ts +848 -0
  91. package/src/version.ts +2 -0
  92. package/src/webhook-verify.ts +147 -0
  93. package/src/webhooks.ts +157 -0
@@ -0,0 +1,802 @@
1
+ /** Options every call takes. */
2
+ export interface RequestOptions {
3
+ /** Cancels the call, retries included. */
4
+ signal?: AbortSignal | undefined;
5
+ }
6
+ /** Options a send takes. */
7
+ export interface SendOptions extends RequestOptions {
8
+ /**
9
+ * Any text of 1 to 255 printable characters that identifies this request.
10
+ * The SDK makes a random UUID when you give none, so a retry never sends
11
+ * twice; give your own to make retries across processes safe too. The
12
+ * API remembers a key for 24 hours and refuses it with a different body.
13
+ */
14
+ idempotencyKey?: string | undefined;
15
+ }
16
+ /** An address as a plain string, or an object with the address and a display name of up to 200 characters. */
17
+ export type Address = string | {
18
+ email: string;
19
+ name?: string | null | undefined;
20
+ };
21
+ /** An attachment as you hand it to the SDK: the bytes, or base64 without line breaks as the API takes it. */
22
+ export interface Attachment {
23
+ /** A file name without path separators, at most 255 characters. */
24
+ name: string;
25
+ /** The bytes, or base64 without line breaks. */
26
+ content: Uint8Array | string;
27
+ /** A media type such as application/pdf, without parameters; application/octet-stream when left out. */
28
+ contentType?: string | undefined;
29
+ /** Lets the HTML part refer to the attachment as cid:<contentId>. */
30
+ contentId?: string | null | undefined;
31
+ }
32
+ /** An attachment on the wire: the content base64-encoded. */
33
+ export interface EncodedAttachment {
34
+ name: string;
35
+ content: string;
36
+ contentType?: string | undefined;
37
+ contentId?: string | null | undefined;
38
+ }
39
+ /** The fields of a message apart from its parts. */
40
+ export interface SendEmailFields {
41
+ /** The sender. Its domain must be a verified sending domain of the account. */
42
+ from: Address;
43
+ /** The stream of this server the message goes on; the default transactional stream when absent. */
44
+ streamId?: string | undefined;
45
+ /** Recipients; at most 50 across to, cc and bcc. */
46
+ to: Address[];
47
+ /** Copied recipients, shown in the message. */
48
+ cc?: Address[] | undefined;
49
+ /** Blind-copied recipients. */
50
+ bcc?: Address[] | undefined;
51
+ /** The subject line, 1 to 998 characters. */
52
+ subject: string;
53
+ /** Custom headers by name. Headers Sendora sets itself, such as From and DKIM-Signature, are refused. */
54
+ headers?: Record<string, string> | undefined;
55
+ /** At most 20. The built message, attachments encoded, may not exceed 10 MB. */
56
+ attachments?: Attachment[] | undefined;
57
+ /** A label of up to 100 characters, returned with the message and its events. */
58
+ tag?: string | null | undefined;
59
+ /** Up to 20 key-value pairs of your own, returned with the message and its events. */
60
+ metadata?: Record<string, string> | undefined;
61
+ }
62
+ /** What `email.send` takes: the fields and at least one of `text` and `html`. */
63
+ export type SendEmailRequest = SendEmailFields & ({
64
+ text: string;
65
+ html?: string | undefined;
66
+ } | {
67
+ html: string;
68
+ text?: string | undefined;
69
+ });
70
+ /** The body POST /v1/email takes; equal to the API's own schema. */
71
+ export interface SendEmailBody {
72
+ from: Address;
73
+ streamId?: string | undefined;
74
+ to: Address[];
75
+ cc?: Address[] | undefined;
76
+ bcc?: Address[] | undefined;
77
+ subject: string;
78
+ text?: string | undefined;
79
+ html?: string | undefined;
80
+ headers?: Record<string, string> | undefined;
81
+ attachments?: EncodedAttachment[] | undefined;
82
+ tag?: string | null | undefined;
83
+ metadata?: Record<string, string> | undefined;
84
+ }
85
+ /** A message accepted for delivery. Delivery, deferral, bounce and complaint arrive later as events and webhooks. */
86
+ export interface AcceptedEmail {
87
+ /** The id the message log, the events and the webhooks refer to. */
88
+ messageId: string;
89
+ status: 'accepted';
90
+ /** When the message was accepted. */
91
+ submittedAt: string;
92
+ }
93
+ /** One invalid field of a request. */
94
+ export interface ValidationIssue {
95
+ /** The field, dotted, such as to.0.email; empty when the whole body is wrong. */
96
+ path: string;
97
+ message: string;
98
+ }
99
+ export type SuppressionReason = 'hard_bounce' | 'spam_complaint' | 'manual' | 'unsubscribe';
100
+ /** A recipient the server refused because it is on the suppression list. */
101
+ export interface SuppressedRecipient {
102
+ address: string;
103
+ reason: SuppressionReason;
104
+ }
105
+ /** Whose limit or cap it is. */
106
+ export type LimitScope = 'tenant' | 'server';
107
+ /** One result of a batch, in request order: accepted with its id, or refused with the error a single send would give. */
108
+ export type BatchItemResult = {
109
+ messageId: string;
110
+ status: 'accepted';
111
+ submittedAt: string;
112
+ /** The position of the message in the request. */
113
+ index: number;
114
+ /** True when an earlier request under the same key already sent this item. */
115
+ replayed: boolean;
116
+ } | {
117
+ index: number;
118
+ status: 'error';
119
+ error: 'invalid_request';
120
+ message: string;
121
+ issues: ValidationIssue[];
122
+ } | {
123
+ error: 'from_domain_not_verified';
124
+ message: string;
125
+ index: number;
126
+ status: 'error';
127
+ } | {
128
+ error: 'stream_not_found';
129
+ message: string;
130
+ index: number;
131
+ status: 'error';
132
+ } | {
133
+ error: 'stream_archived';
134
+ message: string;
135
+ index: number;
136
+ status: 'error';
137
+ } | {
138
+ error: 'stream_paused';
139
+ message: string;
140
+ index: number;
141
+ status: 'error';
142
+ } | {
143
+ error: 'stream_not_sendable';
144
+ message: string;
145
+ index: number;
146
+ status: 'error';
147
+ } | {
148
+ error: 'broadcast_not_enabled';
149
+ message: string;
150
+ index: number;
151
+ status: 'error';
152
+ } | {
153
+ error: 'unsubscribe_placeholder_missing';
154
+ message: string;
155
+ index: number;
156
+ status: 'error';
157
+ } | {
158
+ error: 'list_unsubscribe_reserved';
159
+ message: string;
160
+ index: number;
161
+ status: 'error';
162
+ } | {
163
+ error: 'recipient_suppressed';
164
+ message: string;
165
+ streamId: string;
166
+ suppressed: SuppressedRecipient[];
167
+ index: number;
168
+ status: 'error';
169
+ } | {
170
+ error: 'idempotency_key_mismatch';
171
+ message: string;
172
+ index: number;
173
+ status: 'error';
174
+ } | {
175
+ error: 'rate_limited';
176
+ message: string;
177
+ scope: LimitScope;
178
+ limit: number;
179
+ retryAfter: number;
180
+ index: number;
181
+ status: 'error';
182
+ } | {
183
+ error: 'monthly_cap_reached';
184
+ message: string;
185
+ scope: LimitScope;
186
+ cap: number;
187
+ used: number;
188
+ resetsAt: string;
189
+ index: number;
190
+ status: 'error';
191
+ } | {
192
+ error: 'sending_disabled';
193
+ message: string;
194
+ index: number;
195
+ status: 'error';
196
+ } | {
197
+ error: 'tenant_paused';
198
+ message: string;
199
+ index: number;
200
+ status: 'error';
201
+ } | {
202
+ error: 'tenant_not_active';
203
+ message: string;
204
+ index: number;
205
+ status: 'error';
206
+ } | {
207
+ error: 'payment_required';
208
+ message: string;
209
+ index: number;
210
+ status: 'error';
211
+ };
212
+ /** Every message of a batch answered on its own; the batch as a whole never fails halfway. */
213
+ export interface BatchResult {
214
+ results: BatchItemResult[];
215
+ }
216
+ /** accepted until handed to the mail server, injected after; failed if that never worked. */
217
+ export type MessageStatus = 'accepted' | 'injected' | 'failed';
218
+ /** queued until the receiver answers; deferred while it keeps saying try later. */
219
+ export type RecipientStatus = 'queued' | 'delivered' | 'deferred' | 'bounced' | 'expired';
220
+ export type RecipientKind = 'to' | 'cc' | 'bcc';
221
+ export interface MessageRecipient {
222
+ address: string;
223
+ kind: RecipientKind;
224
+ status: RecipientStatus;
225
+ }
226
+ /** A message as the log lists it. */
227
+ export interface Message {
228
+ messageId: string;
229
+ /** The stream the message went on. */
230
+ streamId: string;
231
+ /** The broadcast the message belongs to; null for a message sent on its own. */
232
+ broadcastId: string | null;
233
+ status: MessageStatus;
234
+ from: string;
235
+ subject: string;
236
+ tag: string | null;
237
+ metadata: Record<string, string>;
238
+ submittedAt: string;
239
+ recipients: MessageRecipient[];
240
+ }
241
+ /** Reception when the mail server took it, Delivery, TransientFailure, Bounce, OOB for a bounce report received by mail, Feedback for a spam complaint. */
242
+ export type MessageEventType = 'Reception' | 'Delivery' | 'Bounce' | 'TransientFailure' | 'Expiration' | 'AdminBounce' | 'OOB' | 'Feedback' | 'AdminRebind' | 'DeferredInjectionRebind' | 'Rejection' | 'Delayed';
243
+ /** One step of a message's timeline. */
244
+ export interface MessageEvent {
245
+ /** The recipient the event is about; null when it concerns the message as a whole. */
246
+ recipient: string | null;
247
+ type: MessageEventType;
248
+ at: string;
249
+ /** The SMTP status code the receiver answered. */
250
+ code: number | null;
251
+ /** The receiver's response text. */
252
+ details: string | null;
253
+ /** How a bounce was classified, such as InvalidRecipient. */
254
+ classification: string | null;
255
+ }
256
+ /** An attachment as the log describes it; the content is never returned. */
257
+ export interface MessageAttachment {
258
+ name: string;
259
+ contentType: string;
260
+ contentId: string | null;
261
+ /** Bytes before encoding. */
262
+ size: number;
263
+ }
264
+ /** The message with its attachments described and its timeline, oldest event first. */
265
+ export interface MessageDetail extends Message {
266
+ attachments: MessageAttachment[];
267
+ events: MessageEvent[];
268
+ }
269
+ /** The body POST /v1/messages/search takes; equal to the API's own schema. Every filter is optional. */
270
+ export interface MessageSearchBody {
271
+ /** Messages to this address, in to, cc or bcc. */
272
+ recipient?: string | undefined;
273
+ /** Messages on this stream of the server. */
274
+ streamId?: string | undefined;
275
+ /** Messages of this broadcast. */
276
+ broadcastId?: string | undefined;
277
+ tag?: string | undefined;
278
+ /** Messages with at least one recipient in this state. */
279
+ status?: RecipientStatus | undefined;
280
+ /** Submitted at or after this time, ISO 8601. */
281
+ from?: string | undefined;
282
+ /** Submitted before this time, ISO 8601. */
283
+ to?: string | undefined;
284
+ /** Page size, 1 to 100; 50 when left out. */
285
+ limit?: number | undefined;
286
+ /** The `next` value of the previous page. */
287
+ after?: string | undefined;
288
+ }
289
+ /** What `messages.search` takes: the same filters, with times as Date or ISO 8601 string. */
290
+ export interface MessageSearch {
291
+ /** Messages to this address, in to, cc or bcc. */
292
+ recipient?: string | undefined;
293
+ /** Messages on this stream of the server. */
294
+ streamId?: string | undefined;
295
+ /** Messages of this broadcast. */
296
+ broadcastId?: string | undefined;
297
+ tag?: string | undefined;
298
+ /** Messages with at least one recipient in this state. */
299
+ status?: RecipientStatus | undefined;
300
+ /** Submitted at or after this time. */
301
+ from?: Date | string | undefined;
302
+ /** Submitted before this time. */
303
+ to?: Date | string | undefined;
304
+ /** Page size, 1 to 100; 50 when left out. */
305
+ limit?: number | undefined;
306
+ /** The `next` value of the previous page. */
307
+ after?: string | undefined;
308
+ }
309
+ /** One page of the message log, newest first. */
310
+ export interface MessagePage {
311
+ messages: Message[];
312
+ /** Pass as `after` for the next page; null on the last. */
313
+ next: string | null;
314
+ }
315
+ /** Cursor paging for the lists that page. */
316
+ export interface PageQuery {
317
+ /** Page size, 1 to 1000; 100 when left out. */
318
+ limit?: number | undefined;
319
+ /** The `next` value of the previous page. */
320
+ after?: string | undefined;
321
+ }
322
+ /** The paging of a suppression list, and which stream's list. */
323
+ export interface SuppressionQuery extends PageQuery {
324
+ /** The stream whose list is meant; the default transactional stream when left out. */
325
+ streamId?: string | undefined;
326
+ }
327
+ /** An address a stream of the server no longer sends to. */
328
+ export interface Suppression {
329
+ /** The stream whose list the address is on. */
330
+ streamId: string;
331
+ /** The recipient, lower-cased. */
332
+ address: string;
333
+ /** A hard bounce or a manual entry may be lifted; a spam complaint only by Sendora support. */
334
+ reason: SuppressionReason;
335
+ /** The message whose bounce or complaint put it here. */
336
+ messageId: string | null;
337
+ createdAt: string;
338
+ }
339
+ /** One page of the suppression list, oldest first. */
340
+ export interface SuppressionPage {
341
+ suppressions: Suppression[];
342
+ next: string | null;
343
+ }
344
+ /** The body POST /v1/suppressions/delete takes. */
345
+ export interface DeleteSuppressionRequest {
346
+ /** The address to send to again. */
347
+ address: string;
348
+ /** The stream whose list holds it; the default transactional stream when left out. */
349
+ streamId?: string | undefined;
350
+ }
351
+ /** transactional for mail the recipient expects; broadcast for mail to many, once enabled for the account; inbound for mail the server receives. */
352
+ export type StreamKind = 'transactional' | 'broadcast' | 'inbound';
353
+ /** A stream of the server: what a send names as `streamId`; a sending stream has a suppression list of its own, an inbound one an address. */
354
+ export interface Stream {
355
+ streamId: string;
356
+ kind: StreamKind;
357
+ /** The name given at creation, unique within the server. */
358
+ name: string;
359
+ /** The stream a send without a `streamId` goes on; one per server, transactional. */
360
+ isDefault: boolean;
361
+ createdAt: string;
362
+ /** Set once archived; the stream then takes no new messages. */
363
+ archivedAt: string | null;
364
+ /** Set while Sendora has paused the stream after complaints; it takes no messages until support has resumed it. */
365
+ pausedAt: string | null;
366
+ /** The address of an inbound stream, its id on inbound.sendora.se; null on every other kind. */
367
+ inboundAddress: string | null;
368
+ /** How many days an inbound stream keeps received content, 1 to 30; null means the default of 30, and null on every other kind. */
369
+ contentRetentionDays: number | null;
370
+ }
371
+ /** The body POST /v1/streams takes. */
372
+ export interface CreateStreamRequest {
373
+ /** broadcast needs broadcast enabled for the account by Sendora; a server has one live inbound stream. */
374
+ kind: StreamKind;
375
+ /** 1 to 100 characters. */
376
+ name: string;
377
+ }
378
+ /** The body PATCH /v1/streams/{id} takes: a name, a content window for an inbound stream, or both. */
379
+ export interface UpdateStreamRequest {
380
+ /** 1 to 100 characters. */
381
+ name?: string | undefined;
382
+ /** Days an inbound stream keeps received content, 1 to 30; null for the default of 30. */
383
+ contentRetentionDays?: number | null | undefined;
384
+ }
385
+ export interface StreamList {
386
+ streams: Stream[];
387
+ }
388
+ /** accepted until the first message leaves, processing while messages are leaving, completed when every message has left or failed, cancelled once cancelled. */
389
+ export type BroadcastStatus = 'accepted' | 'processing' | 'completed' | 'cancelled';
390
+ /** One message of a broadcast: its recipients, and what is its own beside the shared content. */
391
+ export interface BroadcastMessageEntry {
392
+ /** Recipients of this message; at most 50 across to, cc and bcc. */
393
+ to: Address[];
394
+ /** Copied recipients, shown in the message. */
395
+ cc?: Address[] | undefined;
396
+ /** Blind-copied recipients. */
397
+ bcc?: Address[] | undefined;
398
+ /** Up to 20 key-value pairs for this message, merged over the broadcast's. */
399
+ metadata?: Record<string, string> | undefined;
400
+ /** Custom headers for this message, merged over the broadcast's. */
401
+ headers?: Record<string, string> | undefined;
402
+ /** Up to 20 strings that replace `{{ key }}` in the subject, the text and the HTML of this message; a key the content names must be given. */
403
+ substitutions?: Record<string, string> | undefined;
404
+ }
405
+ /** The fields of a broadcast apart from its parts. */
406
+ export interface SendBroadcastFields {
407
+ /** The broadcast stream of this server the messages go on. */
408
+ streamId: string;
409
+ /** The sender. Its domain must be a verified sending domain of the account. */
410
+ from: Address;
411
+ /** The subject line, 1 to 998 characters. */
412
+ subject: string;
413
+ /** Custom headers on every message. Headers Sendora sets itself, the List-Unsubscribe pair included, are refused. */
414
+ headers?: Record<string, string> | undefined;
415
+ /** At most 20, sent with every message; the whole broadcast may not exceed 50 MB once built. */
416
+ attachments?: Attachment[] | undefined;
417
+ /** A label of up to 100 characters, on the broadcast and on every message. */
418
+ tag?: string | null | undefined;
419
+ /** Up to 20 key-value pairs of your own, on the broadcast and on every message. */
420
+ metadata?: Record<string, string> | undefined;
421
+ /** One entry per message, at most 50,000; a larger list is several broadcasts under one tag. */
422
+ messages: BroadcastMessageEntry[];
423
+ }
424
+ /** What `broadcasts.send` takes: the fields and at least one of `text` and `html`, each with `{{ unsubscribe_url }}` where the link goes. */
425
+ export type SendBroadcastRequest = SendBroadcastFields & ({
426
+ text: string;
427
+ html?: string | undefined;
428
+ } | {
429
+ html: string;
430
+ text?: string | undefined;
431
+ });
432
+ /** The body POST /v1/broadcasts takes; equal to the API's own schema. */
433
+ export interface SendBroadcastBody {
434
+ streamId: string;
435
+ from: Address;
436
+ subject: string;
437
+ text?: string | undefined;
438
+ html?: string | undefined;
439
+ headers?: Record<string, string> | undefined;
440
+ attachments?: EncodedAttachment[] | undefined;
441
+ tag?: string | null | undefined;
442
+ metadata?: Record<string, string> | undefined;
443
+ messages: BroadcastMessageEntry[];
444
+ }
445
+ /** The broadcast was stored; the worker sends its messages from here. */
446
+ export interface AcceptedBroadcast {
447
+ /** The id the messages, the progress and the cancel refer to. */
448
+ broadcastId: string;
449
+ status: 'accepted';
450
+ /** Messages stored; each is a message in the log. */
451
+ total: number;
452
+ /** Addresses dropped for standing on the stream's suppression list. */
453
+ suppressed: number;
454
+ submittedAt: string;
455
+ }
456
+ /** A broadcast and how far it has come. */
457
+ export interface Broadcast {
458
+ broadcastId: string;
459
+ /** The broadcast stream the messages go on. */
460
+ streamId: string;
461
+ status: BroadcastStatus;
462
+ from: string;
463
+ subject: string;
464
+ tag: string | null;
465
+ metadata: Record<string, string>;
466
+ /** Messages stored, after suppressed addresses were dropped. */
467
+ total: number;
468
+ /** Messages handed to the mail server so far. */
469
+ released: number;
470
+ /** Messages that could not be handed over, cancelled ones included. */
471
+ failed: number;
472
+ /** Addresses dropped from the list for standing on the stream's suppression list. */
473
+ suppressed: number;
474
+ submittedAt: string;
475
+ /** Set once nothing is left to send, or on cancel. */
476
+ completedAt: string | null;
477
+ }
478
+ export interface BroadcastPage {
479
+ broadcasts: Broadcast[];
480
+ /** Pass as `after` for the next page; null on the last. */
481
+ next: string | null;
482
+ }
483
+ /** What `broadcasts.list` takes. */
484
+ export type BroadcastList = PageQuery;
485
+ /** The body POST /v1/tokens takes. */
486
+ export interface CreateTokenRequest {
487
+ /** 1 to 100 characters, for people to tell tokens apart. */
488
+ name: string;
489
+ }
490
+ /** A token of the server; its value is shown only when it is created. */
491
+ export interface Token {
492
+ tokenId: string;
493
+ name: string;
494
+ /** The first characters of the token, to match it with a value in hand. */
495
+ prefix: string;
496
+ createdAt: string;
497
+ revokedAt: string | null;
498
+ }
499
+ /** A token just created, with its value, shown this once. */
500
+ export interface CreatedToken extends Token {
501
+ token: string;
502
+ }
503
+ export interface TokenList {
504
+ tokens: Token[];
505
+ }
506
+ /** The events a webhook can receive. */
507
+ export type WebhookEventName = 'delivered' | 'bounced' | 'deferred' | 'spam_complaint' | 'unsubscribed' | 'cap_warning' | 'cap_reached' | 'inbound';
508
+ /** The body POST /v1/webhooks takes. */
509
+ export interface CreateWebhookRequest {
510
+ /** An https URL on a public host, without credentials or a fragment. */
511
+ url: string;
512
+ /** The events to deliver; every event when left out. */
513
+ events?: WebhookEventName[] | undefined;
514
+ /** Limits the message events to one stream of the server; every stream when left out. Cap events arrive either way. */
515
+ streamId?: string | undefined;
516
+ /** How the inbound event carries a received message: full sends the parsed message with the event; reference sends ids and sizes only. full when left out. */
517
+ inboundContent?: InboundContent | undefined;
518
+ }
519
+ /** How the inbound event carries a received message. */
520
+ export type InboundContent = 'full' | 'reference';
521
+ /** A webhook of the server. */
522
+ export interface Webhook {
523
+ webhookId: string;
524
+ url: string;
525
+ events: WebhookEventName[];
526
+ /** The one stream whose message events it receives; null for every stream. */
527
+ streamId: string | null;
528
+ /** False while switched off in the dashboard; nothing is queued for it then. */
529
+ enabled: boolean;
530
+ /** How the inbound event carries a received message: the parsed message, or a reference. */
531
+ inboundContent: InboundContent;
532
+ createdAt: string;
533
+ }
534
+ /** A webhook just created, with its signing secret, shown this once. */
535
+ export interface CreatedWebhook extends Webhook {
536
+ secret: string;
537
+ }
538
+ export interface WebhookList {
539
+ webhooks: Webhook[];
540
+ }
541
+ /** pending is waiting for its next attempt; dead gave up and can be replayed. */
542
+ export type DeliveryStatus = 'pending' | 'delivered' | 'dead';
543
+ export interface DeliveryQuery extends PageQuery {
544
+ status?: DeliveryStatus | undefined;
545
+ }
546
+ /** One event on its way to a webhook, retried with backoff until delivered or dead. */
547
+ export interface Delivery {
548
+ deliveryId: string;
549
+ event: WebhookEventName;
550
+ /** Null for an event about usage rather than a message. */
551
+ messageId: string | null;
552
+ status: DeliveryStatus;
553
+ attempts: number;
554
+ /** When the next attempt is due, while pending. */
555
+ nextAttemptAt: string | null;
556
+ /** The HTTP status the endpoint last answered. */
557
+ lastStatusCode: number | null;
558
+ /** Why the last attempt failed, when it did. */
559
+ lastError: string | null;
560
+ deliveredAt: string | null;
561
+ createdAt: string;
562
+ }
563
+ /** One page of a webhook's deliveries, newest first. */
564
+ export interface DeliveryPage {
565
+ deliveries: Delivery[];
566
+ next: string | null;
567
+ }
568
+ /** Options `webhooks.receive` takes. */
569
+ export interface ReceiveOptions {
570
+ /** How old a signature may be, in seconds; five minutes by default. */
571
+ toleranceSeconds?: number | undefined;
572
+ }
573
+ /** The body POST /v1/domains takes. */
574
+ export interface CreateDomainRequest {
575
+ /** The domain mail is sent from, such as example.se. */
576
+ domain: string;
577
+ }
578
+ /** A DNS record the domain needs and whether it has been seen. */
579
+ export interface DnsRecord<Type extends 'CNAME' | 'TXT'> {
580
+ type: Type;
581
+ /** The name to create the record under. */
582
+ host: string;
583
+ /** The value the record must hold. */
584
+ value: string;
585
+ verified: boolean;
586
+ verifiedAt: string | null;
587
+ }
588
+ /** A sending domain and the two records it needs. */
589
+ export interface SendingDomain {
590
+ domainId: string;
591
+ domain: string;
592
+ /** True once both records have been seen; only then may mail go out. */
593
+ verified: boolean;
594
+ createdAt: string;
595
+ /** When the records were last looked up. */
596
+ lastCheckedAt: string | null;
597
+ /** The return-path record, which also satisfies SPF. */
598
+ returnPath: DnsRecord<'CNAME'>;
599
+ /** The DKIM public key record. */
600
+ dkim: DnsRecord<'TXT'>;
601
+ }
602
+ /** dns_error is a resolver failure, such as a DNSSEC problem or a timeout, not an absent record. */
603
+ export type RecordCheck = 'ok' | 'missing' | 'mismatch' | 'dns_error';
604
+ /** The domain as it stands after a check, and what each lookup found. */
605
+ export interface VerifiedDomain extends SendingDomain {
606
+ check: {
607
+ returnPath: RecordCheck;
608
+ dkim: RecordCheck;
609
+ };
610
+ }
611
+ export interface DomainList {
612
+ domains: SendingDomain[];
613
+ }
614
+ /** What every event about a message carries. */
615
+ export interface MessageEventFields {
616
+ /** The delivery id. Deliveries arrive at least once, so key your handling on it. */
617
+ id: string;
618
+ /** The attempt number, from 1. */
619
+ attempt: number;
620
+ messageId: string;
621
+ /** The recipient the event is about. */
622
+ recipient: string;
623
+ occurredAt: string;
624
+ serverId: string;
625
+ /** The stream the message went on. */
626
+ streamId: string;
627
+ /** The broadcast the message belongs to; null for a message sent on its own. */
628
+ broadcastId: string | null;
629
+ /** The tag and metadata you sent with the message. */
630
+ tag: string | null;
631
+ metadata: Record<string, string>;
632
+ }
633
+ /** The receiver accepted the message for the recipient. */
634
+ export interface DeliveredEvent extends MessageEventFields {
635
+ event: 'delivered';
636
+ details: {
637
+ /** The SMTP status code the receiver answered. */
638
+ code: number | null;
639
+ /** The receiver's response text. */
640
+ response: string | null;
641
+ };
642
+ }
643
+ /** The receiver refused the message for good, or Sendora gave up; the recipient is suppressed when `hard`. */
644
+ export interface BouncedEvent extends MessageEventFields {
645
+ event: 'bounced';
646
+ details: {
647
+ code: number | null;
648
+ response: string | null;
649
+ /** How the bounce was classified, such as InvalidRecipient. */
650
+ classification: string | null;
651
+ /** True when the address is now on the suppression list. */
652
+ hard: boolean;
653
+ /** True when the message expired after repeated deferrals rather than being refused. */
654
+ expired: boolean;
655
+ };
656
+ }
657
+ /** The receiver asked Sendora to try later; several may follow. */
658
+ export interface DeferredEvent extends MessageEventFields {
659
+ event: 'deferred';
660
+ details: {
661
+ code: number | null;
662
+ response: string | null;
663
+ };
664
+ }
665
+ /** The recipient reported the message as spam; only Sendora support lifts that suppression. */
666
+ export interface SpamComplaintEvent extends MessageEventFields {
667
+ event: 'spam_complaint';
668
+ details: {
669
+ /** The feedback type the receiver reported, such as abuse. */
670
+ feedbackType: string | null;
671
+ };
672
+ }
673
+ /** The recipient unsubscribed through the link or their mail client's one-click button; only Sendora support lifts that suppression. */
674
+ export interface UnsubscribedEvent extends MessageEventFields {
675
+ event: 'unsubscribed';
676
+ details: {
677
+ /** `link` for the page's button, `one_click` for a mail client's request. */
678
+ source: 'link' | 'one_click';
679
+ };
680
+ }
681
+ /** What both usage events carry. */
682
+ export interface CapEventFields {
683
+ id: string;
684
+ attempt: number;
685
+ /** Whose cap it is. */
686
+ scope: LimitScope;
687
+ /** The server whose cap it is, or null when the account's cap is meant. */
688
+ serverId: string | null;
689
+ cap: number;
690
+ used: number;
691
+ periodStart: string;
692
+ periodEnd: string;
693
+ occurredAt: string;
694
+ }
695
+ /** 80 percent of the monthly cap is used. */
696
+ export interface CapWarningEvent extends CapEventFields {
697
+ event: 'cap_warning';
698
+ }
699
+ /** A send was refused because the monthly cap is used up. */
700
+ export interface CapReachedEvent extends CapEventFields {
701
+ event: 'cap_reached';
702
+ }
703
+ export type SpfVerdict = 'pass' | 'fail' | 'softfail' | 'neutral' | 'none' | 'temperror' | 'permerror' | 'unchecked';
704
+ export type AuthVerdict = 'pass' | 'fail' | 'none' | 'temperror' | 'permerror' | 'unchecked';
705
+ export type DmarcPolicy = 'none' | 'quarantine' | 'reject';
706
+ export type ArcVerdict = 'none' | 'pass' | 'fail' | 'unchecked';
707
+ /** What Sendora found when it checked a received message's authentication; `unchecked` until the checks have run. */
708
+ export interface InboundAuthentication {
709
+ /** SPF for the address in MAIL FROM. */
710
+ spf: SpfVerdict;
711
+ /** SPF for the name the sending server gave in HELO. */
712
+ spfHelo: SpfVerdict;
713
+ dkim: AuthVerdict;
714
+ dmarc: AuthVerdict;
715
+ /** What the sender's domain asks for; told only when DMARC failed. */
716
+ dmarcPolicy: DmarcPolicy | null;
717
+ arc: ArcVerdict;
718
+ /** When the checks ran; null until they have. */
719
+ checkedAt: string | null;
720
+ }
721
+ export interface InboundAddress {
722
+ address: string;
723
+ name: string | null;
724
+ }
725
+ export interface InboundHeader {
726
+ name: string;
727
+ value: string;
728
+ }
729
+ /** An attachment of a received message, without its bytes. */
730
+ export interface InboundAttachment {
731
+ /** Its place among the message's attachments, from 0. */
732
+ position: number;
733
+ name: string;
734
+ contentType: string;
735
+ /** The Content-ID an HTML body refers to with `cid:`, when it has one. */
736
+ contentId: string | null;
737
+ size: number;
738
+ /** True for a part shown in the body rather than offered as a file. */
739
+ inline: boolean;
740
+ }
741
+ /** What every inbound event carries: the reference to the received message. */
742
+ export interface InboundEventFields {
743
+ id: string;
744
+ attempt: number;
745
+ event: 'inbound';
746
+ inboundMessageId: string;
747
+ serverId: string;
748
+ /** The inbound stream that received it. */
749
+ streamId: string;
750
+ /** When the message was accepted from the sending server. */
751
+ receivedAt: string;
752
+ /** The address of yours the message was sent to. */
753
+ envelopeRecipient: string;
754
+ /** The text after `+` in the local part of that address, when the sender used one. */
755
+ mailboxHash: string | null;
756
+ sizeBytes: number;
757
+ attachmentCount: number;
758
+ hasText: boolean;
759
+ hasHtml: boolean;
760
+ authentication: InboundAuthentication;
761
+ /** What the parser met, from a closed set; null when the message parsed clean. */
762
+ parseIssue: string | null;
763
+ }
764
+ /** The message itself, added for a webhook with `inboundContent: 'full'`. */
765
+ export interface InboundEventContent {
766
+ /** The envelope sender; null for a bounce, or once the content window has passed. */
767
+ envelope: {
768
+ sender: string | null;
769
+ } | null;
770
+ from: InboundAddress | null;
771
+ replyTo: InboundAddress[];
772
+ /** Up to 100 entries; `toCount` is the whole number. */
773
+ to: InboundAddress[];
774
+ toCount: number;
775
+ cc: InboundAddress[];
776
+ ccCount: number;
777
+ subject: string | null;
778
+ /** The sender's Date header as ISO 8601, when it was a real moment. */
779
+ date: string | null;
780
+ messageIdHeader: string | null;
781
+ inReplyTo: string | null;
782
+ references: string[];
783
+ headers: InboundHeader[];
784
+ /** The plain-text body; null when there is none, or over 1 MiB. */
785
+ text: string | null;
786
+ /** The HTML body; null when there is none, or over 2 MiB. */
787
+ html: string | null;
788
+ attachments: InboundAttachment[];
789
+ /** `too_large` when text or HTML was left out for size; `expired` when the content window has passed and the reference is all that remains. */
790
+ contentOmitted: 'too_large' | 'expired' | null;
791
+ }
792
+ /**
793
+ * A message received on an inbound stream. The content fields are present
794
+ * for a webhook with `inboundContent: 'full'` and absent for
795
+ * `reference`; `'contentOmitted' in event` tells them apart.
796
+ */
797
+ export type InboundEvent = InboundEventFields & (InboundEventContent | {
798
+ contentOmitted?: undefined;
799
+ });
800
+ /** What a webhook request carries, once verified; narrow on `event`. */
801
+ export type WebhookEvent = DeliveredEvent | BouncedEvent | DeferredEvent | SpamComplaintEvent | UnsubscribedEvent | CapWarningEvent | CapReachedEvent | InboundEvent;
802
+ //# sourceMappingURL=types.d.ts.map