coss 0.0.4 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +395 -0
- package/dist/index.d.ts +2823 -0
- package/dist/index.js +1917 -0
- package/package.json +34 -24
- package/.npmignore +0 -4
- package/Cakefile +0 -50
- package/bower.json +0 -25
- package/coss.js +0 -134
- package/coss.min.js +0 -1
- package/readme.md +0 -75
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,2823 @@
|
|
|
1
|
+
//#region src/api-version.d.ts
|
|
2
|
+
/**
|
|
3
|
+
* API versions this SDK knows, oldest first: a hand-written mirror of `API_VERSIONS` in the API
|
|
4
|
+
* (`apps/api/test/sdk-contract.test.ts` keeps them equal).
|
|
5
|
+
*/
|
|
6
|
+
export declare const API_VERSIONS: readonly ["2026-10-10"];
|
|
7
|
+
/** A dated API version, sent as the `Coss-Version` header. */
|
|
8
|
+
type ApiVersion = (typeof API_VERSIONS)[number];
|
|
9
|
+
/** The version this SDK's types describe, sent with every request unless `apiVersion` overrides it. */
|
|
10
|
+
export declare const API_VERSION: ApiVersion;
|
|
11
|
+
//#endregion
|
|
12
|
+
//#region src/core/errors.d.ts
|
|
13
|
+
/** Error types returned by the API, plus the client-side `connection_error` and `timeout_error`. */
|
|
14
|
+
type CossErrorType = "invalid_request_error" | "authentication_error" | "permission_error" | "not_found_error" | "idempotency_error" | "rate_limit_error" | "billing_error" | "api_error" | "connection_error" | "timeout_error";
|
|
15
|
+
/** One field-level validation problem (`invalid_request_error` / `validation_error`). */
|
|
16
|
+
interface CossErrorIssue {
|
|
17
|
+
path: string;
|
|
18
|
+
message: string;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* A failed request. API errors mirror the API's `{ "error": { … } }` envelope; failures that never
|
|
22
|
+
* produced a response (network, timeout, abort) have `status: null`.
|
|
23
|
+
*/
|
|
24
|
+
interface CossError {
|
|
25
|
+
type: CossErrorType;
|
|
26
|
+
/** Machine-readable reason, e.g. `invalid_api_key`, `validation_error`, `aborted`. */
|
|
27
|
+
code: string;
|
|
28
|
+
message: string;
|
|
29
|
+
/** HTTP status, or `null` when no response was received. */
|
|
30
|
+
status: number | null;
|
|
31
|
+
/** The API's `X-Request-Id`. Include it when contacting support. */
|
|
32
|
+
request_id: string | null;
|
|
33
|
+
/** The request parameter the error relates to, when there is one. */
|
|
34
|
+
param?: string;
|
|
35
|
+
issues?: CossErrorIssue[];
|
|
36
|
+
}
|
|
37
|
+
type CossResult<T> = {
|
|
38
|
+
data: T;
|
|
39
|
+
error: null;
|
|
40
|
+
} | {
|
|
41
|
+
data: null;
|
|
42
|
+
error: CossError;
|
|
43
|
+
};
|
|
44
|
+
//#endregion
|
|
45
|
+
//#region src/core/http.d.ts
|
|
46
|
+
/** Any WHATWG-compatible `fetch` (global fetch, undici, a test double, `app.fetch` adapters …). */
|
|
47
|
+
type FetchLike = (input: string | URL | Request, init?: RequestInit) => Promise<Response>;
|
|
48
|
+
/** Per-request options accepted by every resource method. */
|
|
49
|
+
interface RequestOptions {
|
|
50
|
+
/**
|
|
51
|
+
* Sent as `Idempotency-Key` on POST requests. When omitted a random UUID is generated; either way
|
|
52
|
+
* the same key is reused for every retry of the call, so a retried send is never duplicated.
|
|
53
|
+
*/
|
|
54
|
+
idempotencyKey?: string;
|
|
55
|
+
/** Aborting cancels the in-flight attempt and any pending retry. */
|
|
56
|
+
signal?: AbortSignal;
|
|
57
|
+
}
|
|
58
|
+
interface HttpClientOptions {
|
|
59
|
+
apiKey: string;
|
|
60
|
+
baseUrl: string;
|
|
61
|
+
fetch: FetchLike;
|
|
62
|
+
/** Per-attempt timeout in milliseconds. */
|
|
63
|
+
timeout: number;
|
|
64
|
+
maxRetries: number;
|
|
65
|
+
/** Sent as `Coss-Version` with every request. */
|
|
66
|
+
apiVersion: string;
|
|
67
|
+
/** Waits between retries; must resolve early when `signal` aborts. Overridable for tests. */
|
|
68
|
+
sleep?: (ms: number, signal?: AbortSignal) => Promise<void>;
|
|
69
|
+
}
|
|
70
|
+
interface ApiRequest {
|
|
71
|
+
/** Disable automatic retries for operations without server-side deduplication. */
|
|
72
|
+
retry?: boolean;
|
|
73
|
+
method: "GET" | "POST" | "PATCH" | "DELETE";
|
|
74
|
+
/** Path including the version prefix, e.g. `/v1/emails`. */
|
|
75
|
+
path: string;
|
|
76
|
+
/** Query parameters; `undefined` values are left out. */
|
|
77
|
+
query?: Record<string, string | number | undefined>;
|
|
78
|
+
/** Serialized as JSON. */
|
|
79
|
+
body?: unknown;
|
|
80
|
+
/**
|
|
81
|
+
* `text` returns the raw body of a successful response (e.g. CSV) instead of parsing JSON;
|
|
82
|
+
* `bytes` returns it as a `Uint8Array` (a received email's raw message, an attachment).
|
|
83
|
+
*/
|
|
84
|
+
responseType?: "json" | "text" | "bytes";
|
|
85
|
+
idempotencyKey?: string;
|
|
86
|
+
signal?: AbortSignal;
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* The request pipeline shared by all resources: auth + JSON, a per-attempt timeout, retries with
|
|
90
|
+
* backoff, and mapping every failure to a `CossError`. It never throws for API or network errors.
|
|
91
|
+
*/
|
|
92
|
+
declare class HttpClient {
|
|
93
|
+
#private;
|
|
94
|
+
constructor(options: HttpClientOptions);
|
|
95
|
+
request<T>(request: ApiRequest): Promise<CossResult<T>>;
|
|
96
|
+
}
|
|
97
|
+
//#endregion
|
|
98
|
+
//#region src/types/audit-event.d.ts
|
|
99
|
+
/** Audit log wire types (hand-written mirrors of the API's schemas). */
|
|
100
|
+
/**
|
|
101
|
+
* `user`: a member, in the dashboard. `api_key`: a request made with an API key. `system`: COSS
|
|
102
|
+
* itself, including COSS support.
|
|
103
|
+
*/
|
|
104
|
+
type AuditActorType = "user" | "api_key" | "system";
|
|
105
|
+
/** One change to the organization. */
|
|
106
|
+
interface AuditEvent {
|
|
107
|
+
object: "audit_event";
|
|
108
|
+
id: string;
|
|
109
|
+
/** ISO 8601 timestamp. */
|
|
110
|
+
created_at: string;
|
|
111
|
+
actor_type: AuditActorType;
|
|
112
|
+
/** The user's or API key's id; `null` for the system. */
|
|
113
|
+
actor_id: string | null;
|
|
114
|
+
/** The user's email, the API key's id, or `COSS support` (copied when recorded). */
|
|
115
|
+
actor_label: string;
|
|
116
|
+
/** `<resource>.<verb>`, e.g. `api_key.created`, `domain.deleted`, `member.role_changed`. */
|
|
117
|
+
action: string;
|
|
118
|
+
/** What was changed: `domain`, `api_key`, `member`… */
|
|
119
|
+
target_type: string | null;
|
|
120
|
+
target_id: string | null;
|
|
121
|
+
/** A readable name for the target when it was changed. */
|
|
122
|
+
target_label: string | null;
|
|
123
|
+
/** `null` for organization-wide changes (domains, members…). */
|
|
124
|
+
project_id: string | null;
|
|
125
|
+
/** `null` for organization-wide changes (domains, members…). */
|
|
126
|
+
environment_id: string | null;
|
|
127
|
+
/** Details of the change; API changes include their `request_id`. */
|
|
128
|
+
metadata: Record<string, unknown>;
|
|
129
|
+
client_ip: string | null;
|
|
130
|
+
user_agent: string | null;
|
|
131
|
+
}
|
|
132
|
+
type OneOrMany$1<T> = T | readonly T[];
|
|
133
|
+
/** Query of `GET /v1/audit_events`. Lists may be given as arrays or comma-separated strings. */
|
|
134
|
+
interface ListAuditEventsParams {
|
|
135
|
+
/** Actions, e.g. `"api_key.created"`; an entry ending in `.` (`"domain."`) matches a whole resource. */
|
|
136
|
+
action?: OneOrMany$1<string>;
|
|
137
|
+
actor_type?: OneOrMany$1<AuditActorType>;
|
|
138
|
+
/** Only changes made by this user or API key. */
|
|
139
|
+
actor_id?: string;
|
|
140
|
+
/** Only changes to this resource, e.g. a `dom_…` id. */
|
|
141
|
+
target_id?: string;
|
|
142
|
+
/** Only changes in this environment. */
|
|
143
|
+
environment_id?: string;
|
|
144
|
+
/** Only events at or after this time. */
|
|
145
|
+
from?: string | Date;
|
|
146
|
+
/** Only events before this time. */
|
|
147
|
+
to?: string | Date;
|
|
148
|
+
/** 1-100, default 50. */
|
|
149
|
+
limit?: number;
|
|
150
|
+
/** The `id` of the last event of the previous page. */
|
|
151
|
+
after?: string;
|
|
152
|
+
}
|
|
153
|
+
//#endregion
|
|
154
|
+
//#region src/types/suppression.d.ts
|
|
155
|
+
/** Suppression list wire types (hand-written mirrors of the API's schemas). */
|
|
156
|
+
/**
|
|
157
|
+
* Why an address is suppressed. `bounce`: a permanent bounce. `complaint`: a spam complaint.
|
|
158
|
+
* `manual`: added one by one through the API or the dashboard. `import`: added by a bulk import.
|
|
159
|
+
*/
|
|
160
|
+
type SuppressionReason = "bounce" | "complaint" | "manual" | "import";
|
|
161
|
+
/** An entry of the API key's environment's suppression list. */
|
|
162
|
+
interface Suppression {
|
|
163
|
+
object: "suppression";
|
|
164
|
+
id: string;
|
|
165
|
+
/** The bare, lower-cased address. */
|
|
166
|
+
address: string;
|
|
167
|
+
/** `"*"` (every email) or a category: only emails sent with that `category` skip the address. */
|
|
168
|
+
scope: string;
|
|
169
|
+
reason: SuppressionReason;
|
|
170
|
+
/** The email whose bounce or complaint added this entry. */
|
|
171
|
+
email_id: string | null;
|
|
172
|
+
/** ISO 8601 timestamp. */
|
|
173
|
+
created_at: string;
|
|
174
|
+
}
|
|
175
|
+
/** Body of `POST /v1/suppressions`. */
|
|
176
|
+
interface CreateSuppressionParams {
|
|
177
|
+
/** Display names are ignored; matching is case-insensitive. */
|
|
178
|
+
address: string;
|
|
179
|
+
/** `"*"` (the default) suppresses every email; a category only suppresses those emails. */
|
|
180
|
+
scope?: string;
|
|
181
|
+
}
|
|
182
|
+
/** Query of `GET /v1/suppressions`. */
|
|
183
|
+
interface ListSuppressionsParams {
|
|
184
|
+
address?: string;
|
|
185
|
+
scope?: string;
|
|
186
|
+
/** 1-100, default 50. */
|
|
187
|
+
limit?: number;
|
|
188
|
+
/** The `id` of the last entry of the previous page. */
|
|
189
|
+
after?: string;
|
|
190
|
+
}
|
|
191
|
+
/** Query of `GET /v1/suppressions/check`. */
|
|
192
|
+
interface CheckSuppressionParams {
|
|
193
|
+
address: string;
|
|
194
|
+
/** The category of the email you plan to send. Without it, only `"*"` entries count. */
|
|
195
|
+
category?: string;
|
|
196
|
+
}
|
|
197
|
+
/** Whether a send would skip an address. */
|
|
198
|
+
interface SuppressionCheck {
|
|
199
|
+
object: "suppression_check";
|
|
200
|
+
address: string;
|
|
201
|
+
suppressed: boolean;
|
|
202
|
+
/** The entries that match. */
|
|
203
|
+
suppressions: Suppression[];
|
|
204
|
+
}
|
|
205
|
+
/** Response of `DELETE /v1/suppressions/{id}`. */
|
|
206
|
+
interface DeletedSuppression {
|
|
207
|
+
object: "suppression";
|
|
208
|
+
id: string;
|
|
209
|
+
deleted: true;
|
|
210
|
+
}
|
|
211
|
+
/** One entry of `POST /v1/suppressions/import`. */
|
|
212
|
+
interface ImportSuppressionEntry {
|
|
213
|
+
address: string;
|
|
214
|
+
/** `"*"` (the default) or a category. */
|
|
215
|
+
scope?: string;
|
|
216
|
+
}
|
|
217
|
+
/** Input of `coss.email.suppressions.import()`; the SDK sends 1,000 entries per request. */
|
|
218
|
+
interface ImportSuppressionsParams {
|
|
219
|
+
suppressions: ImportSuppressionEntry[];
|
|
220
|
+
}
|
|
221
|
+
/** What an import did. */
|
|
222
|
+
interface SuppressionImport {
|
|
223
|
+
object: "suppression_import";
|
|
224
|
+
/** Entries added. */
|
|
225
|
+
created: number;
|
|
226
|
+
/** Valid entries that were already on the list (or repeated in the import); unchanged. */
|
|
227
|
+
existing: number;
|
|
228
|
+
/** Skipped entries; `index` is the entry's position in `suppressions`. */
|
|
229
|
+
invalid: Array<{
|
|
230
|
+
index: number;
|
|
231
|
+
address: string;
|
|
232
|
+
message: string;
|
|
233
|
+
}>;
|
|
234
|
+
}
|
|
235
|
+
/** Query of `GET /v1/suppressions/export`. */
|
|
236
|
+
interface ExportSuppressionsParams {
|
|
237
|
+
scope?: string;
|
|
238
|
+
reason?: SuppressionReason;
|
|
239
|
+
}
|
|
240
|
+
//#endregion
|
|
241
|
+
//#region src/types/email.d.ts
|
|
242
|
+
/** A `name`/`value` pair attached to an email for your own filtering and analytics. */
|
|
243
|
+
interface EmailTag {
|
|
244
|
+
name: string;
|
|
245
|
+
value: string;
|
|
246
|
+
}
|
|
247
|
+
/**
|
|
248
|
+
* A file to attach (at most 20 per email, 25 MB combined). Executables and other file types the
|
|
249
|
+
* delivery provider refuses (such as `.exe` or `.js`) are rejected.
|
|
250
|
+
*/
|
|
251
|
+
interface EmailAttachmentParams {
|
|
252
|
+
/** The name recipients see. Must include an extension, e.g. `"invoice.pdf"`. */
|
|
253
|
+
filename: string;
|
|
254
|
+
/** The file's bytes, base64-encoded (no line breaks or `data:` prefix). */
|
|
255
|
+
content: string;
|
|
256
|
+
/** Media type such as `"application/pdf"`. Defaults from the filename's extension. */
|
|
257
|
+
content_type?: string;
|
|
258
|
+
/**
|
|
259
|
+
* Makes the attachment inline: reference it from `html` as `<img src="cid:logo@acme">`
|
|
260
|
+
* (without angle brackets here).
|
|
261
|
+
*/
|
|
262
|
+
content_id?: string;
|
|
263
|
+
}
|
|
264
|
+
/** Metadata of a sent attachment. The content itself is never returned. */
|
|
265
|
+
interface EmailAttachment {
|
|
266
|
+
id: string;
|
|
267
|
+
filename: string;
|
|
268
|
+
content_type: string;
|
|
269
|
+
/** Set for inline attachments. */
|
|
270
|
+
content_id: string | null;
|
|
271
|
+
/** Size in bytes. */
|
|
272
|
+
size: number;
|
|
273
|
+
}
|
|
274
|
+
/**
|
|
275
|
+
* Whether the email was handed to the delivery provider. `scheduled` emails wait for their
|
|
276
|
+
* `scheduled_at`; `canceled` ones were canceled before that. Delivery is tracked per recipient.
|
|
277
|
+
*/
|
|
278
|
+
type EmailStatus = "queued" | "sent" | "failed" | "scheduled" | "canceled";
|
|
279
|
+
/**
|
|
280
|
+
* Delivery status of one recipient. It only moves forward: `queued` → `sent` →
|
|
281
|
+
* `delivery_delayed` → `delivered`, then `bounced` / `suppressed` / `failed`, then `complained`.
|
|
282
|
+
* `suppressed` means the address is on the environment's suppression list (for every email or for
|
|
283
|
+
* the email's `category`), so it was skipped. `canceled` means the scheduled email was canceled.
|
|
284
|
+
*/
|
|
285
|
+
type EmailRecipientStatus = "queued" | "sent" | "delivery_delayed" | "delivered" | "bounced" | "suppressed" | "complained" | "failed" | "canceled";
|
|
286
|
+
/** One distinct recipient address of an email. */
|
|
287
|
+
interface EmailRecipient {
|
|
288
|
+
/** The bare, lower-cased address. */
|
|
289
|
+
address: string;
|
|
290
|
+
type: "to" | "cc" | "bcc";
|
|
291
|
+
status: EmailRecipientStatus;
|
|
292
|
+
/** ISO 8601 timestamp of the latest event for this recipient, or `null`. */
|
|
293
|
+
last_event_at: string | null;
|
|
294
|
+
}
|
|
295
|
+
type EmailEventType = "email.sent" | "email.delivered" | "email.delivery_delayed" | "email.bounced" | "email.complained" | "email.failed" | "email.suppressed" | "email.scheduled" | "email.canceled" | "email.opened" | "email.clicked" | "email.rescheduled";
|
|
296
|
+
/** Details of an event; which member is present depends on the event type. */
|
|
297
|
+
interface EmailEventData {
|
|
298
|
+
bounce?: {
|
|
299
|
+
type: "permanent" | "transient" | "undetermined";
|
|
300
|
+
sub_type: string;
|
|
301
|
+
diagnostic_code: string | null;
|
|
302
|
+
};
|
|
303
|
+
complaint?: {
|
|
304
|
+
feedback_type: string | null;
|
|
305
|
+
sub_type: string | null;
|
|
306
|
+
};
|
|
307
|
+
delay?: {
|
|
308
|
+
type: string;
|
|
309
|
+
expires_at: string | null;
|
|
310
|
+
diagnostic_code: string | null;
|
|
311
|
+
};
|
|
312
|
+
delivery?: {
|
|
313
|
+
smtp_response: string | null;
|
|
314
|
+
};
|
|
315
|
+
failure?: {
|
|
316
|
+
code: string;
|
|
317
|
+
message: string;
|
|
318
|
+
};
|
|
319
|
+
/** Only for `email.suppressed`: the entry that matched the recipient. */
|
|
320
|
+
suppression?: {
|
|
321
|
+
id: string;
|
|
322
|
+
scope: string;
|
|
323
|
+
reason: SuppressionReason;
|
|
324
|
+
};
|
|
325
|
+
/** Only for `email.opened`. */
|
|
326
|
+
open?: {
|
|
327
|
+
user_agent: string | null;
|
|
328
|
+
};
|
|
329
|
+
/** Only for `email.clicked`: the original link and its index among the tracked links. */
|
|
330
|
+
click?: {
|
|
331
|
+
url: string;
|
|
332
|
+
link_position: number;
|
|
333
|
+
user_agent: string | null;
|
|
334
|
+
};
|
|
335
|
+
/** Only for `email.rescheduled`: the new time and the one it replaced. */
|
|
336
|
+
reschedule?: {
|
|
337
|
+
scheduled_at: string;
|
|
338
|
+
previous_scheduled_at: string;
|
|
339
|
+
};
|
|
340
|
+
}
|
|
341
|
+
/** A delivery event of an email. */
|
|
342
|
+
interface EmailEvent {
|
|
343
|
+
object: "email_event";
|
|
344
|
+
id: string;
|
|
345
|
+
email_id: string;
|
|
346
|
+
type: EmailEventType;
|
|
347
|
+
/**
|
|
348
|
+
* The recipient this event is about; `null` for the whole email (`email.sent`, `email.failed`),
|
|
349
|
+
* and for opens and clicks of an email with several recipients.
|
|
350
|
+
*/
|
|
351
|
+
recipient: string | null;
|
|
352
|
+
/** ISO 8601 timestamp. */
|
|
353
|
+
occurred_at: string;
|
|
354
|
+
data: EmailEventData;
|
|
355
|
+
}
|
|
356
|
+
/** A list response. */
|
|
357
|
+
interface List<T> {
|
|
358
|
+
object: "list";
|
|
359
|
+
data: T[];
|
|
360
|
+
has_more: boolean;
|
|
361
|
+
}
|
|
362
|
+
/**
|
|
363
|
+
* Overrides the environment's tracking settings for one email. Omitted fields keep the configured
|
|
364
|
+
* setting (the email's category rule, else the environment default, else off).
|
|
365
|
+
*/
|
|
366
|
+
interface TrackingOptions {
|
|
367
|
+
/** Add an invisible pixel to the HTML body and record `email.opened` events. */
|
|
368
|
+
opens?: boolean;
|
|
369
|
+
/**
|
|
370
|
+
* Send HTML links through a COSS redirect and record `email.clicked` events. Links with a
|
|
371
|
+
* `data-coss-no-track` attribute are left alone.
|
|
372
|
+
*/
|
|
373
|
+
clicks?: boolean;
|
|
374
|
+
}
|
|
375
|
+
/** Body of `POST /v1/emails`. */
|
|
376
|
+
interface SendEmailParams {
|
|
377
|
+
/** `"you@example.com"` or `"Your Name <you@example.com>"`. */
|
|
378
|
+
from: string;
|
|
379
|
+
to: string | string[];
|
|
380
|
+
cc?: string | string[];
|
|
381
|
+
bcc?: string | string[];
|
|
382
|
+
reply_to?: string | string[];
|
|
383
|
+
subject: string;
|
|
384
|
+
/** At least one of `html` or `text` is required. */
|
|
385
|
+
html?: string;
|
|
386
|
+
text?: string;
|
|
387
|
+
/** Custom headers. Names are case-insensitive; reserved names such as `subject` are rejected. */
|
|
388
|
+
headers?: Record<string, string>;
|
|
389
|
+
tags?: EmailTag[];
|
|
390
|
+
/**
|
|
391
|
+
* What kind of email this is, e.g. `"marketing"`. Recipients suppressed for this category (or
|
|
392
|
+
* for every email) are skipped.
|
|
393
|
+
*/
|
|
394
|
+
category?: string;
|
|
395
|
+
/**
|
|
396
|
+
* Send at this time instead of now: an ISO 8601 date-time with an offset, e.g.
|
|
397
|
+
* `"2026-10-11T09:00:00Z"`, at most 30 days ahead. A time that is not in the future sends
|
|
398
|
+
* immediately. Until it is sent, move it with `coss.email.reschedule(id, …)` or cancel it with
|
|
399
|
+
* `coss.email.cancel(id)`.
|
|
400
|
+
*/
|
|
401
|
+
scheduled_at?: string;
|
|
402
|
+
attachments?: EmailAttachmentParams[];
|
|
403
|
+
tracking?: TrackingOptions;
|
|
404
|
+
}
|
|
405
|
+
/** Parameters of `coss.email.reschedule`. */
|
|
406
|
+
interface RescheduleEmailParams {
|
|
407
|
+
/**
|
|
408
|
+
* The new time: an ISO 8601 date-time with an offset, at most 30 days ahead. A time that is not
|
|
409
|
+
* in the future sends the email right away.
|
|
410
|
+
*/
|
|
411
|
+
scheduled_at: string;
|
|
412
|
+
}
|
|
413
|
+
/**
|
|
414
|
+
* Open and click tracking as resolved when the email was sent, with engagement so far. Opens can
|
|
415
|
+
* be inflated by mail clients that prefetch images, clicks by link scanners.
|
|
416
|
+
*/
|
|
417
|
+
interface EmailTracking {
|
|
418
|
+
opens: boolean;
|
|
419
|
+
clicks: boolean;
|
|
420
|
+
open_count: number;
|
|
421
|
+
/** ISO 8601 timestamps, or `null`. */
|
|
422
|
+
first_opened_at: string | null;
|
|
423
|
+
last_opened_at: string | null;
|
|
424
|
+
click_count: number;
|
|
425
|
+
first_clicked_at: string | null;
|
|
426
|
+
last_clicked_at: string | null;
|
|
427
|
+
}
|
|
428
|
+
/** A link COSS rewrote for click tracking. */
|
|
429
|
+
interface EmailLink {
|
|
430
|
+
object: "email_link";
|
|
431
|
+
id: string;
|
|
432
|
+
email_id: string;
|
|
433
|
+
/** Index of the link among the email's tracked links, in document order. */
|
|
434
|
+
position: number;
|
|
435
|
+
url: string;
|
|
436
|
+
click_count: number;
|
|
437
|
+
first_clicked_at: string | null;
|
|
438
|
+
last_clicked_at: string | null;
|
|
439
|
+
}
|
|
440
|
+
/** An email as returned by the API. Recipient fields are always arrays. */
|
|
441
|
+
interface Email {
|
|
442
|
+
object: "email";
|
|
443
|
+
id: string;
|
|
444
|
+
from: string;
|
|
445
|
+
to: string[];
|
|
446
|
+
cc: string[];
|
|
447
|
+
bcc: string[];
|
|
448
|
+
reply_to: string[];
|
|
449
|
+
subject: string;
|
|
450
|
+
html: string | null;
|
|
451
|
+
text: string | null;
|
|
452
|
+
/** Header names are lower-cased. */
|
|
453
|
+
headers: Record<string, string>;
|
|
454
|
+
tags: EmailTag[];
|
|
455
|
+
category: string | null;
|
|
456
|
+
status: EmailStatus;
|
|
457
|
+
/** Every distinct recipient across `to`, `cc` and `bcc`, with its delivery status. */
|
|
458
|
+
recipients: EmailRecipient[];
|
|
459
|
+
/** Attachment metadata; the content is discarded once the email is sent. */
|
|
460
|
+
attachments: EmailAttachment[];
|
|
461
|
+
/** `true` when sent with a sandbox (`coss_test_…`) key: nothing is actually delivered. */
|
|
462
|
+
sandbox: boolean;
|
|
463
|
+
tracking: EmailTracking;
|
|
464
|
+
/** ISO 8601 timestamp. */
|
|
465
|
+
created_at: string;
|
|
466
|
+
/** ISO 8601 timestamp, or `null` until the provider accepts the message. */
|
|
467
|
+
sent_at: string | null;
|
|
468
|
+
/** ISO 8601 timestamp the email was scheduled for, or `null` if no schedule was provided. */
|
|
469
|
+
scheduled_at: string | null;
|
|
470
|
+
/** The batch that sent the email (`coss.email.sendBatch`), or `null` if it was sent alone. */
|
|
471
|
+
batch_id: string | null;
|
|
472
|
+
}
|
|
473
|
+
/** Emails sent together by `coss.email.sendBatch`. */
|
|
474
|
+
interface EmailBatch {
|
|
475
|
+
object: "email_batch";
|
|
476
|
+
id: string;
|
|
477
|
+
/** The batch's emails, in the order they were passed. */
|
|
478
|
+
data: Email[];
|
|
479
|
+
/** ISO 8601 timestamp. */
|
|
480
|
+
created_at: string;
|
|
481
|
+
}
|
|
482
|
+
//#endregion
|
|
483
|
+
//#region src/resources/audit-events.d.ts
|
|
484
|
+
type ReadOptions$12 = Pick<RequestOptions, "signal">;
|
|
485
|
+
/**
|
|
486
|
+
* `coss.auditEvents`: the organization's audit log, newest first: changes made by members, API
|
|
487
|
+
* keys and COSS support. Organization-wide, whichever environment the key belongs to.
|
|
488
|
+
*/
|
|
489
|
+
declare class AuditEventsResource {
|
|
490
|
+
#private;
|
|
491
|
+
/** @internal Use `new Coss().auditEvents`. */
|
|
492
|
+
constructor(http: HttpClient);
|
|
493
|
+
/** Lists audit events, newest first. Pass the last `id` as `after` while `has_more` is true. */
|
|
494
|
+
list(params?: ListAuditEventsParams, options?: ReadOptions$12): Promise<CossResult<List<AuditEvent>>>;
|
|
495
|
+
/** Retrieves one audit event. */
|
|
496
|
+
get(id: string, options?: ReadOptions$12): Promise<CossResult<AuditEvent>>;
|
|
497
|
+
}
|
|
498
|
+
//#endregion
|
|
499
|
+
//#region src/types/billing.d.ts
|
|
500
|
+
/**
|
|
501
|
+
* Billing wire types (hand-written mirrors of the API's `Billing`, `Usage`, `Invoice` and `Credit`
|
|
502
|
+
* schemas). Amounts are integers in cents (USD); unit prices are dollar decimal strings.
|
|
503
|
+
*/
|
|
504
|
+
type PlanKey = "free" | "pro" | "scale" | "enterprise";
|
|
505
|
+
type Meter = "email.recipients" | "sms.segments" | "video.participant_minutes" | "scheduling.bookings";
|
|
506
|
+
type BillingHoldReason = "delinquent" | "spend_limit" | "admin";
|
|
507
|
+
/** `GET /v1/billing`: the organization's plan, the current month so far, and its standing. */
|
|
508
|
+
interface Billing {
|
|
509
|
+
object: "billing";
|
|
510
|
+
organization_id: string;
|
|
511
|
+
/** The plan in effect now (`free` without a contract). */
|
|
512
|
+
plan: PlanKey;
|
|
513
|
+
/** The contract in effect; `null` on the Free plan. */
|
|
514
|
+
contract: {
|
|
515
|
+
id: string;
|
|
516
|
+
kind: "self_serve" | "sales" | "internal";
|
|
517
|
+
effective_from: string;
|
|
518
|
+
effective_until: string | null;
|
|
519
|
+
/** End of a committed term. */
|
|
520
|
+
term_end: string | null;
|
|
521
|
+
auto_renew: boolean;
|
|
522
|
+
} | null;
|
|
523
|
+
/** A plan change that takes effect later (a downgrade, a cancellation). */
|
|
524
|
+
scheduled_change: {
|
|
525
|
+
effective_at: string;
|
|
526
|
+
plan: PlanKey;
|
|
527
|
+
} | null;
|
|
528
|
+
/** `past_due`: an invoice is overdue; `delinquent`: past its grace period (live sending is held). */
|
|
529
|
+
status: "active" | "past_due" | "delinquent";
|
|
530
|
+
/** Billing holds on live sending (sandbox keys keep working). */
|
|
531
|
+
holds: {
|
|
532
|
+
reason: BillingHoldReason;
|
|
533
|
+
since: string;
|
|
534
|
+
}[];
|
|
535
|
+
currency: "usd";
|
|
536
|
+
/** The current billing month (UTC). */
|
|
537
|
+
period: {
|
|
538
|
+
start: string;
|
|
539
|
+
end: string;
|
|
540
|
+
};
|
|
541
|
+
usage: {
|
|
542
|
+
meter: Meter;
|
|
543
|
+
quantity: number;
|
|
544
|
+
/** The plan's monthly allowance where usage stops (Free), else `null`. */
|
|
545
|
+
included: number | null;
|
|
546
|
+
}[];
|
|
547
|
+
/** This month so far, as it would be invoiced if it ended now (cents). */
|
|
548
|
+
estimate: {
|
|
549
|
+
usage: number;
|
|
550
|
+
discount: number;
|
|
551
|
+
credit: number;
|
|
552
|
+
total: number;
|
|
553
|
+
};
|
|
554
|
+
/** Unused credit usable this month (cents). */
|
|
555
|
+
credit_remaining: number;
|
|
556
|
+
/** Usage beyond the credit past which live sending is held (cents); `null`: none. */
|
|
557
|
+
spend_limit: number | null;
|
|
558
|
+
payment_method: {
|
|
559
|
+
type: string;
|
|
560
|
+
brand: string | null;
|
|
561
|
+
last4: string | null;
|
|
562
|
+
} | null;
|
|
563
|
+
features: {
|
|
564
|
+
tracking_domains: boolean;
|
|
565
|
+
audit_log: boolean;
|
|
566
|
+
log_drains: boolean;
|
|
567
|
+
sso: boolean;
|
|
568
|
+
scim: boolean;
|
|
569
|
+
};
|
|
570
|
+
/** Resource limits (`null`: unlimited). */
|
|
571
|
+
limits: {
|
|
572
|
+
domains: number | null;
|
|
573
|
+
members: number | null;
|
|
574
|
+
webhook_endpoints_per_environment: number | null;
|
|
575
|
+
};
|
|
576
|
+
}
|
|
577
|
+
/** Billable usage of one meter in one bucket. */
|
|
578
|
+
interface Usage {
|
|
579
|
+
object: "usage";
|
|
580
|
+
meter: Meter;
|
|
581
|
+
/** e.g. `country=US` for SMS; `null` for none. */
|
|
582
|
+
dimension: string | null;
|
|
583
|
+
/** Set with `group_by: "environment"`. */
|
|
584
|
+
environment_id: string | null;
|
|
585
|
+
start: string;
|
|
586
|
+
end: string;
|
|
587
|
+
quantity: number;
|
|
588
|
+
}
|
|
589
|
+
interface ListUsageParams {
|
|
590
|
+
/** Start (inclusive, ISO 8601). Defaults to the start of the current billing month. */
|
|
591
|
+
from?: string;
|
|
592
|
+
/** End (exclusive). Defaults to now. At most 400 days after `from` (7 by hour). */
|
|
593
|
+
to?: string;
|
|
594
|
+
/** Bucket size (UTC). Defaults to `day`. */
|
|
595
|
+
granularity?: "hour" | "day" | "month";
|
|
596
|
+
/** Split each bucket per environment. */
|
|
597
|
+
group_by?: "environment";
|
|
598
|
+
/** Only this meter. */
|
|
599
|
+
meter?: Meter;
|
|
600
|
+
}
|
|
601
|
+
type InvoiceStatus = "open" | "paid" | "void" | "uncollectible";
|
|
602
|
+
type InvoiceLineKind = "plan_fee" | "proration" | "usage" | "credit" | "discount" | "commitment_fee" | "commitment_shortfall" | "add_on" | "adjustment" | "write_off";
|
|
603
|
+
interface InvoiceLine {
|
|
604
|
+
object: "invoice_line";
|
|
605
|
+
id: string;
|
|
606
|
+
kind: InvoiceLineKind;
|
|
607
|
+
description: string;
|
|
608
|
+
meter: Meter | null;
|
|
609
|
+
dimension: string | null;
|
|
610
|
+
quantity: number | null;
|
|
611
|
+
/** Units covered by an allowance or committed volume (not charged). */
|
|
612
|
+
included_quantity: number | null;
|
|
613
|
+
/** Dollars per unit, e.g. `"0.0004"`; `null` when the price varies by volume. */
|
|
614
|
+
unit_price: string | null;
|
|
615
|
+
/** Cents. */
|
|
616
|
+
amount: number;
|
|
617
|
+
period: {
|
|
618
|
+
start: string;
|
|
619
|
+
end: string;
|
|
620
|
+
};
|
|
621
|
+
}
|
|
622
|
+
/** An invoice without its lines (lists and webhook events). Amounts in cents. */
|
|
623
|
+
interface InvoiceSummary {
|
|
624
|
+
object: "invoice";
|
|
625
|
+
id: string;
|
|
626
|
+
number: string | null;
|
|
627
|
+
kind: "period" | "plan_change" | "one_off" | "final";
|
|
628
|
+
status: InvoiceStatus;
|
|
629
|
+
currency: "usd";
|
|
630
|
+
period: {
|
|
631
|
+
start: string;
|
|
632
|
+
end: string;
|
|
633
|
+
};
|
|
634
|
+
subtotal: number;
|
|
635
|
+
discount: number;
|
|
636
|
+
credit: number;
|
|
637
|
+
tax: number;
|
|
638
|
+
total: number;
|
|
639
|
+
amount_paid: number;
|
|
640
|
+
amount_due: number;
|
|
641
|
+
collection_method: "charge_automatically" | "send_invoice";
|
|
642
|
+
due_at: string | null;
|
|
643
|
+
finalized_at: string | null;
|
|
644
|
+
paid_at: string | null;
|
|
645
|
+
voided_at: string | null;
|
|
646
|
+
/** A page to view (and pay) the invoice. */
|
|
647
|
+
hosted_url: string | null;
|
|
648
|
+
pdf_url: string | null;
|
|
649
|
+
}
|
|
650
|
+
interface Invoice extends InvoiceSummary {
|
|
651
|
+
lines: InvoiceLine[];
|
|
652
|
+
}
|
|
653
|
+
interface ListInvoicesParams {
|
|
654
|
+
/** Only invoices in this status. */
|
|
655
|
+
status?: InvoiceStatus;
|
|
656
|
+
/** Continue after this id (the last of the previous page). */
|
|
657
|
+
after?: string;
|
|
658
|
+
/** At most this many (1-100, default 20). */
|
|
659
|
+
limit?: number;
|
|
660
|
+
}
|
|
661
|
+
/** Credit the organization can spend: dollars (cents) or free units of a meter. */
|
|
662
|
+
interface Credit {
|
|
663
|
+
object: "credit";
|
|
664
|
+
id: string;
|
|
665
|
+
/** `amount`: dollars (`amount` and `remaining` in cents); `units`: free units of `meter`. */
|
|
666
|
+
kind: "amount" | "units";
|
|
667
|
+
amount: number;
|
|
668
|
+
remaining: number;
|
|
669
|
+
/** What a `units` credit covers. */
|
|
670
|
+
meter: Meter | null;
|
|
671
|
+
/** What an `amount` credit pays for (`null`: any usage). */
|
|
672
|
+
meters: Meter[] | null;
|
|
673
|
+
/** `any`: also fees and other charges. */
|
|
674
|
+
applies_to: "usage" | "any";
|
|
675
|
+
source: "fee" | "commitment" | "support" | "promotion" | "refund" | "sla";
|
|
676
|
+
description: string;
|
|
677
|
+
effective_at: string;
|
|
678
|
+
expires_at: string | null;
|
|
679
|
+
voided_at: string | null;
|
|
680
|
+
created_at: string;
|
|
681
|
+
}
|
|
682
|
+
interface ListCreditsParams {
|
|
683
|
+
/** `active` (default): usable now or later, with something left; `all`: every credit. */
|
|
684
|
+
status?: "active" | "all";
|
|
685
|
+
/** Continue after this id (the last of the previous page). */
|
|
686
|
+
after?: string;
|
|
687
|
+
/** At most this many (1-100, default 20). */
|
|
688
|
+
limit?: number;
|
|
689
|
+
}
|
|
690
|
+
//#endregion
|
|
691
|
+
//#region src/resources/billing.d.ts
|
|
692
|
+
type ReadOptions$11 = Pick<RequestOptions, "signal">;
|
|
693
|
+
/** `coss.billing.invoices`: the organization's invoices, newest first. */
|
|
694
|
+
declare class BillingInvoicesResource {
|
|
695
|
+
#private;
|
|
696
|
+
/** @internal Use `new Coss().billing.invoices`. */
|
|
697
|
+
constructor(http: HttpClient);
|
|
698
|
+
/** Lists invoices (without lines). Pass the last `id` as `after` while `has_more` is true. */
|
|
699
|
+
list(params?: ListInvoicesParams, options?: ReadOptions$11): Promise<CossResult<List<InvoiceSummary>>>;
|
|
700
|
+
/** Retrieves one invoice with its lines. */
|
|
701
|
+
get(id: string, options?: ReadOptions$11): Promise<CossResult<Invoice>>;
|
|
702
|
+
}
|
|
703
|
+
/** `coss.billing.credits`: the organization's credits and what's left of them. */
|
|
704
|
+
declare class BillingCreditsResource {
|
|
705
|
+
#private;
|
|
706
|
+
/** @internal Use `new Coss().billing.credits`. */
|
|
707
|
+
constructor(http: HttpClient);
|
|
708
|
+
/** Lists credits, newest first (usable ones by default). */
|
|
709
|
+
list(params?: ListCreditsParams, options?: ReadOptions$11): Promise<CossResult<List<Credit>>>;
|
|
710
|
+
}
|
|
711
|
+
/**
|
|
712
|
+
* `coss.billing`: the organization's plan, usage, invoices and credits (read only; plan changes
|
|
713
|
+
* are made in the dashboard). Organization-wide, whichever environment the key belongs to.
|
|
714
|
+
*/
|
|
715
|
+
declare class BillingResource {
|
|
716
|
+
#private;
|
|
717
|
+
readonly invoices: BillingInvoicesResource;
|
|
718
|
+
readonly credits: BillingCreditsResource;
|
|
719
|
+
/** @internal Use `new Coss().billing`. */
|
|
720
|
+
constructor(http: HttpClient);
|
|
721
|
+
/** The plan, the current month's usage and estimate, standing and what the plan includes. */
|
|
722
|
+
get(options?: ReadOptions$11): Promise<CossResult<Billing>>;
|
|
723
|
+
/** Billable usage per meter and bucket (the current month, by day, by default), oldest first. */
|
|
724
|
+
usage(params?: ListUsageParams, options?: ReadOptions$11): Promise<CossResult<List<Usage>>>;
|
|
725
|
+
}
|
|
726
|
+
//#endregion
|
|
727
|
+
//#region src/types/domain.d.ts
|
|
728
|
+
/**
|
|
729
|
+
* Sending domain wire types. Hand-written to mirror the API's snake_case JSON 1:1 (the API's
|
|
730
|
+
* contract test asserts they stay assignable to and from its zod schemas).
|
|
731
|
+
*/
|
|
732
|
+
/**
|
|
733
|
+
* `pending` while the DNS records are being checked, `verified` once they are,
|
|
734
|
+
* `temporary_failure` after a transient DNS problem, and `failed` when verification gave up
|
|
735
|
+
* (72 hours) — call `verify` to start over. `deleting` is a removal in progress.
|
|
736
|
+
*/
|
|
737
|
+
type DomainStatus = "pending" | "verified" | "temporary_failure" | "failed" | "deleting";
|
|
738
|
+
/** Verification state of the `send.` bounce subdomain. */
|
|
739
|
+
type MailFromStatus = "pending" | "success" | "temporary_failure" | "failed";
|
|
740
|
+
/**
|
|
741
|
+
* What a record is for: `dkim` signs messages, `mail_from_mx` and `mail_from_spf` set up the
|
|
742
|
+
* bounce subdomain, and `dmarc` is recommended but not required.
|
|
743
|
+
*/
|
|
744
|
+
type DomainRecordPurpose = "dkim" | "mail_from_mx" | "mail_from_spf" | "dmarc";
|
|
745
|
+
/** What the last DNS check saw. `not_checked` means DNS has not been consulted yet. */
|
|
746
|
+
type DomainRecordStatus = "verified" | "missing" | "mismatch" | "not_checked";
|
|
747
|
+
/** One DNS record a domain needs (or, when `required` is `false`, should have). */
|
|
748
|
+
interface DomainRecord {
|
|
749
|
+
purpose: DomainRecordPurpose;
|
|
750
|
+
type: "CNAME" | "MX" | "TXT";
|
|
751
|
+
/** The fully qualified record name to create. */
|
|
752
|
+
name: string;
|
|
753
|
+
value: string;
|
|
754
|
+
/** `MX` records only. */
|
|
755
|
+
priority: number | null;
|
|
756
|
+
/** `false` for records that are only recommended. */
|
|
757
|
+
required: boolean;
|
|
758
|
+
status: DomainRecordStatus;
|
|
759
|
+
/** What DNS returned when it did not match. */
|
|
760
|
+
found: string[];
|
|
761
|
+
}
|
|
762
|
+
/**
|
|
763
|
+
* `pending` until the CNAME points at COSS and its certificate is issued, `active` once tracking
|
|
764
|
+
* links of emails sent from the domain use it, `temporary_failure` when an active hostname stopped
|
|
765
|
+
* working (emails fall back to the default tracking host meanwhile), and `failed` when setup gave
|
|
766
|
+
* up (72 hours) — call `domains.verify` to start over. `deleting` is a removal in progress.
|
|
767
|
+
*/
|
|
768
|
+
type TrackingDomainStatus = "pending" | "active" | "temporary_failure" | "failed" | "deleting";
|
|
769
|
+
/** The CNAME a tracking domain needs, with the result of the last check. */
|
|
770
|
+
interface TrackingDomainRecord {
|
|
771
|
+
type: "CNAME";
|
|
772
|
+
/** The fully qualified record name to create. */
|
|
773
|
+
name: string;
|
|
774
|
+
/** The host the record must point at. */
|
|
775
|
+
value: string;
|
|
776
|
+
status: DomainRecordStatus;
|
|
777
|
+
/** What DNS returned when it did not match. */
|
|
778
|
+
found: string[];
|
|
779
|
+
}
|
|
780
|
+
/** A domain's custom tracking domain: open pixels and click redirects use it while `active`. */
|
|
781
|
+
interface TrackingDomain {
|
|
782
|
+
/** The tracking hostname, a subdomain of the domain (e.g. `links.acme.com`). */
|
|
783
|
+
hostname: string;
|
|
784
|
+
status: TrackingDomainStatus;
|
|
785
|
+
record: TrackingDomainRecord;
|
|
786
|
+
/** What is holding the hostname up, when the certificate provider said. */
|
|
787
|
+
message: string | null;
|
|
788
|
+
/** ISO 8601 timestamp. */
|
|
789
|
+
created_at: string;
|
|
790
|
+
last_checked_at: string | null;
|
|
791
|
+
activated_at: string | null;
|
|
792
|
+
failed_at: string | null;
|
|
793
|
+
}
|
|
794
|
+
/** The MX record a receiving domain needs, with the result of the last check. */
|
|
795
|
+
interface ReceivingDomainRecord {
|
|
796
|
+
type: "MX";
|
|
797
|
+
/** The fully qualified record name to create. */
|
|
798
|
+
name: string;
|
|
799
|
+
/** The mail exchange the record must point at. */
|
|
800
|
+
value: string;
|
|
801
|
+
priority: number;
|
|
802
|
+
/** `verified` once the most preferred MX records point at COSS. */
|
|
803
|
+
status: DomainRecordStatus;
|
|
804
|
+
/** What DNS returned when it did not match. */
|
|
805
|
+
found: string[];
|
|
806
|
+
}
|
|
807
|
+
/** A domain's receiving hostname: email to any address at it is received by `environment_id`. */
|
|
808
|
+
interface ReceivingDomain {
|
|
809
|
+
/** The domain itself or a subdomain of it (e.g. `inbound.acme.com`). */
|
|
810
|
+
hostname: string;
|
|
811
|
+
environment_id: string;
|
|
812
|
+
record: ReceivingDomainRecord;
|
|
813
|
+
/** ISO 8601 timestamp. */
|
|
814
|
+
created_at: string;
|
|
815
|
+
last_checked_at: string | null;
|
|
816
|
+
}
|
|
817
|
+
/** A sending domain of the organization. */
|
|
818
|
+
interface Domain {
|
|
819
|
+
object: "domain";
|
|
820
|
+
id: string;
|
|
821
|
+
/** The domain, lower-cased. */
|
|
822
|
+
name: string;
|
|
823
|
+
status: DomainStatus;
|
|
824
|
+
/** Whether live keys may send from this domain right now. */
|
|
825
|
+
can_send: boolean;
|
|
826
|
+
region: string | null;
|
|
827
|
+
/** The envelope sender subdomain bounces come back to. */
|
|
828
|
+
mail_from_domain: string;
|
|
829
|
+
mail_from_status: MailFromStatus;
|
|
830
|
+
/** The DNS records to publish, with the result of the last check. */
|
|
831
|
+
records: DomainRecord[];
|
|
832
|
+
/** ISO 8601 timestamp. */
|
|
833
|
+
created_at: string;
|
|
834
|
+
last_checked_at: string | null;
|
|
835
|
+
verified_at: string | null;
|
|
836
|
+
failed_at: string | null;
|
|
837
|
+
/** The custom tracking domain, or `null` when none is set up. */
|
|
838
|
+
tracking: TrackingDomain | null;
|
|
839
|
+
/** The receiving hostname, or `null` when the domain doesn't receive email. */
|
|
840
|
+
receiving: ReceivingDomain | null;
|
|
841
|
+
}
|
|
842
|
+
/** Body of `POST /v1/domains`. */
|
|
843
|
+
interface CreateDomainParams {
|
|
844
|
+
/**
|
|
845
|
+
* The domain to send from, without a scheme or path (`"acme.com"`, `"mail.acme.com"`).
|
|
846
|
+
* Internationalized domains must be punycode-encoded.
|
|
847
|
+
*/
|
|
848
|
+
name: string;
|
|
849
|
+
}
|
|
850
|
+
/** Returned by `domains.delete`. */
|
|
851
|
+
interface DeletedDomain {
|
|
852
|
+
object: "domain";
|
|
853
|
+
id: string;
|
|
854
|
+
deleted: true;
|
|
855
|
+
}
|
|
856
|
+
/** Body of `POST /v1/domains/{id}/tracking`. */
|
|
857
|
+
interface CreateTrackingDomainParams {
|
|
858
|
+
/** A subdomain of the domain to serve tracking links from (`"links.acme.com"`). */
|
|
859
|
+
hostname: string;
|
|
860
|
+
}
|
|
861
|
+
/** Body of `POST /v1/domains/{id}/receiving`. */
|
|
862
|
+
interface CreateReceivingDomainParams {
|
|
863
|
+
/** The domain itself or a subdomain of it (`"inbound.acme.com"`). */
|
|
864
|
+
hostname: string;
|
|
865
|
+
}
|
|
866
|
+
//#endregion
|
|
867
|
+
//#region src/resources/receiving-domains.d.ts
|
|
868
|
+
type DeleteOptions$1 = Pick<RequestOptions, "signal">;
|
|
869
|
+
/**
|
|
870
|
+
* `coss.domains.receiving`: a domain's receiving hostname (the domain itself or a subdomain, e.g.
|
|
871
|
+
* `inbound.acme.com`). Email sent to any address at it is received by the API key's environment.
|
|
872
|
+
*/
|
|
873
|
+
declare class ReceivingDomainsResource {
|
|
874
|
+
#private;
|
|
875
|
+
/** @internal Use `new Coss().domains.receiving`. */
|
|
876
|
+
constructor(http: HttpClient);
|
|
877
|
+
/**
|
|
878
|
+
* Starts receiving at a hostname of the domain, for the API key's environment, and returns the
|
|
879
|
+
* domain with the MX record to publish in `data.receiving.record`.
|
|
880
|
+
*/
|
|
881
|
+
create(domainId: string, params: CreateReceivingDomainParams, options?: RequestOptions): Promise<CossResult<Domain>>;
|
|
882
|
+
/** Stops receiving at the domain's hostname. Emails already received are kept. */
|
|
883
|
+
delete(domainId: string, options?: DeleteOptions$1): Promise<CossResult<Domain>>;
|
|
884
|
+
}
|
|
885
|
+
//#endregion
|
|
886
|
+
//#region src/resources/tracking-domains.d.ts
|
|
887
|
+
type DeleteOptions = Pick<RequestOptions, "signal">;
|
|
888
|
+
/**
|
|
889
|
+
* `coss.domains.tracking`: a domain's custom tracking domain (e.g. `links.acme.com`). Open pixels
|
|
890
|
+
* and click redirects of emails sent from the domain use it while it is `active`.
|
|
891
|
+
*/
|
|
892
|
+
declare class TrackingDomainsResource {
|
|
893
|
+
#private;
|
|
894
|
+
/** @internal Use `new Coss().domains.tracking`. */
|
|
895
|
+
constructor(http: HttpClient);
|
|
896
|
+
/**
|
|
897
|
+
* Sets up a subdomain of the domain as its tracking domain and returns the domain, with the
|
|
898
|
+
* CNAME to publish in `data.tracking.record`. Setup gives up after 72 hours.
|
|
899
|
+
*/
|
|
900
|
+
create(domainId: string, params: CreateTrackingDomainParams, options?: RequestOptions): Promise<CossResult<Domain>>;
|
|
901
|
+
/**
|
|
902
|
+
* Removes the domain's tracking domain. Later emails use the default tracking host; links in
|
|
903
|
+
* emails already sent through it stop working.
|
|
904
|
+
*/
|
|
905
|
+
delete(domainId: string, options?: DeleteOptions): Promise<CossResult<Domain>>;
|
|
906
|
+
}
|
|
907
|
+
//#endregion
|
|
908
|
+
//#region src/resources/domains.d.ts
|
|
909
|
+
type ReadOptions$10 = Pick<RequestOptions, "signal">;
|
|
910
|
+
/**
|
|
911
|
+
* `coss.domains`: the domains live (`coss_live_…`) keys may send from. Domains belong to the
|
|
912
|
+
* organization, so every API key of the organization sees the same ones.
|
|
913
|
+
*/
|
|
914
|
+
declare class DomainsResource {
|
|
915
|
+
#private;
|
|
916
|
+
/** Each domain's custom tracking domain: add and remove it. */
|
|
917
|
+
readonly tracking: TrackingDomainsResource;
|
|
918
|
+
/** Each domain's receiving hostname: start and stop receiving email at it. */
|
|
919
|
+
readonly receiving: ReceivingDomainsResource;
|
|
920
|
+
/** @internal Use `new Coss().domains`. */
|
|
921
|
+
constructor(http: HttpClient);
|
|
922
|
+
/**
|
|
923
|
+
* Adds a domain and returns the DNS records to publish (`data.records`). The records are
|
|
924
|
+
* checked in the background; verification gives up after 72 hours.
|
|
925
|
+
*/
|
|
926
|
+
create(params: CreateDomainParams, options?: RequestOptions): Promise<CossResult<Domain>>;
|
|
927
|
+
/** Lists the organization's domains, ordered by name. */
|
|
928
|
+
list(options?: ReadOptions$10): Promise<CossResult<List<Domain>>>;
|
|
929
|
+
/** Retrieves a domain with the result of the last DNS check. */
|
|
930
|
+
get(id: string, options?: ReadOptions$10): Promise<CossResult<Domain>>;
|
|
931
|
+
/**
|
|
932
|
+
* Checks the domain's records now instead of waiting for the next background check. A `failed`
|
|
933
|
+
* domain starts verification over with fresh DKIM records, which have to be published again.
|
|
934
|
+
* Its tracking domain, if any, is checked too.
|
|
935
|
+
*/
|
|
936
|
+
verify(id: string, options?: RequestOptions): Promise<CossResult<Domain>>;
|
|
937
|
+
/** Removes the domain. Emails already sent are unaffected; live keys can no longer use it. */
|
|
938
|
+
delete(id: string, options?: ReadOptions$10): Promise<CossResult<DeletedDomain>>;
|
|
939
|
+
}
|
|
940
|
+
//#endregion
|
|
941
|
+
//#region src/types/received-email.d.ts
|
|
942
|
+
/**
|
|
943
|
+
* Received (inbound) email wire types. Hand-written to mirror the API's snake_case JSON 1:1 (the
|
|
944
|
+
* API's contract test asserts they stay assignable to and from its zod schemas).
|
|
945
|
+
*/
|
|
946
|
+
/** `received`, or `blocked` when the message carried a virus (only its envelope is kept). */
|
|
947
|
+
type ReceivedEmailStatus = "received" | "blocked";
|
|
948
|
+
/** What the receiving server concluded; `null` when the check did not run. */
|
|
949
|
+
type VerdictStatus = "pass" | "fail" | "gray" | "processing_failed";
|
|
950
|
+
interface ReceivedEmailVerdicts {
|
|
951
|
+
spam: VerdictStatus | null;
|
|
952
|
+
virus: VerdictStatus | null;
|
|
953
|
+
spf: VerdictStatus | null;
|
|
954
|
+
dkim: VerdictStatus | null;
|
|
955
|
+
dmarc: VerdictStatus | null;
|
|
956
|
+
/** The sender domain's DMARC policy (`none`, `quarantine`, `reject`) when DMARC failed. */
|
|
957
|
+
dmarc_policy: string | null;
|
|
958
|
+
}
|
|
959
|
+
/** Metadata of an attachment; download it with `email.received.getAttachment`. */
|
|
960
|
+
interface ReceivedEmailAttachment {
|
|
961
|
+
id: string;
|
|
962
|
+
/** `null` when the part named none. */
|
|
963
|
+
filename: string | null;
|
|
964
|
+
content_type: string;
|
|
965
|
+
/** Set for parts the HTML references (`cid:` URLs). */
|
|
966
|
+
content_id: string | null;
|
|
967
|
+
disposition: "attachment" | "inline";
|
|
968
|
+
/** Size in bytes. */
|
|
969
|
+
size: number;
|
|
970
|
+
}
|
|
971
|
+
/** A received email as lists return it: without bodies and headers. */
|
|
972
|
+
interface ReceivedEmailSummary {
|
|
973
|
+
object: "received_email";
|
|
974
|
+
id: string;
|
|
975
|
+
status: ReceivedEmailStatus;
|
|
976
|
+
blocked_reason: "virus" | null;
|
|
977
|
+
/** The envelope sender (`MAIL FROM`); empty for bounces. */
|
|
978
|
+
mail_from: string;
|
|
979
|
+
/** The envelope recipients this environment received it for (Bcc'd addresses included). */
|
|
980
|
+
recipients: string[];
|
|
981
|
+
/** The `From` header. */
|
|
982
|
+
from: string | null;
|
|
983
|
+
to: string[];
|
|
984
|
+
cc: string[];
|
|
985
|
+
subject: string | null;
|
|
986
|
+
/** The `Message-ID` header. */
|
|
987
|
+
message_id: string | null;
|
|
988
|
+
attachments: ReceivedEmailAttachment[];
|
|
989
|
+
/** Size of the raw message in bytes. */
|
|
990
|
+
size: number;
|
|
991
|
+
/** Whether the spam verdict is `fail`. */
|
|
992
|
+
spam: boolean;
|
|
993
|
+
verdicts: ReceivedEmailVerdicts;
|
|
994
|
+
/** Whether a sandbox environment received it. */
|
|
995
|
+
sandbox: boolean;
|
|
996
|
+
/** ISO 8601 timestamp. */
|
|
997
|
+
received_at: string;
|
|
998
|
+
}
|
|
999
|
+
/** A received email with its headers and bodies. HTML is the sender's: sanitize it to show it. */
|
|
1000
|
+
interface ReceivedEmail extends ReceivedEmailSummary {
|
|
1001
|
+
reply_to: string[];
|
|
1002
|
+
in_reply_to: string | null;
|
|
1003
|
+
/** Message ids of the `References` header. */
|
|
1004
|
+
references: string[];
|
|
1005
|
+
/** The `Date` header, when valid (ISO 8601). */
|
|
1006
|
+
sent_at: string | null;
|
|
1007
|
+
/** Every header in message order, duplicates included. */
|
|
1008
|
+
headers: {
|
|
1009
|
+
name: string;
|
|
1010
|
+
value: string;
|
|
1011
|
+
}[];
|
|
1012
|
+
text: string | null;
|
|
1013
|
+
html: string | null;
|
|
1014
|
+
/** Whether `text`, `html` or `headers` were shortened; `getRaw` always has everything. */
|
|
1015
|
+
truncated: boolean;
|
|
1016
|
+
}
|
|
1017
|
+
/** Query of `email.received.list`. */
|
|
1018
|
+
interface ListReceivedEmailsParams {
|
|
1019
|
+
/** 1-100, default 20. */
|
|
1020
|
+
limit?: number;
|
|
1021
|
+
/** The `id` of the last email of the previous page. */
|
|
1022
|
+
after?: string;
|
|
1023
|
+
}
|
|
1024
|
+
/** Returned by `email.received.delete`. */
|
|
1025
|
+
interface DeletedReceivedEmail {
|
|
1026
|
+
object: "received_email";
|
|
1027
|
+
id: string;
|
|
1028
|
+
deleted: true;
|
|
1029
|
+
}
|
|
1030
|
+
/** The environment's own domain under COSS's inbound domain: any address at it is received. */
|
|
1031
|
+
interface InboundAddress {
|
|
1032
|
+
object: "inbound_address";
|
|
1033
|
+
environment_id: string;
|
|
1034
|
+
domain: string;
|
|
1035
|
+
}
|
|
1036
|
+
//#endregion
|
|
1037
|
+
//#region src/resources/received-emails.d.ts
|
|
1038
|
+
type ReadOptions$9 = Pick<RequestOptions, "signal">;
|
|
1039
|
+
/**
|
|
1040
|
+
* `coss.email.received`: emails received by the API key's environment, at its inbound address
|
|
1041
|
+
* (`address()`) or at a receiving domain (`coss.domains.receiving`). An `email.received` webhook
|
|
1042
|
+
* announces each one.
|
|
1043
|
+
*/
|
|
1044
|
+
declare class ReceivedEmailsResource {
|
|
1045
|
+
#private;
|
|
1046
|
+
/** @internal Use `new Coss().email.received`. */
|
|
1047
|
+
constructor(http: HttpClient);
|
|
1048
|
+
/** Lists received emails, newest first, without bodies. Pass the last `id` as `after` while `has_more` is true. */
|
|
1049
|
+
list(params?: ListReceivedEmailsParams, options?: ReadOptions$9): Promise<CossResult<List<ReceivedEmailSummary>>>;
|
|
1050
|
+
/** Retrieves a received email with its headers and bodies. */
|
|
1051
|
+
get(id: string, options?: ReadOptions$9): Promise<CossResult<ReceivedEmail>>;
|
|
1052
|
+
/** The whole message as received (`message/rfc822` bytes). */
|
|
1053
|
+
getRaw(id: string, options?: ReadOptions$9): Promise<CossResult<Uint8Array>>;
|
|
1054
|
+
/** An attachment's bytes (untrusted: its declared type is the attachment's `content_type`). */
|
|
1055
|
+
getAttachment(id: string, attachmentId: string, options?: ReadOptions$9): Promise<CossResult<Uint8Array>>;
|
|
1056
|
+
/**
|
|
1057
|
+
* The environment's inbound domain: email to any address at it (`support@<domain>`) is
|
|
1058
|
+
* received, with no DNS setup.
|
|
1059
|
+
*/
|
|
1060
|
+
address(options?: ReadOptions$9): Promise<CossResult<InboundAddress>>;
|
|
1061
|
+
/** Deletes a received email with its raw message and attachments right away. */
|
|
1062
|
+
delete(id: string, options?: ReadOptions$9): Promise<CossResult<DeletedReceivedEmail>>;
|
|
1063
|
+
}
|
|
1064
|
+
//#endregion
|
|
1065
|
+
//#region src/resources/suppressions.d.ts
|
|
1066
|
+
type ReadOptions$8 = Pick<RequestOptions, "signal">;
|
|
1067
|
+
/**
|
|
1068
|
+
* `coss.email.suppressions`: the suppression list of the API key's environment. Sends skip
|
|
1069
|
+
* suppressed recipients; permanent bounces and complaints are added automatically.
|
|
1070
|
+
*/
|
|
1071
|
+
declare class SuppressionResource {
|
|
1072
|
+
#private;
|
|
1073
|
+
/** @internal Use `new Coss().email.suppressions`. */
|
|
1074
|
+
constructor(http: HttpClient);
|
|
1075
|
+
/**
|
|
1076
|
+
* Suppresses an address for every email (`scope: "*"`, the default) or for one category, e.g.
|
|
1077
|
+
* when a recipient unsubscribes. Returns the existing entry if there already is one.
|
|
1078
|
+
*/
|
|
1079
|
+
add(params: CreateSuppressionParams, options?: RequestOptions): Promise<CossResult<Suppression>>;
|
|
1080
|
+
/**
|
|
1081
|
+
* Adds many entries at once (reason `import`), 1,000 per request. Invalid entries are skipped
|
|
1082
|
+
* and reported in `invalid`; entries already on the list count as `existing`. If a request
|
|
1083
|
+
* fails, the earlier batches stay imported: importing everything again is safe.
|
|
1084
|
+
*/
|
|
1085
|
+
import(params: ImportSuppressionsParams, options?: ReadOptions$8): Promise<CossResult<SuppressionImport>>;
|
|
1086
|
+
/**
|
|
1087
|
+
* The whole list as CSV (`address,scope,reason,created_at,email_id,id`, oldest first), which
|
|
1088
|
+
* `import` (or the dashboard) accepts again.
|
|
1089
|
+
*/
|
|
1090
|
+
export(params?: ExportSuppressionsParams, options?: ReadOptions$8): Promise<CossResult<string>>;
|
|
1091
|
+
/** Lists entries, newest first. Pass the last `id` as `after` while `has_more` is true. */
|
|
1092
|
+
list(params?: ListSuppressionsParams, options?: ReadOptions$8): Promise<CossResult<List<Suppression>>>;
|
|
1093
|
+
/** Whether a send to `address` (with `category`, if given) would skip it. */
|
|
1094
|
+
check(params: CheckSuppressionParams, options?: ReadOptions$8): Promise<CossResult<SuppressionCheck>>;
|
|
1095
|
+
/** Retrieves one entry. */
|
|
1096
|
+
get(id: string, options?: ReadOptions$8): Promise<CossResult<Suppression>>;
|
|
1097
|
+
/** Removes an entry, so later sends reach the address again (e.g. when a recipient resubscribes). */
|
|
1098
|
+
remove(id: string, options?: ReadOptions$8): Promise<CossResult<DeletedSuppression>>;
|
|
1099
|
+
}
|
|
1100
|
+
//#endregion
|
|
1101
|
+
//#region src/types/tracking.d.ts
|
|
1102
|
+
/** Tracking settings wire types (hand-written mirrors of the API's schemas). */
|
|
1103
|
+
/** An environment's tracking default (`category: null`) or the rule for one category. */
|
|
1104
|
+
interface TrackingRule {
|
|
1105
|
+
object: "tracking_rule";
|
|
1106
|
+
id: string;
|
|
1107
|
+
/** The category the rule applies to; `null` for the environment default. */
|
|
1108
|
+
category: string | null;
|
|
1109
|
+
/** Whether opens are tracked. */
|
|
1110
|
+
opens: boolean;
|
|
1111
|
+
/** Whether clicks are tracked. */
|
|
1112
|
+
clicks: boolean;
|
|
1113
|
+
/** ISO 8601 timestamp. */
|
|
1114
|
+
created_at: string;
|
|
1115
|
+
/** ISO 8601 timestamp. */
|
|
1116
|
+
updated_at: string;
|
|
1117
|
+
}
|
|
1118
|
+
/**
|
|
1119
|
+
* Open and click tracking settings of the API key's environment. For each of `opens` and
|
|
1120
|
+
* `clicks`, a send's own `tracking` wins, then its category's rule, then `default`, then off.
|
|
1121
|
+
*/
|
|
1122
|
+
interface TrackingSettings {
|
|
1123
|
+
object: "tracking_settings";
|
|
1124
|
+
/** The environment default; `null` when none is set. */
|
|
1125
|
+
default: TrackingRule | null;
|
|
1126
|
+
/** Category rules, by category name. */
|
|
1127
|
+
categories: TrackingRule[];
|
|
1128
|
+
}
|
|
1129
|
+
/**
|
|
1130
|
+
* Body of `PATCH /v1/tracking_settings/default` and `…/categories/{category}`: at least one
|
|
1131
|
+
* field. Fields left out keep their value; a new rule starts with both off.
|
|
1132
|
+
*/
|
|
1133
|
+
interface UpdateTrackingRuleParams {
|
|
1134
|
+
opens?: boolean;
|
|
1135
|
+
clicks?: boolean;
|
|
1136
|
+
}
|
|
1137
|
+
/** Returned when a rule is removed. */
|
|
1138
|
+
interface DeletedTrackingRule {
|
|
1139
|
+
object: "tracking_rule";
|
|
1140
|
+
id: string;
|
|
1141
|
+
category: string | null;
|
|
1142
|
+
deleted: true;
|
|
1143
|
+
}
|
|
1144
|
+
//#endregion
|
|
1145
|
+
//#region src/resources/tracking.d.ts
|
|
1146
|
+
type ReadOptions$7 = Pick<RequestOptions, "signal">;
|
|
1147
|
+
/**
|
|
1148
|
+
* `coss.email.tracking`: which emails of the API key's environment have their opens and clicks
|
|
1149
|
+
* tracked. Emails keep the settings that applied when they were sent; a send's own `tracking`
|
|
1150
|
+
* option wins over them.
|
|
1151
|
+
*/
|
|
1152
|
+
declare class TrackingResource {
|
|
1153
|
+
#private;
|
|
1154
|
+
/** @internal Use `new Coss().email.tracking`. */
|
|
1155
|
+
constructor(http: HttpClient);
|
|
1156
|
+
/** The environment default and the category rules. */
|
|
1157
|
+
get(options?: ReadOptions$7): Promise<CossResult<TrackingSettings>>;
|
|
1158
|
+
/**
|
|
1159
|
+
* Sets the environment default, which applies to emails without a rule for their category.
|
|
1160
|
+
* Fields left out keep their value; a new default starts with both off.
|
|
1161
|
+
*/
|
|
1162
|
+
updateDefault(params: UpdateTrackingRuleParams, options?: ReadOptions$7): Promise<CossResult<TrackingRule>>;
|
|
1163
|
+
/** Removes the environment default: emails without a category rule are then not tracked. */
|
|
1164
|
+
removeDefault(options?: ReadOptions$7): Promise<CossResult<DeletedTrackingRule>>;
|
|
1165
|
+
/**
|
|
1166
|
+
* Sets the rule for emails sent with `category`, which wins over the default. Fields left out
|
|
1167
|
+
* keep their value; a new rule starts with both off.
|
|
1168
|
+
*/
|
|
1169
|
+
updateCategory(category: string, params: UpdateTrackingRuleParams, options?: ReadOptions$7): Promise<CossResult<TrackingRule>>;
|
|
1170
|
+
/** Removes a category's rule: its emails follow the environment default again. */
|
|
1171
|
+
removeCategory(category: string, options?: ReadOptions$7): Promise<CossResult<DeletedTrackingRule>>;
|
|
1172
|
+
}
|
|
1173
|
+
//#endregion
|
|
1174
|
+
//#region src/resources/email.d.ts
|
|
1175
|
+
/** `coss.email`: transactional email. */
|
|
1176
|
+
declare class EmailResource {
|
|
1177
|
+
#private;
|
|
1178
|
+
/** The environment's suppression list. */
|
|
1179
|
+
readonly suppressions: SuppressionResource;
|
|
1180
|
+
/** The environment's open and click tracking settings. */
|
|
1181
|
+
readonly tracking: TrackingResource;
|
|
1182
|
+
/** Emails the environment received. */
|
|
1183
|
+
readonly received: ReceivedEmailsResource;
|
|
1184
|
+
/** @internal Use `new Coss().email`. */
|
|
1185
|
+
constructor(http: HttpClient);
|
|
1186
|
+
/**
|
|
1187
|
+
* Sends an email. It is returned `queued` and handed to the delivery provider moments later:
|
|
1188
|
+
* `get` it or listen for the `email.sent` / `email.failed` webhooks for the outcome. Safe to
|
|
1189
|
+
* retry: the request always carries an `Idempotency-Key` (yours, or a generated one reused
|
|
1190
|
+
* across automatic retries), so the API never sends it twice.
|
|
1191
|
+
*/
|
|
1192
|
+
send(params: SendEmailParams, options?: RequestOptions): Promise<CossResult<Email>>;
|
|
1193
|
+
/**
|
|
1194
|
+
* Sends up to 100 emails in one request, each as `send` would. The batch is all or nothing: if
|
|
1195
|
+
* any email is invalid (the error's `issues` name it, e.g. `emails.3.to`), none is sent. Its
|
|
1196
|
+
* recipients count against the send quota together. Safe to retry: one `Idempotency-Key` covers
|
|
1197
|
+
* the whole batch. Larger lists need several calls, each with its own key.
|
|
1198
|
+
*/
|
|
1199
|
+
sendBatch(emails: SendEmailParams[], options?: RequestOptions): Promise<CossResult<EmailBatch>>;
|
|
1200
|
+
/** Retrieves an email sent from the same environment as the API key. */
|
|
1201
|
+
get(id: string, options?: Pick<RequestOptions, "signal">): Promise<CossResult<Email>>;
|
|
1202
|
+
/**
|
|
1203
|
+
* Cancels a scheduled email. Canceling an already canceled email returns it; any other email
|
|
1204
|
+
* fails with `email_not_cancelable`.
|
|
1205
|
+
*/
|
|
1206
|
+
cancel(id: string, options?: Pick<RequestOptions, "signal">): Promise<CossResult<Email>>;
|
|
1207
|
+
/**
|
|
1208
|
+
* Moves a scheduled email to a new time and records an `email.rescheduled` event. The time it
|
|
1209
|
+
* already has returns it unchanged; an email that is no longer scheduled fails with
|
|
1210
|
+
* `email_not_reschedulable`.
|
|
1211
|
+
*/
|
|
1212
|
+
reschedule(id: string, params: RescheduleEmailParams, options?: Pick<RequestOptions, "signal">): Promise<CossResult<Email>>;
|
|
1213
|
+
/** Lists an email's delivery events, oldest first. */
|
|
1214
|
+
listEvents(id: string, options?: Pick<RequestOptions, "signal">): Promise<CossResult<List<EmailEvent>>>;
|
|
1215
|
+
/** Lists the links tracked for clicks in an email, in document order, with click counts. */
|
|
1216
|
+
listLinks(id: string, options?: Pick<RequestOptions, "signal">): Promise<CossResult<List<EmailLink>>>;
|
|
1217
|
+
}
|
|
1218
|
+
//#endregion
|
|
1219
|
+
//#region src/types/hooks.d.ts
|
|
1220
|
+
/**
|
|
1221
|
+
* Hooks wire types (webhooks as a service): you send a message to one of your applications once,
|
|
1222
|
+
* COSS delivers it to every endpoint its users registered, signed, with retries.
|
|
1223
|
+
*/
|
|
1224
|
+
/** One of your customers (or users), with their own endpoints and portal. */
|
|
1225
|
+
interface HookApplication {
|
|
1226
|
+
object: "hook_application";
|
|
1227
|
+
id: string;
|
|
1228
|
+
/** Your own id for it, unique in the environment; every method that takes an application accepts it. */
|
|
1229
|
+
uid: string | null;
|
|
1230
|
+
name: string;
|
|
1231
|
+
metadata: Record<string, string>;
|
|
1232
|
+
/** ISO 8601 timestamp. */
|
|
1233
|
+
created_at: string;
|
|
1234
|
+
updated_at: string;
|
|
1235
|
+
}
|
|
1236
|
+
/** Body of `POST /v1/hooks/applications`. */
|
|
1237
|
+
interface CreateHookApplicationParams {
|
|
1238
|
+
/** Shown to the application's users in the portal. */
|
|
1239
|
+
name: string;
|
|
1240
|
+
/** Your own id for it (1-256 letters, digits and `. _ : @ | -`). */
|
|
1241
|
+
uid?: string;
|
|
1242
|
+
/** Up to 16 keys (up to 40 characters) with string values (up to 500). */
|
|
1243
|
+
metadata?: Record<string, string>;
|
|
1244
|
+
}
|
|
1245
|
+
/** Body of `PATCH /v1/hooks/applications/{application}`. Omitted fields keep their value. */
|
|
1246
|
+
interface UpdateHookApplicationParams {
|
|
1247
|
+
name?: string;
|
|
1248
|
+
/** `null` removes it. */
|
|
1249
|
+
uid?: string | null;
|
|
1250
|
+
/** Replaces the metadata. */
|
|
1251
|
+
metadata?: Record<string, string>;
|
|
1252
|
+
}
|
|
1253
|
+
/** Query of `GET /v1/hooks/applications`. */
|
|
1254
|
+
interface ListHookApplicationsParams {
|
|
1255
|
+
/** 1-100, default 50. */
|
|
1256
|
+
limit?: number;
|
|
1257
|
+
/** Cursor: the `id` of the last application of the previous page. */
|
|
1258
|
+
after?: string;
|
|
1259
|
+
}
|
|
1260
|
+
/** Returned by `hooks.applications.delete`. */
|
|
1261
|
+
interface DeletedHookApplication {
|
|
1262
|
+
object: "hook_application";
|
|
1263
|
+
id: string;
|
|
1264
|
+
deleted: true;
|
|
1265
|
+
}
|
|
1266
|
+
/** A type of message you send (e.g. `invoice.paid`): the catalog your users subscribe from. */
|
|
1267
|
+
interface HookEventType {
|
|
1268
|
+
object: "hook_event_type";
|
|
1269
|
+
name: string;
|
|
1270
|
+
description: string | null;
|
|
1271
|
+
/** A JSON Schema of the payload, shown to your users (not enforced). */
|
|
1272
|
+
schema: Record<string, unknown> | null;
|
|
1273
|
+
/** Example payloads; the first is what a test send delivers. */
|
|
1274
|
+
examples: Record<string, unknown>[];
|
|
1275
|
+
/** Hidden from the portal and new subscriptions; already subscribed endpoints still receive it. */
|
|
1276
|
+
archived: boolean;
|
|
1277
|
+
created_at: string;
|
|
1278
|
+
updated_at: string;
|
|
1279
|
+
}
|
|
1280
|
+
/** Body of `POST /v1/hooks/event_types`. */
|
|
1281
|
+
interface CreateHookEventTypeParams {
|
|
1282
|
+
/** 1-64 letters, digits and `. _ -`. */
|
|
1283
|
+
name: string;
|
|
1284
|
+
description?: string;
|
|
1285
|
+
schema?: Record<string, unknown>;
|
|
1286
|
+
/** Up to 5. */
|
|
1287
|
+
examples?: Record<string, unknown>[];
|
|
1288
|
+
}
|
|
1289
|
+
/** Body of `PATCH /v1/hooks/event_types/{name}`. */
|
|
1290
|
+
interface UpdateHookEventTypeParams {
|
|
1291
|
+
description?: string | null;
|
|
1292
|
+
schema?: Record<string, unknown> | null;
|
|
1293
|
+
examples?: Record<string, unknown>[];
|
|
1294
|
+
/** `false` restores an archived type. */
|
|
1295
|
+
archived?: boolean;
|
|
1296
|
+
}
|
|
1297
|
+
/** Query of `GET /v1/hooks/event_types`. */
|
|
1298
|
+
interface ListHookEventTypesParams {
|
|
1299
|
+
/** Also list archived types. */
|
|
1300
|
+
include_archived?: boolean;
|
|
1301
|
+
/** 1-100, default 50. */
|
|
1302
|
+
limit?: number;
|
|
1303
|
+
/** Cursor: the `name` of the last type of the previous page. */
|
|
1304
|
+
after?: string;
|
|
1305
|
+
}
|
|
1306
|
+
/** Why an endpoint is disabled. */
|
|
1307
|
+
type HookEndpointDisabledReason = "manual" | "failing";
|
|
1308
|
+
/** A URL of an application's user that receives its messages, signed with its own secret. */
|
|
1309
|
+
interface HookEndpoint {
|
|
1310
|
+
object: "hook_endpoint";
|
|
1311
|
+
id: string;
|
|
1312
|
+
application_id: string;
|
|
1313
|
+
url: string;
|
|
1314
|
+
description: string | null;
|
|
1315
|
+
/** Event types delivered; empty means every type. */
|
|
1316
|
+
filter_types: string[];
|
|
1317
|
+
rate_limit_per_second: number | null;
|
|
1318
|
+
enabled: boolean;
|
|
1319
|
+
/** `manual`, or `failing` (its deliveries failed every attempt for five days); `null` while enabled. */
|
|
1320
|
+
disabled_reason: HookEndpointDisabledReason | null;
|
|
1321
|
+
disabled_at: string | null;
|
|
1322
|
+
/** When its current run of failed deliveries began; `null` while healthy. */
|
|
1323
|
+
failing_since: string | null;
|
|
1324
|
+
/** After a secret roll, requests are also signed with the previous secret until then. */
|
|
1325
|
+
previous_secret_expires_at: string | null;
|
|
1326
|
+
metadata: Record<string, string>;
|
|
1327
|
+
created_at: string;
|
|
1328
|
+
updated_at: string;
|
|
1329
|
+
}
|
|
1330
|
+
/** A created endpoint, or one whose secret was just rolled. */
|
|
1331
|
+
interface HookEndpointWithSecret extends HookEndpoint {
|
|
1332
|
+
/** The `whsec_…` signing secret (Standard Webhooks). */
|
|
1333
|
+
secret: string;
|
|
1334
|
+
}
|
|
1335
|
+
/** Body of `POST /v1/hooks/applications/{application}/endpoints`. */
|
|
1336
|
+
interface CreateHookEndpointParams {
|
|
1337
|
+
/** An `https://` URL. */
|
|
1338
|
+
url: string;
|
|
1339
|
+
description?: string;
|
|
1340
|
+
/** Existing, unarchived event types; omitted or empty means every type. */
|
|
1341
|
+
filter_types?: string[];
|
|
1342
|
+
/** A `whsec_` + base64 secret of 24-64 bytes (e.g. migrated from another provider). */
|
|
1343
|
+
secret?: string;
|
|
1344
|
+
/** 1-1000. */
|
|
1345
|
+
rate_limit_per_second?: number;
|
|
1346
|
+
metadata?: Record<string, string>;
|
|
1347
|
+
enabled?: boolean;
|
|
1348
|
+
}
|
|
1349
|
+
/** Body of `PATCH /v1/hooks/applications/{application}/endpoints/{id}`. */
|
|
1350
|
+
interface UpdateHookEndpointParams {
|
|
1351
|
+
url?: string;
|
|
1352
|
+
description?: string | null;
|
|
1353
|
+
filter_types?: string[];
|
|
1354
|
+
rate_limit_per_second?: number | null;
|
|
1355
|
+
metadata?: Record<string, string>;
|
|
1356
|
+
enabled?: boolean;
|
|
1357
|
+
}
|
|
1358
|
+
/** Returned by `hooks.endpoints.delete`. */
|
|
1359
|
+
interface DeletedHookEndpoint {
|
|
1360
|
+
object: "hook_endpoint";
|
|
1361
|
+
id: string;
|
|
1362
|
+
deleted: true;
|
|
1363
|
+
}
|
|
1364
|
+
/** Returned by `hooks.endpoints.getSecret`. */
|
|
1365
|
+
interface HookEndpointSecret {
|
|
1366
|
+
object: "hook_endpoint_secret";
|
|
1367
|
+
secret: string;
|
|
1368
|
+
}
|
|
1369
|
+
/** Body of `POST …/endpoints/{id}/roll_secret`. */
|
|
1370
|
+
interface RollHookEndpointSecretParams {
|
|
1371
|
+
/** Seconds the current secret keeps signing next to the new one: default 86400, at most 604800, `0` stops it now. */
|
|
1372
|
+
previous_secret_expires_in?: number;
|
|
1373
|
+
}
|
|
1374
|
+
/** Body of `POST …/endpoints/{id}/recover`. */
|
|
1375
|
+
interface RecoverHookEndpointParams {
|
|
1376
|
+
/** Requeue failed deliveries of messages sent since then (ISO 8601 string or `Date`). */
|
|
1377
|
+
since: string | Date;
|
|
1378
|
+
}
|
|
1379
|
+
/** A recovery: COSS requeues the matching failed deliveries in the background. */
|
|
1380
|
+
interface HookEndpointRecovery {
|
|
1381
|
+
object: "hook_endpoint_recovery";
|
|
1382
|
+
id: string;
|
|
1383
|
+
endpoint_id: string;
|
|
1384
|
+
since: string;
|
|
1385
|
+
until: string;
|
|
1386
|
+
status: "pending" | "completed";
|
|
1387
|
+
requeued: number;
|
|
1388
|
+
created_at: string;
|
|
1389
|
+
completed_at: string | null;
|
|
1390
|
+
}
|
|
1391
|
+
/** Body of `POST …/endpoints/{id}/test`. */
|
|
1392
|
+
interface SendHookTestParams {
|
|
1393
|
+
event_type: string;
|
|
1394
|
+
/** Defaults to the event type's first example. */
|
|
1395
|
+
payload?: Record<string, unknown>;
|
|
1396
|
+
}
|
|
1397
|
+
/** A message sent to an application. */
|
|
1398
|
+
interface HookMessage {
|
|
1399
|
+
object: "hook_message";
|
|
1400
|
+
/** Also the `webhook-id` header of every request delivering it. */
|
|
1401
|
+
id: string;
|
|
1402
|
+
application_id: string;
|
|
1403
|
+
event_type: string;
|
|
1404
|
+
/** The JSON body delivered to each endpoint. */
|
|
1405
|
+
payload: Record<string, unknown>;
|
|
1406
|
+
created_at: string;
|
|
1407
|
+
}
|
|
1408
|
+
/** Params of `hooks.messages.send`: the application, then the body of `POST …/messages`. */
|
|
1409
|
+
interface SendHookMessageParams {
|
|
1410
|
+
/** The application's id or uid. */
|
|
1411
|
+
application: string;
|
|
1412
|
+
/** e.g. `invoice.paid`; endpoints filtering by type only get the types they chose. */
|
|
1413
|
+
event_type: string;
|
|
1414
|
+
/** At most 256 KB serialized; send integers beyond 2^53 as strings. */
|
|
1415
|
+
payload: Record<string, unknown>;
|
|
1416
|
+
}
|
|
1417
|
+
/** Query of `GET …/messages`. */
|
|
1418
|
+
interface ListHookMessagesParams {
|
|
1419
|
+
/** Only messages of this type. */
|
|
1420
|
+
event_type?: string;
|
|
1421
|
+
/** 1-100, default 50. */
|
|
1422
|
+
limit?: number;
|
|
1423
|
+
/** Cursor: the `id` of the last message of the previous page. */
|
|
1424
|
+
after?: string;
|
|
1425
|
+
}
|
|
1426
|
+
/**
|
|
1427
|
+
* `pending`: waiting for its next attempt. `succeeded`: the endpoint answered 2xx. `failed`: every
|
|
1428
|
+
* attempt failed, or the endpoint was disabled or deleted.
|
|
1429
|
+
*/
|
|
1430
|
+
type HookDeliveryStatus = "pending" | "succeeded" | "failed";
|
|
1431
|
+
/** One message's delivery to one endpoint. */
|
|
1432
|
+
interface HookDelivery {
|
|
1433
|
+
object: "hook_delivery";
|
|
1434
|
+
id: string;
|
|
1435
|
+
application_id: string;
|
|
1436
|
+
message_id: string;
|
|
1437
|
+
endpoint_id: string;
|
|
1438
|
+
status: HookDeliveryStatus;
|
|
1439
|
+
attempt_count: number;
|
|
1440
|
+
next_attempt_at: string | null;
|
|
1441
|
+
last_status_code: number | null;
|
|
1442
|
+
last_error: string | null;
|
|
1443
|
+
created_at: string;
|
|
1444
|
+
finished_at: string | null;
|
|
1445
|
+
}
|
|
1446
|
+
/** Query of `GET …/endpoints/{id}/deliveries`. */
|
|
1447
|
+
interface ListHookDeliveriesParams {
|
|
1448
|
+
status?: HookDeliveryStatus;
|
|
1449
|
+
/** 1-100, default 50. */
|
|
1450
|
+
limit?: number;
|
|
1451
|
+
/** Cursor: the `id` of the last delivery of the previous page. */
|
|
1452
|
+
after?: string;
|
|
1453
|
+
}
|
|
1454
|
+
/** One HTTP request of a delivery. */
|
|
1455
|
+
interface HookAttempt {
|
|
1456
|
+
object: "hook_attempt";
|
|
1457
|
+
id: string;
|
|
1458
|
+
delivery_id: string;
|
|
1459
|
+
endpoint_id: string;
|
|
1460
|
+
attempted_at: string;
|
|
1461
|
+
/** `null` when no response arrived. */
|
|
1462
|
+
status_code: number | null;
|
|
1463
|
+
duration_ms: number;
|
|
1464
|
+
error: string | null;
|
|
1465
|
+
/** At most 1 KB of the response body. */
|
|
1466
|
+
response_excerpt: string | null;
|
|
1467
|
+
}
|
|
1468
|
+
/** Params of `hooks.portal.createSession`. */
|
|
1469
|
+
interface CreateHookPortalSessionParams {
|
|
1470
|
+
/** The application's id or uid. */
|
|
1471
|
+
application: string;
|
|
1472
|
+
/** Seconds until it expires: default 3600, 60-86400. */
|
|
1473
|
+
expires_in?: number;
|
|
1474
|
+
/** The user can look but not change anything. */
|
|
1475
|
+
read_only?: boolean;
|
|
1476
|
+
}
|
|
1477
|
+
/** A portal sign-in for one application's user. */
|
|
1478
|
+
interface HookPortalSession {
|
|
1479
|
+
object: "hook_portal_session";
|
|
1480
|
+
id: string;
|
|
1481
|
+
application_id: string;
|
|
1482
|
+
/** Open it or embed it (from an allowed origin); the token is in its fragment. */
|
|
1483
|
+
url: string;
|
|
1484
|
+
/** The secret part of `url`. */
|
|
1485
|
+
token: string;
|
|
1486
|
+
read_only: boolean;
|
|
1487
|
+
expires_at: string;
|
|
1488
|
+
}
|
|
1489
|
+
//#endregion
|
|
1490
|
+
//#region src/resources/hooks.d.ts
|
|
1491
|
+
type ReadOptions$6 = Pick<RequestOptions, "signal">;
|
|
1492
|
+
/** `coss.hooks.applications`: your customers, each with their own endpoints and portal. */
|
|
1493
|
+
declare class HookApplicationsResource {
|
|
1494
|
+
#private;
|
|
1495
|
+
/** @internal Use `new Coss().hooks.applications`. */
|
|
1496
|
+
constructor(http: HttpClient);
|
|
1497
|
+
/** Creates an application. Never automatically retried (the API does not deduplicate it). */
|
|
1498
|
+
create(params: CreateHookApplicationParams, options?: RequestOptions): Promise<CossResult<HookApplication>>;
|
|
1499
|
+
/** Lists the environment's applications, newest first. */
|
|
1500
|
+
list(params?: ListHookApplicationsParams, options?: ReadOptions$6): Promise<CossResult<List<HookApplication>>>;
|
|
1501
|
+
/** Retrieves an application by its id or uid. */
|
|
1502
|
+
get(application: string, options?: ReadOptions$6): Promise<CossResult<HookApplication>>;
|
|
1503
|
+
update(application: string, params: UpdateHookApplicationParams, options?: ReadOptions$6): Promise<CossResult<HookApplication>>;
|
|
1504
|
+
/** Deletes the application with its endpoints and portal sessions. */
|
|
1505
|
+
delete(application: string, options?: ReadOptions$6): Promise<CossResult<DeletedHookApplication>>;
|
|
1506
|
+
}
|
|
1507
|
+
/** `coss.hooks.eventTypes`: the catalog of messages you send, which your users subscribe from. */
|
|
1508
|
+
declare class HookEventTypesResource {
|
|
1509
|
+
#private;
|
|
1510
|
+
/** @internal Use `new Coss().hooks.eventTypes`. */
|
|
1511
|
+
constructor(http: HttpClient);
|
|
1512
|
+
/** Creates an event type. Never automatically retried (a retry would find it existing). */
|
|
1513
|
+
create(params: CreateHookEventTypeParams, options?: RequestOptions): Promise<CossResult<HookEventType>>;
|
|
1514
|
+
/** Lists event types by name (archived ones only with `include_archived`). */
|
|
1515
|
+
list(params?: ListHookEventTypesParams, options?: ReadOptions$6): Promise<CossResult<List<HookEventType>>>;
|
|
1516
|
+
get(name: string, options?: ReadOptions$6): Promise<CossResult<HookEventType>>;
|
|
1517
|
+
/** Changes its description, schema or examples, or archives or restores it. */
|
|
1518
|
+
update(name: string, params: UpdateHookEventTypeParams, options?: ReadOptions$6): Promise<CossResult<HookEventType>>;
|
|
1519
|
+
/** Archives it: hidden from the portal and new subscriptions. */
|
|
1520
|
+
archive(name: string, options?: ReadOptions$6): Promise<CossResult<HookEventType>>;
|
|
1521
|
+
}
|
|
1522
|
+
/** `coss.hooks.endpoints`: an application's endpoints (usually added by its users in the portal). */
|
|
1523
|
+
declare class HookEndpointsResource {
|
|
1524
|
+
#private;
|
|
1525
|
+
/** @internal Use `new Coss().hooks.endpoints`. */
|
|
1526
|
+
constructor(http: HttpClient);
|
|
1527
|
+
/** Creates an endpoint; the result carries its secret. Never automatically retried. */
|
|
1528
|
+
create(application: string, params: CreateHookEndpointParams, options?: RequestOptions): Promise<CossResult<HookEndpointWithSecret>>;
|
|
1529
|
+
list(application: string, options?: ReadOptions$6): Promise<CossResult<List<HookEndpoint>>>;
|
|
1530
|
+
get(application: string, id: string, options?: ReadOptions$6): Promise<CossResult<HookEndpoint>>;
|
|
1531
|
+
update(application: string, id: string, params: UpdateHookEndpointParams, options?: ReadOptions$6): Promise<CossResult<HookEndpoint>>;
|
|
1532
|
+
delete(application: string, id: string, options?: ReadOptions$6): Promise<CossResult<DeletedHookEndpoint>>;
|
|
1533
|
+
/** The endpoint's current signing secret. */
|
|
1534
|
+
getSecret(application: string, id: string, options?: ReadOptions$6): Promise<CossResult<HookEndpointSecret>>;
|
|
1535
|
+
/** Replaces the signing secret. Never automatically retried (a second roll would stop the first). */
|
|
1536
|
+
rollSecret(application: string, id: string, params?: RollHookEndpointSecretParams, options?: RequestOptions): Promise<CossResult<HookEndpointWithSecret>>;
|
|
1537
|
+
/** Requeues the endpoint's failed deliveries of messages sent since `since` (in the background). */
|
|
1538
|
+
recover(application: string, id: string, params: RecoverHookEndpointParams, options?: RequestOptions): Promise<CossResult<HookEndpointRecovery>>;
|
|
1539
|
+
getRecovery(application: string, id: string, recoveryId: string, options?: ReadOptions$6): Promise<CossResult<HookEndpointRecovery>>;
|
|
1540
|
+
/** Sends a message to this endpoint only. Never automatically retried. */
|
|
1541
|
+
sendTest(application: string, id: string, params: SendHookTestParams, options?: RequestOptions): Promise<CossResult<HookMessage>>;
|
|
1542
|
+
/** The endpoint's deliveries, newest first. */
|
|
1543
|
+
listDeliveries(application: string, id: string, params?: ListHookDeliveriesParams, options?: ReadOptions$6): Promise<CossResult<List<HookDelivery>>>;
|
|
1544
|
+
}
|
|
1545
|
+
/** `coss.hooks.messages`: send a message once; COSS delivers it to every subscribed endpoint. */
|
|
1546
|
+
declare class HookMessagesResource {
|
|
1547
|
+
#private;
|
|
1548
|
+
/** @internal Use `new Coss().hooks.messages`. */
|
|
1549
|
+
constructor(http: HttpClient);
|
|
1550
|
+
/**
|
|
1551
|
+
* Sends a message to an application. Safe to retry: every attempt carries the same
|
|
1552
|
+
* `Idempotency-Key`, so a retried send is delivered once.
|
|
1553
|
+
*/
|
|
1554
|
+
send(params: SendHookMessageParams, options?: RequestOptions): Promise<CossResult<HookMessage>>;
|
|
1555
|
+
/** The application's messages, newest first. */
|
|
1556
|
+
list(application: string, params?: ListHookMessagesParams, options?: ReadOptions$6): Promise<CossResult<List<HookMessage>>>;
|
|
1557
|
+
get(application: string, id: string, options?: ReadOptions$6): Promise<CossResult<HookMessage>>;
|
|
1558
|
+
/** One delivery per endpoint the message went to. */
|
|
1559
|
+
listDeliveries(application: string, id: string, options?: ReadOptions$6): Promise<CossResult<List<HookDelivery>>>;
|
|
1560
|
+
}
|
|
1561
|
+
/** `coss.hooks.deliveries`: one message's delivery to one endpoint. */
|
|
1562
|
+
declare class HookDeliveriesResource {
|
|
1563
|
+
#private;
|
|
1564
|
+
/** @internal Use `new Coss().hooks.deliveries`. */
|
|
1565
|
+
constructor(http: HttpClient);
|
|
1566
|
+
get(application: string, id: string, options?: ReadOptions$6): Promise<CossResult<HookDelivery>>;
|
|
1567
|
+
/** Every HTTP request of the delivery, oldest first. */
|
|
1568
|
+
listAttempts(application: string, id: string, options?: ReadOptions$6): Promise<CossResult<List<HookAttempt>>>;
|
|
1569
|
+
/** Queues a finished delivery for one more attempt. Never automatically retried. */
|
|
1570
|
+
retry(application: string, id: string, options?: RequestOptions): Promise<CossResult<HookDelivery>>;
|
|
1571
|
+
}
|
|
1572
|
+
/** `coss.hooks.portal`: a ready-made page for an application's user to manage their endpoints. */
|
|
1573
|
+
declare class HookPortalResource {
|
|
1574
|
+
#private;
|
|
1575
|
+
/** @internal Use `new Coss().hooks.portal`. */
|
|
1576
|
+
constructor(http: HttpClient);
|
|
1577
|
+
/**
|
|
1578
|
+
* Signs the application's user in to the portal: open or embed the returned `url`. Call it from
|
|
1579
|
+
* your backend each time the user opens the portal.
|
|
1580
|
+
*/
|
|
1581
|
+
createSession(params: CreateHookPortalSessionParams, options?: RequestOptions): Promise<CossResult<HookPortalSession>>;
|
|
1582
|
+
}
|
|
1583
|
+
/**
|
|
1584
|
+
* `coss.hooks`: webhooks as a service. Send a message to one of your applications once
|
|
1585
|
+
* (`coss.hooks.messages.send`); COSS delivers it to every endpoint its users registered, signed
|
|
1586
|
+
* (Standard Webhooks), with retries, and gives them a portal to manage it all.
|
|
1587
|
+
*/
|
|
1588
|
+
declare class HooksResource {
|
|
1589
|
+
readonly applications: HookApplicationsResource;
|
|
1590
|
+
readonly eventTypes: HookEventTypesResource;
|
|
1591
|
+
readonly endpoints: HookEndpointsResource;
|
|
1592
|
+
readonly messages: HookMessagesResource;
|
|
1593
|
+
readonly deliveries: HookDeliveriesResource;
|
|
1594
|
+
readonly portal: HookPortalResource;
|
|
1595
|
+
/** @internal Use `new Coss().hooks`. */
|
|
1596
|
+
constructor(http: HttpClient);
|
|
1597
|
+
}
|
|
1598
|
+
//#endregion
|
|
1599
|
+
//#region src/types/log.d.ts
|
|
1600
|
+
/** Log wire types (hand-written mirrors of the API's schemas). */
|
|
1601
|
+
/**
|
|
1602
|
+
* `api`: a request to the API. `email`: an email event. `webhook`: a webhook delivery attempt.
|
|
1603
|
+
* `risk`: a risk assessment or its feedback.
|
|
1604
|
+
*/
|
|
1605
|
+
type LogSource = "api" | "email" | "webhook" | "risk";
|
|
1606
|
+
/**
|
|
1607
|
+
* `error`: 5xx responses, bounces, complaints, failures. `warning`: 4xx responses, delays,
|
|
1608
|
+
* suppressions, failed webhook attempts that will be retried. `info`: everything else.
|
|
1609
|
+
*/
|
|
1610
|
+
type LogLevel = "info" | "warning" | "error";
|
|
1611
|
+
/** One line of the API key's environment's log. */
|
|
1612
|
+
interface Log {
|
|
1613
|
+
object: "log";
|
|
1614
|
+
id: string;
|
|
1615
|
+
/** ISO 8601 timestamp. */
|
|
1616
|
+
occurred_at: string;
|
|
1617
|
+
source: LogSource;
|
|
1618
|
+
level: LogLevel;
|
|
1619
|
+
/** `api.request`, `webhook.attempt`, or an email event type such as `email.delivered`. */
|
|
1620
|
+
type: string;
|
|
1621
|
+
/** A one-line summary. */
|
|
1622
|
+
message: string;
|
|
1623
|
+
/** The `X-Request-Id` of the API request this line belongs to. */
|
|
1624
|
+
request_id: string | null;
|
|
1625
|
+
api_key_id: string | null;
|
|
1626
|
+
method: string | null;
|
|
1627
|
+
path: string | null;
|
|
1628
|
+
/** The matched route, e.g. `/v1/emails/:id`. */
|
|
1629
|
+
route: string | null;
|
|
1630
|
+
/** The API response status, or the webhook endpoint's response status. */
|
|
1631
|
+
status_code: number | null;
|
|
1632
|
+
duration_ms: number | null;
|
|
1633
|
+
client_ip: string | null;
|
|
1634
|
+
user_agent: string | null;
|
|
1635
|
+
error_code: string | null;
|
|
1636
|
+
/** What the line is about: `email`, `domain`, `webhook_endpoint`… */
|
|
1637
|
+
resource_type: string | null;
|
|
1638
|
+
resource_id: string | null;
|
|
1639
|
+
recipient: string | null;
|
|
1640
|
+
/**
|
|
1641
|
+
* Details: redacted request and response bodies for API requests, event data for emails and
|
|
1642
|
+
* webhooks.
|
|
1643
|
+
*/
|
|
1644
|
+
attributes: Record<string, unknown>;
|
|
1645
|
+
}
|
|
1646
|
+
type OneOrMany<T> = T | readonly T[];
|
|
1647
|
+
/** Query of `GET /v1/logs`. Lists may be given as arrays or comma-separated strings. */
|
|
1648
|
+
interface ListLogsParams {
|
|
1649
|
+
/** Start of the range (inclusive). Defaults to an hour before `to`. */
|
|
1650
|
+
from?: string | Date;
|
|
1651
|
+
/** End of the range (exclusive). Defaults to now. At most 31 days after `from`. */
|
|
1652
|
+
to?: string | Date;
|
|
1653
|
+
source?: OneOrMany<LogSource>;
|
|
1654
|
+
level?: OneOrMany<LogLevel>;
|
|
1655
|
+
/** e.g. `"email.bounced"`. */
|
|
1656
|
+
type?: OneOrMany<string>;
|
|
1657
|
+
/** Status codes or classes, e.g. `["4xx", "503"]`. */
|
|
1658
|
+
status?: OneOrMany<string | number>;
|
|
1659
|
+
method?: OneOrMany<string>;
|
|
1660
|
+
/** Routes such as `/v1/emails/:id`. */
|
|
1661
|
+
route?: OneOrMany<string>;
|
|
1662
|
+
api_key_id?: OneOrMany<string>;
|
|
1663
|
+
request_id?: string;
|
|
1664
|
+
/** Only lines about this resource, e.g. an `email_…` id. */
|
|
1665
|
+
resource_id?: string;
|
|
1666
|
+
/** Free text, matched against the message, path, ids and recipient. */
|
|
1667
|
+
q?: string;
|
|
1668
|
+
/** 1-100, default 50. */
|
|
1669
|
+
limit?: number;
|
|
1670
|
+
/** The `id` of the last line of the previous page. */
|
|
1671
|
+
after?: string;
|
|
1672
|
+
}
|
|
1673
|
+
//#endregion
|
|
1674
|
+
//#region src/types/log-drain.d.ts
|
|
1675
|
+
/**
|
|
1676
|
+
* What a drain forwards: `api` (requests made with the environment's API keys), `email` (email
|
|
1677
|
+
* events), `webhook` (webhook delivery attempts) and `audit` (changes to the environment, from
|
|
1678
|
+
* the organization's audit log).
|
|
1679
|
+
*/
|
|
1680
|
+
type LogDrainSource = LogSource | "audit";
|
|
1681
|
+
/** An HTTPS endpoint the environment's log is streamed to, in signed NDJSON batches. */
|
|
1682
|
+
interface LogDrain {
|
|
1683
|
+
object: "log_drain";
|
|
1684
|
+
id: string;
|
|
1685
|
+
url: string;
|
|
1686
|
+
description: string | null;
|
|
1687
|
+
/** Empty means every source, including ones added later. */
|
|
1688
|
+
sources: LogDrainSource[];
|
|
1689
|
+
/** A disabled drain receives nothing, and lines logged meanwhile are not kept for it. */
|
|
1690
|
+
enabled: boolean;
|
|
1691
|
+
/** `manual`, or `failing`: a batch failed every attempt, so COSS disabled it. */
|
|
1692
|
+
disabled_reason: "manual" | "failing" | null;
|
|
1693
|
+
/** ISO 8601 timestamp; `null` while enabled. */
|
|
1694
|
+
disabled_at: string | null;
|
|
1695
|
+
created_at: string;
|
|
1696
|
+
updated_at: string;
|
|
1697
|
+
}
|
|
1698
|
+
/** A drain with its `whsec_…` signing secret, returned only when it is created. */
|
|
1699
|
+
interface LogDrainWithSecret extends LogDrain {
|
|
1700
|
+
secret: string;
|
|
1701
|
+
}
|
|
1702
|
+
interface DeletedLogDrain {
|
|
1703
|
+
object: "log_drain";
|
|
1704
|
+
id: string;
|
|
1705
|
+
deleted: true;
|
|
1706
|
+
}
|
|
1707
|
+
interface CreateLogDrainParams {
|
|
1708
|
+
/** An `https://` URL COSS posts batches to. */
|
|
1709
|
+
url: string;
|
|
1710
|
+
description?: string | null;
|
|
1711
|
+
/** Defaults to every source. */
|
|
1712
|
+
sources?: LogDrainSource[];
|
|
1713
|
+
}
|
|
1714
|
+
interface UpdateLogDrainParams {
|
|
1715
|
+
url?: string;
|
|
1716
|
+
/** `null` clears it. */
|
|
1717
|
+
description?: string | null;
|
|
1718
|
+
sources?: LogDrainSource[];
|
|
1719
|
+
/** Disabling drops the lines still waiting for the drain. */
|
|
1720
|
+
enabled?: boolean;
|
|
1721
|
+
}
|
|
1722
|
+
type LogDrainBatchStatus = "pending" | "succeeded" | "failed";
|
|
1723
|
+
/** One HTTP attempt of a batch. */
|
|
1724
|
+
interface LogDrainAttempt {
|
|
1725
|
+
object: "log_drain_attempt";
|
|
1726
|
+
id: string;
|
|
1727
|
+
attempted_at: string;
|
|
1728
|
+
/** `null` when no response arrived. */
|
|
1729
|
+
status_code: number | null;
|
|
1730
|
+
duration_ms: number;
|
|
1731
|
+
error: string | null;
|
|
1732
|
+
/** At most 1 KB of the response body, as text. */
|
|
1733
|
+
response_excerpt: string | null;
|
|
1734
|
+
}
|
|
1735
|
+
/** One NDJSON request; its `id` is the `webhook-id` header, the same on every attempt. */
|
|
1736
|
+
interface LogDrainBatch {
|
|
1737
|
+
object: "log_drain_batch";
|
|
1738
|
+
id: string;
|
|
1739
|
+
drain_id: string;
|
|
1740
|
+
status: LogDrainBatchStatus;
|
|
1741
|
+
line_count: number;
|
|
1742
|
+
byte_size: number;
|
|
1743
|
+
attempt_count: number;
|
|
1744
|
+
next_attempt_at: string | null;
|
|
1745
|
+
last_status_code: number | null;
|
|
1746
|
+
last_error: string | null;
|
|
1747
|
+
/** Oldest first. */
|
|
1748
|
+
attempts: LogDrainAttempt[];
|
|
1749
|
+
created_at: string;
|
|
1750
|
+
updated_at: string;
|
|
1751
|
+
}
|
|
1752
|
+
interface ListLogDrainBatchesParams {
|
|
1753
|
+
status?: LogDrainBatchStatus;
|
|
1754
|
+
/** 1-100, default 50. */
|
|
1755
|
+
limit?: number;
|
|
1756
|
+
/** The `id` of the last batch of the previous page. */
|
|
1757
|
+
after?: string;
|
|
1758
|
+
}
|
|
1759
|
+
/**
|
|
1760
|
+
* One line of a log drain batch: a log line (as `coss.logs.list()` returns it) or an audit event
|
|
1761
|
+
* of the environment (as `coss.auditEvents.list()` returns it).
|
|
1762
|
+
*/
|
|
1763
|
+
type LogDrainLine = Log | AuditEvent;
|
|
1764
|
+
//#endregion
|
|
1765
|
+
//#region src/resources/log-drains.d.ts
|
|
1766
|
+
type ReadOptions$5 = Pick<RequestOptions, "signal">;
|
|
1767
|
+
/** `coss.logDrains.batches`: a drain's delivery log, each batch with every HTTP attempt. */
|
|
1768
|
+
declare class LogDrainBatchesResource {
|
|
1769
|
+
#private;
|
|
1770
|
+
/** @internal Use `new Coss().logDrains.batches`. */
|
|
1771
|
+
constructor(http: HttpClient);
|
|
1772
|
+
/** Lists the drain's batches, newest first. Pass the last `id` as `after` while `has_more` is true. */
|
|
1773
|
+
list(drainId: string, params?: ListLogDrainBatchesParams, options?: ReadOptions$5): Promise<CossResult<List<LogDrainBatch>>>;
|
|
1774
|
+
/** Retrieves one batch of the drain. */
|
|
1775
|
+
get(drainId: string, id: string, options?: ReadOptions$5): Promise<CossResult<LogDrainBatch>>;
|
|
1776
|
+
}
|
|
1777
|
+
/**
|
|
1778
|
+
* `coss.logDrains`: HTTPS endpoints the environment's log is streamed to (API requests, email
|
|
1779
|
+
* events, webhook attempts and audit events), in signed NDJSON batches. Drains belong to the API
|
|
1780
|
+
* key's own environment, so a `coss_test_…` key only ever manages sandbox drains.
|
|
1781
|
+
*/
|
|
1782
|
+
declare class LogDrainsResource {
|
|
1783
|
+
#private;
|
|
1784
|
+
/** Each drain's delivery log. */
|
|
1785
|
+
readonly batches: LogDrainBatchesResource;
|
|
1786
|
+
/** @internal Use `new Coss().logDrains`. */
|
|
1787
|
+
constructor(http: HttpClient);
|
|
1788
|
+
/**
|
|
1789
|
+
* Creates a drain. The result carries its `secret` (returned only here) — store it and pass it
|
|
1790
|
+
* to `verifyLogDrainBatch` for every request. Creation is never automatically retried: the API
|
|
1791
|
+
* does not deduplicate it. After a lost response, list drains and remove the one with the
|
|
1792
|
+
* unknown secret before creating a replacement.
|
|
1793
|
+
*/
|
|
1794
|
+
create(params: CreateLogDrainParams, options?: RequestOptions): Promise<CossResult<LogDrainWithSecret>>;
|
|
1795
|
+
/** Lists the environment's drains, oldest first. Secrets are never included. */
|
|
1796
|
+
list(options?: ReadOptions$5): Promise<CossResult<List<LogDrain>>>;
|
|
1797
|
+
/** Retrieves a drain of the API key's environment. */
|
|
1798
|
+
get(id: string, options?: ReadOptions$5): Promise<CossResult<LogDrain>>;
|
|
1799
|
+
/**
|
|
1800
|
+
* Changes the URL, description, sources or `enabled` flag. The signing secret stays the same.
|
|
1801
|
+
* Disabling drops the lines still waiting for the drain; enabling it again (also after COSS
|
|
1802
|
+
* disabled it for failing) sends lines logged from then on.
|
|
1803
|
+
*/
|
|
1804
|
+
update(id: string, params: UpdateLogDrainParams, options?: ReadOptions$5): Promise<CossResult<LogDrain>>;
|
|
1805
|
+
/** Deletes the drain and its batch log. To pause it instead, update `enabled` to false. */
|
|
1806
|
+
delete(id: string, options?: ReadOptions$5): Promise<CossResult<DeletedLogDrain>>;
|
|
1807
|
+
}
|
|
1808
|
+
//#endregion
|
|
1809
|
+
//#region src/resources/logs.d.ts
|
|
1810
|
+
type ReadOptions$4 = Pick<RequestOptions, "signal">;
|
|
1811
|
+
/**
|
|
1812
|
+
* `coss.logs`: the API key's environment log, newest first: API requests made with its keys,
|
|
1813
|
+
* email events and webhook delivery attempts.
|
|
1814
|
+
*/
|
|
1815
|
+
declare class LogsResource {
|
|
1816
|
+
#private;
|
|
1817
|
+
/** @internal Use `new Coss().logs`. */
|
|
1818
|
+
constructor(http: HttpClient);
|
|
1819
|
+
/**
|
|
1820
|
+
* Lists log lines, newest first (the last hour unless `from`/`to` say otherwise). Pass the last
|
|
1821
|
+
* `id` as `after` while `has_more` is true.
|
|
1822
|
+
*/
|
|
1823
|
+
list(params?: ListLogsParams, options?: ReadOptions$4): Promise<CossResult<List<Log>>>;
|
|
1824
|
+
/** Retrieves one log line. */
|
|
1825
|
+
get(id: string, options?: ReadOptions$4): Promise<CossResult<Log>>;
|
|
1826
|
+
}
|
|
1827
|
+
//#endregion
|
|
1828
|
+
//#region src/types/reputation.d.ts
|
|
1829
|
+
/** Reputation wire types (hand-written mirrors of the API's `Reputation` schema). */
|
|
1830
|
+
type ReputationStatus = "good" | "warning" | "suspended";
|
|
1831
|
+
type ReputationCheckSeverity = "ok" | "warning" | "suspend";
|
|
1832
|
+
/** One signal the reputation guard measured, e.g. the bounce rate. */
|
|
1833
|
+
interface ReputationCheck {
|
|
1834
|
+
/** What was measured, e.g. `bounce_rate` or `complaint_rate`. */
|
|
1835
|
+
trigger: string;
|
|
1836
|
+
severity: ReputationCheckSeverity;
|
|
1837
|
+
message: string;
|
|
1838
|
+
/** `count / volume`; `null` with no volume. */
|
|
1839
|
+
rate: number | null;
|
|
1840
|
+
count: number;
|
|
1841
|
+
/** Recipients sent to (live environments) in the window. */
|
|
1842
|
+
volume: number;
|
|
1843
|
+
warning_threshold: number | null;
|
|
1844
|
+
suspend_threshold: number | null;
|
|
1845
|
+
/** Below this volume the rate is reported but never acted on. */
|
|
1846
|
+
minimum_volume: number | null;
|
|
1847
|
+
}
|
|
1848
|
+
/** `GET /v1/reputation`: the organization's standing with the reputation guard. */
|
|
1849
|
+
interface Reputation {
|
|
1850
|
+
object: "reputation";
|
|
1851
|
+
/**
|
|
1852
|
+
* `suspended` means live sending is refused (`account_suspended`) until COSS support
|
|
1853
|
+
* reinstates the organization; sandbox keys keep working.
|
|
1854
|
+
*/
|
|
1855
|
+
status: ReputationStatus;
|
|
1856
|
+
/** The trigger behind a `warning` or `suspended` status. */
|
|
1857
|
+
reason: string | null;
|
|
1858
|
+
/** ISO 8601 timestamp. */
|
|
1859
|
+
status_changed_at: string | null;
|
|
1860
|
+
/** When `checks` were computed; `null` before the first evaluation. */
|
|
1861
|
+
evaluated_at: string | null;
|
|
1862
|
+
/** The period `checks` cover. */
|
|
1863
|
+
window: {
|
|
1864
|
+
start: string;
|
|
1865
|
+
end: string;
|
|
1866
|
+
} | null;
|
|
1867
|
+
checks: ReputationCheck[];
|
|
1868
|
+
}
|
|
1869
|
+
//#endregion
|
|
1870
|
+
//#region src/resources/reputation.d.ts
|
|
1871
|
+
type ReadOptions$3 = Pick<RequestOptions, "signal">;
|
|
1872
|
+
/**
|
|
1873
|
+
* `coss.reputation`: the organization's standing with the COSS reputation guard, which suspends
|
|
1874
|
+
* live sending automatically when bounce or complaint rates cross its thresholds.
|
|
1875
|
+
*/
|
|
1876
|
+
declare class ReputationResource {
|
|
1877
|
+
#private;
|
|
1878
|
+
/** @internal Use `new Coss().reputation`. */
|
|
1879
|
+
constructor(http: HttpClient);
|
|
1880
|
+
/** The current status and the latest rates measured over live environments. */
|
|
1881
|
+
get(options?: ReadOptions$3): Promise<CossResult<Reputation>>;
|
|
1882
|
+
}
|
|
1883
|
+
//#endregion
|
|
1884
|
+
//#region src/types/risk.d.ts
|
|
1885
|
+
/** Risk wire types (hand-written mirrors of the API's schemas). */
|
|
1886
|
+
/** What is being assessed. Velocity is counted per event (`custom` events per `event_name`). */
|
|
1887
|
+
type RiskEvent = "signup" | "login" | "message" | "checkout" | "custom";
|
|
1888
|
+
/** `allow`: go ahead. `review`: suspicious; limit or hold it for a person. `block`: refuse it. */
|
|
1889
|
+
type RiskDecision = "allow" | "review" | "block";
|
|
1890
|
+
/** What really happened: `legitimate`, `fraud`, or `abuse` (spam, free-tier abuse…). */
|
|
1891
|
+
type RiskOutcome = "legitimate" | "fraud" | "abuse";
|
|
1892
|
+
type RiskList = "allow" | "block";
|
|
1893
|
+
/**
|
|
1894
|
+
* `email` (matched by mailbox, dots and `+tags` folded), `domain` (subdomains included), `ip` (an
|
|
1895
|
+
* address or CIDR range), `asn`, `country` (ISO 3166-1 alpha-2), `user` (your user id).
|
|
1896
|
+
*/
|
|
1897
|
+
type RiskListEntryType = "email" | "domain" | "ip" | "asn" | "country" | "user";
|
|
1898
|
+
/** Signal groups an assessment was made without (a lookup failed or timed out). */
|
|
1899
|
+
type RiskDegradedSignal = "email_dns" | "domain_age" | "ip_data" | "velocity" | "captcha";
|
|
1900
|
+
/** Every reason an assessment can give (see the reason catalog in the docs). */
|
|
1901
|
+
type RiskReasonCode = "email.invalid" | "email.disposable" | "email.undeliverable" | "email.role_account" | "email.typo" | "email.domain_new" | "ip.tor" | "ip.vpn_network" | "ip.hosting_provider" | "ip.private" | "velocity.signups_per_ip_1h" | "velocity.signups_per_ip_24h" | "velocity.signups_per_subnet_1h" | "velocity.signups_per_email_domain_1h" | "velocity.signups_per_mailbox_24h" | "velocity.logins_per_ip_1h" | "velocity.logins_per_user_1h" | "velocity.events_per_ip_1h" | "velocity.events_per_user_1h" | "duplicate.canonical_mailbox" | "history.fraud_mailbox" | "history.fraud_user" | "history.fraud_ip" | "history.fraud_subnet" | "login.new_country" | "login.new_network" | "captcha.failed" | "captcha.missing" | "rule.matched" | "list.blocked" | "list.allowed";
|
|
1902
|
+
/** Why an assessment decided what it did. Never show reasons to the person being assessed. */
|
|
1903
|
+
interface RiskReason {
|
|
1904
|
+
code: RiskReasonCode;
|
|
1905
|
+
/** For developers (dashboards, logs). */
|
|
1906
|
+
message: string;
|
|
1907
|
+
/** The count behind a `velocity.*` reason. */
|
|
1908
|
+
value?: number;
|
|
1909
|
+
/** The count a `velocity.*` reason fires at. */
|
|
1910
|
+
threshold?: number;
|
|
1911
|
+
window?: "1h" | "24h";
|
|
1912
|
+
/** `email.typo`: the likely domain, which you may show the user ("Did you mean …?"). */
|
|
1913
|
+
suggestion?: string;
|
|
1914
|
+
/** `ip.hosting_provider`, `ip.vpn_network`: the network's operator. */
|
|
1915
|
+
provider?: string;
|
|
1916
|
+
/** `duplicate.canonical_mailbox`: your id of the user who has the mailbox, if known. */
|
|
1917
|
+
previous_user?: string | null;
|
|
1918
|
+
/** `duplicate.canonical_mailbox`: the assessment that first saw the mailbox. */
|
|
1919
|
+
previous_assessment?: string;
|
|
1920
|
+
/** `list.*`: the matching list entry. */
|
|
1921
|
+
entry?: string;
|
|
1922
|
+
/** `list.*`: what matched. */
|
|
1923
|
+
type?: RiskListEntryType;
|
|
1924
|
+
/** `rule.matched`: the rule's id. */
|
|
1925
|
+
rule?: string;
|
|
1926
|
+
/** `rule.matched`: the rule's name. */
|
|
1927
|
+
name?: string;
|
|
1928
|
+
}
|
|
1929
|
+
interface RiskEmailSignals {
|
|
1930
|
+
/** `null` once the address is removed (90 days after the assessment). */
|
|
1931
|
+
domain: string | null;
|
|
1932
|
+
valid: boolean;
|
|
1933
|
+
disposable: boolean;
|
|
1934
|
+
/** From DNS (MX, A, AAAA). `unknown` when the lookup failed or timed out. */
|
|
1935
|
+
deliverability: "deliverable" | "undeliverable" | "unknown";
|
|
1936
|
+
role_account: boolean;
|
|
1937
|
+
free_provider: boolean;
|
|
1938
|
+
suggestion: string | null;
|
|
1939
|
+
/**
|
|
1940
|
+
* Days since the domain was registered (RDAP); `null` when unknown or not looked up (free
|
|
1941
|
+
* providers, disposable domains).
|
|
1942
|
+
*/
|
|
1943
|
+
domain_age_days: number | null;
|
|
1944
|
+
}
|
|
1945
|
+
interface RiskCaptchaSignals {
|
|
1946
|
+
provided: boolean;
|
|
1947
|
+
/** `null` when it couldn't be checked (no captcha configured, or the provider was unreachable). */
|
|
1948
|
+
passed: boolean | null;
|
|
1949
|
+
}
|
|
1950
|
+
/** Logins of a user with history: whether the country or network is new for them. */
|
|
1951
|
+
interface RiskLoginSignals {
|
|
1952
|
+
new_country: boolean;
|
|
1953
|
+
new_network: boolean;
|
|
1954
|
+
}
|
|
1955
|
+
interface RiskIpSignals {
|
|
1956
|
+
version: 4 | 6;
|
|
1957
|
+
private: boolean;
|
|
1958
|
+
tor: boolean;
|
|
1959
|
+
hosting: boolean;
|
|
1960
|
+
hosting_provider: string | null;
|
|
1961
|
+
hosting_kind: "cloud" | "hosting" | "vpn" | null;
|
|
1962
|
+
asn: number | null;
|
|
1963
|
+
as_name: string | null;
|
|
1964
|
+
/** ISO 3166-1 alpha-2. */
|
|
1965
|
+
country: string | null;
|
|
1966
|
+
}
|
|
1967
|
+
/** An assessment of one event. */
|
|
1968
|
+
interface RiskAssessment {
|
|
1969
|
+
object: "risk_assessment";
|
|
1970
|
+
id: string;
|
|
1971
|
+
event: RiskEvent;
|
|
1972
|
+
event_name: string | null;
|
|
1973
|
+
decision: RiskDecision;
|
|
1974
|
+
/** 0-1: how risky the signals are together. Lists can decide regardless of the score. */
|
|
1975
|
+
score: number;
|
|
1976
|
+
/** Why, most significant first. */
|
|
1977
|
+
reasons: RiskReason[];
|
|
1978
|
+
signals: {
|
|
1979
|
+
email: RiskEmailSignals | null;
|
|
1980
|
+
ip: RiskIpSignals | null;
|
|
1981
|
+
/**
|
|
1982
|
+
* Events of the same kind in this environment, this one included, keyed
|
|
1983
|
+
* `<dimension>_<window>` (e.g. `ip_1h`, `mailbox_24h`); `null` when unavailable.
|
|
1984
|
+
*/
|
|
1985
|
+
velocity: Record<string, number> | null;
|
|
1986
|
+
captcha: RiskCaptchaSignals | null;
|
|
1987
|
+
login: RiskLoginSignals | null;
|
|
1988
|
+
};
|
|
1989
|
+
user: {
|
|
1990
|
+
id: string | null;
|
|
1991
|
+
email: string | null;
|
|
1992
|
+
};
|
|
1993
|
+
/** `null` once removed (90 days after the assessment). */
|
|
1994
|
+
ip: string | null;
|
|
1995
|
+
degraded: RiskDegradedSignal[];
|
|
1996
|
+
/** The latest outcome you reported with `coss.risk.feedback`. */
|
|
1997
|
+
outcome: RiskOutcome | null;
|
|
1998
|
+
/** `open` for `review` decisions until you send feedback, then `resolved`. */
|
|
1999
|
+
review_status: "open" | "resolved" | null;
|
|
2000
|
+
/** ISO 8601 timestamp. */
|
|
2001
|
+
created_at: string;
|
|
2002
|
+
}
|
|
2003
|
+
/** Body of `POST /v1/risk/assessments`. */
|
|
2004
|
+
interface AssessRiskParams {
|
|
2005
|
+
event: RiskEvent;
|
|
2006
|
+
/** Required for `custom` events (e.g. `invite_sent`), not allowed otherwise. */
|
|
2007
|
+
event_name?: string;
|
|
2008
|
+
user?: {
|
|
2009
|
+
/** Your id for the user, when it exists (logins always; sign-ups once the account exists). */
|
|
2010
|
+
id?: string;
|
|
2011
|
+
/** The email address the user gave. */
|
|
2012
|
+
email?: string;
|
|
2013
|
+
};
|
|
2014
|
+
/** The client's IP address (not your server's or proxy's). */
|
|
2015
|
+
ip?: string;
|
|
2016
|
+
/** The client's user agent. */
|
|
2017
|
+
user_agent?: string;
|
|
2018
|
+
/**
|
|
2019
|
+
* The token your captcha widget (Turnstile or hCaptcha, set in the risk settings) gave the
|
|
2020
|
+
* browser. Verified once: don't reuse it.
|
|
2021
|
+
*/
|
|
2022
|
+
captcha?: {
|
|
2023
|
+
token: string;
|
|
2024
|
+
};
|
|
2025
|
+
}
|
|
2026
|
+
/** Query of `GET /v1/risk/assessments`. */
|
|
2027
|
+
interface ListRiskAssessmentsParams {
|
|
2028
|
+
event?: RiskEvent;
|
|
2029
|
+
decision?: RiskDecision;
|
|
2030
|
+
user_id?: string;
|
|
2031
|
+
/** `open`: the review queue. */
|
|
2032
|
+
review_status?: "open" | "resolved";
|
|
2033
|
+
/** 1-100, default 50. */
|
|
2034
|
+
limit?: number;
|
|
2035
|
+
/** The `id` of the last assessment of the previous page. */
|
|
2036
|
+
after?: string;
|
|
2037
|
+
}
|
|
2038
|
+
/** Body of `POST /v1/risk/assessments/{id}/feedback`. */
|
|
2039
|
+
interface RiskFeedbackParams {
|
|
2040
|
+
outcome: RiskOutcome;
|
|
2041
|
+
/** For your team; never shared. */
|
|
2042
|
+
note?: string;
|
|
2043
|
+
}
|
|
2044
|
+
/** An entry of the environment's allow or block list. */
|
|
2045
|
+
interface RiskListEntry {
|
|
2046
|
+
object: "risk_list_entry";
|
|
2047
|
+
id: string;
|
|
2048
|
+
list: RiskList;
|
|
2049
|
+
type: RiskListEntryType;
|
|
2050
|
+
/** Normalized: emails as their mailbox, CIDR ranges canonical, ASNs as numbers. */
|
|
2051
|
+
value: string;
|
|
2052
|
+
note: string | null;
|
|
2053
|
+
/** ISO 8601 timestamp: the entry stops matching then. */
|
|
2054
|
+
expires_at: string | null;
|
|
2055
|
+
/** ISO 8601 timestamp. */
|
|
2056
|
+
created_at: string;
|
|
2057
|
+
}
|
|
2058
|
+
/** Body of `POST /v1/risk/list_entries` (`coss.risk.lists.add` builds it). */
|
|
2059
|
+
interface CreateRiskListEntryParams {
|
|
2060
|
+
list: RiskList;
|
|
2061
|
+
type: RiskListEntryType;
|
|
2062
|
+
value: string;
|
|
2063
|
+
note?: string;
|
|
2064
|
+
/** ISO 8601 timestamp with an offset. */
|
|
2065
|
+
expires_at?: string;
|
|
2066
|
+
}
|
|
2067
|
+
/** What `coss.risk.lists.add` matches on: exactly one of these. */
|
|
2068
|
+
type RiskListEntryValue = {
|
|
2069
|
+
email: string;
|
|
2070
|
+
} | {
|
|
2071
|
+
domain: string;
|
|
2072
|
+
} | {
|
|
2073
|
+
ip: string;
|
|
2074
|
+
} | {
|
|
2075
|
+
asn: string | number;
|
|
2076
|
+
} | {
|
|
2077
|
+
country: string;
|
|
2078
|
+
} | {
|
|
2079
|
+
user: string;
|
|
2080
|
+
};
|
|
2081
|
+
/** Query of `GET /v1/risk/list_entries`. */
|
|
2082
|
+
interface ListRiskListEntriesParams {
|
|
2083
|
+
list?: RiskList;
|
|
2084
|
+
type?: RiskListEntryType;
|
|
2085
|
+
/** 1-100, default 50. */
|
|
2086
|
+
limit?: number;
|
|
2087
|
+
after?: string;
|
|
2088
|
+
}
|
|
2089
|
+
/** Response of `DELETE /v1/risk/list_entries/{id}`. */
|
|
2090
|
+
interface DeletedRiskListEntry {
|
|
2091
|
+
object: "risk_list_entry";
|
|
2092
|
+
id: string;
|
|
2093
|
+
deleted: true;
|
|
2094
|
+
}
|
|
2095
|
+
/** Response of `DELETE /v1/risk/users/{user_id}`. */
|
|
2096
|
+
interface ForgottenRiskUser {
|
|
2097
|
+
object: "risk_user";
|
|
2098
|
+
/** Your user id. */
|
|
2099
|
+
id: string;
|
|
2100
|
+
deleted: true;
|
|
2101
|
+
}
|
|
2102
|
+
type RiskCaptchaProvider = "turnstile" | "hcaptcha";
|
|
2103
|
+
/** The environment's risk settings. */
|
|
2104
|
+
interface RiskSettings {
|
|
2105
|
+
object: "risk_settings";
|
|
2106
|
+
/** Scores at or above it are `review`. */
|
|
2107
|
+
review_threshold: number;
|
|
2108
|
+
/** Scores at or above it are `block`. */
|
|
2109
|
+
block_threshold: number;
|
|
2110
|
+
/** Reasons that never fire in this environment. */
|
|
2111
|
+
disabled_reasons: RiskReasonCode[];
|
|
2112
|
+
/** The captcha provider assessments verify tokens with (never the secret). */
|
|
2113
|
+
captcha: {
|
|
2114
|
+
provider: RiskCaptchaProvider;
|
|
2115
|
+
required: boolean;
|
|
2116
|
+
} | null;
|
|
2117
|
+
/** ISO 8601 timestamp; `null` while on the defaults. */
|
|
2118
|
+
updated_at: string | null;
|
|
2119
|
+
}
|
|
2120
|
+
/** Body of `PATCH /v1/risk/settings`: only the fields given change. */
|
|
2121
|
+
interface UpdateRiskSettingsParams {
|
|
2122
|
+
review_threshold?: number;
|
|
2123
|
+
block_threshold?: number;
|
|
2124
|
+
disabled_reasons?: RiskReasonCode[];
|
|
2125
|
+
/** `null` turns captcha verification off and deletes the secret. */
|
|
2126
|
+
captcha?: {
|
|
2127
|
+
provider: RiskCaptchaProvider;
|
|
2128
|
+
/** Required when setting a provider for the first time or changing it. */
|
|
2129
|
+
secret?: string;
|
|
2130
|
+
/** Assessments without a token get `captcha.missing`. */
|
|
2131
|
+
required?: boolean;
|
|
2132
|
+
} | null;
|
|
2133
|
+
}
|
|
2134
|
+
/** A field a rule condition can test (see the rules guide). */
|
|
2135
|
+
type RiskRuleField = "email.valid" | "email.disposable" | "email.undeliverable" | "email.role_account" | "email.free_provider" | "email.typo" | "email.domain_new" | "email.domain" | "email.domain_age_days" | "ip.tor" | "ip.hosting" | "ip.vpn" | "ip.private" | "ip.country" | "ip.asn" | "ip.hosting_provider" | "captcha.passed" | "duplicate.canonical_mailbox" | "history.fraud" | "login.new_country" | "login.new_network" | "score" | "velocity.ip_1h" | "velocity.ip_24h" | "velocity.subnet_1h" | "velocity.subnet_24h" | "velocity.email_domain_1h" | "velocity.email_domain_24h" | "velocity.mailbox_1h" | "velocity.mailbox_24h" | "velocity.user_1h" | "velocity.user_24h";
|
|
2136
|
+
/** A test of one field. A field without a value (no IP, no email…) never matches. */
|
|
2137
|
+
interface RiskRuleCondition {
|
|
2138
|
+
field: RiskRuleField;
|
|
2139
|
+
/** `is` (booleans); `eq`, `neq`, `gt`, `gte`, `lt`, `lte` (numbers); `eq`, `neq`, `in`, `not_in` (strings). */
|
|
2140
|
+
operator: "is" | "eq" | "neq" | "gt" | "gte" | "lt" | "lte" | "in" | "not_in";
|
|
2141
|
+
value: boolean | number | string | string[];
|
|
2142
|
+
}
|
|
2143
|
+
/** A rule: the first enabled one whose conditions match decides (after the lists). */
|
|
2144
|
+
interface RiskRule {
|
|
2145
|
+
object: "risk_rule";
|
|
2146
|
+
id: string;
|
|
2147
|
+
name: string;
|
|
2148
|
+
enabled: boolean;
|
|
2149
|
+
/** Rules are tried in ascending order. */
|
|
2150
|
+
position: number;
|
|
2151
|
+
/** Events it applies to; empty: every event. */
|
|
2152
|
+
events: RiskEvent[];
|
|
2153
|
+
/** `all`: every condition must hold. `any`: one is enough. */
|
|
2154
|
+
match: "all" | "any";
|
|
2155
|
+
conditions: RiskRuleCondition[];
|
|
2156
|
+
action: RiskDecision;
|
|
2157
|
+
/** ISO 8601 timestamp. */
|
|
2158
|
+
created_at: string;
|
|
2159
|
+
/** ISO 8601 timestamp. */
|
|
2160
|
+
updated_at: string;
|
|
2161
|
+
}
|
|
2162
|
+
/** Body of `POST /v1/risk/rules`. */
|
|
2163
|
+
interface CreateRiskRuleParams {
|
|
2164
|
+
name: string;
|
|
2165
|
+
enabled?: boolean;
|
|
2166
|
+
/** Default 0. */
|
|
2167
|
+
position?: number;
|
|
2168
|
+
events?: RiskEvent[];
|
|
2169
|
+
/** Default `all`. */
|
|
2170
|
+
match?: "all" | "any";
|
|
2171
|
+
conditions: RiskRuleCondition[];
|
|
2172
|
+
action: RiskDecision;
|
|
2173
|
+
}
|
|
2174
|
+
/** Body of `PATCH /v1/risk/rules/{id}`: only the fields given change. */
|
|
2175
|
+
type UpdateRiskRuleParams = Partial<CreateRiskRuleParams>;
|
|
2176
|
+
/** Response of `DELETE /v1/risk/rules/{id}`. */
|
|
2177
|
+
interface DeletedRiskRule {
|
|
2178
|
+
object: "risk_rule";
|
|
2179
|
+
id: string;
|
|
2180
|
+
deleted: true;
|
|
2181
|
+
}
|
|
2182
|
+
//#endregion
|
|
2183
|
+
//#region src/resources/risk.d.ts
|
|
2184
|
+
type ReadOptions$2 = Pick<RequestOptions, "signal">;
|
|
2185
|
+
/** `coss.risk.assessments`: reading past assessments (`assess` lives on `coss.risk`). */
|
|
2186
|
+
declare class RiskAssessmentsResource {
|
|
2187
|
+
#private;
|
|
2188
|
+
/** @internal Use `new Coss().risk.assessments`. */
|
|
2189
|
+
constructor(http: HttpClient);
|
|
2190
|
+
/** Retrieves one assessment. */
|
|
2191
|
+
get(id: string, options?: ReadOptions$2): Promise<CossResult<RiskAssessment>>;
|
|
2192
|
+
/**
|
|
2193
|
+
* Lists assessments, newest first (`review_status: "open"` is the review queue). Pass the last
|
|
2194
|
+
* `id` as `after` while `has_more` is true.
|
|
2195
|
+
*/
|
|
2196
|
+
list(params?: ListRiskAssessmentsParams, options?: ReadOptions$2): Promise<CossResult<List<RiskAssessment>>>;
|
|
2197
|
+
}
|
|
2198
|
+
/** `coss.risk.lists`: the environment's allow and block lists. */
|
|
2199
|
+
declare class RiskListsResource {
|
|
2200
|
+
#private;
|
|
2201
|
+
/** @internal Use `new Coss().risk.lists`. */
|
|
2202
|
+
constructor(http: HttpClient);
|
|
2203
|
+
/**
|
|
2204
|
+
* Adds an entry: `coss.risk.lists.add("block", { domain: "evil.example" })`. An allow-list match
|
|
2205
|
+
* makes decisions `allow`, a block-list match `block`. Returns the existing entry if there is one.
|
|
2206
|
+
*/
|
|
2207
|
+
add(list: RiskList, entry: RiskListEntryValue & {
|
|
2208
|
+
note?: string;
|
|
2209
|
+
expires_at?: string | Date;
|
|
2210
|
+
}, options?: RequestOptions): Promise<CossResult<RiskListEntry>>;
|
|
2211
|
+
/** Lists entries, newest first. Pass the last `id` as `after` while `has_more` is true. */
|
|
2212
|
+
list(params?: ListRiskListEntriesParams, options?: ReadOptions$2): Promise<CossResult<List<RiskListEntry>>>;
|
|
2213
|
+
/** Retrieves one entry. */
|
|
2214
|
+
get(id: string, options?: ReadOptions$2): Promise<CossResult<RiskListEntry>>;
|
|
2215
|
+
/** Removes an entry. */
|
|
2216
|
+
remove(id: string, options?: ReadOptions$2): Promise<CossResult<DeletedRiskListEntry>>;
|
|
2217
|
+
}
|
|
2218
|
+
/** `coss.risk.settings`: the environment's thresholds, disabled reasons and captcha provider. */
|
|
2219
|
+
declare class RiskSettingsResource {
|
|
2220
|
+
#private;
|
|
2221
|
+
/** @internal Use `new Coss().risk.settings`. */
|
|
2222
|
+
constructor(http: HttpClient);
|
|
2223
|
+
get(options?: ReadOptions$2): Promise<CossResult<RiskSettings>>;
|
|
2224
|
+
/** Changes the fields given. The captcha secret is write-only. */
|
|
2225
|
+
update(params: UpdateRiskSettingsParams, options?: ReadOptions$2): Promise<CossResult<RiskSettings>>;
|
|
2226
|
+
}
|
|
2227
|
+
/**
|
|
2228
|
+
* `coss.risk.rules`: the environment's rules. After the lists, the first enabled rule whose
|
|
2229
|
+
* conditions match an event decides it.
|
|
2230
|
+
*/
|
|
2231
|
+
declare class RiskRulesResource {
|
|
2232
|
+
#private;
|
|
2233
|
+
/** @internal Use `new Coss().risk.rules`. */
|
|
2234
|
+
constructor(http: HttpClient);
|
|
2235
|
+
/** Creates a rule. Not retried automatically: a retry could create it twice. */
|
|
2236
|
+
create(params: CreateRiskRuleParams, options?: ReadOptions$2): Promise<CossResult<RiskRule>>;
|
|
2237
|
+
/** Every rule, in evaluation order. */
|
|
2238
|
+
list(options?: ReadOptions$2): Promise<CossResult<List<RiskRule>>>;
|
|
2239
|
+
get(id: string, options?: ReadOptions$2): Promise<CossResult<RiskRule>>;
|
|
2240
|
+
/** Changes the fields given; `conditions` replaces the whole list. */
|
|
2241
|
+
update(id: string, params: UpdateRiskRuleParams, options?: ReadOptions$2): Promise<CossResult<RiskRule>>;
|
|
2242
|
+
delete(id: string, options?: ReadOptions$2): Promise<CossResult<DeletedRiskRule>>;
|
|
2243
|
+
}
|
|
2244
|
+
/** `coss.risk.users`: what COSS remembers about your users. */
|
|
2245
|
+
declare class RiskUsersResource {
|
|
2246
|
+
#private;
|
|
2247
|
+
/** @internal Use `new Coss().risk.users`. */
|
|
2248
|
+
constructor(http: HttpClient);
|
|
2249
|
+
/**
|
|
2250
|
+
* Call when you delete a user: COSS deletes what identifies them (their mailbox, fraud reports,
|
|
2251
|
+
* and the user id, email, IP and user agent on their assessments). Safe to repeat.
|
|
2252
|
+
*/
|
|
2253
|
+
forget(userId: string, options?: ReadOptions$2): Promise<CossResult<ForgottenRiskUser>>;
|
|
2254
|
+
}
|
|
2255
|
+
/**
|
|
2256
|
+
* `coss.risk`: assess sign-ups, logins and other events. Call it from your server and treat an
|
|
2257
|
+
* error as `allow` (fail open), so an outage never locks your users out.
|
|
2258
|
+
*
|
|
2259
|
+
* ```ts
|
|
2260
|
+
* const { data } = await coss.risk.assess({ event: "signup", user: { email }, ip, user_agent });
|
|
2261
|
+
* if (data?.decision === "block") return refuse();
|
|
2262
|
+
* ```
|
|
2263
|
+
*/
|
|
2264
|
+
declare class RiskResource {
|
|
2265
|
+
#private;
|
|
2266
|
+
/** Past assessments (`get`, `list`). */
|
|
2267
|
+
readonly assessments: RiskAssessmentsResource;
|
|
2268
|
+
/** Allow and block lists (`add`, `list`, `get`, `remove`). */
|
|
2269
|
+
readonly lists: RiskListsResource;
|
|
2270
|
+
/** Forgetting deleted users. */
|
|
2271
|
+
readonly users: RiskUsersResource;
|
|
2272
|
+
/** Thresholds, disabled reasons and the captcha provider (`get`, `update`). */
|
|
2273
|
+
readonly settings: RiskSettingsResource;
|
|
2274
|
+
/** Rules (`create`, `list`, `get`, `update`, `delete`). */
|
|
2275
|
+
readonly rules: RiskRulesResource;
|
|
2276
|
+
/** @internal Use `new Coss().risk`. */
|
|
2277
|
+
constructor(http: HttpClient);
|
|
2278
|
+
/**
|
|
2279
|
+
* Assesses an event and returns the decision with its score and reasons. Retries reuse one
|
|
2280
|
+
* `Idempotency-Key`, so an event is never counted twice.
|
|
2281
|
+
*/
|
|
2282
|
+
assess(params: AssessRiskParams, options?: RequestOptions): Promise<CossResult<RiskAssessment>>;
|
|
2283
|
+
/**
|
|
2284
|
+
* Reports what an assessed user turned out to be: `fraud` and `abuse` teach later assessments to
|
|
2285
|
+
* flag the same mailbox, user, IP and subnet; `legitimate` takes that back. Resolves a review.
|
|
2286
|
+
*/
|
|
2287
|
+
feedback(id: string, params: RiskFeedbackParams, options?: RequestOptions): Promise<CossResult<RiskAssessment>>;
|
|
2288
|
+
}
|
|
2289
|
+
//#endregion
|
|
2290
|
+
//#region src/types/webhook.d.ts
|
|
2291
|
+
/** What a webhook says about the email; never its content, cc or bcc. */
|
|
2292
|
+
interface EmailWebhookEventData extends EmailEventData {
|
|
2293
|
+
email_id: string;
|
|
2294
|
+
from: string;
|
|
2295
|
+
to: string[];
|
|
2296
|
+
subject: string;
|
|
2297
|
+
tags: EmailTag[];
|
|
2298
|
+
category: string | null;
|
|
2299
|
+
/** `true` for emails sent with a sandbox (`coss_test_…`) key. */
|
|
2300
|
+
sandbox: boolean;
|
|
2301
|
+
/** The recipient this event is about; `null` for the whole email. */
|
|
2302
|
+
recipient: string | null;
|
|
2303
|
+
/** ISO 8601 timestamp of the event itself (deliveries can arrive later, and out of order). */
|
|
2304
|
+
occurred_at: string;
|
|
2305
|
+
}
|
|
2306
|
+
/** An email event. `id` equals the `webhook-id` header and `EmailEvent.id`. */
|
|
2307
|
+
interface EmailWebhookEvent {
|
|
2308
|
+
id: string;
|
|
2309
|
+
object: "event";
|
|
2310
|
+
type: EmailEventType;
|
|
2311
|
+
/** The API version this event is rendered in: the receiving endpoint's `api_version`. */
|
|
2312
|
+
api_version: string;
|
|
2313
|
+
/** ISO 8601 timestamp. */
|
|
2314
|
+
created_at: string;
|
|
2315
|
+
data: EmailWebhookEventData;
|
|
2316
|
+
}
|
|
2317
|
+
/** Events about received (inbound) emails. */
|
|
2318
|
+
type ReceivedEmailEventType = "email.received";
|
|
2319
|
+
/** What a webhook says about a received email; never its content, headers or cc. */
|
|
2320
|
+
interface ReceivedEmailWebhookEventData {
|
|
2321
|
+
/** Retrieve the email (bodies, headers, attachments) with `coss.email.received.get`. */
|
|
2322
|
+
received_email_id: string;
|
|
2323
|
+
/** The `From` header. */
|
|
2324
|
+
from: string | null;
|
|
2325
|
+
/** The `To` header's addresses. */
|
|
2326
|
+
to: string[];
|
|
2327
|
+
/** The envelope recipients this environment received it for. */
|
|
2328
|
+
recipients: string[];
|
|
2329
|
+
subject: string | null;
|
|
2330
|
+
message_id: string | null;
|
|
2331
|
+
attachment_count: number;
|
|
2332
|
+
size: number;
|
|
2333
|
+
/** Whether the spam verdict is `fail`. */
|
|
2334
|
+
spam: boolean;
|
|
2335
|
+
verdicts: ReceivedEmailVerdicts;
|
|
2336
|
+
sandbox: boolean;
|
|
2337
|
+
/** ISO 8601 timestamp. */
|
|
2338
|
+
received_at: string;
|
|
2339
|
+
}
|
|
2340
|
+
/** An email arrived. `id` equals the `webhook-id` header. */
|
|
2341
|
+
interface ReceivedEmailWebhookEvent {
|
|
2342
|
+
id: string;
|
|
2343
|
+
object: "event";
|
|
2344
|
+
type: ReceivedEmailEventType;
|
|
2345
|
+
/** The API version this event is rendered in: the receiving endpoint's `api_version`. */
|
|
2346
|
+
api_version: string;
|
|
2347
|
+
/** ISO 8601 timestamp. */
|
|
2348
|
+
created_at: string;
|
|
2349
|
+
data: ReceivedEmailWebhookEventData;
|
|
2350
|
+
}
|
|
2351
|
+
/** Changes of the organization's reputation standing (sent to live environments only). */
|
|
2352
|
+
type AccountEventType = "account.reputation_warning" | "account.reputation_recovered" | "account.suspended" | "account.reinstated";
|
|
2353
|
+
interface AccountWebhookEventData {
|
|
2354
|
+
organization_id: string;
|
|
2355
|
+
status: ReputationStatus;
|
|
2356
|
+
previous_status: ReputationStatus;
|
|
2357
|
+
/** The trigger behind a `warning` or `suspended` status, e.g. `complaint_rate`. */
|
|
2358
|
+
reason: string | null;
|
|
2359
|
+
/** ISO 8601 timestamp. */
|
|
2360
|
+
occurred_at: string;
|
|
2361
|
+
/** The measurements behind the change (see `coss.reputation.get()`). */
|
|
2362
|
+
checks: ReputationCheck[];
|
|
2363
|
+
}
|
|
2364
|
+
/** A reputation change. `id` equals the `webhook-id` header. */
|
|
2365
|
+
interface AccountWebhookEvent {
|
|
2366
|
+
id: string;
|
|
2367
|
+
object: "event";
|
|
2368
|
+
type: AccountEventType;
|
|
2369
|
+
/** The API version this event is rendered in: the receiving endpoint's `api_version`. */
|
|
2370
|
+
api_version: string;
|
|
2371
|
+
/** ISO 8601 timestamp. */
|
|
2372
|
+
created_at: string;
|
|
2373
|
+
data: AccountWebhookEventData;
|
|
2374
|
+
}
|
|
2375
|
+
/** Billing events (organization-wide; sent to live environments only). */
|
|
2376
|
+
type BillingEventType = "billing.invoice_finalized" | "billing.invoice_paid" | "billing.invoice_payment_failed" | "billing.invoice_voided" | "billing.plan_changed" | "billing.usage_threshold_reached" | "billing.hold_placed" | "billing.hold_lifted" | "billing.credit_granted";
|
|
2377
|
+
interface BillingEventFields {
|
|
2378
|
+
/** Equals the `webhook-id` header. */
|
|
2379
|
+
id: string;
|
|
2380
|
+
object: "event";
|
|
2381
|
+
/** The API version this event is rendered in: the receiving endpoint's `api_version`. */
|
|
2382
|
+
api_version: string;
|
|
2383
|
+
/** ISO 8601 timestamp. */
|
|
2384
|
+
created_at: string;
|
|
2385
|
+
}
|
|
2386
|
+
/** Every billing event's `data` has these. */
|
|
2387
|
+
interface BillingEventData {
|
|
2388
|
+
organization_id: string;
|
|
2389
|
+
/** When it happened (ISO 8601): sort events by it. */
|
|
2390
|
+
occurred_at: string;
|
|
2391
|
+
}
|
|
2392
|
+
/** A billing event; narrow on `type` for its `data`. */
|
|
2393
|
+
type BillingWebhookEvent = (BillingEventFields & {
|
|
2394
|
+
type: "billing.invoice_finalized" | "billing.invoice_paid" | "billing.invoice_voided";
|
|
2395
|
+
data: BillingEventData & {
|
|
2396
|
+
invoice: InvoiceSummary;
|
|
2397
|
+
};
|
|
2398
|
+
}) | (BillingEventFields & {
|
|
2399
|
+
type: "billing.invoice_payment_failed";
|
|
2400
|
+
data: BillingEventData & {
|
|
2401
|
+
invoice: InvoiceSummary;
|
|
2402
|
+
failure: {
|
|
2403
|
+
message: string;
|
|
2404
|
+
};
|
|
2405
|
+
};
|
|
2406
|
+
}) | (BillingEventFields & {
|
|
2407
|
+
type: "billing.plan_changed";
|
|
2408
|
+
data: BillingEventData & {
|
|
2409
|
+
/**
|
|
2410
|
+
* `upgrade` (in effect now), `downgrade`/`cancellation` (scheduled), `reverted` (a
|
|
2411
|
+
* scheduled change was undone), `contract` (a contract changed).
|
|
2412
|
+
*/
|
|
2413
|
+
change: "upgrade" | "downgrade" | "cancellation" | "reverted" | "contract";
|
|
2414
|
+
/** The plan from `effective_at`. */
|
|
2415
|
+
plan: PlanKey;
|
|
2416
|
+
previous_plan: PlanKey;
|
|
2417
|
+
effective_at: string;
|
|
2418
|
+
};
|
|
2419
|
+
}) | (BillingEventFields & {
|
|
2420
|
+
type: "billing.usage_threshold_reached";
|
|
2421
|
+
data: BillingEventData & {
|
|
2422
|
+
/** The threshold crossed, e.g. 80. */
|
|
2423
|
+
percent: number;
|
|
2424
|
+
/** `credit`: the month's usage credit; `allowance`: a capped plan's included units. */
|
|
2425
|
+
of: "credit" | "allowance";
|
|
2426
|
+
meter: Meter | null;
|
|
2427
|
+
period: {
|
|
2428
|
+
start: string;
|
|
2429
|
+
end: string;
|
|
2430
|
+
};
|
|
2431
|
+
};
|
|
2432
|
+
}) | (BillingEventFields & {
|
|
2433
|
+
type: "billing.hold_placed" | "billing.hold_lifted";
|
|
2434
|
+
data: BillingEventData & {
|
|
2435
|
+
reason: BillingHoldReason;
|
|
2436
|
+
};
|
|
2437
|
+
}) | (BillingEventFields & {
|
|
2438
|
+
type: "billing.credit_granted";
|
|
2439
|
+
data: BillingEventData & {
|
|
2440
|
+
credit: Credit;
|
|
2441
|
+
};
|
|
2442
|
+
});
|
|
2443
|
+
/** Risk events: `review` decisions, and their resolution, for a queue you work through. */
|
|
2444
|
+
type RiskEventType = "risk.assessment.review" | "risk.assessment.reviewed";
|
|
2445
|
+
interface RiskWebhookEventData {
|
|
2446
|
+
assessment_id: string;
|
|
2447
|
+
event: RiskEvent;
|
|
2448
|
+
event_name: string | null;
|
|
2449
|
+
decision: RiskDecision;
|
|
2450
|
+
score: number;
|
|
2451
|
+
reasons: RiskReason[];
|
|
2452
|
+
/** Your user id, if the assessment had one. Never the email or IP address. */
|
|
2453
|
+
user_id: string | null;
|
|
2454
|
+
/** `risk.assessment.reviewed`: the outcome that resolved the review. */
|
|
2455
|
+
outcome: RiskOutcome | null;
|
|
2456
|
+
/** ISO 8601 timestamp. */
|
|
2457
|
+
occurred_at: string;
|
|
2458
|
+
}
|
|
2459
|
+
/** A risk review opened or resolved. `id` equals the `webhook-id` header. */
|
|
2460
|
+
interface RiskWebhookEvent {
|
|
2461
|
+
id: string;
|
|
2462
|
+
object: "event";
|
|
2463
|
+
type: RiskEventType;
|
|
2464
|
+
/** The API version this event is rendered in: the receiving endpoint's `api_version`. */
|
|
2465
|
+
api_version: string;
|
|
2466
|
+
/** ISO 8601 timestamp. */
|
|
2467
|
+
created_at: string;
|
|
2468
|
+
data: RiskWebhookEventData;
|
|
2469
|
+
}
|
|
2470
|
+
/** Events about Hooks: an endpoint of one of your applications was disabled for failing. */
|
|
2471
|
+
type HookOperationalEventType = "hook_endpoint.disabled";
|
|
2472
|
+
interface HookEndpointWebhookEventData {
|
|
2473
|
+
application_id: string;
|
|
2474
|
+
/** Your uid for the application, when it has one. */
|
|
2475
|
+
application_uid: string | null;
|
|
2476
|
+
endpoint_id: string;
|
|
2477
|
+
url: string;
|
|
2478
|
+
/** ISO 8601 timestamp: when its deliveries started failing every attempt. */
|
|
2479
|
+
failing_since: string;
|
|
2480
|
+
/** ISO 8601 timestamp. */
|
|
2481
|
+
occurred_at: string;
|
|
2482
|
+
}
|
|
2483
|
+
/** A Hooks endpoint of one of your applications was disabled. `id` equals the `webhook-id` header. */
|
|
2484
|
+
interface HookEndpointWebhookEvent {
|
|
2485
|
+
id: string;
|
|
2486
|
+
object: "event";
|
|
2487
|
+
type: HookOperationalEventType;
|
|
2488
|
+
/** The API version this event is rendered in: the receiving endpoint's `api_version`. */
|
|
2489
|
+
api_version: string;
|
|
2490
|
+
/** ISO 8601 timestamp. */
|
|
2491
|
+
created_at: string;
|
|
2492
|
+
data: HookEndpointWebhookEventData;
|
|
2493
|
+
}
|
|
2494
|
+
/** The JSON body of a webhook request; narrow on `type`. */
|
|
2495
|
+
type WebhookEvent = EmailWebhookEvent | ReceivedEmailWebhookEvent | AccountWebhookEvent | BillingWebhookEvent | RiskWebhookEvent | HookEndpointWebhookEvent;
|
|
2496
|
+
//#endregion
|
|
2497
|
+
//#region src/types/webhook-endpoint.d.ts
|
|
2498
|
+
/** Every event type an endpoint can subscribe to. */
|
|
2499
|
+
type WebhookEventType = EmailEventType | ReceivedEmailEventType | AccountEventType | BillingEventType | RiskEventType | HookOperationalEventType;
|
|
2500
|
+
/** Why an endpoint is disabled. */
|
|
2501
|
+
type WebhookEndpointDisabledReason = "manual" | "failing";
|
|
2502
|
+
/** A URL of the API key's environment that receives signed event notifications. */
|
|
2503
|
+
interface WebhookEndpoint {
|
|
2504
|
+
object: "webhook_endpoint";
|
|
2505
|
+
id: string;
|
|
2506
|
+
url: string;
|
|
2507
|
+
description: string | null;
|
|
2508
|
+
/**
|
|
2509
|
+
* Event types delivered to this endpoint. An empty array means every event type, including
|
|
2510
|
+
* ones added later.
|
|
2511
|
+
*/
|
|
2512
|
+
event_types: string[];
|
|
2513
|
+
/** The API version events are rendered in for this endpoint (each event's `api_version`). */
|
|
2514
|
+
api_version: string;
|
|
2515
|
+
/** A disabled endpoint receives nothing until it is enabled again. */
|
|
2516
|
+
enabled: boolean;
|
|
2517
|
+
/**
|
|
2518
|
+
* `manual`: someone disabled it. `failing`: its deliveries failed every attempt for five days,
|
|
2519
|
+
* so COSS disabled it. `null` while enabled.
|
|
2520
|
+
*/
|
|
2521
|
+
disabled_reason: WebhookEndpointDisabledReason | null;
|
|
2522
|
+
/** When it was disabled (ISO 8601); `null` while enabled. */
|
|
2523
|
+
disabled_at: string | null;
|
|
2524
|
+
/**
|
|
2525
|
+
* When the endpoint's current run of failed deliveries began (ISO 8601); cleared by the next
|
|
2526
|
+
* successful delivery. An endpoint failing for five days is disabled. `null` while healthy.
|
|
2527
|
+
*/
|
|
2528
|
+
failing_since: string | null;
|
|
2529
|
+
/**
|
|
2530
|
+
* After a secret roll, deliveries are also signed with the previous secret until this time
|
|
2531
|
+
* (ISO 8601). `null` when only the current secret signs.
|
|
2532
|
+
*/
|
|
2533
|
+
previous_secret_expires_at: string | null;
|
|
2534
|
+
/** ISO 8601 timestamp. */
|
|
2535
|
+
created_at: string;
|
|
2536
|
+
updated_at: string;
|
|
2537
|
+
}
|
|
2538
|
+
/** A freshly created endpoint, or one whose secret was just rolled: the only responses with the signing secret. */
|
|
2539
|
+
interface WebhookEndpointWithSecret extends WebhookEndpoint {
|
|
2540
|
+
/**
|
|
2541
|
+
* The endpoint's `whsec_…` signing secret, for `verifyWebhook`. Returned only on creation and
|
|
2542
|
+
* on a roll — store it now; it cannot be read back through the API.
|
|
2543
|
+
*/
|
|
2544
|
+
secret: string;
|
|
2545
|
+
}
|
|
2546
|
+
/** Body of `POST /v1/webhook_endpoints`. */
|
|
2547
|
+
interface CreateWebhookEndpointParams {
|
|
2548
|
+
/** An `https://` URL COSS posts events to. */
|
|
2549
|
+
url: string;
|
|
2550
|
+
/** A note for your own reference. */
|
|
2551
|
+
description?: string | null;
|
|
2552
|
+
/** Defaults to every event type, including ones added later. */
|
|
2553
|
+
event_types?: WebhookEventType[];
|
|
2554
|
+
/**
|
|
2555
|
+
* The API version events are rendered in. Defaults to the client's `apiVersion`, so events match
|
|
2556
|
+
* this SDK's `WebhookEvent` types.
|
|
2557
|
+
*/
|
|
2558
|
+
api_version?: ApiVersion;
|
|
2559
|
+
}
|
|
2560
|
+
/** Body of `PATCH /v1/webhook_endpoints/{id}`. Omitted fields keep their current value. */
|
|
2561
|
+
interface UpdateWebhookEndpointParams {
|
|
2562
|
+
url?: string;
|
|
2563
|
+
/** `null` clears the description. */
|
|
2564
|
+
description?: string | null;
|
|
2565
|
+
event_types?: WebhookEventType[];
|
|
2566
|
+
api_version?: ApiVersion;
|
|
2567
|
+
enabled?: boolean;
|
|
2568
|
+
}
|
|
2569
|
+
/** Body of `POST /v1/webhook_endpoints/{id}/roll_secret`. */
|
|
2570
|
+
interface RollWebhookEndpointSecretParams {
|
|
2571
|
+
/**
|
|
2572
|
+
* Seconds the current secret keeps signing deliveries next to the new one, so receivers can
|
|
2573
|
+
* switch without rejecting anything. Default 86400 (a day), at most 604800 (a week). `0` stops
|
|
2574
|
+
* it immediately, e.g. after a leak.
|
|
2575
|
+
*/
|
|
2576
|
+
previous_secret_expires_in?: number;
|
|
2577
|
+
}
|
|
2578
|
+
/** Body of `POST /v1/webhook_endpoints/{id}/recover`. */
|
|
2579
|
+
interface RecoverWebhookEndpointParams {
|
|
2580
|
+
/**
|
|
2581
|
+
* Requeue the deliveries that failed and were created at or after this time (ISO 8601 string or
|
|
2582
|
+
* `Date`). Deliveries are kept for 30 days.
|
|
2583
|
+
*/
|
|
2584
|
+
since: string | Date;
|
|
2585
|
+
}
|
|
2586
|
+
/** Returned by `webhookEndpoints.recover`. */
|
|
2587
|
+
interface WebhookEndpointRecovery {
|
|
2588
|
+
object: "webhook_endpoint_recovery";
|
|
2589
|
+
endpoint_id: string;
|
|
2590
|
+
/** How many failed deliveries were queued for one more attempt (spread over the next minute). */
|
|
2591
|
+
requeued: number;
|
|
2592
|
+
/** At most 1,000 are requeued per call; `true` means call again with the same `since`. */
|
|
2593
|
+
has_more: boolean;
|
|
2594
|
+
}
|
|
2595
|
+
/** Returned by `webhookEndpoints.delete`. */
|
|
2596
|
+
interface DeletedWebhookEndpoint {
|
|
2597
|
+
object: "webhook_endpoint";
|
|
2598
|
+
id: string;
|
|
2599
|
+
deleted: true;
|
|
2600
|
+
}
|
|
2601
|
+
/**
|
|
2602
|
+
* `pending`: waiting for its next attempt. `succeeded`: the endpoint answered with a 2xx status.
|
|
2603
|
+
* `failed`: every attempt failed, or the endpoint was disabled.
|
|
2604
|
+
*/
|
|
2605
|
+
type WebhookDeliveryStatus = "pending" | "succeeded" | "failed";
|
|
2606
|
+
/** One HTTP request of a delivery. */
|
|
2607
|
+
interface WebhookAttempt {
|
|
2608
|
+
object: "webhook_attempt";
|
|
2609
|
+
id: string;
|
|
2610
|
+
/** ISO 8601 timestamp. */
|
|
2611
|
+
attempted_at: string;
|
|
2612
|
+
/** The endpoint's HTTP status; `null` when no response arrived. */
|
|
2613
|
+
status_code: number | null;
|
|
2614
|
+
duration_ms: number;
|
|
2615
|
+
/** Why the attempt failed (e.g. `HTTP 500`, a timeout); `null` on success. */
|
|
2616
|
+
error: string | null;
|
|
2617
|
+
/** At most 1 KB of the response body, as text. */
|
|
2618
|
+
response_excerpt: string | null;
|
|
2619
|
+
}
|
|
2620
|
+
/** One event sent to one endpoint, retried with backoff until it succeeds or gives up. */
|
|
2621
|
+
interface WebhookDelivery {
|
|
2622
|
+
object: "webhook_delivery";
|
|
2623
|
+
id: string;
|
|
2624
|
+
endpoint_id: string;
|
|
2625
|
+
/** The event's id: the `id` of the payload and the `webhook-id` header. */
|
|
2626
|
+
event_id: string;
|
|
2627
|
+
event_type: string;
|
|
2628
|
+
status: WebhookDeliveryStatus;
|
|
2629
|
+
attempt_count: number;
|
|
2630
|
+
/** When the next attempt is due; `null` once the delivery is finished. */
|
|
2631
|
+
next_attempt_at: string | null;
|
|
2632
|
+
last_status_code: number | null;
|
|
2633
|
+
last_error: string | null;
|
|
2634
|
+
/** The event body, exactly as posted to the endpoint (a `WebhookEvent`). */
|
|
2635
|
+
payload: Record<string, unknown>;
|
|
2636
|
+
/** Every HTTP attempt of this delivery, oldest first. */
|
|
2637
|
+
attempts: WebhookAttempt[];
|
|
2638
|
+
created_at: string;
|
|
2639
|
+
updated_at: string;
|
|
2640
|
+
}
|
|
2641
|
+
/** Query of `GET /v1/webhook_endpoints/{id}/deliveries`. */
|
|
2642
|
+
interface ListWebhookDeliveriesParams {
|
|
2643
|
+
/** Only deliveries with this status. */
|
|
2644
|
+
status?: WebhookDeliveryStatus;
|
|
2645
|
+
/** Only the delivery of this event. */
|
|
2646
|
+
event_id?: string;
|
|
2647
|
+
/** 1-100, default 50. */
|
|
2648
|
+
limit?: number;
|
|
2649
|
+
/** Cursor: the `id` of the last delivery of the previous page. */
|
|
2650
|
+
after?: string;
|
|
2651
|
+
}
|
|
2652
|
+
//#endregion
|
|
2653
|
+
//#region src/resources/webhook-deliveries.d.ts
|
|
2654
|
+
type ReadOptions$1 = Pick<RequestOptions, "signal">;
|
|
2655
|
+
/**
|
|
2656
|
+
* `coss.webhookEndpoints.deliveries`: an endpoint's delivery log. Each delivery carries every
|
|
2657
|
+
* HTTP attempt and the payload as sent.
|
|
2658
|
+
*/
|
|
2659
|
+
declare class WebhookDeliveriesResource {
|
|
2660
|
+
#private;
|
|
2661
|
+
/** @internal Use `new Coss().webhookEndpoints.deliveries`. */
|
|
2662
|
+
constructor(http: HttpClient);
|
|
2663
|
+
/** Lists the endpoint's deliveries, newest first. Pass the last `id` as `after` while `has_more` is true. */
|
|
2664
|
+
list(endpointId: string, params?: ListWebhookDeliveriesParams, options?: ReadOptions$1): Promise<CossResult<List<WebhookDelivery>>>;
|
|
2665
|
+
/** Retrieves one delivery of the endpoint. */
|
|
2666
|
+
get(endpointId: string, id: string, options?: ReadOptions$1): Promise<CossResult<WebhookDelivery>>;
|
|
2667
|
+
/**
|
|
2668
|
+
* Queues a finished delivery for one more attempt, made within seconds. A delivery that is
|
|
2669
|
+
* still `pending` is returned unchanged (it is already scheduled for `next_attempt_at`).
|
|
2670
|
+
* Never automatically retried: the API does not deduplicate replay requests, even with an
|
|
2671
|
+
* idempotency key.
|
|
2672
|
+
*/
|
|
2673
|
+
retry(endpointId: string, id: string, options?: RequestOptions): Promise<CossResult<WebhookDelivery>>;
|
|
2674
|
+
}
|
|
2675
|
+
//#endregion
|
|
2676
|
+
//#region src/resources/webhook-endpoints.d.ts
|
|
2677
|
+
type ReadOptions = Pick<RequestOptions, "signal">;
|
|
2678
|
+
/**
|
|
2679
|
+
* `coss.webhookEndpoints`: the URLs that receive signed event notifications. Endpoints belong to
|
|
2680
|
+
* the API key's own environment, so a `coss_test_…` key only ever manages sandbox endpoints.
|
|
2681
|
+
*/
|
|
2682
|
+
declare class WebhookEndpointsResource {
|
|
2683
|
+
#private;
|
|
2684
|
+
/** Each endpoint's delivery log: list, retrieve and retry deliveries. */
|
|
2685
|
+
readonly deliveries: WebhookDeliveriesResource;
|
|
2686
|
+
/** @internal Use `new Coss().webhookEndpoints`. */
|
|
2687
|
+
constructor(http: HttpClient);
|
|
2688
|
+
/**
|
|
2689
|
+
* Creates an endpoint. The result carries its `secret` (returned again only by `rollSecret`) —
|
|
2690
|
+
* store it and pass it to `verifyWebhook` for every delivery. Creation is never automatically retried:
|
|
2691
|
+
* the API does not deduplicate it, even with an idempotency key. After a lost response,
|
|
2692
|
+
* list endpoints and remove the endpoint with the unknown secret before creating a replacement.
|
|
2693
|
+
*/
|
|
2694
|
+
create(params: CreateWebhookEndpointParams, options?: RequestOptions): Promise<CossResult<WebhookEndpointWithSecret>>;
|
|
2695
|
+
/** Lists the environment's endpoints, oldest first. Secrets are never included. */
|
|
2696
|
+
list(options?: ReadOptions): Promise<CossResult<List<WebhookEndpoint>>>;
|
|
2697
|
+
/** Retrieves an endpoint of the API key's environment. */
|
|
2698
|
+
get(id: string, options?: ReadOptions): Promise<CossResult<WebhookEndpoint>>;
|
|
2699
|
+
/**
|
|
2700
|
+
* Changes the URL, description, subscribed event types or `enabled` flag. The signing secret
|
|
2701
|
+
* stays the same (see `rollSecret`), so receivers keep verifying deliveries.
|
|
2702
|
+
*/
|
|
2703
|
+
update(id: string, params: UpdateWebhookEndpointParams, options?: ReadOptions): Promise<CossResult<WebhookEndpoint>>;
|
|
2704
|
+
/**
|
|
2705
|
+
* Replaces the endpoint's signing secret; the result carries the new `secret`. Until
|
|
2706
|
+
* `previous_secret_expires_at` (a day by default), deliveries are signed with both secrets, so
|
|
2707
|
+
* `verifyWebhook` accepts them with either: deploy the new one, then let the old one expire.
|
|
2708
|
+
* Never automatically retried (a second roll would stop the original secret at once): after a
|
|
2709
|
+
* lost response, roll again and deploy that secret.
|
|
2710
|
+
*/
|
|
2711
|
+
rollSecret(id: string, params?: RollWebhookEndpointSecretParams, options?: RequestOptions): Promise<CossResult<WebhookEndpointWithSecret>>;
|
|
2712
|
+
/**
|
|
2713
|
+
* Queues the endpoint's deliveries that failed since `since` for one more attempt each (at most
|
|
2714
|
+
* 1,000 per call; while `has_more` is true, call again with the same `since`), e.g. after fixing a
|
|
2715
|
+
* receiver that was down. The endpoint must be enabled.
|
|
2716
|
+
*/
|
|
2717
|
+
recover(id: string, params: RecoverWebhookEndpointParams, options?: RequestOptions): Promise<CossResult<WebhookEndpointRecovery>>;
|
|
2718
|
+
/** Deletes the endpoint and its delivery log. To pause it instead, update `enabled` to false. */
|
|
2719
|
+
delete(id: string, options?: ReadOptions): Promise<CossResult<DeletedWebhookEndpoint>>;
|
|
2720
|
+
}
|
|
2721
|
+
//#endregion
|
|
2722
|
+
//#region src/client.d.ts
|
|
2723
|
+
interface CossOptions {
|
|
2724
|
+
/** Secret API key (`coss_live_…` or `coss_test_…`). Defaults to the `COSS_API_KEY` env variable. */
|
|
2725
|
+
apiKey?: string;
|
|
2726
|
+
/** Defaults to the `COSS_BASE_URL` env variable, then `https://api.coss.com`. */
|
|
2727
|
+
baseUrl?: string;
|
|
2728
|
+
/** Custom `fetch` implementation. Defaults to the global `fetch`. */
|
|
2729
|
+
fetch?: FetchLike;
|
|
2730
|
+
/** Per-attempt timeout in milliseconds. Default `30000`. */
|
|
2731
|
+
timeout?: number;
|
|
2732
|
+
/** Retries for connection errors, timeouts, 409, 429 and 5xx. Default `2`; excludes webhook creation. */
|
|
2733
|
+
maxRetries?: number;
|
|
2734
|
+
/**
|
|
2735
|
+
* The API version (`Coss-Version`) to request. Defaults to `API_VERSION`, the version this SDK's
|
|
2736
|
+
* types describe; requests never fall back to your organization's pinned version.
|
|
2737
|
+
*/
|
|
2738
|
+
apiVersion?: ApiVersion;
|
|
2739
|
+
/**
|
|
2740
|
+
* Allow use where a `document` global exists. Off by default because shipping a secret API key
|
|
2741
|
+
* to a browser exposes it to anyone who opens the page.
|
|
2742
|
+
*/
|
|
2743
|
+
dangerouslyAllowBrowser?: boolean;
|
|
2744
|
+
}
|
|
2745
|
+
/**
|
|
2746
|
+
* The COSS client. One API key covers every product.
|
|
2747
|
+
*
|
|
2748
|
+
* ```ts
|
|
2749
|
+
* const coss = new Coss({ apiKey: "coss_test_…" });
|
|
2750
|
+
* const { data, error } = await coss.email.send({ from, to, subject, html });
|
|
2751
|
+
* ```
|
|
2752
|
+
*/
|
|
2753
|
+
export declare class Coss {
|
|
2754
|
+
readonly email: EmailResource;
|
|
2755
|
+
/** Sending domains of the organization (`coss.domains.create`, `.verify`, …). */
|
|
2756
|
+
readonly domains: DomainsResource;
|
|
2757
|
+
/** Webhook endpoints of the API key's environment. */
|
|
2758
|
+
readonly webhookEndpoints: WebhookEndpointsResource;
|
|
2759
|
+
/** The organization's sending reputation (`coss.reputation.get()`). */
|
|
2760
|
+
readonly reputation: ReputationResource;
|
|
2761
|
+
/** The environment's log: API requests, email events, webhook attempts (`coss.logs.list()`). */
|
|
2762
|
+
readonly logs: LogsResource;
|
|
2763
|
+
/** HTTPS endpoints the environment's log is streamed to (`coss.logDrains.create()`). */
|
|
2764
|
+
readonly logDrains: LogDrainsResource;
|
|
2765
|
+
/** The organization's audit log: changes by members, API keys and COSS support (`coss.auditEvents.list()`). */
|
|
2766
|
+
readonly auditEvents: AuditEventsResource;
|
|
2767
|
+
/** Hooks, webhooks as a service: `coss.hooks.messages.send()` delivers to your users' endpoints. */
|
|
2768
|
+
readonly hooks: HooksResource;
|
|
2769
|
+
/** Risk assessments of sign-ups, logins and other events (`coss.risk.assess()`). */
|
|
2770
|
+
readonly risk: RiskResource;
|
|
2771
|
+
/** The organization's plan, usage, invoices and credits (`coss.billing.get()`). */
|
|
2772
|
+
readonly billing: BillingResource;
|
|
2773
|
+
/**
|
|
2774
|
+
* Throws only for programmer errors: no API key, or running in a browser without
|
|
2775
|
+
* `dangerouslyAllowBrowser`. Request failures are returned as `{ data: null, error }`.
|
|
2776
|
+
*/
|
|
2777
|
+
constructor(options?: CossOptions);
|
|
2778
|
+
}
|
|
2779
|
+
//#endregion
|
|
2780
|
+
//#region src/version.d.ts
|
|
2781
|
+
/** SDK version, sent in the User-Agent. A test keeps it equal to package.json's `version`. */
|
|
2782
|
+
export declare const VERSION = "0.2.0";
|
|
2783
|
+
//#endregion
|
|
2784
|
+
//#region src/webhooks.d.ts
|
|
2785
|
+
/** A webhook request failed verification: reject it (e.g. respond 400). */
|
|
2786
|
+
export declare class WebhookVerificationError extends Error {
|
|
2787
|
+
constructor(message: string);
|
|
2788
|
+
}
|
|
2789
|
+
/** Request headers as a `Headers` object or a plain (Node-style) record. */
|
|
2790
|
+
type WebhookHeaders = Headers | Record<string, string | string[] | undefined>;
|
|
2791
|
+
interface VerifyWebhookOptions {
|
|
2792
|
+
/** Maximum age (and clock skew) of the `webhook-timestamp`, in seconds. Default 300. */
|
|
2793
|
+
toleranceSeconds?: number;
|
|
2794
|
+
/** The current time; for tests. */
|
|
2795
|
+
now?: Date;
|
|
2796
|
+
}
|
|
2797
|
+
/**
|
|
2798
|
+
* Checks the request's signature and age, then returns the parsed event. Pass the raw request
|
|
2799
|
+
* body exactly as received (not re-serialized JSON) and the endpoint's `whsec_…` signing secret.
|
|
2800
|
+
* Throws `WebhookVerificationError` when the request must be rejected.
|
|
2801
|
+
*
|
|
2802
|
+
* ```ts
|
|
2803
|
+
* const event = await verifyWebhook(await request.text(), request.headers, process.env.COSS_WEBHOOK_SECRET);
|
|
2804
|
+
* ```
|
|
2805
|
+
*
|
|
2806
|
+
* The same check verifies messages your own users receive from COSS Hooks (`coss.hooks`): pass
|
|
2807
|
+
* the endpoint's secret and name your payload type, e.g. `verifyWebhook<InvoicePaid>(…)`.
|
|
2808
|
+
*/
|
|
2809
|
+
export declare function verifyWebhook<T = WebhookEvent>(payload: string, headers: WebhookHeaders, secret: string, options?: VerifyWebhookOptions): Promise<T>;
|
|
2810
|
+
/**
|
|
2811
|
+
* Checks a log drain request's signature and age, then returns its lines (NDJSON: one log line or
|
|
2812
|
+
* audit event per line). Pass the raw request body exactly as received and the drain's `whsec_…`
|
|
2813
|
+
* signing secret. The `webhook-id` header is the batch id, the same on every retry of a batch:
|
|
2814
|
+
* use it (or each line's `id`) to skip a batch you already stored. Throws
|
|
2815
|
+
* `WebhookVerificationError` when the request must be rejected.
|
|
2816
|
+
*
|
|
2817
|
+
* ```ts
|
|
2818
|
+
* const lines = await verifyLogDrainBatch(await request.text(), request.headers, process.env.COSS_LOG_DRAIN_SECRET);
|
|
2819
|
+
* ```
|
|
2820
|
+
*/
|
|
2821
|
+
export declare function verifyLogDrainBatch(payload: string, headers: WebhookHeaders, secret: string, options?: VerifyWebhookOptions): Promise<LogDrainLine[]>;
|
|
2822
|
+
//#endregion
|
|
2823
|
+
export type { AccountEventType, AccountWebhookEvent, AccountWebhookEventData, ApiVersion, AssessRiskParams, AuditActorType, AuditEvent, AuditEventsResource, Billing, BillingCreditsResource, BillingEventType, BillingHoldReason, BillingInvoicesResource, BillingResource, BillingWebhookEvent, CheckSuppressionParams, CossError, CossErrorIssue, CossErrorType, CossOptions, CossResult, CreateDomainParams, CreateHookApplicationParams, CreateHookEndpointParams, CreateHookEventTypeParams, CreateHookPortalSessionParams, CreateLogDrainParams, CreateReceivingDomainParams, CreateRiskListEntryParams, CreateRiskRuleParams, CreateSuppressionParams, CreateTrackingDomainParams, CreateWebhookEndpointParams, Credit, DeletedDomain, DeletedHookApplication, DeletedHookEndpoint, DeletedLogDrain, DeletedReceivedEmail, DeletedRiskListEntry, DeletedRiskRule, DeletedSuppression, DeletedTrackingRule, DeletedWebhookEndpoint, Domain, DomainRecord, DomainRecordPurpose, DomainRecordStatus, DomainStatus, DomainsResource, Email, EmailAttachment, EmailAttachmentParams, EmailBatch, EmailEvent, EmailEventData, EmailEventType, EmailLink, EmailRecipient, EmailRecipientStatus, EmailResource, EmailStatus, EmailTag, EmailTracking, EmailWebhookEvent, EmailWebhookEventData, ExportSuppressionsParams, FetchLike, ForgottenRiskUser, HookApplication, HookApplicationsResource, HookAttempt, HookDeliveriesResource, HookDelivery, HookDeliveryStatus, HookEndpoint, HookEndpointDisabledReason, HookEndpointRecovery, HookEndpointSecret, HookEndpointWebhookEvent, HookEndpointWebhookEventData, HookEndpointWithSecret, HookEndpointsResource, HookEventType, HookEventTypesResource, HookMessage, HookMessagesResource, HookOperationalEventType, HookPortalResource, HookPortalSession, HooksResource, ImportSuppressionEntry, ImportSuppressionsParams, InboundAddress, Invoice, InvoiceLine, InvoiceLineKind, InvoiceStatus, InvoiceSummary, List, ListAuditEventsParams, ListCreditsParams, ListHookApplicationsParams, ListHookDeliveriesParams, ListHookEventTypesParams, ListHookMessagesParams, ListInvoicesParams, ListLogDrainBatchesParams, ListLogsParams, ListReceivedEmailsParams, ListRiskAssessmentsParams, ListRiskListEntriesParams, ListSuppressionsParams, ListUsageParams, ListWebhookDeliveriesParams, Log, LogDrain, LogDrainAttempt, LogDrainBatch, LogDrainBatchStatus, LogDrainBatchesResource, LogDrainLine, LogDrainSource, LogDrainWithSecret, LogDrainsResource, LogLevel, LogSource, LogsResource, MailFromStatus, Meter, PlanKey, ReceivedEmail, ReceivedEmailAttachment, ReceivedEmailEventType, ReceivedEmailStatus, ReceivedEmailSummary, ReceivedEmailVerdicts, ReceivedEmailWebhookEvent, ReceivedEmailWebhookEventData, ReceivedEmailsResource, ReceivingDomain, ReceivingDomainRecord, ReceivingDomainsResource, RecoverHookEndpointParams, RecoverWebhookEndpointParams, Reputation, ReputationCheck, ReputationCheckSeverity, ReputationResource, ReputationStatus, RequestOptions, RescheduleEmailParams, RiskAssessment, RiskAssessmentsResource, RiskCaptchaProvider, RiskCaptchaSignals, RiskDecision, RiskDegradedSignal, RiskEmailSignals, RiskEvent, RiskEventType, RiskFeedbackParams, RiskIpSignals, RiskList, RiskListEntry, RiskListEntryType, RiskListEntryValue, RiskListsResource, RiskLoginSignals, RiskOutcome, RiskReason, RiskReasonCode, RiskResource, RiskRule, RiskRuleCondition, RiskRuleField, RiskRulesResource, RiskSettings, RiskSettingsResource, RiskUsersResource, RiskWebhookEvent, RiskWebhookEventData, RollHookEndpointSecretParams, RollWebhookEndpointSecretParams, SendEmailParams, SendHookMessageParams, SendHookTestParams, Suppression, SuppressionCheck, SuppressionImport, SuppressionReason, SuppressionResource, TrackingDomain, TrackingDomainRecord, TrackingDomainStatus, TrackingDomainsResource, TrackingOptions, TrackingResource, TrackingRule, TrackingSettings, UpdateHookApplicationParams, UpdateHookEndpointParams, UpdateHookEventTypeParams, UpdateLogDrainParams, UpdateRiskRuleParams, UpdateRiskSettingsParams, UpdateTrackingRuleParams, UpdateWebhookEndpointParams, Usage, VerdictStatus, VerifyWebhookOptions, WebhookAttempt, WebhookDeliveriesResource, WebhookDelivery, WebhookDeliveryStatus, WebhookEndpoint, WebhookEndpointDisabledReason, WebhookEndpointRecovery, WebhookEndpointWithSecret, WebhookEndpointsResource, WebhookEvent, WebhookEventType, WebhookHeaders };
|