@messagebird/sdk 0.14.0 → 0.15.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/dist/index.mjs CHANGED
@@ -3426,397 +3426,330 @@ var EmailStatsResource = class extends Resource {
3426
3426
  }
3427
3427
  };
3428
3428
  //#endregion
3429
- //#region src/resources/email.ts
3430
- var EmailResource = class extends EmailResourceBase {
3431
- #defaults;
3432
- /** Email statistics — `bird.email.stats.summary(...)`, `.daily(...)`, `.byTag(...)`, … */
3433
- stats;
3434
- constructor(core, client, defaults) {
3435
- super(core, client);
3436
- this.#defaults = defaults;
3437
- this.stats = new EmailStatsResource(core, client);
3438
- }
3429
+ //#region src/resources/emailMailboxes.gen.ts
3430
+ var EmailMailboxesResource$1 = class extends Resource {
3439
3431
  /**
3440
- * Send an email message. Resolves once the message is accepted for delivery
3441
- * (the API's 202). Throws on failure — a 422 (unverified sender, all
3442
- * recipients suppressed, validation) is a `BirdValidationError`. Fields set as
3443
- * channel defaults may be omitted (per-send value wins).
3444
- *
3445
- * @example Send a message
3446
- * const msg = await bird.email.send({
3447
- * from: { email: "onboarding@messagebird.dev", name: "Bird" },
3448
- * to: ["delivered@messagebird.dev"],
3449
- * subject: "Hello from Bird",
3450
- * html: "<p>My first Bird email.</p>",
3451
- * });
3452
- * console.log(msg.id, msg.status); // "em_…", "accepted"
3453
- *
3454
- * @example A richer send — cc/bcc, reply-to, tags, metadata, click-tracking off, and an idempotency key (safe to retry; the server dedupes)
3455
- * await bird.email.send(
3456
- * {
3457
- * from: "hello@acme.com",
3458
- * to: ["a@example.com", "b@example.com"],
3459
- * cc: ["manager@example.com"],
3460
- * reply_to: ["support@acme.com"],
3461
- * subject: "Your March invoice",
3462
- * html: "<p>Attached.</p>",
3463
- * tags: [{ name: "category", value: "billing" }],
3464
- * metadata: { invoice_id: "inv_123" },
3465
- * track_clicks: false,
3466
- * },
3467
- * { idempotencyKey: "invoice-march/cust_1" },
3468
- * );
3469
- *
3470
- * @example Branch on the typed error hierarchy
3471
- * import { BirdRateLimitError, BirdValidationError, BirdAPIError } from "@messagebird/sdk";
3432
+ * List the workspace's mailboxes as a cursor page, newest first. Search addresses and display names with q, or filter by exact address, state, or domain.
3472
3433
  *
3473
- * try {
3474
- * await bird.email.send({
3475
- * from: { email: "onboarding@messagebird.dev", name: "Bird" },
3476
- * to: ["delivered@messagebird.dev"],
3477
- * subject: "Hello from Bird",
3478
- * html: "<p>My first Bird email.</p>",
3479
- * });
3480
- * } catch (err) {
3481
- * if (err instanceof BirdRateLimitError) console.log(`rate limited — retry in ${err.retryAfter}s`);
3482
- * else if (err instanceof BirdValidationError) console.error(err.details);
3483
- * else if (err instanceof BirdAPIError) console.error(err.code, err.requestId);
3484
- * else throw err;
3434
+ * @example List mailboxes
3435
+ * for await (const mailbox of bird.email.mailboxes.list()) {
3436
+ * console.log(mailbox.address);
3485
3437
  * }
3486
- *
3487
- * @example Errors as values with `.safe()`
3488
- * const { data, error } = await bird.email
3489
- * .send({
3490
- * from: { email: "onboarding@messagebird.dev", name: "Bird" },
3491
- * to: ["delivered@messagebird.dev"],
3492
- * subject: "Hello from Bird",
3493
- * html: "<p>My first Bird email.</p>",
3494
- * })
3495
- * .safe();
3496
- * if (error) console.error(error.message);
3497
- * else console.log(data.id);
3498
3438
  */
3499
- send(params, options) {
3500
- const body = {
3501
- ...this.#defaults,
3502
- ...params
3503
- };
3504
- return this.call("POST", options, ({ signal, headers }) => createEmailMessage({
3439
+ list(query, options) {
3440
+ return this.paginated("GET", options, ({ signal, headers }, cursor) => listMailboxes({
3505
3441
  client: this.client,
3506
- body,
3442
+ query: {
3443
+ ...query,
3444
+ starting_after: cursor ?? query?.starting_after
3445
+ },
3507
3446
  headers,
3508
3447
  signal
3509
3448
  }));
3510
3449
  }
3511
3450
  /**
3512
- * Send a batch of up to 100 independent email messages in one request. The
3513
- * batch is validated as a unit — if any item fails validation (unverified
3514
- * sender, all recipients suppressed, field-level errors) the whole batch is
3515
- * rejected with a `BirdValidationError` and nothing is queued. Resolves with
3516
- * one accepted item per submitted message, in submission order, once the batch
3517
- * is accepted (the API's 202). Channel defaults are applied per item.
3451
+ * Create a mailbox a durable agent identity that owns an email address, groups mail into threads, and remembers conversations for its retention tier.
3518
3452
  *
3519
- * @example Send a batch of messages
3520
- * const batch = await bird.email.sendBatch([
3521
- * {
3522
- * from: { email: "onboarding@messagebird.dev", name: "Bird" },
3523
- * to: ["alice@example.com"],
3524
- * subject: "Your receipt",
3525
- * html: "<p>Thanks, Alice.</p>",
3526
- * },
3527
- * {
3528
- * from: { email: "onboarding@messagebird.dev", name: "Bird" },
3529
- * to: ["bob@example.com"],
3530
- * subject: "Your receipt",
3531
- * html: "<p>Thanks, Bob.</p>",
3532
- * },
3533
- * ]);
3534
- * for (const item of batch.data) console.log(item.id, item.status);
3453
+ * @example Create a mailbox
3454
+ * const mailbox = await bird.email.mailboxes.create({ display_name: "Support" });
3455
+ * console.log(mailbox.address); // "abc123@inbox.ai"
3535
3456
  */
3536
- sendBatch(params, options) {
3537
- const body = params.map((item) => ({
3538
- ...this.#defaults,
3539
- ...item
3540
- }));
3541
- return this.call("POST", options, ({ signal, headers }) => createEmailMessageBatch({
3457
+ create(params = {}, options) {
3458
+ return this.call("POST", options, ({ signal, headers }) => createMailbox({
3542
3459
  client: this.client,
3543
- body,
3460
+ body: params,
3544
3461
  headers,
3545
3462
  signal
3546
3463
  }));
3547
3464
  }
3548
- };
3549
- //#endregion
3550
- //#region src/resources/audiences.gen.ts
3551
- var AudiencesResource = class extends Resource {
3552
3465
  /**
3553
- * List the workspace's audiences as a cursor page, newest first. Filter by name substring with `q`.
3554
- *
3555
- * @example Iterate every audience, or take one page
3556
- * for await (const audience of bird.audiences.list()) {
3557
- * console.log(audience.id, audience.name);
3558
- * }
3466
+ * @example Get a mailbox
3467
+ * const mailbox = await bird.email.mailboxes.get("mbx_01abc");
3468
+ * console.log(mailbox.state); // "active"
3559
3469
  */
3560
- list(query, options) {
3561
- return this.paginated("GET", options, ({ signal, headers }, cursor) => listAudiences({
3470
+ get(mailboxId, options) {
3471
+ return this.call("GET", options, ({ signal, headers }) => getMailbox({
3562
3472
  client: this.client,
3563
- query: {
3564
- ...query,
3565
- starting_after: cursor ?? query?.starting_after
3566
- },
3473
+ path: { mailbox_id: mailboxId },
3567
3474
  headers,
3568
3475
  signal
3569
3476
  }));
3570
3477
  }
3571
3478
  /**
3572
- * Get a single audience by ID: name, description, and type. Members are listed separately with `audiences.list_contacts`.
3479
+ * Update a mailbox's display name, reply-to, receive policy, retention tier, contact, or metadata. Lowering the retention tier onto remembered messages older than the new horizon requires confirm=true.
3573
3480
  *
3574
- * @example Fetch an audience by id
3575
- * const audience = await bird.audiences.get("adn_01krdgeqcxet5s7t44vh8rt9mg");
3576
- * console.log(audience.name);
3481
+ * @example Change a mailbox's receive policy
3482
+ * const mailbox = await bird.email.mailboxes.update("mbx_01abc", {
3483
+ * receive_policy: "open",
3484
+ * });
3485
+ * console.log(mailbox.id, mailbox.receive_policy);
3577
3486
  */
3578
- get(audienceId, options) {
3579
- return this.call("GET", options, ({ signal, headers }) => getAudience({
3487
+ update(mailboxId, params = {}, query, options) {
3488
+ return this.call("PATCH", options, ({ signal, headers }) => updateMailbox({
3580
3489
  client: this.client,
3581
- path: { audience_id: audienceId },
3490
+ path: { mailbox_id: mailboxId },
3491
+ body: params,
3492
+ query,
3582
3493
  headers,
3583
3494
  signal
3584
3495
  }));
3585
3496
  }
3586
3497
  /**
3587
- * Create an audience in the workspace. New audiences start empty; add contacts with `audiences.add_contacts` or `contacts.batch`. Only static audiences can be created today.
3498
+ * Delete a mailbox. The address stops receiving immediately and is quarantined; the mailbox and its remembered messages stay restorable for 30 days via the restore endpoint, then are permanently deleted.
3588
3499
  *
3589
- * @example Create an audience
3590
- * const audience = await bird.audiences.create({ name: "Newsletter subscribers" });
3591
- * console.log(audience.id); // "adn_…"
3500
+ * @example Delete a mailbox
3501
+ * await bird.email.mailboxes.delete("mbx_01abc");
3592
3502
  */
3593
- create(params, options) {
3594
- return this.call("POST", options, ({ signal, headers }) => createAudience({
3503
+ delete(mailboxId, options) {
3504
+ return this.call("DELETE", options, ({ signal, headers }) => deleteMailbox({
3595
3505
  client: this.client,
3596
- body: params,
3506
+ path: { mailbox_id: mailboxId },
3597
3507
  headers,
3598
3508
  signal
3599
3509
  }));
3600
3510
  }
3601
3511
  /**
3602
- * Update an audience's name or description. Omitted fields are unchanged; a null description clears it.
3512
+ * Restore a mailbox deleted less than 30 days ago: the address starts receiving again and the remembered messages are back. Past the window the mailbox is permanently deleted and returns 404; a mailbox that is not deleted returns 409.
3603
3513
  *
3604
- * @example Rename an audience
3605
- * await bird.audiences.update("adn_01krdgeqcxet5s7t44vh8rt9mg", { name: "Renamed" });
3514
+ * @example Restore a deleted mailbox
3515
+ * const mailbox = await bird.email.mailboxes.restore("mbx_01abc");
3516
+ * console.log(mailbox.deleted_at); // null
3606
3517
  */
3607
- update(audienceId, params = {}, options) {
3608
- return this.call("PATCH", options, ({ signal, headers }) => updateAudience({
3518
+ restore(mailboxId, options) {
3519
+ return this.call("POST", options, ({ signal, headers }) => restoreMailbox({
3609
3520
  client: this.client,
3610
- path: { audience_id: audienceId },
3611
- body: params,
3521
+ path: { mailbox_id: mailboxId },
3612
3522
  headers,
3613
3523
  signal
3614
3524
  }));
3615
3525
  }
3616
3526
  /**
3617
- * Delete an audience and its memberships; contacts themselves are not deleted. Fails while a broadcast targeting the audience is scheduled, accepted, sending, or canceling.
3527
+ * Reactivate a suspended mailbox so it can send and receive again and its threads become visible. Fails if your plan does not have room for another active mailbox (or another custom inbox.ai handle); delete an active mailbox or upgrade first. A mailbox that is not suspended returns 409.
3618
3528
  *
3619
- * @example Delete an audience by id
3620
- * await bird.audiences.delete("adn_01krdgeqcxet5s7t44vh8rt9mg");
3529
+ * @example Resume a suspended mailbox
3530
+ * const mailbox = await bird.email.mailboxes.resume("mbx_01abc");
3531
+ * console.log(mailbox.state); // "active"
3621
3532
  */
3622
- delete(audienceId, options) {
3623
- return this.call("DELETE", options, ({ signal, headers }) => deleteAudience({
3533
+ resume(mailboxId, options) {
3534
+ return this.call("POST", options, ({ signal, headers }) => resumeMailbox({
3624
3535
  client: this.client,
3625
- path: { audience_id: audienceId },
3536
+ path: { mailbox_id: mailboxId },
3626
3537
  headers,
3627
3538
  signal
3628
3539
  }));
3629
3540
  }
3630
3541
  /**
3631
- * List the contacts in a static audience by ID, as a cursor page ordered by when each contact joined (most recent first). Each entry pairs the contact with its join time.
3632
- *
3633
- * @example Iterate an audience's members
3634
- * for await (const member of bird.audiences.listContacts("adn_01krdgeqcxet5s7t44vh8rt9mg")) {
3635
- * console.log(member.contact.id, member.joined_at);
3636
- * }
3542
+ * @example Get mailbox stats
3543
+ * const stats = await bird.email.mailboxes.stats("mbx_01abc");
3544
+ * console.log(stats.summary?.sends_accepted);
3637
3545
  */
3638
- listContacts(audienceId, query, options) {
3639
- return this.paginated("GET", options, ({ signal, headers }, cursor) => listAudienceContacts({
3546
+ stats(mailboxId, query, options) {
3547
+ return this.call("GET", options, ({ signal, headers }) => getMailboxStats({
3640
3548
  client: this.client,
3641
- path: { audience_id: audienceId },
3642
- query: {
3643
- ...query,
3644
- starting_after: cursor ?? query?.starting_after
3645
- },
3549
+ path: { mailbox_id: mailboxId },
3550
+ query,
3646
3551
  headers,
3647
3552
  signal
3648
3553
  }));
3649
3554
  }
3650
3555
  /**
3651
- * Add up to 1,000 existing contacts to a static audience by ID. Fails entirely if any contact ID does not exist.
3556
+ * List the labels available in a mailbox: the built-in system labels (inbox, archive, spam, blocked, sent, trash, unread) plus every custom label in use.
3652
3557
  *
3653
- * @example Add contacts to an audience
3654
- * await bird.audiences.addContacts("adn_01krdgeqcxet5s7t44vh8rt9mg", {
3655
- * contact_ids: ["con_01krdgeqcxet5s7t44vh8rt9mg"],
3656
- * });
3558
+ * @example List a mailbox's labels
3559
+ * const labels = await bird.email.mailboxes.labels("mbx_01abc");
3560
+ * console.log(labels.data.map((label) => label.name));
3657
3561
  */
3658
- addContacts(audienceId, params, options) {
3659
- return this.call("POST", options, ({ signal, headers }) => assignAudienceContacts({
3562
+ labels(mailboxId, options) {
3563
+ return this.call("GET", options, ({ signal, headers }) => listMailboxLabels({
3660
3564
  client: this.client,
3661
- path: { audience_id: audienceId },
3662
- body: params,
3565
+ path: { mailbox_id: mailboxId },
3663
3566
  headers,
3664
3567
  signal
3665
3568
  }));
3666
3569
  }
3570
+ };
3571
+ //#endregion
3572
+ //#region src/resources/emailMailboxesMessages.ts
3573
+ var EmailMailboxesMessagesResource = class extends Resource {
3667
3574
  /**
3668
- * Remove up to 1,000 contacts from a static audience by ID. Fails entirely if any contact ID does not exist; contacts are not deleted.
3575
+ * Send a new email from this mailbox, starting a new conversation.
3669
3576
  *
3670
- * @example Remove contacts from an audience
3671
- * await bird.audiences.removeContacts("adn_01krdgeqcxet5s7t44vh8rt9mg", {
3672
- * contact_ids: ["con_01krdgeqcxet5s7t44vh8rt9mg"],
3577
+ * @example Send from a mailbox
3578
+ * const msg = await bird.email.mailboxes.messages.create("mbx_01abc", {
3579
+ * to: ["customer@example.com"],
3580
+ * subject: "Hello",
3581
+ * text: "Hi there!",
3673
3582
  * });
3674
3583
  */
3675
- removeContacts(audienceId, params, options) {
3676
- return this.call("POST", options, ({ signal, headers }) => unassignAudienceContacts({
3584
+ create(mailboxId, params, options) {
3585
+ return this.call("POST", options, ({ signal, headers }) => createMailboxMessage({
3677
3586
  client: this.client,
3678
- path: { audience_id: audienceId },
3587
+ path: { mailbox_id: mailboxId },
3679
3588
  body: params,
3680
3589
  headers,
3681
3590
  signal
3682
3591
  }));
3683
3592
  }
3593
+ };
3594
+ //#endregion
3595
+ //#region src/resources/emailMailboxesReceiveRules.gen.ts
3596
+ var EmailMailboxesReceiveRulesResource = class extends Resource {
3684
3597
  /**
3685
- * Remove one contact's membership from an audience. The contact itself is not deleted and stays a member of any other audiences.
3598
+ * List a mailbox's allow/block receive rules as a cursor page, oldest first. Filter by action.
3686
3599
  *
3687
- * @example Remove one contact's membership
3688
- * await bird.audiences.removeContact(
3689
- * "adn_01krdgeqcxet5s7t44vh8rt9mg",
3690
- * "con_01krdgeqcxet5s7t44vh8rt9mg",
3691
- * );
3600
+ * @example List a mailbox's receive rules
3601
+ * for await (const rule of bird.email.mailboxes.receiveRules.list("mbx_01abc")) {
3602
+ * console.log(rule.action, rule.entry);
3603
+ * }
3692
3604
  */
3693
- removeContact(audienceId, contactId, options) {
3694
- return this.call("DELETE", options, ({ signal, headers }) => unassignAudienceContact({
3605
+ list(mailboxId, query, options) {
3606
+ return this.paginated("GET", options, ({ signal, headers }, cursor) => listMailboxReceiveRules({
3695
3607
  client: this.client,
3696
- path: {
3697
- audience_id: audienceId,
3698
- contact_id: contactId
3608
+ path: { mailbox_id: mailboxId },
3609
+ query: {
3610
+ ...query,
3611
+ starting_after: cursor ?? query?.starting_after
3699
3612
  },
3700
3613
  headers,
3701
3614
  signal
3702
3615
  }));
3703
3616
  }
3704
- };
3705
- //#endregion
3706
- //#region src/resources/domains.gen.ts
3707
- var DomainsResource = class extends Resource {
3708
3617
  /**
3709
- * List the workspace's sending domains with their verification status, as a cursor page.
3618
+ * Add an allow or block rule for a sender address or domain to a mailbox. Block always wins; up to 200 rules per mailbox.
3710
3619
  *
3711
- * @example Iterate every sending domain
3712
- * for await (const domain of bird.domains.list()) {
3713
- * console.log(domain.id, domain.status);
3714
- * }
3620
+ * @example Block a domain
3621
+ * const rule = await bird.email.mailboxes.receiveRules.create("mbx_01abc", {
3622
+ * action: "block",
3623
+ * entry: "spam.example.com",
3624
+ * });
3625
+ * console.log(rule.id);
3715
3626
  */
3716
- list(query, options) {
3717
- return this.paginated("GET", options, ({ signal, headers }, cursor) => listDomains({
3627
+ create(mailboxId, params, options) {
3628
+ return this.call("POST", options, ({ signal, headers }) => createMailboxReceiveRule({
3718
3629
  client: this.client,
3719
- query: {
3720
- ...query,
3721
- starting_after: cursor ?? query?.starting_after
3722
- },
3630
+ path: { mailbox_id: mailboxId },
3631
+ body: params,
3723
3632
  headers,
3724
3633
  signal
3725
3634
  }));
3726
3635
  }
3727
3636
  /**
3728
- * Fetch one sending domain: verification status and the DNS records with their individual verification states.
3637
+ * Remove a receive rule from a mailbox. Delete-and-recreate is how an entry's action is flipped.
3729
3638
  *
3730
- * @example Fetch a sending domain by id
3731
- * const domain = await bird.domains.get("dom_01krdgeqcxet5s7t44vh8rt9mg");
3732
- * console.log(domain.domain);
3639
+ * @example Delete a rule
3640
+ * await bird.email.mailboxes.receiveRules.delete("mbx_01abc", "erl_01xyz");
3733
3641
  */
3734
- get(domainId, options) {
3735
- return this.call("GET", options, ({ signal, headers }) => getDomain({
3642
+ delete(mailboxId, ruleId, options) {
3643
+ return this.call("DELETE", options, ({ signal, headers }) => deleteMailboxReceiveRule({
3736
3644
  client: this.client,
3737
- path: { domain_id: domainId },
3645
+ path: {
3646
+ mailbox_id: mailboxId,
3647
+ rule_id: ruleId
3648
+ },
3738
3649
  headers,
3739
3650
  signal
3740
3651
  }));
3741
3652
  }
3653
+ };
3654
+ //#endregion
3655
+ //#region src/resources/emailMailboxes.ts
3656
+ var EmailMailboxesResource = class extends EmailMailboxesResource$1 {
3657
+ /** Messages sent from the mailbox's own address — `bird.email.mailboxes.messages.create(...)`. */
3658
+ messages;
3659
+ /** Per-sender allow/block rules — `bird.email.mailboxes.receiveRules.create(...)`, `.list(...)`, `.delete(...)`. */
3660
+ receiveRules;
3661
+ constructor(...args) {
3662
+ super(...args);
3663
+ this.messages = new EmailMailboxesMessagesResource(...args);
3664
+ this.receiveRules = new EmailMailboxesReceiveRulesResource(...args);
3665
+ }
3666
+ };
3667
+ //#endregion
3668
+ //#region src/resources/emailThreads.gen.ts
3669
+ var EmailThreadsResource$1 = class extends Resource {
3742
3670
  /**
3743
- * Register a new sending domain and get the DNS records to publish. Flow: call this, publish the returned DNS records at your DNS provider, then call email_domains_verify (repeat until status is verified DNS propagation can take minutes to hours).
3671
+ * List mailbox conversations as a cursor page, most recently active first. `label` selects the view inbox (default), archive, spam, blocked, or a custom label. Filter by mailbox, contact, participant address, or subject substring.
3744
3672
  *
3745
- * @example Register a sending domain
3746
- * const domain = await bird.domains.create({ domain: "mail.acme.com" });
3747
- * console.log(domain.id, domain.status); // "dom_…", "pending"
3673
+ * @example List conversation threads
3674
+ * for await (const thread of bird.email.threads.list({ mailbox_id: "mbx_01abc" })) {
3675
+ * console.log(thread.id, thread.subject);
3676
+ * }
3748
3677
  */
3749
- create(params, options) {
3750
- return this.call("POST", options, ({ signal, headers }) => createDomain({
3678
+ list(query, options) {
3679
+ return this.paginated("GET", options, ({ signal, headers }, cursor) => listEmailThreads({
3751
3680
  client: this.client,
3752
- body: params,
3681
+ query: {
3682
+ ...query,
3683
+ starting_after: cursor ?? query?.starting_after
3684
+ },
3753
3685
  headers,
3754
3686
  signal
3755
3687
  }));
3756
3688
  }
3757
3689
  /**
3758
- * Trigger a DNS verification check for a sending domain and return the refreshed domain with per-record results. Safe to repeat while waiting for DNS propagation.
3690
+ * Get one conversation: participants, counts, labels, read state. Fetch its messages with the thread messages endpoint.
3759
3691
  *
3760
- * @example Re-run the DNS verification check
3761
- * const domain = await bird.domains.verify("dom_01krdgeqcxet5s7t44vh8rt9mg");
3762
- * console.log(domain.status); // "verified" once DNS is in place
3692
+ * @example Get a thread
3693
+ * const thread = await bird.email.threads.get("thr_01abc");
3694
+ * console.log(thread.subject);
3763
3695
  */
3764
- verify(domainId, options) {
3765
- return this.call("POST", options, ({ signal, headers }) => verifyDomain({
3696
+ get(threadId, options) {
3697
+ return this.call("GET", options, ({ signal, headers }) => getEmailThread({
3766
3698
  client: this.client,
3767
- path: { domain_id: domainId },
3699
+ path: { thread_id: threadId },
3768
3700
  headers,
3769
3701
  signal
3770
3702
  }));
3771
3703
  }
3772
3704
  /**
3773
- * Update a sending domain's tracking and inbound configuration. Tracking: toggle click_tracking and open_tracking (applied immediately to new sends), and set, change, or remove the tracking domain (the name part only Bird appends the sending domain). Enabling either toggle with no tracking domain configured returns 409; removing the tracking domain while either toggle is still on also returns 409. Tracking-domain changes on a verified domain are staged behind DNS verification, so the current config keeps serving until the new records verify. Inbound receiving: set inbound.enabled to start or stop receiving mail for the domain. Enabling requires the domain's DKIM to be verified first (a fresh enable on an unverified domain returns 422), and a domain already receiving inbound for another organization returns 422. The MX records to publish are always listed in dns_records regardless, so enabling — not merely publishing them — is what turns receiving on.
3705
+ * Add or remove labels on a conversationadding `spam` files it as spam, adding `archive` clears it out of the inbox, adding `inbox` brings it back or link/unlink a contact.
3774
3706
  *
3775
- * @example Enable tracking on a domain
3776
- * await bird.domains.update("dom_01krdgeqcxet5s7t44vh8rt9mg", {
3777
- * settings: { click_tracking: true, open_tracking: true },
3778
- * tracking: { name: "links" },
3707
+ * @example Apply label changes to a thread
3708
+ * const thread = await bird.email.threads.update("thr_01abc", {
3709
+ * labels: { add: ["archive"] },
3779
3710
  * });
3711
+ * console.log(thread.id);
3780
3712
  */
3781
- update(domainId, params = {}, options) {
3782
- return this.call("PATCH", options, ({ signal, headers }) => updateDomain({
3713
+ update(threadId, params = {}, options) {
3714
+ return this.call("PATCH", options, ({ signal, headers }) => updateEmailThread({
3783
3715
  client: this.client,
3784
- path: { domain_id: domainId },
3716
+ path: { thread_id: threadId },
3785
3717
  body: params,
3786
3718
  headers,
3787
3719
  signal
3788
3720
  }));
3789
3721
  }
3790
3722
  /**
3791
- * Delete a sending domain by id. Revokes its sender authorization: new sends from the domain are rejected afterward, while historical statistics and events for past sends are preserved. Destructive.
3723
+ * Move a conversation and all its messages to trash (purged after 30 days), or delete permanently with ?permanent=true.
3792
3724
  *
3793
- * @example Delete a sending domain by id
3794
- * await bird.domains.delete("dom_01krdgeqcxet5s7t44vh8rt9mg");
3725
+ * @example Delete a thread
3726
+ * await bird.email.threads.delete("thr_01abc", { permanent: true });
3795
3727
  */
3796
- delete(domainId, options) {
3797
- return this.call("DELETE", options, ({ signal, headers }) => deleteDomain({
3728
+ delete(threadId, query, options) {
3729
+ return this.call("DELETE", options, ({ signal, headers }) => deleteEmailThread({
3798
3730
  client: this.client,
3799
- path: { domain_id: domainId },
3731
+ path: { thread_id: threadId },
3732
+ query,
3800
3733
  headers,
3801
3734
  signal
3802
3735
  }));
3803
3736
  }
3804
3737
  };
3805
3738
  //#endregion
3806
- //#region src/resources/contactProperties.gen.ts
3807
- var ContactPropertiesResource = class extends Resource {
3739
+ //#region src/resources/emailThreadsMessages.gen.ts
3740
+ var EmailThreadsMessagesResource = class extends Resource {
3808
3741
  /**
3809
- * List the workspace's contact properties as a cursor page, newest first. Archived properties are included, marked by their archived flag.
3742
+ * List the messages in a conversation newest first, both directions. Page older messages with starting_after, and pass include=extracted_text to inline each message's durable plain text.
3810
3743
  *
3811
- * @example Iterate every contact property, or take one page
3812
- * for await (const prop of bird.contactProperties.list()) {
3813
- * console.log(prop.key, prop.type);
3744
+ * @example List a thread's messages
3745
+ * for await (const msg of bird.email.threads.messages.list("thr_01abc")) {
3746
+ * console.log(msg.id, msg.direction);
3814
3747
  * }
3815
- * const page = await bird.contactProperties.list({ limit: 50 }); // page.data, page.next_cursor
3816
3748
  */
3817
- list(query, options) {
3818
- return this.paginated("GET", options, ({ signal, headers }, cursor) => listContactProperties({
3749
+ list(threadId, query, options) {
3750
+ return this.paginated("GET", options, ({ signal, headers }, cursor) => listEmailThreadMessages({
3819
3751
  client: this.client,
3752
+ path: { thread_id: threadId },
3820
3753
  query: {
3821
3754
  ...query,
3822
3755
  starting_after: cursor ?? query?.starting_after
@@ -3826,339 +3759,387 @@ var ContactPropertiesResource = class extends Resource {
3826
3759
  }));
3827
3760
  }
3828
3761
  /**
3829
- * Get a single contact property by ID: key, type, fallback value, and archived state.
3762
+ * Get one conversation message with its extracted plain text readable for the mailbox's full retention period, no MIME parsing needed.
3830
3763
  *
3831
- * @example Fetch a contact property by id
3832
- * const prop = await bird.contactProperties.get("cp_01krdgeqcxet5s7t44vh8rt9mg");
3833
- * console.log(prop.key, prop.type);
3764
+ * @example Get a message
3765
+ * const msg = await bird.email.threads.messages.get("thr_01abc", "rem_01xyz");
3766
+ * console.log(msg.direction); // "inbound"
3834
3767
  */
3835
- get(propertyId, options) {
3836
- return this.call("GET", options, ({ signal, headers }) => getContactProperty({
3768
+ get(threadId, messageId, options) {
3769
+ return this.call("GET", options, ({ signal, headers }) => getEmailThreadMessage({
3837
3770
  client: this.client,
3838
- path: { property_id: propertyId },
3771
+ path: {
3772
+ thread_id: threadId,
3773
+ message_id: messageId
3774
+ },
3839
3775
  headers,
3840
3776
  signal
3841
3777
  }));
3842
3778
  }
3843
3779
  /**
3844
- * Define a custom contact property (key + value type) that becomes available in contact data and as a broadcast template variable. The key and type cannot change after creation; a workspace holds at most 200 properties, archived included.
3780
+ * Get the original rendered HTML and plain-text body of a conversation message. Available 30 days; after that use the message's extracted_text.
3845
3781
  *
3846
- * @example Define a custom property
3847
- * const prop = await bird.contactProperties.create({ key: "plan", type: "string" });
3848
- * console.log(prop.id); // "cp_…"
3782
+ * @example Get a message body
3783
+ * const body = await bird.email.threads.messages.body("thr_01abc", "rem_01xyz");
3784
+ * console.log(body.text);
3849
3785
  */
3850
- create(params, options) {
3851
- return this.call("POST", options, ({ signal, headers }) => createContactProperty({
3786
+ body(threadId, messageId, options) {
3787
+ return this.call("GET", options, ({ signal, headers }) => getEmailThreadMessageBody({
3852
3788
  client: this.client,
3853
- body: params,
3789
+ path: {
3790
+ thread_id: threadId,
3791
+ message_id: messageId
3792
+ },
3854
3793
  headers,
3855
3794
  signal
3856
3795
  }));
3857
3796
  }
3858
3797
  /**
3859
- * Update a contact property's fallback value. The key and type are immutable; create a new property instead.
3798
+ * Reply to a specific conversation message from the mailbox's own address. To reply to a conversation, target its newest received message. Recipients, subject, and threading headers are derived automatically.
3860
3799
  *
3861
- * @example Change a property's fallback value
3862
- * await bird.contactProperties.update("cp_01krdgeqcxet5s7t44vh8rt9mg", { fallback_value: "free" });
3800
+ * @example Reply to a message
3801
+ * const reply = await bird.email.threads.messages.reply("thr_01abc", "rem_01xyz", {
3802
+ * text: "Thanks for reaching out!",
3803
+ * });
3804
+ * console.log(reply.id);
3863
3805
  */
3864
- update(propertyId, params = {}, options) {
3865
- return this.call("PATCH", options, ({ signal, headers }) => updateContactProperty({
3806
+ reply(threadId, messageId, params = {}, options) {
3807
+ return this.call("POST", options, ({ signal, headers }) => replyEmailThreadMessage({
3866
3808
  client: this.client,
3867
- path: { property_id: propertyId },
3809
+ path: {
3810
+ thread_id: threadId,
3811
+ message_id: messageId
3812
+ },
3868
3813
  body: params,
3869
3814
  headers,
3870
3815
  signal
3871
3816
  }));
3872
3817
  }
3873
3818
  /**
3874
- * Archive a contact property: the key is rejected in new contact writes and stops rendering in templates, while stored values remain readable. The key stays reserved and counts toward the 200-property limit; reverse with `contact_properties.unarchive`.
3819
+ * List the attachments on a conversation message. Bytes are downloadable for 30 days; the metadata also rides the message's attachment_manifest durably.
3875
3820
  *
3876
- * @example Archive a property, retiring the field without deleting its data
3877
- * const prop = await bird.contactProperties.archive("cp_01krdgeqcxet5s7t44vh8rt9mg");
3878
- * console.log(prop.key, prop.archived);
3821
+ * @example List a message's attachments
3822
+ * const atts = await bird.email.threads.messages.attachments("thr_01abc", "rem_01xyz");
3823
+ * console.log(atts.data.map((a) => a.filename));
3879
3824
  */
3880
- archive(propertyId, options) {
3881
- return this.call("POST", options, ({ signal, headers }) => archiveContactProperty({
3825
+ attachments(threadId, messageId, options) {
3826
+ return this.call("GET", options, ({ signal, headers }) => listEmailThreadMessageAttachments({
3882
3827
  client: this.client,
3883
- path: { property_id: propertyId },
3828
+ path: {
3829
+ thread_id: threadId,
3830
+ message_id: messageId
3831
+ },
3884
3832
  headers,
3885
3833
  signal
3886
3834
  }));
3887
3835
  }
3888
- /**
3889
- * Reactivate an archived contact property so its key is accepted in contact writes and renders in templates again. Fails with a conflict if the property is not archived.
3890
- *
3891
- * @example Restore an archived property
3892
- * await bird.contactProperties.unarchive("cp_01krdgeqcxet5s7t44vh8rt9mg");
3893
- */
3894
- unarchive(propertyId, options) {
3895
- return this.call("POST", options, ({ signal, headers }) => unarchiveContactProperty({
3896
- client: this.client,
3897
- path: { property_id: propertyId },
3898
- headers,
3899
- signal
3900
- }));
3836
+ };
3837
+ //#endregion
3838
+ //#region src/resources/emailThreads.ts
3839
+ var EmailThreadsResource = class extends EmailThreadsResource$1 {
3840
+ /** Messages in a conversation — `bird.email.threads.messages.list(...)`, `.reply(...)`, … */
3841
+ messages;
3842
+ constructor(...args) {
3843
+ super(...args);
3844
+ this.messages = new EmailThreadsMessagesResource(...args);
3901
3845
  }
3902
3846
  };
3903
3847
  //#endregion
3904
- //#region src/resources/contacts.gen.ts
3905
- var ContactsResource = class extends Resource {
3848
+ //#region src/resources/email.ts
3849
+ var EmailResource = class extends EmailResourceBase {
3850
+ #defaults;
3851
+ /** Email statistics — `bird.email.stats.summary(...)`, `.daily(...)`, `.byTag(...)`, … */
3852
+ stats;
3853
+ /** Durable agent mailboxes — `bird.email.mailboxes.list(...)`, `.create(...)`, … */
3854
+ mailboxes;
3855
+ /** Conversations across every mailbox — `bird.email.threads.list(...)`, `.get(...)`, … */
3856
+ threads;
3857
+ constructor(core, client, defaults) {
3858
+ super(core, client);
3859
+ this.#defaults = defaults;
3860
+ this.stats = new EmailStatsResource(core, client);
3861
+ this.mailboxes = new EmailMailboxesResource(core, client);
3862
+ this.threads = new EmailThreadsResource(core, client);
3863
+ }
3906
3864
  /**
3907
- * List the workspace's contacts as a cursor page, newest first. Look one up by exact email or external_id, or search by email substring.
3865
+ * Send an email message. Resolves once the message is accepted for delivery
3866
+ * (the API's 202). Throws on failure — a 422 (unverified sender, all
3867
+ * recipients suppressed, validation) is a `BirdValidationError`. Fields set as
3868
+ * channel defaults may be omitted (per-send value wins).
3908
3869
  *
3909
- * @example Iterate every contact, or take one page
3910
- * for await (const contact of bird.contacts.list({ q: "acme.com" })) {
3911
- * console.log(contact.id, contact.email);
3870
+ * @example Send a message
3871
+ * const msg = await bird.email.send({
3872
+ * from: { email: "onboarding@messagebird.dev", name: "Bird" },
3873
+ * to: ["delivered@messagebird.dev"],
3874
+ * subject: "Hello from Bird",
3875
+ * html: "<p>My first Bird email.</p>",
3876
+ * });
3877
+ * console.log(msg.id, msg.status); // "em_…", "accepted"
3878
+ *
3879
+ * @example A richer send — cc/bcc, reply-to, tags, metadata, click-tracking off, and an idempotency key (safe to retry; the server dedupes)
3880
+ * await bird.email.send(
3881
+ * {
3882
+ * from: "hello@acme.com",
3883
+ * to: ["a@example.com", "b@example.com"],
3884
+ * cc: ["manager@example.com"],
3885
+ * reply_to: ["support@acme.com"],
3886
+ * subject: "Your March invoice",
3887
+ * html: "<p>Attached.</p>",
3888
+ * tags: [{ name: "category", value: "billing" }],
3889
+ * metadata: { invoice_id: "inv_123" },
3890
+ * track_clicks: false,
3891
+ * },
3892
+ * { idempotencyKey: "invoice-march/cust_1" },
3893
+ * );
3894
+ *
3895
+ * @example Branch on the typed error hierarchy
3896
+ * import { BirdRateLimitError, BirdValidationError, BirdAPIError } from "@messagebird/sdk";
3897
+ *
3898
+ * try {
3899
+ * await bird.email.send({
3900
+ * from: { email: "onboarding@messagebird.dev", name: "Bird" },
3901
+ * to: ["delivered@messagebird.dev"],
3902
+ * subject: "Hello from Bird",
3903
+ * html: "<p>My first Bird email.</p>",
3904
+ * });
3905
+ * } catch (err) {
3906
+ * if (err instanceof BirdRateLimitError) console.log(`rate limited — retry in ${err.retryAfter}s`);
3907
+ * else if (err instanceof BirdValidationError) console.error(err.details);
3908
+ * else if (err instanceof BirdAPIError) console.error(err.code, err.requestId);
3909
+ * else throw err;
3912
3910
  * }
3913
- * const page = await bird.contacts.list({ limit: 50 }); // page.data, page.next_cursor
3914
- */
3915
- list(query, options) {
3916
- return this.paginated("GET", options, ({ signal, headers }, cursor) => listContacts({
3917
- client: this.client,
3918
- query: {
3919
- ...query,
3920
- starting_after: cursor ?? query?.starting_after
3921
- },
3922
- headers,
3923
- signal
3924
- }));
3925
- }
3926
- /**
3927
- * Get a single contact by ID (`con_`-prefixed). Look up an ID by exact email or external_id with `contacts.list`.
3928
3911
  *
3929
- * @example Fetch a contact by id
3930
- * const contact = await bird.contacts.get("con_01krdgeqcxet5s7t44vh8rt9mg");
3931
- * console.log(contact.email, contact.first_name);
3912
+ * @example Errors as values with `.safe()`
3913
+ * const { data, error } = await bird.email
3914
+ * .send({
3915
+ * from: { email: "onboarding@messagebird.dev", name: "Bird" },
3916
+ * to: ["delivered@messagebird.dev"],
3917
+ * subject: "Hello from Bird",
3918
+ * html: "<p>My first Bird email.</p>",
3919
+ * })
3920
+ * .safe();
3921
+ * if (error) console.error(error.message);
3922
+ * else console.log(data.id);
3932
3923
  */
3933
- get(contactId, options) {
3934
- return this.call("GET", options, ({ signal, headers }) => getContact({
3924
+ send(params, options) {
3925
+ const body = {
3926
+ ...this.#defaults,
3927
+ ...params
3928
+ };
3929
+ return this.call("POST", options, ({ signal, headers }) => createEmailMessage({
3935
3930
  client: this.client,
3936
- path: { contact_id: contactId },
3931
+ body,
3937
3932
  headers,
3938
3933
  signal
3939
3934
  }));
3940
3935
  }
3941
3936
  /**
3942
- * Create a contact by email address in the workspace. Fails with a conflict if the email or external_id is already used by another contact. For bulk import or create-or-update semantics use `contacts.batch`.
3937
+ * Send a batch of up to 100 independent email messages in one request. The
3938
+ * batch is validated as a unit — if any item fails validation (unverified
3939
+ * sender, all recipients suppressed, field-level errors) the whole batch is
3940
+ * rejected with a `BirdValidationError` and nothing is queued. Resolves with
3941
+ * one accepted item per submitted message, in submission order, once the batch
3942
+ * is accepted (the API's 202). Channel defaults are applied per item.
3943
3943
  *
3944
- * @example Create a contact
3945
- * const contact = await bird.contacts.create({
3946
- * email: "jane@acme.com",
3947
- * first_name: "Jane",
3948
- * });
3949
- * console.log(contact.id); // "con_…"
3944
+ * @example Send a batch of messages
3945
+ * const batch = await bird.email.sendBatch([
3946
+ * {
3947
+ * from: { email: "onboarding@messagebird.dev", name: "Bird" },
3948
+ * to: ["alice@example.com"],
3949
+ * subject: "Your receipt",
3950
+ * html: "<p>Thanks, Alice.</p>",
3951
+ * },
3952
+ * {
3953
+ * from: { email: "onboarding@messagebird.dev", name: "Bird" },
3954
+ * to: ["bob@example.com"],
3955
+ * subject: "Your receipt",
3956
+ * html: "<p>Thanks, Bob.</p>",
3957
+ * },
3958
+ * ]);
3959
+ * for (const item of batch.data) console.log(item.id, item.status);
3950
3960
  */
3951
- create(params, options) {
3952
- return this.call("POST", options, ({ signal, headers }) => createContact({
3953
- client: this.client,
3954
- body: params,
3955
- headers,
3956
- signal
3961
+ sendBatch(params, options) {
3962
+ const body = params.map((item) => ({
3963
+ ...this.#defaults,
3964
+ ...item
3957
3965
  }));
3958
- }
3959
- /**
3960
- * Update a contact's name, external_id, email, or custom data. Only supplied fields change; custom data keys are merged, with null removing a key.
3961
- *
3962
- * @example Change a contact's fields
3963
- * const contact = await bird.contacts.update("con_01krdgeqcxet5s7t44vh8rt9mg", {
3964
- * first_name: "Jane",
3965
- * });
3966
- * console.log(contact.first_name);
3967
- */
3968
- update(contactId, params = {}, options) {
3969
- return this.call("PATCH", options, ({ signal, headers }) => updateContact({
3966
+ return this.call("POST", options, ({ signal, headers }) => createEmailMessageBatch({
3970
3967
  client: this.client,
3971
- path: { contact_id: contactId },
3972
- body: params,
3968
+ body,
3973
3969
  headers,
3974
3970
  signal
3975
3971
  }));
3976
3972
  }
3973
+ };
3974
+ //#endregion
3975
+ //#region src/resources/audiences.gen.ts
3976
+ var AudiencesResource = class extends Resource {
3977
3977
  /**
3978
- * Delete a contact and remove it from every audience it belongs to. Suppression records for the address are unaffected.
3978
+ * List the workspace's audiences as a cursor page, newest first. Filter by name substring with `q`.
3979
3979
  *
3980
- * @example Delete a contact by id
3981
- * await bird.contacts.delete("con_01krdgeqcxet5s7t44vh8rt9mg");
3980
+ * @example Iterate every audience, or take one page
3981
+ * for await (const audience of bird.audiences.list()) {
3982
+ * console.log(audience.id, audience.name);
3983
+ * }
3982
3984
  */
3983
- delete(contactId, options) {
3984
- return this.call("DELETE", options, ({ signal, headers }) => deleteContact({
3985
+ list(query, options) {
3986
+ return this.paginated("GET", options, ({ signal, headers }, cursor) => listAudiences({
3985
3987
  client: this.client,
3986
- path: { contact_id: contactId },
3988
+ query: {
3989
+ ...query,
3990
+ starting_after: cursor ?? query?.starting_after
3991
+ },
3987
3992
  headers,
3988
3993
  signal
3989
3994
  }));
3990
3995
  }
3991
3996
  /**
3992
- * Create or update up to 1,000 contacts in one request, matched by email address, and optionally add them all to one or more audiences. Per-contact results are returned in submission order.
3997
+ * Get a single audience by ID: name, description, and type. Members are listed separately with `audiences.list_contacts`.
3993
3998
  *
3994
- * @example Create or update many contacts at once, matched by email
3995
- * const result = await bird.contacts.batch({
3996
- * contacts: [{ email: "jane@acme.com", first_name: "Jane" }],
3997
- * });
3998
- * for (const item of result.data) {
3999
- * console.log(item.email, item.status);
4000
- * }
3999
+ * @example Fetch an audience by id
4000
+ * const audience = await bird.audiences.get("adn_01krdgeqcxet5s7t44vh8rt9mg");
4001
+ * console.log(audience.name);
4001
4002
  */
4002
- batch(params, options) {
4003
- return this.call("POST", options, ({ signal, headers }) => createContactBatch({
4003
+ get(audienceId, options) {
4004
+ return this.call("GET", options, ({ signal, headers }) => getAudience({
4004
4005
  client: this.client,
4005
- body: params,
4006
+ path: { audience_id: audienceId },
4006
4007
  headers,
4007
4008
  signal
4008
4009
  }));
4009
4010
  }
4010
- };
4011
- //#endregion
4012
- //#region src/resources/sms.gen.ts
4013
- var SmsResourceBase = class extends Resource {
4014
4011
  /**
4015
- * Get one SMS message by id: its current delivery status, segment breakdown, cost, and failure detail if it failed.
4012
+ * Create an audience in the workspace. New audiences start empty; add contacts with `audiences.add_contacts` or `contacts.batch`. Only static audiences can be created today.
4016
4013
  *
4017
- * @example Read a message back
4018
- * const msg = await bird.sms.get("sms_abc123");
4019
- * msg.status; // "accepted" | "delivered" | …
4014
+ * @example Create an audience
4015
+ * const audience = await bird.audiences.create({ name: "Newsletter subscribers" });
4016
+ * console.log(audience.id); // "adn_…"
4020
4017
  */
4021
- get(messageId, options) {
4022
- return this.call("GET", options, ({ signal, headers }) => getSmsMessage({
4018
+ create(params, options) {
4019
+ return this.call("POST", options, ({ signal, headers }) => createAudience({
4023
4020
  client: this.client,
4024
- path: { message_id: messageId },
4021
+ body: params,
4025
4022
  headers,
4026
4023
  signal
4027
4024
  }));
4028
4025
  }
4029
4026
  /**
4030
- * List SMS messages, newest first, as a cursor page ({data, next_cursor, …}). Pass next_cursor back as starting_after to fetch the next page. Filter by direction, status, category, recipient, sender, or tag.
4027
+ * Update an audience's name or description. Omitted fields are unchanged; a null description clears it.
4031
4028
  *
4032
- * @example Iterate outbound messages
4033
- * for await (const msg of bird.sms.list({ direction: "outbound" })) {
4034
- * console.log(msg.id, msg.status);
4035
- * }
4029
+ * @example Rename an audience
4030
+ * await bird.audiences.update("adn_01krdgeqcxet5s7t44vh8rt9mg", { name: "Renamed" });
4036
4031
  */
4037
- list(query, options) {
4038
- return this.paginated("GET", options, ({ signal, headers }, cursor) => listSmsMessages({
4032
+ update(audienceId, params = {}, options) {
4033
+ return this.call("PATCH", options, ({ signal, headers }) => updateAudience({
4039
4034
  client: this.client,
4040
- query: {
4041
- ...query,
4042
- starting_after: cursor ?? query?.starting_after
4043
- },
4035
+ path: { audience_id: audienceId },
4036
+ body: params,
4044
4037
  headers,
4045
4038
  signal
4046
4039
  }));
4047
4040
  }
4048
- };
4049
- //#endregion
4050
- //#region src/resources/sms.ts
4051
- /** Filters and cursor params for `bird.sms.list`. */
4052
- var SmsResource = class extends SmsResourceBase {
4053
4041
  /**
4054
- * Send one SMS to a single recipient. Supply either `text` (with a `category`)
4055
- * or a stored `template` (by `id` or `name`, with its `parameters`). The
4056
- * result is `accepted`, not yet delivered — read it back with `get` to confirm.
4057
- *
4058
- * @example Send free text
4059
- * const msg = await bird.sms.send({
4060
- * from: "MyBrand",
4061
- * to: "+14155550100",
4062
- * text: "Your verification code is 123456.",
4063
- * category: "authentication",
4064
- * });
4065
- * console.log(msg.id, msg.status);
4042
+ * Delete an audience and its memberships; contacts themselves are not deleted. Fails while a broadcast targeting the audience is scheduled, accepted, sending, or canceling.
4066
4043
  *
4067
- * @example Send by template
4068
- * await bird.sms.send({
4069
- * to: "+14155550100",
4070
- * template: { name: "bird_otp_verification", parameters: { code: "123456" } },
4071
- * });
4044
+ * @example Delete an audience by id
4045
+ * await bird.audiences.delete("adn_01krdgeqcxet5s7t44vh8rt9mg");
4072
4046
  */
4073
- send(params, options) {
4074
- return this.call("POST", options, ({ signal, headers }) => createSmsMessage({
4047
+ delete(audienceId, options) {
4048
+ return this.call("DELETE", options, ({ signal, headers }) => deleteAudience({
4075
4049
  client: this.client,
4076
- body: params,
4050
+ path: { audience_id: audienceId },
4077
4051
  headers,
4078
4052
  signal
4079
4053
  }));
4080
4054
  }
4081
4055
  /**
4082
- * Send up to 100 independent SMS messages in one call. Each item is a full send
4083
- * (free text or template); all items are validated before any are queued.
4056
+ * List the contacts in a static audience by ID, as a cursor page ordered by when each contact joined (most recent first). Each entry pairs the contact with its join time.
4084
4057
  *
4085
- * @example
4086
- * const result = await bird.sms.sendBatch([
4087
- * { to: "+15551111111", text: "Hi Alice!", category: "marketing" },
4088
- * { to: "+15552222222", text: "Hi Bob!", category: "marketing" },
4089
- * ]);
4058
+ * @example Iterate an audience's members
4059
+ * for await (const member of bird.audiences.listContacts("adn_01krdgeqcxet5s7t44vh8rt9mg")) {
4060
+ * console.log(member.contact.id, member.joined_at);
4061
+ * }
4090
4062
  */
4091
- sendBatch(params, options) {
4092
- return this.call("POST", options, ({ signal, headers }) => createSmsMessageBatch({
4063
+ listContacts(audienceId, query, options) {
4064
+ return this.paginated("GET", options, ({ signal, headers }, cursor) => listAudienceContacts({
4093
4065
  client: this.client,
4094
- body: params,
4066
+ path: { audience_id: audienceId },
4067
+ query: {
4068
+ ...query,
4069
+ starting_after: cursor ?? query?.starting_after
4070
+ },
4095
4071
  headers,
4096
4072
  signal
4097
4073
  }));
4098
4074
  }
4099
- };
4100
- //#endregion
4101
- //#region src/resources/smsTemplates.gen.ts
4102
- var SmsTemplatesResource = class extends Resource {
4103
4075
  /**
4104
- * List the SMS templates available to your workspace, including Bird's built-in templates. Filter by scope, category, or language. The catalogue is small and returned in full; this list is not paginated. Use sms_templates_get to read one template's variables before sending with it.
4076
+ * Add up to 1,000 existing contacts to a static audience by ID. Fails entirely if any contact ID does not exist.
4105
4077
  *
4106
- * @example List the built-in templates
4107
- * const { data } = await bird.smsTemplates.list({ scope: "system" });
4108
- * for (const tpl of data) console.log(tpl.id, tpl.name);
4078
+ * @example Add contacts to an audience
4079
+ * await bird.audiences.addContacts("adn_01krdgeqcxet5s7t44vh8rt9mg", {
4080
+ * contact_ids: ["con_01krdgeqcxet5s7t44vh8rt9mg"],
4081
+ * });
4109
4082
  */
4110
- list(query, options) {
4111
- return this.call("GET", options, ({ signal, headers }) => listSmsTemplates({
4083
+ addContacts(audienceId, params, options) {
4084
+ return this.call("POST", options, ({ signal, headers }) => assignAudienceContacts({
4112
4085
  client: this.client,
4113
- query,
4086
+ path: { audience_id: audienceId },
4087
+ body: params,
4114
4088
  headers,
4115
4089
  signal
4116
4090
  }));
4117
4091
  }
4118
4092
  /**
4119
- * Get one SMS template by its name or id, including its body and the variables it expects. Fetch it before sms_send to see which parameter keys a template send requires.
4093
+ * Remove up to 1,000 contacts from a static audience by ID. Fails entirely if any contact ID does not exist; contacts are not deleted.
4120
4094
  *
4121
- * @example Read one template by name or id
4122
- * const tpl = await bird.smsTemplates.get("bird_otp_verification");
4123
- * console.log(tpl.body, tpl.variables);
4095
+ * @example Remove contacts from an audience
4096
+ * await bird.audiences.removeContacts("adn_01krdgeqcxet5s7t44vh8rt9mg", {
4097
+ * contact_ids: ["con_01krdgeqcxet5s7t44vh8rt9mg"],
4098
+ * });
4124
4099
  */
4125
- get(templateRef, options) {
4126
- return this.call("GET", options, ({ signal, headers }) => getSmsTemplate({
4100
+ removeContacts(audienceId, params, options) {
4101
+ return this.call("POST", options, ({ signal, headers }) => unassignAudienceContacts({
4127
4102
  client: this.client,
4128
- path: { template_ref: templateRef },
4103
+ path: { audience_id: audienceId },
4104
+ body: params,
4129
4105
  headers,
4130
4106
  signal
4131
4107
  }));
4132
4108
  }
4133
- };
4134
- //#endregion
4135
- //#region src/resources/whatsapp.gen.ts
4136
- var WhatsappResourceBase = class extends Resource {
4137
4109
  /**
4138
- * Get one WhatsApp message by id: current delivery status, sent/delivered/read timestamps, the template it was sent from, and failure detail if it failed. For the per-event timeline use whatsapp_list_events.
4110
+ * Remove one contact's membership from an audience. The contact itself is not deleted and stays a member of any other audiences.
4139
4111
  *
4140
- * @example Read a message back
4141
- * const msg = await bird.whatsapp.get("wa_abc123");
4142
- * msg.status; // "accepted" | "delivered" | …
4112
+ * @example Remove one contact's membership
4113
+ * await bird.audiences.removeContact(
4114
+ * "adn_01krdgeqcxet5s7t44vh8rt9mg",
4115
+ * "con_01krdgeqcxet5s7t44vh8rt9mg",
4116
+ * );
4143
4117
  */
4144
- get(messageId, options) {
4145
- return this.call("GET", options, ({ signal, headers }) => getWhatsAppMessage({
4118
+ removeContact(audienceId, contactId, options) {
4119
+ return this.call("DELETE", options, ({ signal, headers }) => unassignAudienceContact({
4146
4120
  client: this.client,
4147
- path: { message_id: messageId },
4121
+ path: {
4122
+ audience_id: audienceId,
4123
+ contact_id: contactId
4124
+ },
4148
4125
  headers,
4149
4126
  signal
4150
4127
  }));
4151
4128
  }
4129
+ };
4130
+ //#endregion
4131
+ //#region src/resources/domains.gen.ts
4132
+ var DomainsResource = class extends Resource {
4152
4133
  /**
4153
- * List WhatsApp messages, newest first, as a cursor page ({data, next_cursor, …}). Pass next_cursor back as starting_after to fetch the next page. Filter by status, contact phone number, bsuid, or tag. Use whatsapp_get for one message's current state.
4134
+ * List the workspace's sending domains with their verification status, as a cursor page.
4154
4135
  *
4155
- * @example Iterate delivered messages
4156
- * for await (const msg of bird.whatsapp.list({ status: ["delivered"] })) {
4157
- * console.log(msg.id, msg.status);
4136
+ * @example Iterate every sending domain
4137
+ * for await (const domain of bird.domains.list()) {
4138
+ * console.log(domain.id, domain.status);
4158
4139
  * }
4159
4140
  */
4160
4141
  list(query, options) {
4161
- return this.paginated("GET", options, ({ signal, headers }, cursor) => listWhatsAppMessages({
4142
+ return this.paginated("GET", options, ({ signal, headers }, cursor) => listDomains({
4162
4143
  client: this.client,
4163
4144
  query: {
4164
4145
  ...query,
@@ -4169,174 +4150,97 @@ var WhatsappResourceBase = class extends Resource {
4169
4150
  }));
4170
4151
  }
4171
4152
  /**
4172
- * Get one WhatsApp message's delivery timeline, oldest first: whatsapp.accepted, whatsapp.sent, whatsapp.delivered, whatsapp.read, and whatsapp.failed events, with failure detail on failed events. Not paginated; an unknown message id is a 404. Use whatsapp_get for the condensed current status.
4153
+ * Fetch one sending domain: verification status and the DNS records with their individual verification states.
4173
4154
  *
4174
- * @example Read one message's delivery timeline
4175
- * const { data } = await bird.whatsapp.listEvents("wa_abc123");
4176
- * for (const event of data) console.log(event.type, event.occurred_at);
4155
+ * @example Fetch a sending domain by id
4156
+ * const domain = await bird.domains.get("dom_01krdgeqcxet5s7t44vh8rt9mg");
4157
+ * console.log(domain.domain);
4177
4158
  */
4178
- listEvents(messageId, query, options) {
4179
- return this.call("GET", options, ({ signal, headers }) => listWhatsAppMessageEvents({
4159
+ get(domainId, options) {
4160
+ return this.call("GET", options, ({ signal, headers }) => getDomain({
4180
4161
  client: this.client,
4181
- path: { message_id: messageId },
4182
- query,
4162
+ path: { domain_id: domainId },
4183
4163
  headers,
4184
4164
  signal
4185
4165
  }));
4186
4166
  }
4187
- };
4188
- //#endregion
4189
- //#region src/resources/whatsapp.ts
4190
- var WhatsappResource = class extends WhatsappResourceBase {
4191
4167
  /**
4192
- * Send a template message. Bird selects the sender number from the
4193
- * template's category, so there is no sender field on the request. The
4194
- * result is `accepted`, not yet delivered — read it back with `get` to
4195
- * confirm.
4168
+ * Register a new sending domain and get the DNS records to publish. Flow: call this, publish the returned DNS records at your DNS provider, then call email_domains_verify (repeat until status is verified — DNS propagation can take minutes to hours).
4196
4169
  *
4197
- * @example
4198
- * const msg = await bird.whatsapp.send({
4199
- * to: "+15551234567",
4200
- * template: {
4201
- * name: "bird_otp",
4202
- * components: [
4203
- * { type: "body", parameters: [{ type: "text", text: "123456" }] },
4204
- * ],
4205
- * },
4206
- * });
4207
- * console.log(msg.id, msg.status);
4170
+ * @example Register a sending domain
4171
+ * const domain = await bird.domains.create({ domain: "mail.acme.com" });
4172
+ * console.log(domain.id, domain.status); // "dom_…", "pending"
4208
4173
  */
4209
- send(params, options) {
4210
- return this.call("POST", options, ({ signal, headers }) => sendWhatsAppMessage({
4174
+ create(params, options) {
4175
+ return this.call("POST", options, ({ signal, headers }) => createDomain({
4211
4176
  client: this.client,
4212
4177
  body: params,
4213
4178
  headers,
4214
4179
  signal
4215
4180
  }));
4216
4181
  }
4217
- };
4218
- //#endregion
4219
- //#region src/resources/verifyVerifications.gen.ts
4220
- var VerifyVerificationsResource = class extends Resource {
4221
4182
  /**
4222
- * Start a verification: generate a one-time passcode and send it to the recipient in `to` (a phone number over SMS, an email address over email, or both; with both, it is sent over one channel and fails over to the other, not to both at once). Calling again for the same recipient reuses the in-progress verification and sends a fresh code after the resend cooldown; it does not start a second one, so use this both to send and to resend. The passcode is never returned; submit what the recipient enters with verify_verifications_check. SMS delivery draws on the workspace's SMS balance.
4183
+ * Trigger a DNS verification check for a sending domain and return the refreshed domain with per-record results. Safe to repeat while waiting for DNS propagation.
4223
4184
  *
4224
- * @example Start a verification over SMS
4225
- * const verification = await bird.verify.verifications.create({
4226
- * to: { phone_number: "+15551234567" },
4227
- * });
4228
- * console.log(verification.id, verification.status);
4185
+ * @example Re-run the DNS verification check
4186
+ * const domain = await bird.domains.verify("dom_01krdgeqcxet5s7t44vh8rt9mg");
4187
+ * console.log(domain.status); // "verified" once DNS is in place
4229
4188
  */
4230
- create(params, options) {
4231
- return this.call("POST", options, ({ signal, headers }) => createVerification({
4189
+ verify(domainId, options) {
4190
+ return this.call("POST", options, ({ signal, headers }) => verifyDomain({
4232
4191
  client: this.client,
4233
- body: params,
4192
+ path: { domain_id: domainId },
4234
4193
  headers,
4235
4194
  signal
4236
4195
  }));
4237
4196
  }
4238
4197
  /**
4239
- * Check a passcode a recipient submitted. Identify the verification by the same `to` recipient used to start it; no verification id needed. A wrong or expired code returns HTTP 200 with `success: false` and a `reason` (for example `incorrect_code` or `expired`), not an error. A verification that has already reached a final state is no longer checkable and returns 404, as does a missing verification; malformed input or rate limiting is also an error status.
4198
+ * Update a sending domain's tracking and inbound configuration. Tracking: toggle click_tracking and open_tracking (applied immediately to new sends), and set, change, or remove the tracking domain (the name part only — Bird appends the sending domain). Enabling either toggle with no tracking domain configured returns 409; removing the tracking domain while either toggle is still on also returns 409. Tracking-domain changes on a verified domain are staged behind DNS verification, so the current config keeps serving until the new records verify. Inbound receiving: set inbound.enabled to start or stop receiving mail for the domain. Enabling requires the domain's DKIM to be verified first (a fresh enable on an unverified domain returns 422), and a domain already receiving inbound for another organization returns 422. The MX records to publish are always listed in dns_records regardless, so enabling — not merely publishing them — is what turns receiving on.
4240
4199
  *
4241
- * @example Check a submitted passcode
4242
- * const result = await bird.verify.verifications.check({
4243
- * to: { phone_number: "+15551234567" },
4244
- * code: "123456",
4200
+ * @example Enable tracking on a domain
4201
+ * await bird.domains.update("dom_01krdgeqcxet5s7t44vh8rt9mg", {
4202
+ * settings: { click_tracking: true, open_tracking: true },
4203
+ * tracking: { name: "links" },
4245
4204
  * });
4246
- * console.log(result.success);
4247
4205
  */
4248
- check(params, options) {
4249
- return this.call("POST", options, ({ signal, headers }) => createVerificationCheck({
4206
+ update(domainId, params = {}, options) {
4207
+ return this.call("PATCH", options, ({ signal, headers }) => updateDomain({
4250
4208
  client: this.client,
4209
+ path: { domain_id: domainId },
4251
4210
  body: params,
4252
4211
  headers,
4253
- signal
4254
- }));
4255
- }
4256
- };
4257
- //#endregion
4258
- //#region src/resources/verify.ts
4259
- /** The Verify product namespace holds the `verifications` collection. */
4260
- var VerifyResource = class {
4261
- verifications;
4262
- constructor(...args) {
4263
- this.verifications = new VerifyVerificationsResource(...args);
4264
- }
4265
- };
4266
- //#endregion
4267
- //#region src/resources/webhooks.ts
4268
- var WebhooksResource = class {
4269
- #secret;
4270
- constructor(config) {
4271
- this.#secret = config?.secret;
4272
- }
4273
- /**
4274
- * Verify a webhook delivery and return the typed event.
4275
- *
4276
- * **Pass the raw request body**, exactly as received — do NOT parse it first.
4277
- * The Standard Webhooks signature is computed over the raw bytes, so parsing
4278
- * and re-serializing before verifying is the classic webhook bug.
4279
- *
4280
- * The secret comes from `webhooks.secret` on the client; pass `{ secret }` to
4281
- * override per call. Throws {@link BirdWebhookVerificationError} on a bad
4282
- * signature, a stale timestamp, or missing/malformed headers. Unknown event
4283
- * types are returned as-is (handle them in a `default` case) so a newer server
4284
- * event can't break an older SDK.
4285
- *
4286
- * @example One call verifies the signature and returns the typed event
4287
- * // Pass the RAW request body; set the secret via new BirdClient({ webhooks: { secret } }).
4288
- * const event = bird.webhooks.unwrap(rawBody, headers);
4289
- * console.log(event.type); // discriminated union: narrow on event.type
4290
- *
4291
- * @example Verify and dispatch: pass the raw request body, never the parsed JSON
4292
- * // new BirdClient({ apiKey, webhooks: { secret } })
4293
- * try {
4294
- * const event = bird.webhooks.unwrap(rawBody, req.headers);
4295
- * switch (event.type) {
4296
- * case "email.delivered":
4297
- * markDelivered(event.data.email_id, event.data.recipient); // narrowed by event.type
4298
- * break;
4299
- * case "email.bounced":
4300
- * case "email.complained":
4301
- * suppress(event.data.recipient);
4302
- * break;
4303
- * default: // unknown future event types — an older SDK won't break on a new one
4304
- * }
4305
- * } catch (err) {
4306
- * if (err instanceof BirdWebhookVerificationError) {
4307
- * // reject with 400 — bad signature, stale timestamp, or missing/malformed headers
4308
- * } else throw err;
4309
- * }
4310
- */
4311
- unwrap(payload, headers, options) {
4312
- const secret = options?.secret ?? this.#secret;
4313
- if (!secret) throw new Error("No webhook secret. Set `webhooks: { secret }` on the client, or pass `{ secret }` to unwrap.");
4314
- const wh = new Webhook(secret);
4315
- let verified;
4316
- try {
4317
- verified = wh.verify(payload, toHeaderRecord(headers));
4318
- } catch (err) {
4319
- throw new BirdWebhookVerificationError(err instanceof Error ? err.message : "Webhook signature verification failed");
4320
- }
4321
- return verified;
4212
+ signal
4213
+ }));
4214
+ }
4215
+ /**
4216
+ * Delete a sending domain by id. Revokes its sender authorization: new sends from the domain are rejected afterward, while historical statistics and events for past sends are preserved. Destructive.
4217
+ *
4218
+ * @example Delete a sending domain by id
4219
+ * await bird.domains.delete("dom_01krdgeqcxet5s7t44vh8rt9mg");
4220
+ */
4221
+ delete(domainId, options) {
4222
+ return this.call("DELETE", options, ({ signal, headers }) => deleteDomain({
4223
+ client: this.client,
4224
+ path: { domain_id: domainId },
4225
+ headers,
4226
+ signal
4227
+ }));
4322
4228
  }
4323
4229
  };
4324
- function toHeaderRecord(headers) {
4325
- return headers instanceof Headers ? Object.fromEntries(headers) : headers;
4326
- }
4327
4230
  //#endregion
4328
- //#region src/resources/mailbox.gen.ts
4329
- var MailboxResourceBase = class extends Resource {
4231
+ //#region src/resources/contactProperties.gen.ts
4232
+ var ContactPropertiesResource = class extends Resource {
4330
4233
  /**
4331
- * List the workspace's mailboxes as a cursor page, newest first. Search addresses and display names with q, or filter by exact address, state, or domain.
4234
+ * List the workspace's contact properties as a cursor page, newest first. Archived properties are included, marked by their archived flag.
4332
4235
  *
4333
- * @example List mailboxes
4334
- * for await (const mailbox of bird.mailbox.list()) {
4335
- * console.log(mailbox.address);
4236
+ * @example Iterate every contact property, or take one page
4237
+ * for await (const prop of bird.contactProperties.list()) {
4238
+ * console.log(prop.key, prop.type);
4336
4239
  * }
4240
+ * const page = await bird.contactProperties.list({ limit: 50 }); // page.data, page.next_cursor
4337
4241
  */
4338
4242
  list(query, options) {
4339
- return this.paginated("GET", options, ({ signal, headers }, cursor) => listMailboxes({
4243
+ return this.paginated("GET", options, ({ signal, headers }, cursor) => listContactProperties({
4340
4244
  client: this.client,
4341
4245
  query: {
4342
4246
  ...query,
@@ -4347,143 +4251,182 @@ var MailboxResourceBase = class extends Resource {
4347
4251
  }));
4348
4252
  }
4349
4253
  /**
4350
- * Create a mailbox a durable agent identity that owns an email address, groups mail into threads, and remembers conversations for its retention tier.
4254
+ * Get a single contact property by ID: key, type, fallback value, and archived state.
4351
4255
  *
4352
- * @example Create a mailbox
4353
- * const mailbox = await bird.mailbox.create({ display_name: "Support" });
4354
- * console.log(mailbox.address); // "abc123@inbox.ai"
4256
+ * @example Fetch a contact property by id
4257
+ * const prop = await bird.contactProperties.get("cp_01krdgeqcxet5s7t44vh8rt9mg");
4258
+ * console.log(prop.key, prop.type);
4355
4259
  */
4356
- create(params = {}, options) {
4357
- return this.call("POST", options, ({ signal, headers }) => createMailbox({
4260
+ get(propertyId, options) {
4261
+ return this.call("GET", options, ({ signal, headers }) => getContactProperty({
4358
4262
  client: this.client,
4359
- body: params,
4263
+ path: { property_id: propertyId },
4360
4264
  headers,
4361
4265
  signal
4362
4266
  }));
4363
4267
  }
4364
4268
  /**
4365
- * @example Get a mailbox
4366
- * const mailbox = await bird.mailbox.get("mbx_01abc");
4367
- * console.log(mailbox.state); // "active"
4269
+ * Define a custom contact property (key + value type) that becomes available in contact data and as a broadcast template variable. The key and type cannot change after creation; a workspace holds at most 200 properties, archived included.
4270
+ *
4271
+ * @example Define a custom property
4272
+ * const prop = await bird.contactProperties.create({ key: "plan", type: "string" });
4273
+ * console.log(prop.id); // "cp_…"
4368
4274
  */
4369
- get(mailboxId, options) {
4370
- return this.call("GET", options, ({ signal, headers }) => getMailbox({
4275
+ create(params, options) {
4276
+ return this.call("POST", options, ({ signal, headers }) => createContactProperty({
4371
4277
  client: this.client,
4372
- path: { mailbox_id: mailboxId },
4278
+ body: params,
4373
4279
  headers,
4374
4280
  signal
4375
4281
  }));
4376
4282
  }
4377
4283
  /**
4378
- * Update a mailbox's display name, reply-to, receive policy, retention tier, contact, or metadata. Lowering the retention tier onto remembered messages older than the new horizon requires confirm=true.
4284
+ * Update a contact property's fallback value. The key and type are immutable; create a new property instead.
4379
4285
  *
4380
- * @example Change a mailbox's receive policy
4381
- * const mailbox = await bird.mailbox.update("mbx_01abc", {
4382
- * receive_policy: "open",
4383
- * });
4384
- * console.log(mailbox.id, mailbox.receive_policy);
4286
+ * @example Change a property's fallback value
4287
+ * await bird.contactProperties.update("cp_01krdgeqcxet5s7t44vh8rt9mg", { fallback_value: "free" });
4385
4288
  */
4386
- update(mailboxId, params = {}, query, options) {
4387
- return this.call("PATCH", options, ({ signal, headers }) => updateMailbox({
4289
+ update(propertyId, params = {}, options) {
4290
+ return this.call("PATCH", options, ({ signal, headers }) => updateContactProperty({
4388
4291
  client: this.client,
4389
- path: { mailbox_id: mailboxId },
4292
+ path: { property_id: propertyId },
4390
4293
  body: params,
4391
- query,
4392
4294
  headers,
4393
4295
  signal
4394
4296
  }));
4395
4297
  }
4396
4298
  /**
4397
- * Delete a mailbox. The address stops receiving immediately and is quarantined; the mailbox and its remembered messages stay restorable for 30 days via the restore endpoint, then are permanently deleted.
4299
+ * Archive a contact property: the key is rejected in new contact writes and stops rendering in templates, while stored values remain readable. The key stays reserved and counts toward the 200-property limit; reverse with `contact_properties.unarchive`.
4398
4300
  *
4399
- * @example Delete a mailbox
4400
- * await bird.mailbox.delete("mbx_01abc");
4301
+ * @example Archive a property, retiring the field without deleting its data
4302
+ * const prop = await bird.contactProperties.archive("cp_01krdgeqcxet5s7t44vh8rt9mg");
4303
+ * console.log(prop.key, prop.archived);
4401
4304
  */
4402
- delete(mailboxId, options) {
4403
- return this.call("DELETE", options, ({ signal, headers }) => deleteMailbox({
4305
+ archive(propertyId, options) {
4306
+ return this.call("POST", options, ({ signal, headers }) => archiveContactProperty({
4404
4307
  client: this.client,
4405
- path: { mailbox_id: mailboxId },
4308
+ path: { property_id: propertyId },
4406
4309
  headers,
4407
4310
  signal
4408
4311
  }));
4409
4312
  }
4410
4313
  /**
4411
- * Restore a mailbox deleted less than 30 days ago: the address starts receiving again and the remembered messages are back. Past the window the mailbox is permanently deleted and returns 404; a mailbox that is not deleted returns 409.
4314
+ * Reactivate an archived contact property so its key is accepted in contact writes and renders in templates again. Fails with a conflict if the property is not archived.
4412
4315
  *
4413
- * @example Restore a deleted mailbox
4414
- * const mailbox = await bird.mailbox.restore("mbx_01abc");
4415
- * console.log(mailbox.deleted_at); // null
4316
+ * @example Restore an archived property
4317
+ * await bird.contactProperties.unarchive("cp_01krdgeqcxet5s7t44vh8rt9mg");
4416
4318
  */
4417
- restore(mailboxId, options) {
4418
- return this.call("POST", options, ({ signal, headers }) => restoreMailbox({
4319
+ unarchive(propertyId, options) {
4320
+ return this.call("POST", options, ({ signal, headers }) => unarchiveContactProperty({
4419
4321
  client: this.client,
4420
- path: { mailbox_id: mailboxId },
4322
+ path: { property_id: propertyId },
4421
4323
  headers,
4422
4324
  signal
4423
4325
  }));
4424
4326
  }
4327
+ };
4328
+ //#endregion
4329
+ //#region src/resources/contacts.gen.ts
4330
+ var ContactsResource = class extends Resource {
4425
4331
  /**
4426
- * Reactivate a suspended mailbox so it can send and receive again and its threads become visible. Fails if your plan does not have room for another active mailbox (or another custom inbox.ai handle); delete an active mailbox or upgrade first. A mailbox that is not suspended returns 409.
4332
+ * List the workspace's contacts as a cursor page, newest first. Look one up by exact email or external_id, or search by email substring.
4427
4333
  *
4428
- * @example Resume a suspended mailbox
4429
- * const mailbox = await bird.mailbox.resume("mbx_01abc");
4430
- * console.log(mailbox.state); // "active"
4334
+ * @example Iterate every contact, or take one page
4335
+ * for await (const contact of bird.contacts.list({ q: "acme.com" })) {
4336
+ * console.log(contact.id, contact.email);
4337
+ * }
4338
+ * const page = await bird.contacts.list({ limit: 50 }); // page.data, page.next_cursor
4431
4339
  */
4432
- resume(mailboxId, options) {
4433
- return this.call("POST", options, ({ signal, headers }) => resumeMailbox({
4340
+ list(query, options) {
4341
+ return this.paginated("GET", options, ({ signal, headers }, cursor) => listContacts({
4434
4342
  client: this.client,
4435
- path: { mailbox_id: mailboxId },
4343
+ query: {
4344
+ ...query,
4345
+ starting_after: cursor ?? query?.starting_after
4346
+ },
4436
4347
  headers,
4437
4348
  signal
4438
4349
  }));
4439
4350
  }
4440
4351
  /**
4441
- * @example Get mailbox stats
4442
- * const stats = await bird.mailbox.stats("mbx_01abc");
4443
- * console.log(stats.summary?.sends_accepted);
4352
+ * Get a single contact by ID (`con_`-prefixed). Look up an ID by exact email or external_id with `contacts.list`.
4353
+ *
4354
+ * @example Fetch a contact by id
4355
+ * const contact = await bird.contacts.get("con_01krdgeqcxet5s7t44vh8rt9mg");
4356
+ * console.log(contact.email, contact.first_name);
4444
4357
  */
4445
- stats(mailboxId, query, options) {
4446
- return this.call("GET", options, ({ signal, headers }) => getMailboxStats({
4358
+ get(contactId, options) {
4359
+ return this.call("GET", options, ({ signal, headers }) => getContact({
4447
4360
  client: this.client,
4448
- path: { mailbox_id: mailboxId },
4449
- query,
4361
+ path: { contact_id: contactId },
4450
4362
  headers,
4451
4363
  signal
4452
4364
  }));
4453
4365
  }
4454
4366
  /**
4455
- * List the labels available in a mailbox: the built-in system labels (inbox, archive, spam, blocked, sent, trash, unread) plus every custom label in use.
4367
+ * Create a contact by email address in the workspace. Fails with a conflict if the email or external_id is already used by another contact. For bulk import or create-or-update semantics use `contacts.batch`.
4456
4368
  *
4457
- * @example List a mailbox's labels
4458
- * const labels = await bird.mailbox.labels("mbx_01abc");
4459
- * console.log(labels.data.map((label) => label.name));
4369
+ * @example Create a contact
4370
+ * const contact = await bird.contacts.create({
4371
+ * email: "jane@acme.com",
4372
+ * first_name: "Jane",
4373
+ * });
4374
+ * console.log(contact.id); // "con_…"
4460
4375
  */
4461
- labels(mailboxId, options) {
4462
- return this.call("GET", options, ({ signal, headers }) => listMailboxLabels({
4376
+ create(params, options) {
4377
+ return this.call("POST", options, ({ signal, headers }) => createContact({
4463
4378
  client: this.client,
4464
- path: { mailbox_id: mailboxId },
4379
+ body: params,
4465
4380
  headers,
4466
4381
  signal
4467
4382
  }));
4468
4383
  }
4469
- };
4470
- //#endregion
4471
- //#region src/resources/mailbox.ts
4472
- var MailboxResource = class extends MailboxResourceBase {
4473
4384
  /**
4474
- * Send a new email from this mailbox, starting a new conversation.
4385
+ * Update a contact's name, external_id, email, or custom data. Only supplied fields change; custom data keys are merged, with null removing a key.
4475
4386
  *
4476
- * @example Send from a mailbox
4477
- * const msg = await bird.mailbox.compose("mbx_01abc", {
4478
- * to: ["customer@example.com"],
4479
- * subject: "Hello",
4480
- * text: "Hi there!",
4387
+ * @example Change a contact's fields
4388
+ * const contact = await bird.contacts.update("con_01krdgeqcxet5s7t44vh8rt9mg", {
4389
+ * first_name: "Jane",
4481
4390
  * });
4391
+ * console.log(contact.first_name);
4482
4392
  */
4483
- compose(mailboxId, params, options) {
4484
- return this.call("POST", options, ({ signal, headers }) => createMailboxMessage({
4393
+ update(contactId, params = {}, options) {
4394
+ return this.call("PATCH", options, ({ signal, headers }) => updateContact({
4395
+ client: this.client,
4396
+ path: { contact_id: contactId },
4397
+ body: params,
4398
+ headers,
4399
+ signal
4400
+ }));
4401
+ }
4402
+ /**
4403
+ * Delete a contact and remove it from every audience it belongs to. Suppression records for the address are unaffected.
4404
+ *
4405
+ * @example Delete a contact by id
4406
+ * await bird.contacts.delete("con_01krdgeqcxet5s7t44vh8rt9mg");
4407
+ */
4408
+ delete(contactId, options) {
4409
+ return this.call("DELETE", options, ({ signal, headers }) => deleteContact({
4410
+ client: this.client,
4411
+ path: { contact_id: contactId },
4412
+ headers,
4413
+ signal
4414
+ }));
4415
+ }
4416
+ /**
4417
+ * Create or update up to 1,000 contacts in one request, matched by email address, and optionally add them all to one or more audiences. Per-contact results are returned in submission order.
4418
+ *
4419
+ * @example Create or update many contacts at once, matched by email
4420
+ * const result = await bird.contacts.batch({
4421
+ * contacts: [{ email: "jane@acme.com", first_name: "Jane" }],
4422
+ * });
4423
+ * for (const item of result.data) {
4424
+ * console.log(item.email, item.status);
4425
+ * }
4426
+ */
4427
+ batch(params, options) {
4428
+ return this.call("POST", options, ({ signal, headers }) => createContactBatch({
4485
4429
  client: this.client,
4486
- path: { mailbox_id: mailboxId },
4487
4430
  body: params,
4488
4431
  headers,
4489
4432
  signal
@@ -4491,20 +4434,34 @@ var MailboxResource = class extends MailboxResourceBase {
4491
4434
  }
4492
4435
  };
4493
4436
  //#endregion
4494
- //#region src/resources/mailboxReceiveRule.gen.ts
4495
- var MailboxReceiveRuleResource = class extends Resource {
4437
+ //#region src/resources/sms.gen.ts
4438
+ var SmsResourceBase = class extends Resource {
4496
4439
  /**
4497
- * List a mailbox's allow/block receive rules as a cursor page, oldest first. Filter by action.
4440
+ * Get one SMS message by id: its current delivery status, segment breakdown, cost, and failure detail if it failed.
4498
4441
  *
4499
- * @example List a mailbox's receive rules
4500
- * for await (const rule of bird.mailboxReceiveRule.list("mbx_01abc")) {
4501
- * console.log(rule.action, rule.entry);
4442
+ * @example Read a message back
4443
+ * const msg = await bird.sms.get("sms_abc123");
4444
+ * msg.status; // "accepted" | "delivered" | …
4445
+ */
4446
+ get(messageId, options) {
4447
+ return this.call("GET", options, ({ signal, headers }) => getSmsMessage({
4448
+ client: this.client,
4449
+ path: { message_id: messageId },
4450
+ headers,
4451
+ signal
4452
+ }));
4453
+ }
4454
+ /**
4455
+ * List SMS messages, newest first, as a cursor page ({data, next_cursor, …}). Pass next_cursor back as starting_after to fetch the next page. Filter by direction, status, category, recipient, sender, or tag.
4456
+ *
4457
+ * @example Iterate outbound messages
4458
+ * for await (const msg of bird.sms.list({ direction: "outbound" })) {
4459
+ * console.log(msg.id, msg.status);
4502
4460
  * }
4503
4461
  */
4504
- list(mailboxId, query, options) {
4505
- return this.paginated("GET", options, ({ signal, headers }, cursor) => listMailboxReceiveRules({
4462
+ list(query, options) {
4463
+ return this.paginated("GET", options, ({ signal, headers }, cursor) => listSmsMessages({
4506
4464
  client: this.client,
4507
- path: { mailbox_id: mailboxId },
4508
4465
  query: {
4509
4466
  ...query,
4510
4467
  starting_after: cursor ?? query?.starting_after
@@ -4513,129 +4470,121 @@ var MailboxReceiveRuleResource = class extends Resource {
4513
4470
  signal
4514
4471
  }));
4515
4472
  }
4473
+ };
4474
+ //#endregion
4475
+ //#region src/resources/sms.ts
4476
+ /** Filters and cursor params for `bird.sms.list`. */
4477
+ var SmsResource = class extends SmsResourceBase {
4516
4478
  /**
4517
- * Add an allow or block rule for a sender address or domain to a mailbox. Block always wins; up to 200 rules per mailbox.
4479
+ * Send one SMS to a single recipient. Supply either `text` (with a `category`)
4480
+ * or a stored `template` (by `id` or `name`, with its `parameters`). The
4481
+ * result is `accepted`, not yet delivered — read it back with `get` to confirm.
4518
4482
  *
4519
- * @example Block a domain
4520
- * const rule = await bird.mailboxReceiveRule.create("mbx_01abc", {
4521
- * action: "block",
4522
- * entry: "spam.example.com",
4483
+ * @example Send free text
4484
+ * const msg = await bird.sms.send({
4485
+ * from: "MyBrand",
4486
+ * to: "+14155550100",
4487
+ * text: "Your verification code is 123456.",
4488
+ * category: "authentication",
4489
+ * });
4490
+ * console.log(msg.id, msg.status);
4491
+ *
4492
+ * @example Send by template
4493
+ * await bird.sms.send({
4494
+ * to: "+14155550100",
4495
+ * template: { name: "bird_otp_verification", parameters: { code: "123456" } },
4523
4496
  * });
4524
- * console.log(rule.id);
4525
4497
  */
4526
- create(mailboxId, params, options) {
4527
- return this.call("POST", options, ({ signal, headers }) => createMailboxReceiveRule({
4498
+ send(params, options) {
4499
+ return this.call("POST", options, ({ signal, headers }) => createSmsMessage({
4528
4500
  client: this.client,
4529
- path: { mailbox_id: mailboxId },
4530
4501
  body: params,
4531
4502
  headers,
4532
4503
  signal
4533
4504
  }));
4534
4505
  }
4535
4506
  /**
4536
- * Remove a receive rule from a mailbox. Delete-and-recreate is how an entry's action is flipped.
4507
+ * Send up to 100 independent SMS messages in one call. Each item is a full send
4508
+ * (free text or template); all items are validated before any are queued.
4537
4509
  *
4538
- * @example Delete a rule
4539
- * await bird.mailboxReceiveRule.delete("mbx_01abc", "erl_01xyz");
4510
+ * @example
4511
+ * const result = await bird.sms.sendBatch([
4512
+ * { to: "+15551111111", text: "Hi Alice!", category: "marketing" },
4513
+ * { to: "+15552222222", text: "Hi Bob!", category: "marketing" },
4514
+ * ]);
4540
4515
  */
4541
- delete(mailboxId, ruleId, options) {
4542
- return this.call("DELETE", options, ({ signal, headers }) => deleteMailboxReceiveRule({
4516
+ sendBatch(params, options) {
4517
+ return this.call("POST", options, ({ signal, headers }) => createSmsMessageBatch({
4543
4518
  client: this.client,
4544
- path: {
4545
- mailbox_id: mailboxId,
4546
- rule_id: ruleId
4547
- },
4519
+ body: params,
4548
4520
  headers,
4549
4521
  signal
4550
4522
  }));
4551
4523
  }
4552
4524
  };
4553
4525
  //#endregion
4554
- //#region src/resources/mailboxThread.gen.ts
4555
- var MailboxThreadResource = class extends Resource {
4526
+ //#region src/resources/smsTemplates.gen.ts
4527
+ var SmsTemplatesResource = class extends Resource {
4556
4528
  /**
4557
- * List mailbox conversations as a cursor page, most recently active first. `label` selects the view inbox (default), archive, spam, blocked, or a custom label. Filter by mailbox, contact, participant address, or subject substring.
4529
+ * List the SMS templates available to your workspace, including Bird's built-in templates. Filter by scope, category, or language. The catalogue is small and returned in full; this list is not paginated. Use sms_templates_get to read one template's variables before sending with it.
4558
4530
  *
4559
- * @example List conversation threads
4560
- * for await (const thread of bird.mailboxThread.list({ mailbox_id: "mbx_01abc" })) {
4561
- * console.log(thread.id, thread.subject);
4562
- * }
4531
+ * @example List the built-in templates
4532
+ * const { data } = await bird.smsTemplates.list({ scope: "system" });
4533
+ * for (const tpl of data) console.log(tpl.id, tpl.name);
4563
4534
  */
4564
4535
  list(query, options) {
4565
- return this.paginated("GET", options, ({ signal, headers }, cursor) => listEmailThreads({
4566
- client: this.client,
4567
- query: {
4568
- ...query,
4569
- starting_after: cursor ?? query?.starting_after
4570
- },
4571
- headers,
4572
- signal
4573
- }));
4574
- }
4575
- /**
4576
- * Get one conversation: participants, counts, labels, read state. Fetch its messages with the thread messages endpoint.
4577
- *
4578
- * @example Get a thread
4579
- * const thread = await bird.mailboxThread.get("thr_01abc");
4580
- * console.log(thread.subject);
4581
- */
4582
- get(threadId, options) {
4583
- return this.call("GET", options, ({ signal, headers }) => getEmailThread({
4536
+ return this.call("GET", options, ({ signal, headers }) => listSmsTemplates({
4584
4537
  client: this.client,
4585
- path: { thread_id: threadId },
4538
+ query,
4586
4539
  headers,
4587
4540
  signal
4588
4541
  }));
4589
4542
  }
4590
4543
  /**
4591
- * Add or remove labels on a conversation adding `spam` files it as spam, adding `archive` clears it out of the inbox, adding `inbox` brings it back or link/unlink a contact.
4544
+ * Get one SMS template by its name or id, including its body and the variables it expects. Fetch it before sms_send to see which parameter keys a template send requires.
4592
4545
  *
4593
- * @example Apply label changes to a thread
4594
- * const thread = await bird.mailboxThread.update("thr_01abc", {
4595
- * labels: { add: ["archive"] },
4596
- * });
4597
- * console.log(thread.id);
4546
+ * @example Read one template by name or id
4547
+ * const tpl = await bird.smsTemplates.get("bird_otp_verification");
4548
+ * console.log(tpl.body, tpl.variables);
4598
4549
  */
4599
- update(threadId, params = {}, options) {
4600
- return this.call("PATCH", options, ({ signal, headers }) => updateEmailThread({
4550
+ get(templateRef, options) {
4551
+ return this.call("GET", options, ({ signal, headers }) => getSmsTemplate({
4601
4552
  client: this.client,
4602
- path: { thread_id: threadId },
4603
- body: params,
4553
+ path: { template_ref: templateRef },
4604
4554
  headers,
4605
4555
  signal
4606
4556
  }));
4607
4557
  }
4558
+ };
4559
+ //#endregion
4560
+ //#region src/resources/whatsapp.gen.ts
4561
+ var WhatsappResourceBase = class extends Resource {
4608
4562
  /**
4609
- * Move a conversation and all its messages to trash (purged after 30 days), or delete permanently with ?permanent=true.
4563
+ * Get one WhatsApp message by id: current delivery status, sent/delivered/read timestamps, the template it was sent from, and failure detail if it failed. For the per-event timeline use whatsapp_list_events.
4610
4564
  *
4611
- * @example Delete a thread
4612
- * await bird.mailboxThread.delete("thr_01abc", { permanent: true });
4565
+ * @example Read a message back
4566
+ * const msg = await bird.whatsapp.get("wa_abc123");
4567
+ * msg.status; // "accepted" | "delivered" | …
4613
4568
  */
4614
- delete(threadId, query, options) {
4615
- return this.call("DELETE", options, ({ signal, headers }) => deleteEmailThread({
4569
+ get(messageId, options) {
4570
+ return this.call("GET", options, ({ signal, headers }) => getWhatsAppMessage({
4616
4571
  client: this.client,
4617
- path: { thread_id: threadId },
4618
- query,
4572
+ path: { message_id: messageId },
4619
4573
  headers,
4620
4574
  signal
4621
4575
  }));
4622
4576
  }
4623
- };
4624
- //#endregion
4625
- //#region src/resources/mailboxThreadMessage.gen.ts
4626
- var MailboxThreadMessageResource = class extends Resource {
4627
4577
  /**
4628
- * List the messages in a conversation newest first, both directions. Page older messages with starting_after, and pass include=extracted_text to inline each message's durable plain text.
4578
+ * List WhatsApp messages, newest first, as a cursor page ({data, next_cursor, …}). Pass next_cursor back as starting_after to fetch the next page. Filter by status, contact phone number, bsuid, or tag. Use whatsapp_get for one message's current state.
4629
4579
  *
4630
- * @example List a thread's messages
4631
- * for await (const msg of bird.mailboxThreadMessage.list("thr_01abc")) {
4632
- * console.log(msg.id, msg.direction);
4580
+ * @example Iterate delivered messages
4581
+ * for await (const msg of bird.whatsapp.list({ status: ["delivered"] })) {
4582
+ * console.log(msg.id, msg.status);
4633
4583
  * }
4634
4584
  */
4635
- list(threadId, query, options) {
4636
- return this.paginated("GET", options, ({ signal, headers }, cursor) => listEmailThreadMessages({
4585
+ list(query, options) {
4586
+ return this.paginated("GET", options, ({ signal, headers }, cursor) => listWhatsAppMessages({
4637
4587
  client: this.client,
4638
- path: { thread_id: threadId },
4639
4588
  query: {
4640
4589
  ...query,
4641
4590
  starting_after: cursor ?? query?.starting_after
@@ -4645,82 +4594,162 @@ var MailboxThreadMessageResource = class extends Resource {
4645
4594
  }));
4646
4595
  }
4647
4596
  /**
4648
- * Get one conversation message with its extracted plain text readable for the mailbox's full retention period, no MIME parsing needed.
4597
+ * Get one WhatsApp message's delivery timeline, oldest first: whatsapp.accepted, whatsapp.sent, whatsapp.delivered, whatsapp.read, and whatsapp.failed events, with failure detail on failed events. Not paginated; an unknown message id is a 404. Use whatsapp_get for the condensed current status.
4649
4598
  *
4650
- * @example Get a message
4651
- * const msg = await bird.mailboxThreadMessage.get("thr_01abc", "rem_01xyz");
4652
- * console.log(msg.direction); // "inbound"
4599
+ * @example Read one message's delivery timeline
4600
+ * const { data } = await bird.whatsapp.listEvents("wa_abc123");
4601
+ * for (const event of data) console.log(event.type, event.occurred_at);
4653
4602
  */
4654
- get(threadId, messageId, options) {
4655
- return this.call("GET", options, ({ signal, headers }) => getEmailThreadMessage({
4603
+ listEvents(messageId, query, options) {
4604
+ return this.call("GET", options, ({ signal, headers }) => listWhatsAppMessageEvents({
4656
4605
  client: this.client,
4657
- path: {
4658
- thread_id: threadId,
4659
- message_id: messageId
4660
- },
4606
+ path: { message_id: messageId },
4607
+ query,
4661
4608
  headers,
4662
4609
  signal
4663
4610
  }));
4664
4611
  }
4612
+ };
4613
+ //#endregion
4614
+ //#region src/resources/whatsapp.ts
4615
+ var WhatsappResource = class extends WhatsappResourceBase {
4665
4616
  /**
4666
- * Get the original rendered HTML and plain-text body of a conversation message. Available 30 days; after that use the message's extracted_text.
4617
+ * Send a template message. Bird selects the sender number from the
4618
+ * template's category, so there is no sender field on the request. The
4619
+ * result is `accepted`, not yet delivered — read it back with `get` to
4620
+ * confirm.
4667
4621
  *
4668
- * @example Get a message body
4669
- * const body = await bird.mailboxThreadMessage.body("thr_01abc", "rem_01xyz");
4670
- * console.log(body.text);
4622
+ * @example
4623
+ * const msg = await bird.whatsapp.send({
4624
+ * to: "+15551234567",
4625
+ * template: {
4626
+ * name: "bird_otp",
4627
+ * components: [
4628
+ * { type: "body", parameters: [{ type: "text", text: "123456" }] },
4629
+ * ],
4630
+ * },
4631
+ * });
4632
+ * console.log(msg.id, msg.status);
4671
4633
  */
4672
- body(threadId, messageId, options) {
4673
- return this.call("GET", options, ({ signal, headers }) => getEmailThreadMessageBody({
4634
+ send(params, options) {
4635
+ return this.call("POST", options, ({ signal, headers }) => sendWhatsAppMessage({
4674
4636
  client: this.client,
4675
- path: {
4676
- thread_id: threadId,
4677
- message_id: messageId
4678
- },
4637
+ body: params,
4679
4638
  headers,
4680
4639
  signal
4681
4640
  }));
4682
4641
  }
4642
+ };
4643
+ //#endregion
4644
+ //#region src/resources/verifyVerifications.gen.ts
4645
+ var VerifyVerificationsResource = class extends Resource {
4683
4646
  /**
4684
- * Reply to a specific conversation message from the mailbox's own address. To reply to a conversation, target its newest received message. Recipients, subject, and threading headers are derived automatically.
4647
+ * Start a verification: generate a one-time passcode and send it to the recipient in `to` (a phone number over SMS, an email address over email, or both; with both, it is sent over one channel and fails over to the other, not to both at once). Calling again for the same recipient reuses the in-progress verification and sends a fresh code after the resend cooldown; it does not start a second one, so use this both to send and to resend. The passcode is never returned; submit what the recipient enters with verify_verifications_check. SMS delivery draws on the workspace's SMS balance.
4685
4648
  *
4686
- * @example Reply to a message
4687
- * const reply = await bird.mailboxThreadMessage.reply("thr_01abc", "rem_01xyz", {
4688
- * text: "Thanks for reaching out!",
4649
+ * @example Start a verification over SMS
4650
+ * const verification = await bird.verify.verifications.create({
4651
+ * to: { phone_number: "+15551234567" },
4689
4652
  * });
4690
- * console.log(reply.id);
4653
+ * console.log(verification.id, verification.status);
4691
4654
  */
4692
- reply(threadId, messageId, params = {}, options) {
4693
- return this.call("POST", options, ({ signal, headers }) => replyEmailThreadMessage({
4655
+ create(params, options) {
4656
+ return this.call("POST", options, ({ signal, headers }) => createVerification({
4694
4657
  client: this.client,
4695
- path: {
4696
- thread_id: threadId,
4697
- message_id: messageId
4698
- },
4699
4658
  body: params,
4700
4659
  headers,
4701
4660
  signal
4702
4661
  }));
4703
4662
  }
4704
4663
  /**
4705
- * List the attachments on a conversation message. Bytes are downloadable for 30 days; the metadata also rides the message's attachment_manifest durably.
4664
+ * Check a passcode a recipient submitted. Identify the verification by the same `to` recipient used to start it; no verification id needed. A wrong or expired code returns HTTP 200 with `success: false` and a `reason` (for example `incorrect_code` or `expired`), not an error. A verification that has already reached a final state is no longer checkable and returns 404, as does a missing verification; malformed input or rate limiting is also an error status.
4706
4665
  *
4707
- * @example List a message's attachments
4708
- * const atts = await bird.mailboxThreadMessage.attachments("thr_01abc", "rem_01xyz");
4709
- * console.log(atts.data.map((a) => a.filename));
4666
+ * @example Check a submitted passcode
4667
+ * const result = await bird.verify.verifications.check({
4668
+ * to: { phone_number: "+15551234567" },
4669
+ * code: "123456",
4670
+ * });
4671
+ * console.log(result.success);
4710
4672
  */
4711
- attachments(threadId, messageId, options) {
4712
- return this.call("GET", options, ({ signal, headers }) => listEmailThreadMessageAttachments({
4673
+ check(params, options) {
4674
+ return this.call("POST", options, ({ signal, headers }) => createVerificationCheck({
4713
4675
  client: this.client,
4714
- path: {
4715
- thread_id: threadId,
4716
- message_id: messageId
4717
- },
4676
+ body: params,
4718
4677
  headers,
4719
4678
  signal
4720
4679
  }));
4721
4680
  }
4722
4681
  };
4723
4682
  //#endregion
4683
+ //#region src/resources/verify.ts
4684
+ /** The Verify product namespace — holds the `verifications` collection. */
4685
+ var VerifyResource = class {
4686
+ verifications;
4687
+ constructor(...args) {
4688
+ this.verifications = new VerifyVerificationsResource(...args);
4689
+ }
4690
+ };
4691
+ //#endregion
4692
+ //#region src/resources/webhooks.ts
4693
+ var WebhooksResource = class {
4694
+ #secret;
4695
+ constructor(config) {
4696
+ this.#secret = config?.secret;
4697
+ }
4698
+ /**
4699
+ * Verify a webhook delivery and return the typed event.
4700
+ *
4701
+ * **Pass the raw request body**, exactly as received — do NOT parse it first.
4702
+ * The Standard Webhooks signature is computed over the raw bytes, so parsing
4703
+ * and re-serializing before verifying is the classic webhook bug.
4704
+ *
4705
+ * The secret comes from `webhooks.secret` on the client; pass `{ secret }` to
4706
+ * override per call. Throws {@link BirdWebhookVerificationError} on a bad
4707
+ * signature, a stale timestamp, or missing/malformed headers. Unknown event
4708
+ * types are returned as-is (handle them in a `default` case) so a newer server
4709
+ * event can't break an older SDK.
4710
+ *
4711
+ * @example One call verifies the signature and returns the typed event
4712
+ * // Pass the RAW request body; set the secret via new BirdClient({ webhooks: { secret } }).
4713
+ * const event = bird.webhooks.unwrap(rawBody, headers);
4714
+ * console.log(event.type); // discriminated union: narrow on event.type
4715
+ *
4716
+ * @example Verify and dispatch: pass the raw request body, never the parsed JSON
4717
+ * // new BirdClient({ apiKey, webhooks: { secret } })
4718
+ * try {
4719
+ * const event = bird.webhooks.unwrap(rawBody, req.headers);
4720
+ * switch (event.type) {
4721
+ * case "email.delivered":
4722
+ * markDelivered(event.data.email_id, event.data.recipient); // narrowed by event.type
4723
+ * break;
4724
+ * case "email.bounced":
4725
+ * case "email.complained":
4726
+ * suppress(event.data.recipient);
4727
+ * break;
4728
+ * default: // unknown future event types — an older SDK won't break on a new one
4729
+ * }
4730
+ * } catch (err) {
4731
+ * if (err instanceof BirdWebhookVerificationError) {
4732
+ * // reject with 400 — bad signature, stale timestamp, or missing/malformed headers
4733
+ * } else throw err;
4734
+ * }
4735
+ */
4736
+ unwrap(payload, headers, options) {
4737
+ const secret = options?.secret ?? this.#secret;
4738
+ if (!secret) throw new Error("No webhook secret. Set `webhooks: { secret }` on the client, or pass `{ secret }` to unwrap.");
4739
+ const wh = new Webhook(secret);
4740
+ let verified;
4741
+ try {
4742
+ verified = wh.verify(payload, toHeaderRecord(headers));
4743
+ } catch (err) {
4744
+ throw new BirdWebhookVerificationError(err instanceof Error ? err.message : "Webhook signature verification failed");
4745
+ }
4746
+ return verified;
4747
+ }
4748
+ };
4749
+ function toHeaderRecord(headers) {
4750
+ return headers instanceof Headers ? Object.fromEntries(headers) : headers;
4751
+ }
4752
+ //#endregion
4724
4753
  //#region src/resources/realtime.ts
4725
4754
  var RealtimeBase = class extends Resource {
4726
4755
  #config;
@@ -5002,14 +5031,6 @@ var BirdClient = class {
5002
5031
  domains;
5003
5032
  /** Webhooks — `bird.webhooks.unwrap(payload, headers)` verifies an inbound delivery. */
5004
5033
  webhooks;
5005
- /** Agent mailboxes — `bird.mailbox.create(...)`, `.compose(...)`, `.list(...)`, … */
5006
- mailbox;
5007
- /** Mailbox receive rules — `bird.mailboxReceiveRule.create(...)`, `.delete(...)`, `.list(...)`. */
5008
- mailboxReceiveRule;
5009
- /** Mailbox threads — `bird.mailboxThread.list(...)`, `.get(...)`, `.update(...)`, `.delete(...)`. */
5010
- mailboxThread;
5011
- /** Thread messages — `bird.mailboxThreadMessage.list(...)`, `.get(...)`, `.reply(...)`, `.body(...)`, … */
5012
- mailboxThreadMessage;
5013
5034
  /** Realtime — `bird.realtime.publish(...)`, `.channels.list(...)`, `.members.disconnect(...)`, … */
5014
5035
  realtime;
5015
5036
  constructor(options) {
@@ -5019,9 +5040,9 @@ var BirdClient = class {
5019
5040
  this.#headers = {
5020
5041
  ...opts.defaultHeaders,
5021
5042
  Authorization: `Bearer ${opts.apiKey}`,
5022
- "User-Agent": `bird-sdk-js/0.14.0`,
5043
+ "User-Agent": `bird-sdk-js/0.15.0`,
5023
5044
  "Bird-Surface": "sdk-js",
5024
- "Bird-Version": "0.14.0"
5045
+ "Bird-Version": "0.15.0"
5025
5046
  };
5026
5047
  const caller = detectCaller();
5027
5048
  if (caller) this.#headers["Bird-Caller"] = caller;
@@ -5044,10 +5065,6 @@ var BirdClient = class {
5044
5065
  this.contactProperties = new ContactPropertiesResource(this.core, this.#client);
5045
5066
  this.domains = new DomainsResource(this.core, this.#client);
5046
5067
  this.webhooks = new WebhooksResource(opts.webhooks);
5047
- this.mailbox = new MailboxResource(this.core, this.#client);
5048
- this.mailboxReceiveRule = new MailboxReceiveRuleResource(this.core, this.#client);
5049
- this.mailboxThread = new MailboxThreadResource(this.core, this.#client);
5050
- this.mailboxThreadMessage = new MailboxThreadMessageResource(this.core, this.#client);
5051
5068
  this.realtime = new RealtimeResource(this.core, this.#client, opts.realtime);
5052
5069
  }
5053
5070
  /**