@pidgeon-ai/sdk 0.1.0 → 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/CHANGELOG.md +51 -0
- package/dist/index.cjs +250 -5
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +495 -8
- package/dist/index.d.ts +495 -8
- package/dist/index.js +250 -5
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.cts
CHANGED
|
@@ -72,10 +72,79 @@ interface Thread {
|
|
|
72
72
|
subject: string | null;
|
|
73
73
|
status: 'open' | 'waiting' | 'resolved' | 'human_review';
|
|
74
74
|
owner_type: 'human' | 'automation' | 'agent';
|
|
75
|
+
/**
|
|
76
|
+
* Which person is answering. Null is the unassigned queue.
|
|
77
|
+
*
|
|
78
|
+
* It composes with `owner_type` rather than replacing it: that says which
|
|
79
|
+
* *kind* of thing is answering, and this says which human. A thread with
|
|
80
|
+
* `status: 'human_review'` and no assignee is a handover nobody has taken.
|
|
81
|
+
*/
|
|
82
|
+
assignee_id: string | null;
|
|
83
|
+
assigned_at: string | null;
|
|
75
84
|
message_count: number;
|
|
76
85
|
last_message_at: string | null;
|
|
77
86
|
created_at: string;
|
|
78
87
|
}
|
|
88
|
+
/**
|
|
89
|
+
* A person in the workspace, for assigning conversations to.
|
|
90
|
+
*
|
|
91
|
+
* No avatar: it is a pointer at an image on somebody else's host, and an
|
|
92
|
+
* integration has no use for one.
|
|
93
|
+
*/
|
|
94
|
+
/**
|
|
95
|
+
* One folder of a mailbox, and what is in it.
|
|
96
|
+
*
|
|
97
|
+
* Null rather than zero where the product does not count that folder — zero
|
|
98
|
+
* would be a claim, and the counts query answers what a sidebar needs rather
|
|
99
|
+
* than everything that could be counted.
|
|
100
|
+
*/
|
|
101
|
+
interface Mailbox {
|
|
102
|
+
folder: 'inbox' | 'starred' | 'sent' | 'drafts' | 'scheduled' | 'snoozed' | 'archive' | 'spam' | 'trash';
|
|
103
|
+
total: number | null;
|
|
104
|
+
unread: number | null;
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* A conversation in a folder listing — the newest message in each thread.
|
|
108
|
+
*
|
|
109
|
+
* Deliberately not a `Message`: it has no body, because a list of forty
|
|
110
|
+
* conversations does not want forty bodies. `GET /messages?thread_id=` opens
|
|
111
|
+
* one.
|
|
112
|
+
*/
|
|
113
|
+
interface MessageListItem {
|
|
114
|
+
id: string;
|
|
115
|
+
thread_id: string;
|
|
116
|
+
direction: string;
|
|
117
|
+
/** Who the row is about: the sender in inbox, the recipient in sent. */
|
|
118
|
+
from: string;
|
|
119
|
+
from_name: string;
|
|
120
|
+
subject: string | null;
|
|
121
|
+
preview: string | null;
|
|
122
|
+
is_read: boolean;
|
|
123
|
+
is_starred: boolean;
|
|
124
|
+
is_draft: boolean;
|
|
125
|
+
is_spam: boolean;
|
|
126
|
+
has_attachments: boolean;
|
|
127
|
+
attachment_count: number;
|
|
128
|
+
message_count: number;
|
|
129
|
+
assignee_id: string | null;
|
|
130
|
+
timestamp: string;
|
|
131
|
+
}
|
|
132
|
+
/** Every state change the API can apply to a conversation. */
|
|
133
|
+
type MessageActionName = 'read' | 'unread' | 'star' | 'unstar' | 'archive' | 'unarchive' | 'delete' | 'restore' | 'spam' | 'not_spam' | 'delete_forever';
|
|
134
|
+
/** A file uploaded ahead of a send. Expires in a day if never used. */
|
|
135
|
+
interface UploadedAttachment {
|
|
136
|
+
id: string;
|
|
137
|
+
filename: string;
|
|
138
|
+
content_type: string;
|
|
139
|
+
size: number;
|
|
140
|
+
}
|
|
141
|
+
interface Member {
|
|
142
|
+
id: string;
|
|
143
|
+
email: string;
|
|
144
|
+
name: string | null;
|
|
145
|
+
role: 'owner' | 'member';
|
|
146
|
+
joined_at: string;
|
|
147
|
+
}
|
|
79
148
|
interface Webhook {
|
|
80
149
|
id: string;
|
|
81
150
|
url: string;
|
|
@@ -97,18 +166,113 @@ interface Event {
|
|
|
97
166
|
data: Record<string, unknown>;
|
|
98
167
|
created_at: string;
|
|
99
168
|
}
|
|
169
|
+
/**
|
|
170
|
+
* Where mail to an address goes.
|
|
171
|
+
*
|
|
172
|
+
* An address resolves in one of three ways and the first match wins: it *is*
|
|
173
|
+
* an address of its own, a rule points it somewhere, or the domain's
|
|
174
|
+
* catch-all takes it. So a rule never overrides a real address — creating one
|
|
175
|
+
* for an address that already exists is refused rather than silently ignored.
|
|
176
|
+
*/
|
|
100
177
|
interface RoutingRule {
|
|
101
178
|
id: string;
|
|
102
|
-
/** The address or
|
|
179
|
+
/** The address this rule matches, or `*@domain` for the catch-all. */
|
|
103
180
|
match: string;
|
|
104
|
-
/** `
|
|
105
|
-
match_type:
|
|
181
|
+
/** `address` for one address, `catch_all` for the domain's fallback. */
|
|
182
|
+
match_type: 'address' | 'catch_all';
|
|
106
183
|
/** `identity` for an inbox, `webhook` for a URL. */
|
|
107
|
-
destination_type:
|
|
184
|
+
destination_type: 'identity' | 'webhook';
|
|
185
|
+
/** The address or the endpoint URL — what to show somebody. */
|
|
108
186
|
destination: string;
|
|
109
|
-
|
|
187
|
+
/** The id of that address or endpoint — what to pass back. */
|
|
188
|
+
destination_id: string | null;
|
|
189
|
+
/** `disabled` keeps the rule and stops it firing. */
|
|
190
|
+
status: 'active' | 'disabled';
|
|
110
191
|
domain: string;
|
|
192
|
+
domain_id: string;
|
|
193
|
+
created_at: string;
|
|
194
|
+
}
|
|
195
|
+
/**
|
|
196
|
+
* One attempt to hand an event to one endpoint.
|
|
197
|
+
*
|
|
198
|
+
* `status` is ours: `pending` is queued, `sending` is in flight, `delivered`
|
|
199
|
+
* succeeded, `failed` is still being retried and `dead` has stopped being.
|
|
200
|
+
* `response_status` is your server's answer, where there was one — a network
|
|
201
|
+
* failure leaves it null and puts the reason in `error`.
|
|
202
|
+
*/
|
|
203
|
+
interface Delivery {
|
|
204
|
+
id: string;
|
|
205
|
+
event_id: string;
|
|
206
|
+
event_type: string;
|
|
207
|
+
status: string;
|
|
208
|
+
attempts: number;
|
|
209
|
+
/** The HTTP status your endpoint answered with, or null if it did not. */
|
|
210
|
+
response_status: number | null;
|
|
211
|
+
error: string | null;
|
|
111
212
|
created_at: string;
|
|
213
|
+
delivered_at: string | null;
|
|
214
|
+
}
|
|
215
|
+
/**
|
|
216
|
+
* A key, as a record. Never the secret — that is returned once, on create.
|
|
217
|
+
*
|
|
218
|
+
* `identity_ids` is the key's scope: the addresses it reaches, and the
|
|
219
|
+
* ceiling on what a key it mints may reach.
|
|
220
|
+
*/
|
|
221
|
+
interface ApiKey {
|
|
222
|
+
id: string;
|
|
223
|
+
name: string;
|
|
224
|
+
/** Enough to recognise it in a list. Not enough to use. */
|
|
225
|
+
prefix: string;
|
|
226
|
+
identity_ids: string[];
|
|
227
|
+
/** The key that minted this one, where a key did. */
|
|
228
|
+
created_by_key_id: string | null;
|
|
229
|
+
last_used_at: string | null;
|
|
230
|
+
revoked_at: string | null;
|
|
231
|
+
created_at: string;
|
|
232
|
+
}
|
|
233
|
+
/**
|
|
234
|
+
* A credential for one mailbox, over IMAP and SMTP.
|
|
235
|
+
*
|
|
236
|
+
* The secret comes back once, on create, as `password` — grouped for typing
|
|
237
|
+
* into a mail client — beside the `username` it must be paired with. A
|
|
238
|
+
* password presented for the wrong address is a failed login.
|
|
239
|
+
*/
|
|
240
|
+
interface AppPassword {
|
|
241
|
+
id: string;
|
|
242
|
+
name: string;
|
|
243
|
+
prefix: string;
|
|
244
|
+
last_used_at: string | null;
|
|
245
|
+
revoked_at: string | null;
|
|
246
|
+
created_at: string;
|
|
247
|
+
}
|
|
248
|
+
/**
|
|
249
|
+
* One DNS record a domain needs, and whether it is published yet.
|
|
250
|
+
*
|
|
251
|
+
* `status` is `connected` when it is right, `waiting` when nothing is there,
|
|
252
|
+
* `incorrect` when something else is, and `not_required` for a record this
|
|
253
|
+
* provider does not need. `found` is what we actually read — a record with
|
|
254
|
+
* the right name and the wrong value looks identical to a missing one until
|
|
255
|
+
* you can see it.
|
|
256
|
+
*/
|
|
257
|
+
interface DnsRecord {
|
|
258
|
+
/** `ownership`, `mx`, `spf`, `dkim` or `dmarc`. */
|
|
259
|
+
type: string;
|
|
260
|
+
/** `TXT`, `MX` or `CNAME`. */
|
|
261
|
+
record_type: string;
|
|
262
|
+
name: string;
|
|
263
|
+
value: string;
|
|
264
|
+
priority: number | null;
|
|
265
|
+
status: 'connected' | 'waiting' | 'incorrect' | 'not_required';
|
|
266
|
+
found: string | null;
|
|
267
|
+
/** One sentence, written for the person who has to publish it. */
|
|
268
|
+
description: string;
|
|
269
|
+
checked_at: string | null;
|
|
270
|
+
}
|
|
271
|
+
interface Workspace {
|
|
272
|
+
id: string;
|
|
273
|
+
name: string;
|
|
274
|
+
plan: string;
|
|
275
|
+
status: string;
|
|
112
276
|
}
|
|
113
277
|
interface Domain {
|
|
114
278
|
id: string;
|
|
@@ -130,7 +294,34 @@ interface Page<T> {
|
|
|
130
294
|
data: T[];
|
|
131
295
|
has_more: boolean;
|
|
132
296
|
next_cursor: string | null;
|
|
297
|
+
/**
|
|
298
|
+
* Where a delta should start, on the listings that support one.
|
|
299
|
+
*
|
|
300
|
+
* Keep it when you finish the initial load and hand it to
|
|
301
|
+
* `mailboxes.changes`. It is taken before the rows are read, so anything
|
|
302
|
+
* that changed while you were paging comes back in the first delta rather
|
|
303
|
+
* than falling into the gap.
|
|
304
|
+
*/
|
|
305
|
+
sync_cursor?: string;
|
|
133
306
|
}
|
|
307
|
+
/**
|
|
308
|
+
* One thing that happened to a mailbox since a cursor.
|
|
309
|
+
*
|
|
310
|
+
* A change carries the whole conversation, in the same shape a listing row
|
|
311
|
+
* has — so a client holds one type rather than two. A deletion carries the
|
|
312
|
+
* id and nothing else, because there is nothing else left: the message is
|
|
313
|
+
* gone, and a record of what it said would make "delete" mean "delete most
|
|
314
|
+
* of it".
|
|
315
|
+
*/
|
|
316
|
+
type MailboxChange = ({
|
|
317
|
+
deleted: false;
|
|
318
|
+
folder: Mailbox['folder'];
|
|
319
|
+
changed_at: string;
|
|
320
|
+
} & MessageListItem) | {
|
|
321
|
+
deleted: true;
|
|
322
|
+
id: string;
|
|
323
|
+
changed_at: string;
|
|
324
|
+
};
|
|
134
325
|
|
|
135
326
|
/**
|
|
136
327
|
* The Pidgeon client.
|
|
@@ -168,7 +359,21 @@ declare class Pidgeon {
|
|
|
168
359
|
#private;
|
|
169
360
|
constructor(options: PidgeonOptions);
|
|
170
361
|
identities: {
|
|
171
|
-
|
|
362
|
+
/**
|
|
363
|
+
* A page of addresses, alphabetically.
|
|
364
|
+
*
|
|
365
|
+
* `cursor` is the last address on the page before it, not a timestamp —
|
|
366
|
+
* this is the one list that is not ordered by time, because it is read
|
|
367
|
+
* by somebody looking for a particular address.
|
|
368
|
+
*
|
|
369
|
+
* It returned every address and no page before this, which made
|
|
370
|
+
* `const { data } = await pidgeon.identities.list()` — the line in our
|
|
371
|
+
* own quickstart — resolve to `undefined`.
|
|
372
|
+
*/
|
|
373
|
+
list: (options?: {
|
|
374
|
+
limit?: number;
|
|
375
|
+
cursor?: string;
|
|
376
|
+
}) => Promise<Page<Identity>>;
|
|
172
377
|
get: (id: string) => Promise<Identity>;
|
|
173
378
|
create: (input: {
|
|
174
379
|
domain_id: string;
|
|
@@ -192,6 +397,66 @@ declare class Pidgeon {
|
|
|
192
397
|
listInThread: (threadId: string, options?: {
|
|
193
398
|
limit?: number;
|
|
194
399
|
}) => Promise<Page<Message>>;
|
|
400
|
+
/**
|
|
401
|
+
* Change one conversation: read, starred, or which folder it is in.
|
|
402
|
+
*
|
|
403
|
+
* Returns an `undo` you can hand to `messages.undo`.
|
|
404
|
+
*/
|
|
405
|
+
update: (id: string, input: {
|
|
406
|
+
/**
|
|
407
|
+
* Readable, and **not writable with an API key**. Read state belongs
|
|
408
|
+
* to a person; setting it here is refused rather than silently
|
|
409
|
+
* dropped. Archive the conversation, or track what you have seen
|
|
410
|
+
* with `mailboxes.changes`.
|
|
411
|
+
*/
|
|
412
|
+
is_read?: boolean;
|
|
413
|
+
is_starred?: boolean;
|
|
414
|
+
folder?: "inbox" | "archive" | "spam" | "trash";
|
|
415
|
+
}) => Promise<{
|
|
416
|
+
id: string;
|
|
417
|
+
undo: unknown[];
|
|
418
|
+
}>;
|
|
419
|
+
/** One action, up to 200 conversations. */
|
|
420
|
+
act: (messageIds: string[], action: MessageActionName) => Promise<{
|
|
421
|
+
applied: number;
|
|
422
|
+
undo: unknown[];
|
|
423
|
+
}>;
|
|
424
|
+
/**
|
|
425
|
+
* Put an action back.
|
|
426
|
+
*
|
|
427
|
+
* Unusual for an API to have, and the argument is that software makes
|
|
428
|
+
* mistakes at a speed a person does not: an agent that archived the
|
|
429
|
+
* wrong forty conversations should be able to say so.
|
|
430
|
+
*/
|
|
431
|
+
undo: (undo: unknown[]) => Promise<{
|
|
432
|
+
restored: number;
|
|
433
|
+
}>;
|
|
434
|
+
/**
|
|
435
|
+
* Search one mailbox, narrowed.
|
|
436
|
+
*
|
|
437
|
+
* Full text in `q`, and six filters beside it. Everything is optional
|
|
438
|
+
* except having *something*: a filter with no words is a legitimate
|
|
439
|
+
* search — "everything unread from Marcus" is a question — and neither
|
|
440
|
+
* words nor filters is not.
|
|
441
|
+
*
|
|
442
|
+
* `in` is the only way to look in Trash, which a plain search skips on
|
|
443
|
+
* purpose. Results say which folder each hit is in.
|
|
444
|
+
*/
|
|
445
|
+
search: (identityId: string, options?: {
|
|
446
|
+
q?: string;
|
|
447
|
+
/** One folder. Omit for everywhere except Trash. */
|
|
448
|
+
in?: string;
|
|
449
|
+
/** Substring of the sender's address or display name. */
|
|
450
|
+
from?: string;
|
|
451
|
+
/** Substring of any recipient. */
|
|
452
|
+
to?: string;
|
|
453
|
+
has_attachment?: boolean;
|
|
454
|
+
is_unread?: boolean;
|
|
455
|
+
is_starred?: boolean;
|
|
456
|
+
limit?: number;
|
|
457
|
+
}) => Promise<Page<MessageListItem & {
|
|
458
|
+
folder: string;
|
|
459
|
+
}>>;
|
|
195
460
|
send: (input: {
|
|
196
461
|
from: string;
|
|
197
462
|
to: string | string[];
|
|
@@ -199,6 +464,10 @@ declare class Pidgeon {
|
|
|
199
464
|
bcc?: string | string[];
|
|
200
465
|
subject?: string;
|
|
201
466
|
text?: string;
|
|
467
|
+
/** An HTML body. `text` stays required — see the docs for why. */
|
|
468
|
+
html?: string;
|
|
469
|
+
/** Ids from `attachments.upload`. */
|
|
470
|
+
attachment_ids?: string[];
|
|
202
471
|
in_reply_to?: string | null;
|
|
203
472
|
}) => Promise<{
|
|
204
473
|
id: string;
|
|
@@ -214,11 +483,129 @@ declare class Pidgeon {
|
|
|
214
483
|
id: string;
|
|
215
484
|
url: string;
|
|
216
485
|
}>;
|
|
486
|
+
/**
|
|
487
|
+
* Upload a file, then name its id in `messages.send`.
|
|
488
|
+
*
|
|
489
|
+
* An upload expires in a day: it is a file no message refers to yet, so
|
|
490
|
+
* the window is long enough for a retry and short enough that a crashed
|
|
491
|
+
* client does not leave its files with us.
|
|
492
|
+
*/
|
|
493
|
+
upload: (identityId: string, file: File | Blob, filename?: string) => Promise<UploadedAttachment>;
|
|
494
|
+
};
|
|
495
|
+
mailboxes: {
|
|
496
|
+
/** The folders of one address, with their counts. */
|
|
497
|
+
list: (identityId: string) => Promise<Page<Mailbox>>;
|
|
498
|
+
/**
|
|
499
|
+
* One folder, a page at a time.
|
|
500
|
+
*
|
|
501
|
+
* `cursor` is the `next_cursor` of the page before it and is opaque —
|
|
502
|
+
* it carries the sort key and the id together, because several messages
|
|
503
|
+
* can share a millisecond. Do not construct one.
|
|
504
|
+
*/
|
|
505
|
+
list_folder: (folder: Mailbox["folder"], identityId: string, options?: {
|
|
506
|
+
limit?: number;
|
|
507
|
+
cursor?: string;
|
|
508
|
+
}) => Promise<Page<MessageListItem>>;
|
|
509
|
+
/**
|
|
510
|
+
* What changed since you last looked.
|
|
511
|
+
*
|
|
512
|
+
* Per mailbox, not per folder: a message moving from the inbox to the
|
|
513
|
+
* archive is one event, and the row says where it went. Arrivals are in
|
|
514
|
+
* it too, so this is the only thing you need to poll.
|
|
515
|
+
*
|
|
516
|
+
* `since` is the `sync_cursor` from a listing, or the `next_cursor` from
|
|
517
|
+
* a previous call to this. It is **not** a page cursor — the two are
|
|
518
|
+
* different orders and passing one for the other is refused rather than
|
|
519
|
+
* guessed at.
|
|
520
|
+
*
|
|
521
|
+
* Throws `resync` when the cursor is older than the window in which we
|
|
522
|
+
* keep the record of what was deleted. List the folders again.
|
|
523
|
+
*/
|
|
524
|
+
changes: (identityId: string, since: string, options?: {
|
|
525
|
+
limit?: number;
|
|
526
|
+
}) => Promise<Page<MailboxChange>>;
|
|
527
|
+
/**
|
|
528
|
+
* Empty the trash, permanently.
|
|
529
|
+
*
|
|
530
|
+
* Only the trash. It takes attachments and archived originals with it and
|
|
531
|
+
* there is no undo — `messages.undo` replays column values, and these
|
|
532
|
+
* rows are gone.
|
|
533
|
+
*
|
|
534
|
+
* `messages.act(ids, 'delete_forever')` does the same to a list you name,
|
|
535
|
+
* and caps at 200. This needs no ids.
|
|
536
|
+
*/
|
|
537
|
+
empty_trash: (identityId: string) => Promise<{
|
|
538
|
+
folder: string;
|
|
539
|
+
deleted: number;
|
|
540
|
+
}>;
|
|
541
|
+
};
|
|
542
|
+
workspace: {
|
|
543
|
+
/** Which account this key is for, and which plan sets its limits. */
|
|
544
|
+
get: () => Promise<Workspace>;
|
|
545
|
+
/**
|
|
546
|
+
* The people here, so a conversation can be assigned to one of them.
|
|
547
|
+
*
|
|
548
|
+
* Read-only. Inviting somebody is mail to a person and removing somebody
|
|
549
|
+
* hands on their mailboxes; neither is a thing to do without a human
|
|
550
|
+
* deciding it.
|
|
551
|
+
*/
|
|
552
|
+
members: () => Promise<Page<Member>>;
|
|
553
|
+
};
|
|
554
|
+
/**
|
|
555
|
+
* A credential per customer, minted by this one.
|
|
556
|
+
*
|
|
557
|
+
* `identity_ids` is required and must be a subset of what this key already
|
|
558
|
+
* reaches — a key cannot delegate reach it does not have. Hand the new key
|
|
559
|
+
* to the tenant it was scoped for, and revoke it when they leave.
|
|
560
|
+
*
|
|
561
|
+
* **Revoking takes the keys it made with it**, transitively. That is what
|
|
562
|
+
* makes rotating a leaked key true: its first useful move would otherwise
|
|
563
|
+
* be to mint a second one and keep it.
|
|
564
|
+
*/
|
|
565
|
+
keys: {
|
|
566
|
+
list: () => Promise<ApiKey[]>;
|
|
567
|
+
/** The response carries `token`, once. Store it before you discard it. */
|
|
568
|
+
create: (input: {
|
|
569
|
+
name: string;
|
|
570
|
+
identity_ids: string[];
|
|
571
|
+
}) => Promise<ApiKey & {
|
|
572
|
+
token: string;
|
|
573
|
+
}>;
|
|
574
|
+
/** Revokes it and everything it minted. A key may revoke itself. */
|
|
575
|
+
revoke: (id: string) => Promise<{
|
|
576
|
+
id: string;
|
|
577
|
+
}>;
|
|
578
|
+
};
|
|
579
|
+
/**
|
|
580
|
+
* Working IMAP and SMTP credentials for one address.
|
|
581
|
+
*
|
|
582
|
+
* What lets you hand a customer a mailbox they can open in Apple Mail. The
|
|
583
|
+
* address you may issue one for is an address this key can already send
|
|
584
|
+
* from — the credential reads the inbox and sends as it, so issuing one is
|
|
585
|
+
* handing over exactly that.
|
|
586
|
+
*
|
|
587
|
+
* `username` and `password` are useless apart: a password presented for the
|
|
588
|
+
* wrong address is a failed login, not a successful one.
|
|
589
|
+
*/
|
|
590
|
+
appPasswords: {
|
|
591
|
+
list: (identityId: string) => Promise<AppPassword[]>;
|
|
592
|
+
create: (input: {
|
|
593
|
+
identity_id: string;
|
|
594
|
+
name: string;
|
|
595
|
+
}) => Promise<AppPassword & {
|
|
596
|
+
username: string;
|
|
597
|
+
password: string;
|
|
598
|
+
}>;
|
|
599
|
+
revoke: (id: string) => Promise<{
|
|
600
|
+
id: string;
|
|
601
|
+
}>;
|
|
217
602
|
};
|
|
218
603
|
threads: {
|
|
219
604
|
list: (options?: {
|
|
220
605
|
identity_id?: string;
|
|
221
606
|
status?: string;
|
|
607
|
+
/** A person's id, or `'unassigned'` for the queue nobody has taken. */
|
|
608
|
+
assignee_id?: string;
|
|
222
609
|
limit?: number;
|
|
223
610
|
cursor?: string;
|
|
224
611
|
}) => Promise<Page<Thread>>;
|
|
@@ -226,6 +613,8 @@ declare class Pidgeon {
|
|
|
226
613
|
update: (id: string, input: {
|
|
227
614
|
status?: "open" | "waiting" | "resolved" | "human_review";
|
|
228
615
|
owner_type?: "human" | "automation" | "agent";
|
|
616
|
+
/** A person's id to hand it to, or `null` to put it back in the queue. */
|
|
617
|
+
assignee_id?: string | null;
|
|
229
618
|
}) => Promise<Thread>;
|
|
230
619
|
/** Hand the conversation to a person. The takeover primitive, named. */
|
|
231
620
|
handOff: (id: string) => Promise<Thread>;
|
|
@@ -243,6 +632,25 @@ declare class Pidgeon {
|
|
|
243
632
|
delete: (id: string) => Promise<{
|
|
244
633
|
id: string;
|
|
245
634
|
}>;
|
|
635
|
+
/**
|
|
636
|
+
* Turn an endpoint off, or back on.
|
|
637
|
+
*
|
|
638
|
+
* We disable one ourselves after enough consecutive failures. Without
|
|
639
|
+
* this you would have to delete and recreate it, which changes the
|
|
640
|
+
* signing secret every receiver is verifying against.
|
|
641
|
+
*/
|
|
642
|
+
update: (id: string, input: {
|
|
643
|
+
status: "active" | "disabled";
|
|
644
|
+
}) => Promise<Webhook>;
|
|
645
|
+
/** What happened to each event we tried to hand this endpoint. */
|
|
646
|
+
deliveries: (webhookId: string, options?: {
|
|
647
|
+
limit?: number;
|
|
648
|
+
}) => Promise<Delivery[]>;
|
|
649
|
+
/** Queue one up again. Not idempotent — sending twice is the point. */
|
|
650
|
+
replay: (deliveryId: string) => Promise<{
|
|
651
|
+
id: string;
|
|
652
|
+
status: string;
|
|
653
|
+
}>;
|
|
246
654
|
};
|
|
247
655
|
events: {
|
|
248
656
|
list: (options?: {
|
|
@@ -253,9 +661,88 @@ declare class Pidgeon {
|
|
|
253
661
|
}) => Promise<Page<Event>>;
|
|
254
662
|
get: (id: string) => Promise<Event>;
|
|
255
663
|
};
|
|
664
|
+
/**
|
|
665
|
+
* Domains, and the one step this API cannot perform for you.
|
|
666
|
+
*
|
|
667
|
+
* We cannot write records in somebody else's zone. What we can do is make
|
|
668
|
+
* the human step **delegable**: `create` hands back the records alongside
|
|
669
|
+
* the domain, so you show them to your own customer in your own interface
|
|
670
|
+
* and never send anybody to a Pidgeon screen. Then poll `verify`, or
|
|
671
|
+
* subscribe to `domain.verified` and do not poll at all.
|
|
672
|
+
*
|
|
673
|
+
* `dns_complete` is not a detail: the DKIM records come from what the mail
|
|
674
|
+
* provider issued, so a list returned before provisioning finished looks
|
|
675
|
+
* complete and is missing three CNAMEs. Publishing that gives you a domain
|
|
676
|
+
* that verifies and cannot sign mail.
|
|
677
|
+
*/
|
|
256
678
|
domains: {
|
|
257
|
-
/** Read-only. Adding and verifying a domain is a DNS-and-a-human task. */
|
|
258
679
|
list: () => Promise<Domain[]>;
|
|
680
|
+
get: (id: string) => Promise<Domain & {
|
|
681
|
+
dns_records: DnsRecord[];
|
|
682
|
+
dns_complete: boolean;
|
|
683
|
+
}>;
|
|
684
|
+
create: (input: {
|
|
685
|
+
domain: string;
|
|
686
|
+
}) => Promise<Domain & {
|
|
687
|
+
dns_records: DnsRecord[];
|
|
688
|
+
dns_complete: boolean;
|
|
689
|
+
}>;
|
|
690
|
+
/** Idempotent and safe to poll. Calling it on a verified domain re-checks. */
|
|
691
|
+
verify: (id: string) => Promise<{
|
|
692
|
+
verified: boolean;
|
|
693
|
+
mail_configured: boolean;
|
|
694
|
+
message: string;
|
|
695
|
+
dns_records: DnsRecord[];
|
|
696
|
+
dns_complete: boolean;
|
|
697
|
+
}>;
|
|
698
|
+
/** Takes its addresses, their mail, their rules and their webhooks with it. */
|
|
699
|
+
delete: (id: string) => Promise<{
|
|
700
|
+
id: string;
|
|
701
|
+
}>;
|
|
702
|
+
/**
|
|
703
|
+
* The catch-all switch — the one thing about a domain that can change.
|
|
704
|
+
*
|
|
705
|
+
* Catch-all is two gates: this, and a `catch_all` routing rule saying
|
|
706
|
+
* where the mail goes. Turning this on without the rule does nothing, so
|
|
707
|
+
* that turning it off later does not throw away where the mail was going.
|
|
708
|
+
*/
|
|
709
|
+
update: (id: string, input: {
|
|
710
|
+
catch_all_enabled: boolean;
|
|
711
|
+
}) => Promise<Domain>;
|
|
712
|
+
};
|
|
713
|
+
/**
|
|
714
|
+
* Where mail to an address goes.
|
|
715
|
+
*
|
|
716
|
+
* The piece that makes per-customer addresses work without a person in the
|
|
717
|
+
* loop: `acme@yourdomain.com` routed into one inbox you already have, or
|
|
718
|
+
* into a webhook with no inbox at all. An address always beats a rule, so a
|
|
719
|
+
* rule never shadows a real address — creating one that would is refused.
|
|
720
|
+
*
|
|
721
|
+
* The destination must be an address you could already send from, because
|
|
722
|
+
* routing an address to a mailbox also lets that mailbox send as it.
|
|
723
|
+
*/
|
|
724
|
+
routing: {
|
|
725
|
+
list: (options?: {
|
|
726
|
+
domain_id?: string;
|
|
727
|
+
}) => Promise<RoutingRule[]>;
|
|
728
|
+
create: (input: {
|
|
729
|
+
match_type: "address";
|
|
730
|
+
local_part: string;
|
|
731
|
+
destination_identity_id?: string;
|
|
732
|
+
destination_webhook_id?: string;
|
|
733
|
+
} | {
|
|
734
|
+
match_type: "catch_all";
|
|
735
|
+
domain_id: string;
|
|
736
|
+
destination_identity_id?: string;
|
|
737
|
+
destination_webhook_id?: string;
|
|
738
|
+
}) => Promise<RoutingRule>;
|
|
739
|
+
/** Stop a rule firing without forgetting where it pointed. */
|
|
740
|
+
update: (id: string, input: {
|
|
741
|
+
status: "active" | "disabled";
|
|
742
|
+
}) => Promise<RoutingRule>;
|
|
743
|
+
delete: (id: string) => Promise<{
|
|
744
|
+
id: string;
|
|
745
|
+
}>;
|
|
259
746
|
};
|
|
260
747
|
}
|
|
261
748
|
|
|
@@ -299,4 +786,4 @@ declare function verifyWebhook(input: {
|
|
|
299
786
|
now?: Date;
|
|
300
787
|
}): Promise<WebhookEnvelope>;
|
|
301
788
|
|
|
302
|
-
export { type Address, type Attachment, type Domain, type Event, type Identity, type Message, type Page, Pidgeon, PidgeonError, type PidgeonOptions, type RoutingRule, SIGNATURE_HEADER, TIMESTAMP_HEADER, type Thread, type Webhook, type WebhookEnvelope, verifyWebhook };
|
|
789
|
+
export { type Address, type ApiKey, type AppPassword, type Attachment, type Delivery, type DnsRecord, type Domain, type Event, type Identity, type Mailbox, type MailboxChange, type Member, type Message, type MessageActionName, type MessageListItem, type Page, Pidgeon, PidgeonError, type PidgeonOptions, type RoutingRule, SIGNATURE_HEADER, TIMESTAMP_HEADER, type Thread, type UploadedAttachment, type Webhook, type WebhookEnvelope, type Workspace, verifyWebhook };
|