@messagebird/sdk 0.29.0 → 0.30.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
@@ -334,9 +334,7 @@ async function setAuthParams(options) {
334
334
  case "cookie":
335
335
  options.headers.append("Cookie", `${name}=${token}`);
336
336
  break;
337
- default:
338
- options.headers.set(name, token);
339
- break;
337
+ default: options.headers.set(name, token);
340
338
  }
341
339
  }
342
340
  }
@@ -493,9 +491,7 @@ const createClient = (config = {}) => {
493
491
  case "stream":
494
492
  emptyData = response.body;
495
493
  break;
496
- default:
497
- emptyData = {};
498
- break;
494
+ default: emptyData = {};
499
495
  }
500
496
  return opts.responseStyle === "data" ? emptyData : {
501
497
  data: emptyData,
@@ -809,7 +805,6 @@ var BirdAPIError = class extends BirdError {
809
805
  vendorCode;
810
806
  remediation;
811
807
  next;
812
- unmetGates;
813
808
  constructor(fields) {
814
809
  super(fields.message);
815
810
  this.name = "BirdAPIError";
@@ -823,7 +818,6 @@ var BirdAPIError = class extends BirdError {
823
818
  this.vendorCode = fields.vendorCode;
824
819
  this.remediation = fields.remediation;
825
820
  this.next = fields.next;
826
- this.unmetGates = fields.unmetGates;
827
821
  Object.setPrototypeOf(this, new.target.prototype);
828
822
  }
829
823
  };
@@ -993,8 +987,7 @@ function mapResponseToError(status, body, headers) {
993
987
  param: b.param,
994
988
  vendorCode: b.vendor_code,
995
989
  remediation: b.remediation,
996
- next: b.next ?? [],
997
- unmetGates: b.unmet_gates ?? []
990
+ next: b.next ?? []
998
991
  };
999
992
  switch (fields.type) {
1000
993
  case "auth_error": return new BirdAuthError(fields);
@@ -1294,7 +1287,7 @@ const listRealtimeAppChannels = (options) => (options.client ?? client).get({
1294
1287
  /**
1295
1288
  * Get a Realtime channel
1296
1289
  *
1297
- * Returns a single channel's occupancy and (on request) counts. Channels exist implicitly — a channel appears when the first connection subscribes and vanishes when the last one leaves so this endpoint reports state, not existence: an unknown or never-used name returns 200 with `occupied: false`, never 404.
1290
+ * Returns a single channel's occupancy and optional counts. A channel appears when its first connection subscribes and disappears when its last connection leaves. An unknown or unused name returns `200 OK` with `occupied: false`.
1298
1291
  */
1299
1292
  const getRealtimeAppChannel = (options) => (options.client ?? client).get({
1300
1293
  security: [
@@ -1322,7 +1315,7 @@ const getRealtimeAppChannel = (options) => (options.client ?? client).get({
1322
1315
  /**
1323
1316
  * List members on a presence channel
1324
1317
  *
1325
- * Lists the member ids currently subscribed to a presence channel. Ids only: `member_info` (the profile data attached by your authorization endpoint) is delivered to subscribed clients over the realtime connection and is not available over REST.
1318
+ * Lists the member IDs currently subscribed to a presence channel. IDs only: `member_info` (the profile data attached by your authorization endpoint) is delivered to subscribed clients over the realtime connection and is not available over REST.
1326
1319
  */
1327
1320
  const listRealtimeAppChannelMembers = (options) => (options.client ?? client).get({
1328
1321
  security: [
@@ -1350,7 +1343,7 @@ const listRealtimeAppChannelMembers = (options) => (options.client ?? client).ge
1350
1343
  /**
1351
1344
  * Disconnect a member
1352
1345
  *
1353
- * Disconnects all of a member's active connections (e.g. on sign-out or ban).
1346
+ * Disconnects all of a member's active connections, for example on sign-out or ban.
1354
1347
  */
1355
1348
  const disconnectRealtimeAppMember = (options) => (options.client ?? client).post({
1356
1349
  security: [
@@ -1378,8 +1371,13 @@ const disconnectRealtimeAppMember = (options) => (options.client ?? client).post
1378
1371
  /**
1379
1372
  * Send an event to a member
1380
1373
  *
1381
- * Delivers an event to one member of a Realtime app, addressing the person rather than a channel. Every connection that member currently holds receives it, across tabs and devices, so there is no need to track their connections or give them a channel of their own.
1382
- * The member must have signed in on the connection for it to be addressable. Delivery is best-effort and not queued: a member holding no connections at the moment of the call simply does not receive the event.
1374
+ * Delivers an event to one member of a Realtime app, addressing the person
1375
+ * rather than a channel. Every connection that member currently holds receives
1376
+ * it across tabs and devices, without requiring a dedicated channel.
1377
+ *
1378
+ * The member must have signed in on the connection for it to be addressable.
1379
+ * Delivery is best-effort and not queued. A member with no active connections
1380
+ * at the time of the call does not receive the event.
1383
1381
  */
1384
1382
  const sendRealtimeAppMemberEvent = (options) => (options.client ?? client).post({
1385
1383
  security: [
@@ -1411,7 +1409,7 @@ const sendRealtimeAppMemberEvent = (options) => (options.client ?? client).post(
1411
1409
  /**
1412
1410
  * List messages
1413
1411
  *
1414
- * Returns the workspace's sent and scheduled messages, newest first, as a cursor page. Each item has the aggregate delivery `status` and per-state recipient counts, not the message body.
1412
+ * Returns the workspace's sent and scheduled messages, newest first, as a cursor page. Each item has the aggregate delivery `status` and per-state recipient counts. Message bodies are omitted.
1415
1413
  *
1416
1414
  * Combine filters to narrow the page:
1417
1415
  *
@@ -1435,17 +1433,17 @@ const listEmailMessages = (options) => (options?.client ?? client).get({
1435
1433
  ...options
1436
1434
  });
1437
1435
  /**
1438
- * Send an email message
1436
+ * Create an email message
1439
1437
  *
1440
1438
  * Sends an email to the recipients you list explicitly in `to`/`cc`/`bcc`. Use it for
1441
1439
  * transactional sends (receipts, password resets, alerts) and for marketing sends where
1442
1440
  * you have the recipient addresses on hand. To submit many independent messages in one
1443
- * request, use [Send a batch of messages](/docs/api/reference/create-email-message-batch)
1441
+ * request, use [Create a batch of email messages](/docs/api/reference/create-email-message-batch)
1444
1442
  * instead. The `category` field controls suppression policy independently of content:
1445
- * set it to `marketing` when sending marketing content from this endpoint.
1443
+ * set it to `marketing` when sending marketing content.
1446
1444
  *
1447
- * The `202` response means the message is safely accepted for delivery, not yet
1448
- * delivered. Fetch it by `id` or subscribe to webhook events to follow delivery. The
1445
+ * The `202` response means the message is safely accepted and awaiting delivery.
1446
+ * Fetch it by `id` or subscribe to webhook events to follow delivery. The
1449
1447
  * request never half-succeeds: an unverified sender domain or any field-level
1450
1448
  * validation failure rejects it immediately with a `422` naming the reason.
1451
1449
  * Suppression is evaluated per recipient after acceptance, so a suppressed recipient
@@ -1472,9 +1470,9 @@ const createEmailMessage = (options) => (options.client ?? client).post({
1472
1470
  }
1473
1471
  });
1474
1472
  /**
1475
- * Send a batch of messages
1473
+ * Create a batch of email messages
1476
1474
  *
1477
- * Accepts up to 100 independent email messages and queues them for delivery. All items are validated before any are queued: if one fails validation, the entire batch is rejected. Field-level validation failures and business-rule failures (such as `domain_not_verified`) both return `422`. Suppression is evaluated per recipient after acceptance, never as a synchronous error. The `202` response returns one entry per message in submission order, each with its own `id` you can use to fetch that message or match it against webhook events. Attachments are allowed per message. Each message must stay within the 20 MB estimated generated message-size cap, and the serialized JSON request body for the whole batch has a hard 20 MB cap.
1475
+ * Accepts up to 100 independent email messages and queues them for delivery. All items are validated before any are queued: if one fails validation, the entire batch is rejected. Field-level validation failures and business-rule failures, such as sending from a domain that is not verified, both return `422`. None of the items can set `scheduled_at`; schedule a single message with [Create an email message](/docs/api/reference/create-email-message) instead. Suppression is evaluated per recipient after acceptance, never as a synchronous error. The `202` response returns one entry per message in submission order, each with its own `id` you can use to fetch that message or match it against webhook events. Attachments are allowed per message. Each message must stay within the 20 MB estimated generated message-size cap, and the serialized JSON request body for the whole batch has a hard 20 MB cap.
1478
1476
  *
1479
1477
  */
1480
1478
  const createEmailMessageBatch = (options) => (options.client ?? client).post({
@@ -1574,7 +1572,7 @@ const createContact = (options) => (options.client ?? client).post({
1574
1572
  /**
1575
1573
  * Create or update contacts in bulk
1576
1574
  *
1577
- * Creates or updates up to 1,000 contacts in one request. Each entry is matched automatically against every identifier it supplies: its email address (trimmed and lowercased before matching), its phone number (normalized to international form), and your own `external_id`. An entry that matches no existing contact creates one; an entry whose identifiers all point at one contact updates it with the fields it supplies, and omitted fields keep their stored values, so a contact's email address can change under a stable `external_id` without creating a second record. An entry whose identifiers belong to more than one contact fails with an error naming each matched contact, since Bird never merges contacts or picks between them. Supplying `match_on` overrides the automatic matching: every entry is matched by that one field only, and must carry it. Optionally adds every contact in the request to up to 10 audiences.
1575
+ * Creates or updates up to 1,000 contacts in one request. Each entry is matched automatically against every identifier it supplies: its email address (trimmed and lowercased), its phone number (normalized to international form), and your own `external_id`. An entry with no match creates a contact. An entry whose identifiers all match one contact updates the supplied fields and preserves omitted fields. This lets an email address change under a stable `external_id` without creating a second contact. An entry whose identifiers belong to several contacts fails with an error naming each match; contacts are never merged automatically. Supplying `match_on` makes that field the only matching key, and every entry must include it. You can also add every contact in the request to up to 10 audiences.
1578
1576
  *
1579
1577
  * Each entry succeeds or fails on its own: the response lists one result per contact in submission order (`created`, `updated`, or `failed` with the reason), and a failed entry does not abort the rest. If the request itself is invalid, for example when an entry in `audience_ids` does not exist, the whole request fails with a validation error and no contacts are written.
1580
1578
  *
@@ -1634,9 +1632,9 @@ const getContact = (options) => (options.client ?? client).get({
1634
1632
  /**
1635
1633
  * Update a contact
1636
1634
  *
1637
- * Updates a contact. Supplied fields are changed and omitted fields are left unchanged; set `first_name`, `last_name`, or `external_id` to null to clear them. Custom values in `data` are merged: keys you supply are set, keys set to null are removed, and keys you omit are unchanged.
1635
+ * Updates a contact. Supplied fields are changed and omitted fields are left unchanged; set `first_name`, `last_name`, or `external_id` to `null` to clear them. Custom values in `data` are merged: keys you supply are set, keys set to `null` are removed, and keys you omit are unchanged.
1638
1636
  *
1639
- * Changing the email address, phone number, or `external_id` to a value already used by another contact returns a conflict error, and a contact always keeps at least one identifier: clearing both email and phone in the same contact is rejected.
1637
+ * Changing the email address, phone number, or `external_id` to a value already used by another contact returns a conflict error. A contact always keeps at least one identifier. Clearing both email and phone in the same contact is rejected.
1640
1638
  *
1641
1639
  */
1642
1640
  const updateContact = (options) => (options.client ?? client).patch({
@@ -1796,7 +1794,7 @@ const listAudiences = (options) => (options?.client ?? client).get({
1796
1794
  /**
1797
1795
  * Create an audience
1798
1796
  *
1799
- * Creates an audience in the workspace. New audiences start empty: add members with [Add contacts to an audience](/docs/api/reference/assign-audience-contacts) or through [Create or update contacts in bulk](/docs/api/reference/create-contact-batch). Only `static` audiences can be created today; requesting `dynamic` or `external` returns a validation error.
1797
+ * Creates an audience in the workspace. New audiences start empty: add members with [Add contacts to an audience](/docs/api/reference/assign-audience-contacts) or through [Create or update contacts in bulk](/docs/api/reference/create-contact-batch). The `type` field currently accepts only `static` audiences.
1800
1798
  *
1801
1799
  */
1802
1800
  const createAudience = (options) => (options.client ?? client).post({
@@ -1854,7 +1852,7 @@ const getAudience = (options) => (options.client ?? client).get({
1854
1852
  /**
1855
1853
  * Update an audience
1856
1854
  *
1857
- * Updates an audience's name or description. Omitted fields are left unchanged; set `description` to null to clear it.
1855
+ * Updates an audience's name or description. Omitted fields are left unchanged; set `description` to `null` to clear it.
1858
1856
  *
1859
1857
  */
1860
1858
  const updateAudience = (options) => (options.client ?? client).patch({
@@ -1892,9 +1890,9 @@ const listAudienceContacts = (options) => (options.client ?? client).get({
1892
1890
  ...options
1893
1891
  });
1894
1892
  /**
1895
- * Add contacts to an audience
1893
+ * Assign contacts to an audience
1896
1894
  *
1897
- * Adds up to 1,000 contacts to an audience. Adding is idempotent: contacts that are already members are left in place and keep their original join time. If any contact ID does not exist in the workspace, the whole request fails with a validation error and no contacts are added.
1895
+ * Adds up to 1,000 contacts to an audience. Adding is idempotent: contacts that are already members are left in place and keep their original join time. If any contact ID does not exist in the workspace, the whole request fails with `422 Unprocessable Entity` and no contacts are added.
1898
1896
  *
1899
1897
  */
1900
1898
  const assignAudienceContacts = (options) => (options.client ?? client).post({
@@ -1914,9 +1912,9 @@ const assignAudienceContacts = (options) => (options.client ?? client).post({
1914
1912
  }
1915
1913
  });
1916
1914
  /**
1917
- * Remove contacts from an audience
1915
+ * Unassign contacts from an audience
1918
1916
  *
1919
- * Removes up to 1,000 contacts from an audience. Contacts that are not members are skipped. If any contact ID does not exist in the workspace, the whole request fails with a validation error and no memberships are removed. The contacts themselves are not deleted and remain members of any other audiences.
1917
+ * Removes up to 1,000 contacts from an audience. Contacts that are not members are skipped. If any contact ID does not exist in the workspace, the whole request fails with `422 Unprocessable Entity` and no memberships are removed. The contacts themselves are not deleted and remain members of any other audiences.
1920
1918
  *
1921
1919
  */
1922
1920
  const unassignAudienceContacts = (options) => (options.client ?? client).post({
@@ -1936,9 +1934,9 @@ const unassignAudienceContacts = (options) => (options.client ?? client).post({
1936
1934
  }
1937
1935
  });
1938
1936
  /**
1939
- * Remove a contact from an audience
1937
+ * Unassign a contact from an audience
1940
1938
  *
1941
- * Removes a contact's membership in an audience. The contact itself is not deleted and remains a member of any other audiences. Removing a contact that is not a member of the audience succeeds with no effect (204); an unknown audience or contact returns a not-found error.
1939
+ * Removes a contact's membership in an audience. The contact itself is not deleted and remains a member of any other audiences. Removing a contact that is not a member of the audience succeeds with no effect (`204 No Content`); an unknown audience or contact returns a not-found error.
1942
1940
  *
1943
1941
  */
1944
1942
  const unassignAudienceContact = (options) => (options.client ?? client).delete({
@@ -1956,9 +1954,17 @@ const unassignAudienceContact = (options) => (options.client ?? client).delete({
1956
1954
  /**
1957
1955
  * List SMS messages
1958
1956
  *
1959
- * Returns the workspace's SMS messages as a cursor-paginated list, newest first. Filter by direction, status, category, recipient, sender, failure reason, tag, or creation time; pass the response's `next_cursor` back as `starting_after` to fetch the next page. To follow a single message's delivery, use [Get an SMS message](/docs/api/reference/get-sms-message) instead.
1957
+ * Returns the workspace's SMS messages as a cursor-paginated list, newest
1958
+ * first. Filter by direction, status, category, recipient, sender, failure
1959
+ * reason, tag, or creation time; pass the response's `next_cursor` back as
1960
+ * `starting_after` to fetch the next page. To follow a single message's
1961
+ * delivery, use [Get an SMS message](/docs/api/reference/get-sms-message)
1962
+ * instead.
1960
1963
  *
1961
- * Messages are retained for **30 days**. A `created_after` earlier than that is accepted and raised to the retention bound rather than rejected, so a wider window returns what is still retained instead of failing. There is no way to read messages older than the window.
1964
+ * Messages are retained for **30 days**. A `created_after` earlier than that
1965
+ * is accepted and raised to the retention bound rather than rejected, so a
1966
+ * wider window returns what is still retained instead of failing. Messages
1967
+ * older than the retention window cannot be retrieved.
1962
1968
  *
1963
1969
  */
1964
1970
  const listSmsMessages = (options) => (options?.client ?? client).get({
@@ -1974,24 +1980,22 @@ const listSmsMessages = (options) => (options?.client ?? client).get({
1974
1980
  ...options
1975
1981
  });
1976
1982
  /**
1977
- * Send an SMS message
1983
+ * Create an SMS message
1978
1984
  *
1979
- * Sends one SMS message to a single recipient. A send carries exactly one
1980
- * content form: `text` (free text, which also requires `category`) or
1981
- * `template` (a stored template that supplies the body and category). To
1982
- * submit up to 100 independent messages in one request, use
1985
+ * Sends one SMS to one recipient with exactly one content form: `text`, which
1986
+ * requires `category` and `from`, or a stored `template`, which selects both
1987
+ * for you. To submit up to 100 independent messages in one request, use
1983
1988
  * [Send a batch of SMS messages](/docs/api/reference/create-sms-message-batch)
1984
1989
  * instead.
1985
1990
  *
1986
- * The `202` response means Bird durably accepted the message for asynchronous
1987
- * delivery, not that it was delivered. Follow delivery with
1991
+ * The `202 Accepted` response means the API durably accepted the message for
1992
+ * asynchronous delivery. Delivery remains pending; follow it with
1988
1993
  * [Get an SMS message](/docs/api/reference/get-sms-message) or by subscribing
1989
1994
  * to `sms.*` webhook events.
1990
1995
  *
1991
- * Sends fail with a `422` when a field is invalid, the body exceeds the
1992
- * 12-segment cap, the destination country is not enabled for the workspace,
1993
- * or the sender is not permitted for the destination; a send from a
1994
- * workspace with no wallet balance fails with a `402`.
1996
+ * An invalid field, more than 12 segments, a disabled destination country, or
1997
+ * a sender not permitted for the destination returns `422`. Insufficient
1998
+ * wallet balance returns `402`.
1995
1999
  *
1996
2000
  */
1997
2001
  const createSmsMessage = (options) => (options.client ?? client).post({
@@ -2011,10 +2015,10 @@ const createSmsMessage = (options) => (options.client ?? client).post({
2011
2015
  }
2012
2016
  });
2013
2017
  /**
2014
- * Send a batch of SMS messages
2018
+ * Create a batch of SMS messages
2015
2019
  *
2016
2020
  * Sends up to 100 independent SMS messages in one request. Each item is a
2017
- * complete send request with its own recipient, content, id, status, and
2021
+ * complete send request with its own recipient, content, ID, status, and
2018
2022
  * cost. For a single message, use
2019
2023
  * [Send an SMS message](/docs/api/reference/create-sms-message) instead.
2020
2024
  *
@@ -2044,7 +2048,7 @@ const createSmsMessageBatch = (options) => (options.client ?? client).post({
2044
2048
  /**
2045
2049
  * Get an SMS message
2046
2050
  *
2047
- * Returns a single SMS message: its current delivery status, segment breakdown, cost, and failure detail when it failed. The `status` advances asynchronously as delivery progresses, and `cost` is null until the message has been priced, so poll this endpoint (or subscribe to `sms.*` webhook events) after a send to confirm delivery. To scan messages in bulk, use [List SMS messages](/docs/api/reference/list-sms-messages) instead.
2051
+ * Returns a single SMS message: its current delivery status, segment breakdown, cost, and failure detail when it failed. The `status` advances asynchronously as delivery progresses, and `cost` is null until the message has been priced, so poll this operation (or subscribe to `sms.*` webhook events) after a send to confirm delivery. To scan messages in bulk, use [List SMS messages](/docs/api/reference/list-sms-messages) instead.
2048
2052
  *
2049
2053
  */
2050
2054
  const getSmsMessage = (options) => (options.client ?? client).get({
@@ -2060,12 +2064,11 @@ const getSmsMessage = (options) => (options.client ?? client).get({
2060
2064
  ...options
2061
2065
  });
2062
2066
  /**
2063
- * List SMS templates
2064
- *
2065
- * Returns the SMS templates you can send from, including Bird's built-in templates. Filter by scope, category, or language; the catalogue is small and returned in full, so this list is not paginated. To read one template's variables before sending with it, use [Get an SMS template](/docs/api/reference/get-sms-template).
2067
+ * List events for an SMS message
2066
2068
  *
2069
+ * Returns the lifecycle event timeline for a message, in chronological order.
2067
2070
  */
2068
- const listSmsTemplates = (options) => (options?.client ?? client).get({
2071
+ const listSmsMessageEvents = (options) => (options.client ?? client).get({
2069
2072
  security: [{
2070
2073
  scheme: "bearer",
2071
2074
  type: "http"
@@ -2074,16 +2077,16 @@ const listSmsTemplates = (options) => (options?.client ?? client).get({
2074
2077
  name: "bird_session",
2075
2078
  type: "apiKey"
2076
2079
  }],
2077
- url: "/v1/sms/templates",
2080
+ url: "/v1/sms/messages/{message_id}/events",
2078
2081
  ...options
2079
2082
  });
2080
2083
  /**
2081
- * Get an SMS template
2084
+ * List SMS templates
2082
2085
  *
2083
- * Returns a single SMS template: its body preview, category, the `variables` it expects (each with its accepted format), and the languages it is available in. Fetch a template before sending with it to see which `parameters` keys are required; an unknown reference returns a `404`. To browse the whole catalogue, use [List SMS templates](/docs/api/reference/list-sms-templates) instead.
2086
+ * Returns the SMS templates you can send from, including our built-in templates. Filter by scope, category, or language; the catalog is small and returned in full, so this list is not paginated. To read one template's variables before sending with it, use [Get an SMS template](/docs/api/reference/get-sms-template).
2084
2087
  *
2085
2088
  */
2086
- const getSmsTemplate = (options) => (options.client ?? client).get({
2089
+ const listSmsTemplates = (options) => (options?.client ?? client).get({
2087
2090
  security: [{
2088
2091
  scheme: "bearer",
2089
2092
  type: "http"
@@ -2092,24 +2095,16 @@ const getSmsTemplate = (options) => (options.client ?? client).get({
2092
2095
  name: "bird_session",
2093
2096
  type: "apiKey"
2094
2097
  }],
2095
- url: "/v1/sms/templates/{template_ref}",
2098
+ url: "/v1/sms/templates",
2096
2099
  ...options
2097
2100
  });
2098
2101
  /**
2099
- * Look up a phone number
2100
- *
2101
- * Returns what we know about a phone number: which network serves it, which network issued it, whether it has been ported, its country, and what kind of line it is. That baseline is included with every lookup.
2102
- *
2103
- * Use `type` to buy more. Each value adds a block to the answer: how the number is classified, whether it is live on the network right now, whether it is roaming, when its SIM last changed, its porting record, or a credibility score. Omit `type` and the response is the baseline alone, and no intelligence provider is contacted.
2104
- *
2105
- * Every block you request comes back carrying a `status`, so a partial answer is visible rather than silent, and **you are billed for exactly the blocks whose status is `ok`**.
2106
- *
2107
- * Send the number in the body rather than the URL when you would rather it did not appear in request logs or browser history. [Look up a phone number by URL](/docs/api/reference/get-phone-number-lookup) is the same lookup with the number in the path.
2102
+ * Get an SMS template
2108
2103
  *
2109
- * Send an `Idempotency-Key` and a retried request returns the stored answer instead of looking the number up and charging again. Without one, every attempt is a new lookup and is billed.
2104
+ * Returns a single SMS template: its body preview, category, the `variables` it expects (each with its accepted format), and the languages it is available in. Fetch a template before sending with it to see which `parameters` keys are required; an unknown reference returns a `404`. To browse the whole catalog, use [List SMS templates](/docs/api/reference/list-sms-templates) instead.
2110
2105
  *
2111
2106
  */
2112
- const createPhoneNumberLookup = (options) => (options.client ?? client).post({
2107
+ const getSmsTemplate = (options) => (options.client ?? client).get({
2113
2108
  security: [{
2114
2109
  scheme: "bearer",
2115
2110
  type: "http"
@@ -2118,34 +2113,20 @@ const createPhoneNumberLookup = (options) => (options.client ?? client).post({
2118
2113
  name: "bird_session",
2119
2114
  type: "apiKey"
2120
2115
  }],
2121
- url: "/v1/lookup/phone-number",
2122
- ...options,
2123
- headers: {
2124
- "Content-Type": "application/json",
2125
- ...options.headers
2126
- }
2116
+ url: "/v1/sms/templates/{template_ref}",
2117
+ ...options
2127
2118
  });
2128
2119
  /**
2129
- * Look up an email address
2120
+ * List SMS suppressions
2130
2121
  *
2131
- * Returns whether an email address is worth sending to:
2122
+ * Returns the suppressions currently stopping your messages, most recent opt-out first. Pass `destination` to look up one subscriber before sending to them.
2132
2123
  *
2133
- * - Whether it will accept mail.
2134
- * - How confident that is.
2135
- * - Why not, when it will not.
2136
- * - Whether it is a role, disposable, or free-provider address.
2137
- * - What it looks like it was meant to be, when it looks misspelled.
2124
+ * A suppression covers one sender and one subscriber, so the same number can appear more than once: opting out of one of your senders does not opt out of the others.
2138
2125
  *
2139
- * One address per call, and one answer: `result` is the field to decide on. Every answer costs the same, including `undeliverable`, which is usually the most valuable one you can get.
2140
- *
2141
- * `result` and `reason` are open vocabularies: the values below are the ones in use today, and further ones may be added. Branch on the values you know and treat anything else as a future value rather than an error. `delivery_confidence` is always present and always comparable, so it is the safe fallback.
2142
- *
2143
- * Send the address in the body rather than the URL when you would rather it did not appear in request logs or browser history. [Look up an email address by URL](/docs/api/reference/get-email-lookup) is the same lookup with the address in the path.
2144
- *
2145
- * Send an `Idempotency-Key` and a retried request returns the stored answer instead of validating the address and charging again. Without one, every attempt is a new lookup and is billed.
2126
+ * Ended suppressions are excluded. A subscriber who opted back in is reachable again and does not appear in this list.
2146
2127
  *
2147
2128
  */
2148
- const createEmailLookup = (options) => (options.client ?? client).post({
2129
+ const listSmsSuppressions = (options) => (options?.client ?? client).get({
2149
2130
  security: [{
2150
2131
  scheme: "bearer",
2151
2132
  type: "http"
@@ -2154,24 +2135,18 @@ const createEmailLookup = (options) => (options.client ?? client).post({
2154
2135
  name: "bird_session",
2155
2136
  type: "apiKey"
2156
2137
  }],
2157
- url: "/v1/lookup/email",
2158
- ...options,
2159
- headers: {
2160
- "Content-Type": "application/json",
2161
- ...options.headers
2162
- }
2138
+ url: "/v1/sms/suppressions",
2139
+ ...options
2163
2140
  });
2164
2141
  /**
2165
- * Create a verification
2142
+ * Create an SMS suppression
2166
2143
  *
2167
- * Creates a verification for a recipient and sends them a one-time passcode. Provide the recipient in `to`: an email address (verified over email), a phone number (verified over the phone channels enabled for its destination country), or both. The passcode is sent over one channel at a time and delivery falls over to the next channel in the plan if one fails; it is never sent over two channels at once.
2144
+ * Stops a sender's messages to a subscriber, with reason `manual`, blocking every category including transactional. Both ends are required: a suppression covers a sender-and-subscriber pair, so stopping all of your senders means one call per sender.
2168
2145
  *
2169
- * Calling this again for the same recipient resumes the verification in progress rather than starting a second one: within the resend cooldown the request returns the current state without sending, and after it a fresh passcode is sent. Use the same call to send and to resend.
2170
- *
2171
- * The `200` response is the verification's current state; the passcode itself is never returned. Submit the passcode the recipient enters with POST /v1/verify/verifications/check before the verification's `expires_at`. An invalid recipient returns `422`, and requesting passcodes for the same recipient too often returns `429`.
2146
+ * Adding is idempotent. A `201` means a new suppression was recorded, and a `200` means a `manual` one for that pair was already in place and is returned unchanged. A pair already stopped for another reason, such as the subscriber having texted a stop keyword, still gets its own `manual` record, and messages stay stopped until every one of them has ended.
2172
2147
  *
2173
2148
  */
2174
- const createVerification = (options) => (options.client ?? client).post({
2149
+ const createSmsSuppression = (options) => (options.client ?? client).post({
2175
2150
  security: [{
2176
2151
  scheme: "bearer",
2177
2152
  type: "http"
@@ -2180,7 +2155,7 @@ const createVerification = (options) => (options.client ?? client).post({
2180
2155
  name: "bird_session",
2181
2156
  type: "apiKey"
2182
2157
  }],
2183
- url: "/v1/verify/verifications",
2158
+ url: "/v1/sms/suppressions",
2184
2159
  ...options,
2185
2160
  headers: {
2186
2161
  "Content-Type": "application/json",
@@ -2188,16 +2163,16 @@ const createVerification = (options) => (options.client ?? client).post({
2188
2163
  }
2189
2164
  });
2190
2165
  /**
2191
- * Check a verification passcode
2166
+ * Delete an SMS suppression
2192
2167
  *
2193
- * Checks a passcode for a recipient and returns the outcome together with the verification's current state. Identify the verification by the same `to` used to create it; you do not need to store a verification ID.
2168
+ * Ends a suppression, so the sender reaches the subscriber again. The record stays with the ending noted on it. This history helps answer later complaints or carrier audits.
2194
2169
  *
2195
- * A wrong or expired passcode is a normal outcome, not an HTTP error: the response is `200` with `success` set to `false` and a `reason` such as `incorrect_code` or `expired`. `success: true` means the verification is complete. Each verification reports its final outcome exactly once and is no longer checkable afterwards.
2170
+ * **Only the `manual` reason can be ended here.** A `keyword_stop` is the subscriber's own statement. It ends only when they text a start keyword to that sender. A `carrier_opted_out` mirrors what the carrier reported, so it ends when the carrier says so. Attempts to end either reason return `422`.
2196
2171
  *
2197
- * An error status is returned only when the check cannot be evaluated: `404` when no verification matches the recipient or the matching one already reached its final state, `422` for an invalid recipient, and `429` when passcodes for a recipient are checked too quickly.
2172
+ * Ending a suppression resumes messaging to someone your own records say did not want it, so do it only when you know why the `manual` record exists. An ID that does not exist in the workspace returns `404`, and one that has already ended returns `204`.
2198
2173
  *
2199
2174
  */
2200
- const createVerificationCheck = (options) => (options.client ?? client).post({
2175
+ const deleteSmsSuppression = (options) => (options.client ?? client).delete({
2201
2176
  security: [{
2202
2177
  scheme: "bearer",
2203
2178
  type: "http"
@@ -2206,24 +2181,18 @@ const createVerificationCheck = (options) => (options.client ?? client).post({
2206
2181
  name: "bird_session",
2207
2182
  type: "apiKey"
2208
2183
  }],
2209
- url: "/v1/verify/verifications/check",
2210
- ...options,
2211
- headers: {
2212
- "Content-Type": "application/json",
2213
- ...options.headers
2214
- }
2184
+ url: "/v1/sms/suppressions/{suppression_id}",
2185
+ ...options
2215
2186
  });
2216
2187
  /**
2217
- * Advance a verification to its next channel
2188
+ * Get an SMS suppression
2218
2189
  *
2219
- * Advances an in-progress verification to the next channel in its plan and sends a fresh passcode there, for a recipient who reports not receiving the code. Identify the verification by the same `to` used to create it; you do not need to store a verification ID.
2190
+ * Returns one suppression: the sender and subscriber it covers, why messages are stopped, how the record came to exist, what it blocks, and whether it is still in force.
2220
2191
  *
2221
- * The send bypasses the resend cooldown (a deliberate channel switch is a different act from a same-channel resend), and every passcode already sent stays valid, so a code that arrives late can still be checked. The response is the verification with `last_channel` set to the channel the new passcode went to. Concurrent requests for the same recipient are safe: each advances the plan at most one step. When two race, the request that completes the newer send is the authoritative one; the other returns the verification's committed state, whose `last_channel` still names the most recent send that completed. A later read of the verification always reflects the settled outcome.
2222
- *
2223
- * An error status is returned when the verification cannot be advanced: `404` when no verification is in progress for the recipient, `422` with `NoNextChannel` when the plan has no further channel (fall back to a plain resend), `422` with `NoAvailableChannel` when every remaining channel failed to send, and `429` when sends for the account are requested too quickly.
2192
+ * This operation also returns a suppression that has already ended. The `blocking` field is `false`, and the `ended_*` fields say when and why. An ID you kept from a create or delete therefore stays readable. To find one when you only know the number, use `GET /v1/sms/suppressions` with the `destination` parameter. An ID that does not exist in the workspace returns `404`.
2224
2193
  *
2225
2194
  */
2226
- const createVerificationNextChannel = (options) => (options.client ?? client).post({
2195
+ const getSmsSuppression = (options) => (options.client ?? client).get({
2227
2196
  security: [{
2228
2197
  scheme: "bearer",
2229
2198
  type: "http"
@@ -2232,31 +2201,20 @@ const createVerificationNextChannel = (options) => (options.client ?? client).po
2232
2201
  name: "bird_session",
2233
2202
  type: "apiKey"
2234
2203
  }],
2235
- url: "/v1/verify/verifications/next-channel",
2236
- ...options,
2237
- headers: {
2238
- "Content-Type": "application/json",
2239
- ...options.headers
2240
- }
2204
+ url: "/v1/sms/suppressions/{suppression_id}",
2205
+ ...options
2241
2206
  });
2242
2207
  /**
2243
- * List WhatsApp messages
2208
+ * List SMS keyword rules
2244
2209
  *
2245
- * Returns the workspace's WhatsApp messages as a cursor-paginated list,
2246
- * newest first. Filter by direction, status, contact phone number,
2247
- * business-scoped user ID, template category, tag, or creation time; pass the response's `next_cursor` back as
2248
- * `starting_after` to fetch the next page. To follow a single message's
2249
- * delivery, use
2250
- * [Get a WhatsApp message](/docs/api/reference/get-whats-app-message)
2251
- * instead.
2210
+ * Returns the default and workspace keyword rules that apply to inbound messages, most specific first. Where the default catalog covers a country, opt-out, opt-in, and help keywords work without setup.
2252
2211
  *
2253
- * Messages are retained for **30 days**. A `created_after` earlier than that
2254
- * is accepted and raised to the retention bound rather than rejected, so a
2255
- * wider window returns what is still retained instead of failing. There is no
2256
- * way to read messages older than the window.
2212
+ * Use the filters to narrow the full, unpaginated list. Set `scope=system` for default rules only. Set `number` for rules in evaluation order, and add `from_country` to account for the sender's country.
2213
+ *
2214
+ * Default coverage varies by country. If a country has no default rules, the service does not recognize keywords, send replies, or record opt-outs there. You can add `custom` keywords for that country. Opt-out, opt-in, and help rules require default coverage.
2257
2215
  *
2258
2216
  */
2259
- const listWhatsAppMessages = (options) => (options?.client ?? client).get({
2217
+ const listSmsKeywordRules = (options) => (options?.client ?? client).get({
2260
2218
  security: [{
2261
2219
  scheme: "bearer",
2262
2220
  type: "http"
@@ -2265,33 +2223,18 @@ const listWhatsAppMessages = (options) => (options?.client ?? client).get({
2265
2223
  name: "bird_session",
2266
2224
  type: "apiKey"
2267
2225
  }],
2268
- url: "/v1/whatsapp/messages",
2226
+ url: "/v1/sms/keyword-rules",
2269
2227
  ...options
2270
2228
  });
2271
2229
  /**
2272
- * Send a WhatsApp message
2273
- *
2274
- * Sends a WhatsApp message built from a message template to one recipient.
2275
- * Name the template, optionally pick its language variant, and fill its
2276
- * placeholders in `components`; a Bird-managed template selects its sender
2277
- * number from its category, so the request carries no sender field. A request
2278
- * that carries no content is rejected with a `422`. Browse your workspace's
2279
- * templates in the Bird dashboard.
2230
+ * Create an SMS keyword rule
2280
2231
  *
2281
- * The `202` response is the accepted message, echoing the resolved template
2282
- * and language; it is not a delivery confirmation. Follow delivery with
2283
- * [Get a WhatsApp message](/docs/api/reference/get-whats-app-message), the
2284
- * per-message timeline from
2285
- * [List events for a WhatsApp message](/docs/api/reference/list-whats-app-message-events),
2286
- * or `whatsapp.*` webhook events.
2232
+ * Creates a workspace keyword rule. Use it to replace the default opt-out, opt-in, or help reply for one country, or to add a `custom` keyword.
2287
2233
  *
2288
- * A template slug or language the catalogue does not stock, parameter values
2289
- * that do not match the template's declared placeholders, and a recipient
2290
- * that is not a valid phone number each return a `422`, as does a request
2291
- * that carries no content at all.
2234
+ * Your rule takes precedence over the default for the same country and keeps default keywords unless you add more. Opt-out and opt-in keywords cannot be assigned to another operation.
2292
2235
  *
2293
2236
  */
2294
- const createWhatsAppMessage = (options) => (options.client ?? client).post({
2237
+ const createSmsKeywordRule = (options) => (options.client ?? client).post({
2295
2238
  security: [{
2296
2239
  scheme: "bearer",
2297
2240
  type: "http"
@@ -2300,7 +2243,7 @@ const createWhatsAppMessage = (options) => (options.client ?? client).post({
2300
2243
  name: "bird_session",
2301
2244
  type: "apiKey"
2302
2245
  }],
2303
- url: "/v1/whatsapp/messages",
2246
+ url: "/v1/sms/keyword-rules",
2304
2247
  ...options,
2305
2248
  headers: {
2306
2249
  "Content-Type": "application/json",
@@ -2308,12 +2251,12 @@ const createWhatsAppMessage = (options) => (options.client ?? client).post({
2308
2251
  }
2309
2252
  });
2310
2253
  /**
2311
- * Get a WhatsApp message
2254
+ * Delete an SMS keyword rule
2312
2255
  *
2313
- * Returns a single WhatsApp message: its current delivery status, per-stage timestamps (`sent_at`, `delivered_at`, `read_at`), the template it was sent from, and failure detail when it failed. The `status` advances asynchronously as delivery progresses, so poll this endpoint (or subscribe to `whatsapp.*` webhook events) after a send to confirm delivery. For the per-event timeline, use [List events for a WhatsApp message](/docs/api/reference/list-whats-app-message-events) instead.
2256
+ * Deletes a rule you created. Bird's default for that operation and country applies again straight away, so deleting an opt-out rule restores Bird's reply rather than switching opt-out off. Bird's defaults cannot be deleted.
2314
2257
  *
2315
2258
  */
2316
- const getWhatsAppMessage = (options) => (options.client ?? client).get({
2259
+ const deleteSmsKeywordRule = (options) => (options.client ?? client).delete({
2317
2260
  security: [{
2318
2261
  scheme: "bearer",
2319
2262
  type: "http"
@@ -2322,16 +2265,17 @@ const getWhatsAppMessage = (options) => (options.client ?? client).get({
2322
2265
  name: "bird_session",
2323
2266
  type: "apiKey"
2324
2267
  }],
2325
- url: "/v1/whatsapp/messages/{message_id}",
2268
+ url: "/v1/sms/keyword-rules/{id}",
2326
2269
  ...options
2327
2270
  });
2328
2271
  /**
2329
- * List events for a WhatsApp message
2272
+ * Get an SMS keyword rule
2330
2273
  *
2331
- * Returns a WhatsApp message's lifecycle events in chronological order, one entry per delivery transition (`whatsapp.accepted`, `whatsapp.sent`, `whatsapp.delivered`, `whatsapp.read`, `whatsapp.failed`). The timeline is bounded and returned in full, so this list is not paginated; an unknown message id returns a `404`. For the message's current state in a single field, use [Get a WhatsApp message](/docs/api/reference/get-whats-app-message) instead.
2274
+ * Returns one keyword rule, either one of Bird's defaults or one you created, including
2275
+ * every keyword that matches it and the reply it sends.
2332
2276
  *
2333
2277
  */
2334
- const listWhatsAppMessageEvents = (options) => (options.client ?? client).get({
2278
+ const getSmsKeywordRule = (options) => (options.client ?? client).get({
2335
2279
  security: [{
2336
2280
  scheme: "bearer",
2337
2281
  type: "http"
@@ -2340,20 +2284,21 @@ const listWhatsAppMessageEvents = (options) => (options.client ?? client).get({
2340
2284
  name: "bird_session",
2341
2285
  type: "apiKey"
2342
2286
  }],
2343
- url: "/v1/whatsapp/messages/{message_id}/events",
2287
+ url: "/v1/sms/keyword-rules/{id}",
2344
2288
  ...options
2345
2289
  });
2346
2290
  /**
2347
- * Daily sending statistics
2348
- *
2349
- * Returns one row of aggregate sending statistics per calendar day for the workspace: UTC days by default, or your local days when `timezone` is set. Days with no activity are included with zero counts, so the series charts without client-side gap handling. Suited to charts and trend lines; for per-message exact accounting use the message detail endpoints.
2291
+ * Update an SMS keyword rule
2350
2292
  *
2351
- * Rows are bucketed by event time, not send time: a complaint received on Wednesday for a message sent the prior Monday is counted in Wednesday's row.
2293
+ * Changes the reply or the added keywords of a rule you created. Bird's defaults cannot be
2294
+ * changed. To replace one, create a rule with the same operation and country and yours
2295
+ * takes precedence.
2352
2296
  *
2353
- * The maximum window is 365 days; requesting a longer range returns 422.
2297
+ * What the rule applies to is fixed once created, so this changes the reply and the keywords
2298
+ * only.
2354
2299
  *
2355
2300
  */
2356
- const getEmailStatsDaily = (options) => (options?.client ?? client).get({
2301
+ const updateSmsKeywordRule = (options) => (options.client ?? client).patch({
2357
2302
  security: [{
2358
2303
  scheme: "bearer",
2359
2304
  type: "http"
@@ -2362,20 +2307,24 @@ const getEmailStatsDaily = (options) => (options?.client ?? client).get({
2362
2307
  name: "bird_session",
2363
2308
  type: "apiKey"
2364
2309
  }],
2365
- url: "/v1/email/stats/daily",
2366
- ...options
2310
+ url: "/v1/sms/keyword-rules/{id}",
2311
+ ...options,
2312
+ headers: {
2313
+ "Content-Type": "application/json",
2314
+ ...options.headers
2315
+ }
2367
2316
  });
2368
2317
  /**
2369
- * Hourly sending statistics
2318
+ * Get aggregate SMS statistics
2370
2319
  *
2371
- * Returns one row of aggregate sending statistics per hour for the workspace: UTC hours by default, or your local hours when `timezone` is set (a timezone with a sub-hour offset gets correctly aligned hours). Useful for inspecting send rate, deliverability, and engagement inside a single day or a recent window; hours with no activity are included with zero counts.
2320
+ * Returns one aggregate row for the requested period. It includes SMS lifecycle counts, delivery and failure rates, and processing, delivery, and total latency percentiles (`p50`, `p95`, and `p99`). Rows use send-time attribution, so recent periods can under-report `delivered` while delivery reports arrive.
2372
2321
  *
2373
- * Rows are bucketed by event time, not send time: a click recorded at 14:07 for a message sent at 09:00 lands in the 14:00 row.
2322
+ * Rate fields are `null` when their denominator is zero. For example, `delivery_rate` is `null` when no message was accepted.
2374
2323
  *
2375
- * A single request may span at most 30 days (720 hourly rows); for longer ranges use the daily endpoint, which has a 365-day window. An hourly window longer than 30 days, or a `from` after `to`, returns 422.
2324
+ * `from` and `to` must both be days or RFC 3339 instants. Day windows cover up to 365 days. Instant bounds round down to the hour and may span up to 720 hours. Mixing the forms returns `422`. Set `timezone` for local boundaries, one dimension filter at most, or `compare=previous_period` for the preceding equal-length window.
2376
2325
  *
2377
2326
  */
2378
- const getEmailStatsHourly = (options) => (options?.client ?? client).get({
2327
+ const getSmsStatsSummary = (options) => (options?.client ?? client).get({
2379
2328
  security: [{
2380
2329
  scheme: "bearer",
2381
2330
  type: "http"
@@ -2384,20 +2333,20 @@ const getEmailStatsHourly = (options) => (options?.client ?? client).get({
2384
2333
  name: "bird_session",
2385
2334
  type: "apiKey"
2386
2335
  }],
2387
- url: "/v1/email/stats/hourly",
2336
+ url: "/v1/sms/stats/summary",
2388
2337
  ...options
2389
2338
  });
2390
2339
  /**
2391
- * Stats by tag
2340
+ * Get daily SMS statistics
2392
2341
  *
2393
- * Returns delivery and engagement counts for the requested period, grouped by tag. Use it to compare performance across the tags you set at send time. Rows are ranked by the `sort` metric, `processed` by default, and capped at the requested `limit` (50 by default, 200 at most).
2342
+ * Returns one row of SMS lifecycle counts per calendar day. Rows use send-time attribution, so a delivery confirmation is counted on the day when its message was accepted. Recent rows can under-report `delivered` while delivery reports arrive. Days without activity contain zero counts.
2394
2343
  *
2395
- * Rows are computed against event time rather than send time, so engagement received during the period counts even for messages that were sent earlier.
2344
+ * Rates and latency are whole-window aggregates available from the summary endpoint. Use the message detail endpoints for individual message status.
2396
2345
  *
2397
- * The window can span at most 365 days. Ask for more and you get a 422.
2346
+ * A request may span up to 365 days; a longer window returns `422`. Set `timezone` for local calendar days instead of UTC.
2398
2347
  *
2399
2348
  */
2400
- const getEmailStatsByTag = (options) => (options?.client ?? client).get({
2349
+ const getSmsStatsDaily = (options) => (options?.client ?? client).get({
2401
2350
  security: [{
2402
2351
  scheme: "bearer",
2403
2352
  type: "http"
@@ -2406,20 +2355,20 @@ const getEmailStatsByTag = (options) => (options?.client ?? client).get({
2406
2355
  name: "bird_session",
2407
2356
  type: "apiKey"
2408
2357
  }],
2409
- url: "/v1/email/stats/tags",
2358
+ url: "/v1/sms/stats/daily",
2410
2359
  ...options
2411
2360
  });
2412
2361
  /**
2413
- * Aggregate stats summary
2362
+ * Get hourly SMS statistics
2414
2363
  *
2415
- * Returns a single-row aggregate across the requested period covering delivery, bounce, complaint, open, and click counts plus the derived rates, along with processing, delivery, and total latency percentiles (p50/p95/p99). Suitable for KPI tiles, campaign reports, and email digests; the daily and hourly endpoints have the same metrics per time bucket.
2364
+ * Returns one row of SMS lifecycle counts per hour. Rows use send-time attribution, so a delivery confirmation is counted in the hour when its message was accepted. Recent rows can under-report `delivered` while delivery reports arrive.
2416
2365
  *
2417
- * The aggregate is computed against event time (not send time), so engagement received during the period for messages sent earlier is included. Rate fields are null when their denominator is zero.
2366
+ * Rates and latency are whole-window aggregates available from the summary endpoint. Set `timezone` for local hours instead of UTC, including zones with sub-hour offsets.
2418
2367
  *
2419
- * The window grain follows the form of `from` and `to`: calendar days (`YYYY-MM-DD`, up to 365 days) or RFC 3339 instants (hour grain, up to 720 hours, 30 days), so a rolling window such as the last 24 hours is a single request. Mixing the two forms returns 422. Set `timezone` to compute day and hour boundaries in a local zone instead of UTC, and `compare=previous_period` to include the preceding equal-length window in the same response.
2368
+ * A request may span up to 30 days (720 rows). `from` and `to` are ISO 8601 instants; each bound rounds down to the hour and remains inclusive. An excessive or reversed window returns `422`. Use the daily endpoint for longer ranges.
2420
2369
  *
2421
2370
  */
2422
- const getEmailStatsSummary = (options) => (options?.client ?? client).get({
2371
+ const getSmsStatsHourly = (options) => (options?.client ?? client).get({
2423
2372
  security: [{
2424
2373
  scheme: "bearer",
2425
2374
  type: "http"
@@ -2428,20 +2377,20 @@ const getEmailStatsSummary = (options) => (options?.client ?? client).get({
2428
2377
  name: "bird_session",
2429
2378
  type: "apiKey"
2430
2379
  }],
2431
- url: "/v1/email/stats/summary",
2380
+ url: "/v1/sms/stats/hourly",
2432
2381
  ...options
2433
2382
  });
2434
2383
  /**
2435
- * Stats by sending IP
2384
+ * Get SMS statistics by originator
2436
2385
  *
2437
- * Returns delivery and deliverability counts for the requested period, grouped by the specific IP address used to send each message. Use it to spot a reputation problem on one IP. Block bounces concentrated on a single IP usually mean that IP's reputation has taken a hit, and sorting by `bounces.block` puts those IPs first.
2386
+ * Returns aggregate delivery and latency stats grouped by originator (the sender address messages were sent from) for the requested period. Rows are ranked by the `sort` metric (default `accepted`) descending and capped at the requested `limit` (default 50, hard maximum 200). Use this to compare sending performance across the senders you dispatch from.
2438
2387
  *
2439
- * A sending IP is only known once the receiving mail server reports an outcome: a delivery, a bounce, a deferral, or a late bounce. So this breakdown starts from the delivery stage onward. Accepted, processed, and rejected counts aren't included at all, and neither are engagement counts or processing latency. Complaints and out-of-band bounces aren't attributed to a sending IP either, so `complained` and `oob_bounces` are included but always read 0 here. Bounced, deferred, delivery latency, and total latency are the ones that have real numbers. For workspace-wide figures, use `GET /v1/email/stats/daily`. Rows are computed against event time rather than send time.
2388
+ * Rows use send-time attribution. A delivery confirmed during the period for a message accepted earlier counts against the earlier period. A recent period therefore under-reports `delivered` while delivery reports are still arriving, and its counts grow as reports arrive.
2440
2389
  *
2441
- * Rows are ranked by the `sort` field, `delivered` by default, and capped at the requested `limit` (50 by default, 200 at most). The window can span at most 365 days. Ask for more and you get a 422.
2390
+ * The maximum window is 365 days; requesting a longer range returns 422.
2442
2391
  *
2443
2392
  */
2444
- const getEmailStatsBySendingIp = (options) => (options?.client ?? client).get({
2393
+ const getSmsStatsByOriginator = (options) => (options?.client ?? client).get({
2445
2394
  security: [{
2446
2395
  scheme: "bearer",
2447
2396
  type: "http"
@@ -2450,20 +2399,20 @@ const getEmailStatsBySendingIp = (options) => (options?.client ?? client).get({
2450
2399
  name: "bird_session",
2451
2400
  type: "apiKey"
2452
2401
  }],
2453
- url: "/v1/email/stats/sending-ips",
2402
+ url: "/v1/sms/stats/originators",
2454
2403
  ...options
2455
2404
  });
2456
2405
  /**
2457
- * Stats by sending domain
2406
+ * Get SMS statistics by country
2458
2407
  *
2459
- * Returns delivery, engagement, and deliverability counts for the requested period, grouped by sending domain: the portion of the `From` address after the `@`. Use it to compare deliverability across multiple verified domains in your workspace, for example transactional versus marketing domains, or sub-domain segregation during IP warming.
2408
+ * Returns aggregate delivery and latency stats grouped by destination country for the requested period. Rows are ranked by the `sort` metric (default `accepted`) descending and capped at the requested `limit` (default 50, hard maximum 200). Use this to compare sending performance across the countries you send to.
2460
2409
  *
2461
- * Rows are computed against event time rather than send time, so engagement and bounces received during the period count even for messages that were sent earlier.
2410
+ * Rows use send-time attribution. A delivery confirmed during the period for a message accepted earlier counts against the earlier period. A recent period therefore under-reports `delivered` while delivery reports are still arriving, and its counts grow as reports arrive.
2462
2411
  *
2463
- * Rows are ranked by the `sort` metric, `processed` by default, and capped at the requested `limit` (50 by default, 200 at most). The window can span at most 365 days. Ask for more and you get a 422.
2412
+ * The maximum window is 365 days; requesting a longer range returns 422.
2464
2413
  *
2465
2414
  */
2466
- const getEmailStatsBySendingDomain = (options) => (options?.client ?? client).get({
2415
+ const getSmsStatsByCountry = (options) => (options?.client ?? client).get({
2467
2416
  security: [{
2468
2417
  scheme: "bearer",
2469
2418
  type: "http"
@@ -2472,20 +2421,20 @@ const getEmailStatsBySendingDomain = (options) => (options?.client ?? client).ge
2472
2421
  name: "bird_session",
2473
2422
  type: "apiKey"
2474
2423
  }],
2475
- url: "/v1/email/stats/sending-domains",
2424
+ url: "/v1/sms/stats/countries",
2476
2425
  ...options
2477
2426
  });
2478
2427
  /**
2479
- * Stats by category
2428
+ * Get SMS statistics by category
2480
2429
  *
2481
- * Returns delivery and engagement counts for the requested period, grouped by category, so you can compare deliverability and engagement between your transactional and marketing traffic. Rows are ranked by the `sort` metric, `processed` by default, and capped at the requested `limit` (50 by default, 200 at most).
2430
+ * Returns aggregate delivery and latency stats grouped by message category for the requested period. Rows are ranked by the `sort` metric (default `accepted`) descending and capped at the requested `limit` (default 50, hard maximum 200). Use this to compare sending performance across the categories you send under.
2482
2431
  *
2483
- * Rows are computed against event time rather than send time, so engagement received during the period counts even for messages that were sent earlier.
2432
+ * Rows use send-time attribution. A delivery confirmed during the period for a message accepted earlier counts against the earlier period. A recent period therefore under-reports `delivered` while delivery reports are still arriving, and its counts grow as reports arrive.
2484
2433
  *
2485
- * The window can span at most 365 days. Ask for more and you get a 422.
2434
+ * The maximum window is 365 days; requesting a longer range returns 422.
2486
2435
  *
2487
2436
  */
2488
- const getEmailStatsByCategory = (options) => (options?.client ?? client).get({
2437
+ const getSmsStatsByCategory = (options) => (options?.client ?? client).get({
2489
2438
  security: [{
2490
2439
  scheme: "bearer",
2491
2440
  type: "http"
@@ -2494,20 +2443,18 @@ const getEmailStatsByCategory = (options) => (options?.client ?? client).get({
2494
2443
  name: "bird_session",
2495
2444
  type: "apiKey"
2496
2445
  }],
2497
- url: "/v1/email/stats/categories",
2446
+ url: "/v1/sms/stats/categories",
2498
2447
  ...options
2499
2448
  });
2500
2449
  /**
2501
- * Stats by mailbox provider
2502
- *
2503
- * Returns delivery, engagement, and deliverability counts for the requested period, grouped by recipient mailbox provider, for example `gmail`, `yahoo`, `microsoft`, or `apple`. Use it to compare how each major inbox provider treats your mail, for example to spot a delivered-rate dip or a complaint spike at one provider before it spreads. For a per-region split within a provider, use the mailbox-provider-region breakdown.
2450
+ * Get SMS statistics by error code
2504
2451
  *
2505
- * A recipient's mailbox provider is only known once the receiving mail system reports an outcome, so this breakdown covers the delivery stage onward. Accepted, processed, and rejected counts and processing latency are not included. Rows are computed against event time rather than send time.
2452
+ * Returns aggregate delivery and latency statistics grouped by normalized failure reason for the requested period. The grouping key matches the `error_code` filter on the message list, so each row maps directly to the affected messages rather than a raw carrier code. Rows are ranked by the `sort` metric (default `failed`) descending and capped at the requested `limit` (default 50, hard maximum 200).
2506
2453
  *
2507
- * Rows are ranked by the `sort` metric, `delivered` by default, and capped at the requested `limit` (50 by default, 200 at most). The window can span at most 365 days. Ask for more and you get a 422.
2454
+ * Rows use send-time attribution. A delivery confirmed during the period for a message accepted earlier counts against the earlier period. A recent period therefore under-reports `delivered` while delivery reports are still arriving, and its counts grow as reports arrive. The maximum window is 365 days; requesting a longer range returns 422.
2508
2455
  *
2509
2456
  */
2510
- const getEmailStatsByMailboxProvider = (options) => (options?.client ?? client).get({
2457
+ const getSmsStatsByErrorCode = (options) => (options?.client ?? client).get({
2511
2458
  security: [{
2512
2459
  scheme: "bearer",
2513
2460
  type: "http"
@@ -2516,20 +2463,20 @@ const getEmailStatsByMailboxProvider = (options) => (options?.client ?? client).
2516
2463
  name: "bird_session",
2517
2464
  type: "apiKey"
2518
2465
  }],
2519
- url: "/v1/email/stats/mailbox-providers",
2466
+ url: "/v1/sms/stats/error-codes",
2520
2467
  ...options
2521
2468
  });
2522
2469
  /**
2523
- * Stats by mailbox provider region
2470
+ * Get SMS statistics by carrier
2524
2471
  *
2525
- * Returns delivery, engagement, and deliverability counts for the requested period, grouped by mailbox provider and provider region pair, for example `gmail` in `NA` or `microsoft` in `EU`. The provider region is the regional grouping the receiving mail system reports for the recipient's provider. Pairing it with the provider tells apart a region label that several providers share. Use it to spot a deliverability problem isolated to one provider in one region. For a per-provider view without the region split, use the mailbox-provider breakdown.
2472
+ * Returns aggregate delivery and latency stats grouped by delivery carrier for the requested period. Rows are ranked by the `sort` metric (default `accepted`) descending and capped at the requested `limit` (default 50, hard maximum 200). Use this to compare delivery performance across the carriers that handled your messages.
2526
2473
  *
2527
- * A provider region is only known once the receiving mail system reports an outcome, so this breakdown covers the delivery stage onward. Accepted, processed, and rejected counts and processing latency are not included. Rows are computed against event time rather than send time.
2474
+ * Rows use send-time attribution. A delivery confirmed during the period for a message accepted earlier counts against the earlier period. A recent period therefore under-reports `delivered` while delivery reports are still arriving, and its counts grow as reports arrive.
2528
2475
  *
2529
- * Rows are ranked by the `sort` metric, `delivered` by default, and capped at the requested `limit` (50 by default, 200 at most). The window can span at most 365 days. Ask for more and you get a 422.
2476
+ * The maximum window is 365 days; requesting a longer range returns 422.
2530
2477
  *
2531
2478
  */
2532
- const getEmailStatsByMailboxProviderRegion = (options) => (options?.client ?? client).get({
2479
+ const getSmsStatsByCarrier = (options) => (options?.client ?? client).get({
2533
2480
  security: [{
2534
2481
  scheme: "bearer",
2535
2482
  type: "http"
@@ -2538,20 +2485,20 @@ const getEmailStatsByMailboxProviderRegion = (options) => (options?.client ?? cl
2538
2485
  name: "bird_session",
2539
2486
  type: "apiKey"
2540
2487
  }],
2541
- url: "/v1/email/stats/mailbox-provider-regions",
2488
+ url: "/v1/sms/stats/carriers",
2542
2489
  ...options
2543
2490
  });
2544
2491
  /**
2545
- * Stats by recipient domain
2492
+ * Get SMS statistics by tag
2546
2493
  *
2547
- * Returns delivery and engagement counts for the requested period, grouped by recipient mailbox domain: the part of each recipient address after the `@`, for example `gmail.com`, `yahoo.com`, or `outlook.com`. This is the finest-grained deliverability view. Where the mailbox-provider breakdown groups recipients into provider buckets such as `gmail` or `microsoft`, this keys on the exact destination domain. Use it to spot a delivery-rate dip or a complaint spike at a specific domain.
2494
+ * Returns delivery and latency statistics grouped by tag (`name:value`). Rows sort by the selected metric in descending order and are capped by `limit`. The default sort is `accepted`; the default limit is 50 and the maximum is 200.
2548
2495
  *
2549
- * Rows are ranked by the `sort` metric, `processed` by default, and capped at the requested `limit` (50 by default, 200 at most). Rows are computed against event time rather than send time, so engagement received during the period counts even for messages that were sent earlier.
2496
+ * Only tagged messages appear. A message with several tags is counted once under each, so rows do not sum to the period total.
2550
2497
  *
2551
- * The window can span at most 365 days. Ask for more and you get a 422.
2498
+ * Rows use send-time attribution, so recent periods can under-report `delivered` while delivery reports arrive. A request may span up to 365 days; a longer window returns `422`.
2552
2499
  *
2553
2500
  */
2554
- const getEmailStatsByRecipientDomain = (options) => (options?.client ?? client).get({
2501
+ const getSmsStatsByTag = (options) => (options?.client ?? client).get({
2555
2502
  security: [{
2556
2503
  scheme: "bearer",
2557
2504
  type: "http"
@@ -2560,20 +2507,20 @@ const getEmailStatsByRecipientDomain = (options) => (options?.client ?? client).
2560
2507
  name: "bird_session",
2561
2508
  type: "apiKey"
2562
2509
  }],
2563
- url: "/v1/email/stats/recipient-domains",
2510
+ url: "/v1/sms/stats/tags",
2564
2511
  ...options
2565
2512
  });
2566
2513
  /**
2567
- * Stats by template
2514
+ * Get SMS statistics by status
2568
2515
  *
2569
- * Returns aggregate delivery and engagement counts grouped by the template each message was sent with, so a template's deliverability and engagement can be compared side by side. Attribution is by the template used at send time; only messages sent with a template appear here, so a workspace that has sent none returns an empty list rather than an error. Each row is keyed by the template ID (`emt_…`); a template deleted after sending still appears by its ID.
2516
+ * Returns one row per lifecycle status with activity in the requested period, ordered by count descending. The statuses are `accepted`, `sent`, `delivered`, `undelivered`, `failed`, `rejected`, and `expired`.
2570
2517
  *
2571
- * Rows are ranked by the `sort` metric (default `processed`) descending and capped at the requested `limit` (default 50, hard maximum 200). Rows are computed against event time (not send time), so engagement received during the period for messages sent earlier is included.
2518
+ * Rows use send-time attribution. A delivery confirmed during the period for a message accepted earlier counts against the earlier period. A recent period therefore under-reports `delivered` while delivery reports are still arriving. With at most seven statuses, this breakdown has no cap, ranking, limit, or trend parameters.
2572
2519
  *
2573
2520
  * The maximum window is 365 days; requesting a longer range returns 422.
2574
2521
  *
2575
2522
  */
2576
- const getEmailStatsByTemplate = (options) => (options?.client ?? client).get({
2523
+ const getSmsStatsByStatus = (options) => (options?.client ?? client).get({
2577
2524
  security: [{
2578
2525
  scheme: "bearer",
2579
2526
  type: "http"
@@ -2582,20 +2529,20 @@ const getEmailStatsByTemplate = (options) => (options?.client ?? client).get({
2582
2529
  name: "bird_session",
2583
2530
  type: "apiKey"
2584
2531
  }],
2585
- url: "/v1/email/stats/templates",
2532
+ url: "/v1/sms/stats/statuses",
2586
2533
  ...options
2587
2534
  });
2588
2535
  /**
2589
- * Engagement by location
2536
+ * Get a received-message summary
2590
2537
  *
2591
- * Returns engagement counts (opens and clicks) for the requested period, grouped by the location they were recorded from. Use it to see where your audience engages, for example the top countries by unique opens. The reading location is only known from open and click events, so rows have engagement counts but no delivery counts or rates.
2538
+ * Returns the total number of messages your numbers received over the period, using the time the carrier received each message.
2592
2539
  *
2593
- * Use `group_by` to choose the granularity: `country` (the default), `region`, or `city`. Each row has the location hierarchy down to the requested level, so a `city` grouping also reports that row's region and country. Rows are ranked by the `sort` metric, `unique_opens` by default, and capped at the requested `limit` (50 by default, 200 at most).
2540
+ * The response contains only a count because a received message has one state. Use the send statistics endpoints for delivery rates and latency data about messages you send.
2594
2541
  *
2595
- * Rows are computed against event time rather than send time. The window can span at most 365 days. Ask for more and you get a 422.
2542
+ * The maximum window is 365 days; a longer range returns 422. Set `timezone` to resolve the period against your local calendar instead of UTC.
2596
2543
  *
2597
2544
  */
2598
- const getEmailStatsByLocation = (options) => (options?.client ?? client).get({
2545
+ const getSmsInboundStatsSummary = (options) => (options?.client ?? client).get({
2599
2546
  security: [{
2600
2547
  scheme: "bearer",
2601
2548
  type: "http"
@@ -2604,20 +2551,20 @@ const getEmailStatsByLocation = (options) => (options?.client ?? client).get({
2604
2551
  name: "bird_session",
2605
2552
  type: "apiKey"
2606
2553
  }],
2607
- url: "/v1/email/stats/locations",
2554
+ url: "/v1/sms/stats/inbound/summary",
2608
2555
  ...options
2609
2556
  });
2610
2557
  /**
2611
- * Engagement by email client
2558
+ * Get daily received-message counts
2612
2559
  *
2613
- * Returns engagement counts (opens and clicks) for the requested period, grouped by the email client, operating system, or device type they were recorded from. Use it for the classic view of opens by mail client, for example the share of opens from Apple Mail compared with Gmail and Outlook. The reading environment is only known from open and click events, so rows have engagement counts but no delivery counts or rates.
2560
+ * Returns the number of messages your numbers received, one row per calendar day. Rows use the time the carrier received each message, and days with no messages contain a zero count.
2614
2561
  *
2615
- * Use `group_by` to choose the facet: `email_client` (the default), `os`, or `device_type`. Each row fills in the facet you chose and leaves the other two null. Rows are ranked by the `sort` metric, `unique_opens` by default, and capped at the requested `limit` (50 by default, 200 at most).
2562
+ * Each row contains only a count because a received message has one state. Use the send statistics endpoints for lifecycle and delivery-latency data about messages you send.
2616
2563
  *
2617
- * Rows are computed against event time rather than send time. The window can span at most 365 days. Ask for more and you get a 422.
2564
+ * The maximum window is 365 days; a longer range returns 422. Set `timezone` to bucket rows by your local calendar day instead of UTC.
2618
2565
  *
2619
2566
  */
2620
- const getEmailStatsByClient = (options) => (options?.client ?? client).get({
2567
+ const getSmsInboundStatsDaily = (options) => (options?.client ?? client).get({
2621
2568
  security: [{
2622
2569
  scheme: "bearer",
2623
2570
  type: "http"
@@ -2626,20 +2573,20 @@ const getEmailStatsByClient = (options) => (options?.client ?? client).get({
2626
2573
  name: "bird_session",
2627
2574
  type: "apiKey"
2628
2575
  }],
2629
- url: "/v1/email/stats/clients",
2576
+ url: "/v1/sms/stats/inbound/daily",
2630
2577
  ...options
2631
2578
  });
2632
2579
  /**
2633
- * Bounces by SMTP error code
2580
+ * Get hourly received-message counts
2634
2581
  *
2635
- * Returns bounce counts for the requested period, grouped by the SMTP error code the receiving mail server returned. It answers the question of which SMTP responses are driving your bounces. Each row reports how many recipients bounced with that code, plus the hard, soft, admin, block, and undetermined split for that code.
2582
+ * Returns the number of messages your numbers received, one row per hour. Rows use the time the carrier received each message, and hours with no messages contain a zero count.
2636
2583
  *
2637
- * This breakdown only covers the failure side. There are no delivered, open, click, or rate fields, because a bounce code is only ever recorded on a bounce event.
2584
+ * Each row contains only a count because a received message has one state. Use the send statistics endpoints for lifecycle and delivery-latency data about messages you send.
2638
2585
  *
2639
- * Rows are ranked by the `sort` metric, `bounced` by default, and capped at the requested `limit` (50 by default, 200 at most). They are computed against event time rather than send time. The window can span at most 365 days. Ask for more and you get a 422.
2586
+ * The maximum window is 720 hours; a longer range returns 422. Set `timezone` to bucket rows by your local hour instead of UTC.
2640
2587
  *
2641
2588
  */
2642
- const getEmailStatsByBounceCode = (options) => (options?.client ?? client).get({
2589
+ const getSmsInboundStatsHourly = (options) => (options?.client ?? client).get({
2643
2590
  security: [{
2644
2591
  scheme: "bearer",
2645
2592
  type: "http"
@@ -2648,20 +2595,18 @@ const getEmailStatsByBounceCode = (options) => (options?.client ?? client).get({
2648
2595
  name: "bird_session",
2649
2596
  type: "apiKey"
2650
2597
  }],
2651
- url: "/v1/email/stats/bounce-codes",
2598
+ url: "/v1/sms/stats/inbound/hourly",
2652
2599
  ...options
2653
2600
  });
2654
2601
  /**
2655
- * Complaints by type
2656
- *
2657
- * Returns spam-complaint counts for the requested period, grouped by the feedback-loop complaint type the mailbox provider reported, for example `abuse`, `fraud`, or `virus`. Use it to see what kind of complaints your mail attracts.
2602
+ * Get received messages by country
2658
2603
  *
2659
- * This breakdown only covers the complaint side. Each row has the complained count for one type and nothing else, because a complaint type is only ever recorded on a spam-complaint event.
2604
+ * Returns the number of messages your numbers received, grouped by the receiving number's country. Rows are ranked by volume, highest first, and use the time the carrier received each message.
2660
2605
  *
2661
- * Rows are ranked by `complained` descending, and capped at the requested `limit` (default 50, hard maximum 200). They are computed against event time rather than send time. The window can span at most 365 days. Ask for more and you get a 422.
2606
+ * Each row contains only a count because a received message has one state. The maximum window is 365 days; a longer range returns `422`. Set `timezone` to resolve the period against your local calendar.
2662
2607
  *
2663
2608
  */
2664
- const getEmailStatsByComplaintType = (options) => (options?.client ?? client).get({
2609
+ const getSmsInboundStatsByCountry = (options) => (options?.client ?? client).get({
2665
2610
  security: [{
2666
2611
  scheme: "bearer",
2667
2612
  type: "http"
@@ -2670,20 +2615,20 @@ const getEmailStatsByComplaintType = (options) => (options?.client ?? client).ge
2670
2615
  name: "bird_session",
2671
2616
  type: "apiKey"
2672
2617
  }],
2673
- url: "/v1/email/stats/complaint-types",
2618
+ url: "/v1/sms/stats/inbound/countries",
2674
2619
  ...options
2675
2620
  });
2676
2621
  /**
2677
- * Stats by broadcast
2622
+ * Get received messages by operator
2678
2623
  *
2679
- * Returns aggregate delivery and engagement counts grouped by broadcast for the requested period, so each broadcast's deliverability and engagement can be compared side by side. Only messages sent as part of a broadcast appear here. One-off and transactional sends are not included, so a workspace that has not sent broadcasts returns an empty list rather than an error.
2624
+ * Returns the number of messages your numbers received, grouped by the sender's mobile operator. Rows are ranked by volume, highest first, and use the time the carrier received each message. Operators are identified by MCC-MNC when the carrier reports it.
2680
2625
  *
2681
- * Rows are ranked by the `sort` metric (default `processed`) descending and capped at the requested `limit` (default 50, hard maximum 200). Rows are computed against event time (not send time), so engagement received during the period for messages sent earlier is included.
2626
+ * Each row contains only a count because a received message has one state. Messages without a reported sending operator are excluded, so the rows can sum to less than the summary total.
2682
2627
  *
2683
- * The maximum window is 365 days. Requesting a longer range returns a 422. This breakdown is computed from per-message activity retained for 30 days, so it reflects roughly the last 30 days of activity even when the requested window reaches further back.
2628
+ * The maximum window is 365 days; a longer range returns `422`. Set `timezone` to resolve the period against your local calendar.
2684
2629
  *
2685
2630
  */
2686
- const getEmailStatsByBroadcast = (options) => (options?.client ?? client).get({
2631
+ const getSmsInboundStatsByOperator = (options) => (options?.client ?? client).get({
2687
2632
  security: [{
2688
2633
  scheme: "bearer",
2689
2634
  type: "http"
@@ -2692,16 +2637,18 @@ const getEmailStatsByBroadcast = (options) => (options?.client ?? client).get({
2692
2637
  name: "bird_session",
2693
2638
  type: "apiKey"
2694
2639
  }],
2695
- url: "/v1/email/stats/broadcasts",
2640
+ url: "/v1/sms/stats/inbound/operators",
2696
2641
  ...options
2697
2642
  });
2698
2643
  /**
2699
- * List sending domains
2644
+ * Get received messages by number
2700
2645
  *
2701
- * Returns all sending domains for the current workspace, newest first by default. Each item is the full domain object, including capability statuses and `dns_records`, so no per-domain follow-up read is needed. Filter with `name` to find a specific domain.
2646
+ * Returns how many messages each of your numbers received. Rows are ranked by volume, highest first, and use the time the carrier received each message.
2647
+ *
2648
+ * Each row contains only a count because a received message has one state. The maximum window is 365 days; a longer range returns `422`. Set `timezone` to resolve the period against your local calendar.
2702
2649
  *
2703
2650
  */
2704
- const listDomains = (options) => (options?.client ?? client).get({
2651
+ const getSmsInboundStatsByNumber = (options) => (options?.client ?? client).get({
2705
2652
  security: [{
2706
2653
  scheme: "bearer",
2707
2654
  type: "http"
@@ -2710,29 +2657,18 @@ const listDomains = (options) => (options?.client ?? client).get({
2710
2657
  name: "bird_session",
2711
2658
  type: "apiKey"
2712
2659
  }],
2713
- url: "/v1/email/domains",
2660
+ url: "/v1/sms/stats/inbound/numbers",
2714
2661
  ...options
2715
2662
  });
2716
2663
  /**
2717
- * Add a sending domain
2664
+ * Create a phone number lookup
2718
2665
  *
2719
- * Registers a new sending domain and returns the DNS records to publish
2720
- * for it. The DKIM TXT record proves ownership, and together with the
2721
- * return-path CNAME (which also covers SPF, so no separate SPF record is
2722
- * needed) and a DMARC policy it gates sending. The tracking CNAME is
2723
- * optional and gates branded link tracking only. Publish the records at
2724
- * your DNS provider, then check progress with
2725
- * [Trigger domain verification](/docs/api/reference/verify-domain). Published
2726
- * records are also re-checked for you automatically. Setup walkthrough:
2727
- * [Sending domains](/docs/guides/email/sending-domains).
2666
+ * Returns the number's serving and issuing networks, porting state, country, and line type. The baseline fields are included in each lookup. Request additional `type` blocks for classification, presence, roaming, SIM-swap, porting-history, or credibility data. Each block reports its own `status`; only blocks with an `ok` status incur an additional charge.
2728
2667
  *
2729
- * The domain starts in `pending` status. A domain already registered in
2730
- * this workspace returns `409`, and creation beyond your organization's
2731
- * domain quota returns `422` `E10000`. A domain that never verifies
2732
- * ownership is removed after about 14 days, with a reminder email first.
2668
+ * This form keeps the number out of the URL. The [URL form](/docs/api/reference/get-phone-number-lookup) performs the same lookup but cannot use an idempotency key. With this form, reuse an `Idempotency-Key` to return the stored result without another lookup or charge.
2733
2669
  *
2734
2670
  */
2735
- const createDomain = (options) => (options.client ?? client).post({
2671
+ const createPhoneNumberLookup = (options) => (options.client ?? client).post({
2736
2672
  security: [{
2737
2673
  scheme: "bearer",
2738
2674
  type: "http"
@@ -2741,7 +2677,7 @@ const createDomain = (options) => (options.client ?? client).post({
2741
2677
  name: "bird_session",
2742
2678
  type: "apiKey"
2743
2679
  }],
2744
- url: "/v1/email/domains",
2680
+ url: "/v1/lookup/phone-number",
2745
2681
  ...options,
2746
2682
  headers: {
2747
2683
  "Content-Type": "application/json",
@@ -2749,12 +2685,14 @@ const createDomain = (options) => (options.client ?? client).post({
2749
2685
  }
2750
2686
  });
2751
2687
  /**
2752
- * Delete a sending domain
2688
+ * Create an email address lookup
2753
2689
  *
2754
- * Removes the domain and revokes its sender authorization. New sends from a deleted domain are rejected. Historical statistics and events for past sends from this domain are preserved.
2690
+ * Returns a deliverability `result`, a `delivery_confidence` score, address characteristics, an undeliverable `reason`, and a suggested correction when available. `result` and `reason` are open vocabularies. Handle unknown values and use `delivery_confidence` as the stable fallback. Each completed lookup incurs the same charge regardless of its result.
2691
+ *
2692
+ * This form keeps the address out of the URL. The [URL form](/docs/api/reference/get-email-lookup) performs the same lookup but cannot use an idempotency key. With this form, reuse an `Idempotency-Key` to return the stored result without another lookup or charge.
2755
2693
  *
2756
2694
  */
2757
- const deleteDomain = (options) => (options.client ?? client).delete({
2695
+ const createEmailLookup = (options) => (options.client ?? client).post({
2758
2696
  security: [{
2759
2697
  scheme: "bearer",
2760
2698
  type: "http"
@@ -2763,16 +2701,24 @@ const deleteDomain = (options) => (options.client ?? client).delete({
2763
2701
  name: "bird_session",
2764
2702
  type: "apiKey"
2765
2703
  }],
2766
- url: "/v1/email/domains/{domain_id}",
2767
- ...options
2704
+ url: "/v1/lookup/email",
2705
+ ...options,
2706
+ headers: {
2707
+ "Content-Type": "application/json",
2708
+ ...options.headers
2709
+ }
2768
2710
  });
2769
2711
  /**
2770
- * Get a sending domain
2712
+ * Create a verification
2771
2713
  *
2772
- * Returns the domain with its capability statuses and every DNS record's current verification state. This read reports the stored result of the last check. To run a fresh DNS check, use [Trigger domain verification](/docs/api/reference/verify-domain).
2714
+ * Creates a verification and sends the recipient a one-time passcode. Provide an email address, a phone number, or both in `to`. The service sends over one channel at a time and moves to the next planned channel if delivery fails.
2715
+ *
2716
+ * Calling this again for the same recipient reuses the verification in progress. During the resend cooldown, it returns the current state without sending. After the cooldown, it sends a fresh passcode.
2717
+ *
2718
+ * The `200` response contains the current state, never the passcode. Submit the recipient's passcode with [Check a verification](/docs/api/reference/create-verification-check) before `expires_at`. An invalid recipient returns `422`; exceeding the send rate limit returns `429`.
2773
2719
  *
2774
2720
  */
2775
- const getDomain = (options) => (options.client ?? client).get({
2721
+ const createVerification = (options) => (options.client ?? client).post({
2776
2722
  security: [{
2777
2723
  scheme: "bearer",
2778
2724
  type: "http"
@@ -2781,27 +2727,27 @@ const getDomain = (options) => (options.client ?? client).get({
2781
2727
  name: "bird_session",
2782
2728
  type: "apiKey"
2783
2729
  }],
2784
- url: "/v1/email/domains/{domain_id}",
2785
- ...options
2730
+ url: "/v1/verify/verifications",
2731
+ ...options,
2732
+ headers: {
2733
+ "Content-Type": "application/json",
2734
+ ...options.headers
2735
+ }
2786
2736
  });
2787
2737
  /**
2788
- * Update a sending domain
2738
+ * Create a verification passcode check
2789
2739
  *
2790
- * Updates settings and configuration on a sending domain. `settings`
2791
- * changes apply immediately. Changes to `return_path`, `tracking`, or
2792
- * `dkim` on a verified capability are staged: the current configuration
2793
- * keeps serving until the new one's DNS records verify, then the change
2794
- * is promoted automatically. Staged values are visible under
2795
- * `capabilities.*.pending`. The records to publish appear in
2796
- * `dns_records` with `state: pending`.
2740
+ * Checks a passcode for a recipient and returns the outcome together with the verification's current state. Identify the verification by the same `to` used to create it; you do not need to store a verification ID.
2797
2741
  *
2798
- * Invalid combinations are rejected. Enabling tracking toggles without a
2799
- * tracking domain, or removing the tracking domain while a toggle is on,
2800
- * returns `409`. Enabling inbound receiving has verification
2801
- * prerequisites that return `422`. Each rule is detailed on its field.
2742
+ * A wrong or expired passcode returns `200 OK` with `success: false` and a `reason` such as `incorrect_code` or `expired`. `success: true` means the verification is complete. Each verification reports its final outcome once and cannot be checked again.
2743
+ *
2744
+ * An error status is returned only when the check cannot be evaluated. A `404`
2745
+ * means no verification matches the recipient or the matching one already
2746
+ * reached its final state. A `422` indicates an invalid recipient. A `429`
2747
+ * means passcodes for a recipient are being checked too quickly.
2802
2748
  *
2803
2749
  */
2804
- const updateDomain = (options) => (options.client ?? client).patch({
2750
+ const createVerificationCheck = (options) => (options.client ?? client).post({
2805
2751
  security: [{
2806
2752
  scheme: "bearer",
2807
2753
  type: "http"
@@ -2810,7 +2756,7 @@ const updateDomain = (options) => (options.client ?? client).patch({
2810
2756
  name: "bird_session",
2811
2757
  type: "apiKey"
2812
2758
  }],
2813
- url: "/v1/email/domains/{domain_id}",
2759
+ url: "/v1/verify/verifications/check",
2814
2760
  ...options,
2815
2761
  headers: {
2816
2762
  "Content-Type": "application/json",
@@ -2818,22 +2764,16 @@ const updateDomain = (options) => (options.client ?? client).patch({
2818
2764
  }
2819
2765
  });
2820
2766
  /**
2821
- * Trigger domain verification
2767
+ * Create the next verification channel attempt
2822
2768
  *
2823
- * Runs a fresh DNS check across the domain's records (DKIM, return path,
2824
- * DMARC, tracking, inbound MX, and any staged changes) and returns the
2825
- * updated domain. Use it for an immediate result after publishing or
2826
- * correcting records. [Get a sending domain](/docs/api/reference/get-domain)
2827
- * only reports the last stored result. Published records are also re-checked
2828
- * for you automatically in the background.
2769
+ * Advances an in-progress verification to the next channel in its plan and sends a fresh passcode there. Identify the verification by the same `to` recipient used to create it; no verification ID is required.
2829
2770
  *
2830
- * A `200` with records still `pending` is not a failure: the records were
2831
- * not found yet, which is normal while DNS propagates (minutes to hours).
2832
- * Recently verified records are not re-queried, so the call is safe to
2833
- * repeat while you wait.
2771
+ * The send bypasses the resend cooldown, and passcodes sent earlier remain valid. The response sets `last_channel` to the most recent completed send. Concurrent requests each advance the plan by at most one channel and return committed state.
2772
+ *
2773
+ * A missing in-progress verification returns `404`. A plan with no further channel returns `422 NoNextChannel`; create the verification again to resend on the current channel. If every remaining channel fails, the operation returns `422 NoAvailableChannel`. Requests that exceed the send rate limit return `429`.
2834
2774
  *
2835
2775
  */
2836
- const verifyDomain = (options) => (options.client ?? client).post({
2776
+ const createVerificationNextChannel = (options) => (options.client ?? client).post({
2837
2777
  security: [{
2838
2778
  scheme: "bearer",
2839
2779
  type: "http"
@@ -2842,15 +2782,644 @@ const verifyDomain = (options) => (options.client ?? client).post({
2842
2782
  name: "bird_session",
2843
2783
  type: "apiKey"
2844
2784
  }],
2845
- url: "/v1/email/domains/{domain_id}/verify",
2846
- ...options
2785
+ url: "/v1/verify/verifications/next-channel",
2786
+ ...options,
2787
+ headers: {
2788
+ "Content-Type": "application/json",
2789
+ ...options.headers
2790
+ }
2847
2791
  });
2848
2792
  /**
2849
- * List mailboxes
2850
- *
2851
- * Returns a paginated list of the workspace's mailboxes, newest first. Search across addresses and display names with `q`, look a mailbox up by its exact address, or filter by lifecycle state or domain.
2793
+ * List WhatsApp messages
2852
2794
  *
2853
- */
2795
+ * Returns the workspace's WhatsApp messages as a cursor-paginated list,
2796
+ * newest first, outbound and inbound alike. Each message carries the one
2797
+ * content object it was built from: `template`, or free-form `text`,
2798
+ * `image`, `video`, `audio`, `sticker`, `document` or `location`. An inbound
2799
+ * message whose content WhatsApp models and we do not carries `unsupported`
2800
+ * instead, naming the type rather than reading back empty.
2801
+ * Filter by direction, status, contact phone number,
2802
+ * business-scoped user ID, template category, tag, or creation time; pass the response's `next_cursor` back as
2803
+ * `starting_after` to fetch the next page. To follow a single message's
2804
+ * delivery, use
2805
+ * [Get a WhatsApp message](/docs/api/reference/get-whatsapp-message)
2806
+ * instead.
2807
+ *
2808
+ * Messages are retained for **30 days**. A `created_after` earlier than that
2809
+ * is accepted and raised to the retention bound rather than rejected, so a
2810
+ * wider window returns what is still retained instead of failing. There is no
2811
+ * way to read messages older than the window.
2812
+ *
2813
+ */
2814
+ const listWhatsAppMessages = (options) => (options?.client ?? client).get({
2815
+ security: [{
2816
+ scheme: "bearer",
2817
+ type: "http"
2818
+ }, {
2819
+ in: "cookie",
2820
+ name: "bird_session",
2821
+ type: "apiKey"
2822
+ }],
2823
+ url: "/v1/whatsapp/messages",
2824
+ ...options
2825
+ });
2826
+ /**
2827
+ * Send a WhatsApp message
2828
+ *
2829
+ * Sends one WhatsApp message to one recipient. The request carries exactly one
2830
+ * kind of content: a message template, or free-form `text`, `image`, `video`,
2831
+ * `audio`, `sticker`, `document` or `location`. A request carrying none is
2832
+ * rejected with a `422`, and one carrying more than one is too.
2833
+ *
2834
+ * A **template** is the only content WhatsApp delivers outside an open
2835
+ * customer service window, so it is what starts a conversation. Name the
2836
+ * template, optionally pick its language variant, and fill its placeholders in
2837
+ * `components`. A Bird-managed template selects its sender number from its
2838
+ * category, so the request carries no `from`; a template your workspace
2839
+ * authored requires one. Browse your workspace's templates in the Bird
2840
+ * dashboard.
2841
+ *
2842
+ * **Free-form content** is deliverable only inside an open 24-hour customer
2843
+ * service window, which the contact opens by messaging or calling you and
2844
+ * resets each time they do it again. We do not track the window, so a send
2845
+ * outside one is accepted and then fails, carrying `service_window_expired` on
2846
+ * the message's `last_error`. Every free-form send requires `from`.
2847
+ *
2848
+ * The `202` response is the accepted message, echoing the resolved content; it
2849
+ * is not a delivery confirmation. Follow delivery with
2850
+ * [Get a WhatsApp message](/docs/api/reference/get-whatsapp-message), the
2851
+ * per-message timeline from
2852
+ * [List events for a WhatsApp message](/docs/api/reference/list-whatsapp-message-events),
2853
+ * or `whatsapp.*` webhook events.
2854
+ *
2855
+ * Each of these returns a `422`:
2856
+ *
2857
+ * - A template slug or language the catalogue does not stock.
2858
+ * - Parameter values that do not match the template's declared placeholders.
2859
+ * - A `from` this workspace cannot send from.
2860
+ * - A recipient that is neither a valid phone number nor a business-scoped user ID.
2861
+ *
2862
+ */
2863
+ const createWhatsAppMessage = (options) => (options.client ?? client).post({
2864
+ security: [{
2865
+ scheme: "bearer",
2866
+ type: "http"
2867
+ }, {
2868
+ in: "cookie",
2869
+ name: "bird_session",
2870
+ type: "apiKey"
2871
+ }],
2872
+ url: "/v1/whatsapp/messages",
2873
+ ...options,
2874
+ headers: {
2875
+ "Content-Type": "application/json",
2876
+ ...options.headers
2877
+ }
2878
+ });
2879
+ /**
2880
+ * Get a WhatsApp message
2881
+ *
2882
+ * Returns a single WhatsApp message: its current delivery status, per-stage timestamps (`sent_at`, `delivered_at`, `read_at`), and failure detail when it failed. It carries the one content object it was built from: `template`, or free-form `text`, `image`, `video`, `audio`, `sticker`, `document` or `location`. An inbound message whose content WhatsApp models and we do not carries `unsupported` instead, naming the type rather than reading back empty. The `status` advances asynchronously as delivery progresses, so poll this endpoint (or subscribe to `whatsapp.*` webhook events) after a send to confirm delivery. For the per-event timeline, use [List events for a WhatsApp message](/docs/api/reference/list-whatsapp-message-events) instead.
2883
+ *
2884
+ */
2885
+ const getWhatsAppMessage = (options) => (options.client ?? client).get({
2886
+ security: [{
2887
+ scheme: "bearer",
2888
+ type: "http"
2889
+ }, {
2890
+ in: "cookie",
2891
+ name: "bird_session",
2892
+ type: "apiKey"
2893
+ }],
2894
+ url: "/v1/whatsapp/messages/{message_id}",
2895
+ ...options
2896
+ });
2897
+ /**
2898
+ * List events for a WhatsApp message
2899
+ *
2900
+ * Returns a WhatsApp message's lifecycle events in chronological order, one entry per delivery transition (`whatsapp.accepted`, `whatsapp.sent`, `whatsapp.delivered`, `whatsapp.read`, `whatsapp.failed`). The timeline is bounded and returned in full, so this list is not paginated; an unknown message ID returns `404`. For the message's current state in a single field, use [Get a WhatsApp message](/docs/api/reference/get-whatsapp-message) instead.
2901
+ *
2902
+ */
2903
+ const listWhatsAppMessageEvents = (options) => (options.client ?? client).get({
2904
+ security: [{
2905
+ scheme: "bearer",
2906
+ type: "http"
2907
+ }, {
2908
+ in: "cookie",
2909
+ name: "bird_session",
2910
+ type: "apiKey"
2911
+ }],
2912
+ url: "/v1/whatsapp/messages/{message_id}/events",
2913
+ ...options
2914
+ });
2915
+ /**
2916
+ * Get daily sending statistics
2917
+ *
2918
+ * Returns one row of aggregate sending statistics per calendar day for the workspace: UTC days by default, or your local days when `timezone` is set. Days with no activity are included with zero counts, so the series charts without client-side gap handling. Suited to charts and trend lines; for per-message exact accounting use the message detail endpoints.
2919
+ *
2920
+ * Rows use event time. For example, a complaint received on Wednesday for a message sent the prior Monday is counted in Wednesday's row.
2921
+ *
2922
+ * The maximum window is 365 days; requesting a longer range returns `422`.
2923
+ *
2924
+ */
2925
+ const getEmailStatsDaily = (options) => (options?.client ?? client).get({
2926
+ security: [{
2927
+ scheme: "bearer",
2928
+ type: "http"
2929
+ }, {
2930
+ in: "cookie",
2931
+ name: "bird_session",
2932
+ type: "apiKey"
2933
+ }],
2934
+ url: "/v1/email/stats/daily",
2935
+ ...options
2936
+ });
2937
+ /**
2938
+ * Get hourly sending statistics
2939
+ *
2940
+ * Returns one row of aggregate sending statistics per hour for the workspace: UTC hours by default, or your local hours when `timezone` is set (a timezone with a sub-hour offset gets correctly aligned hours). Useful for inspecting send rate, deliverability, and engagement inside a single day or a recent window; hours with no activity are included with zero counts.
2941
+ *
2942
+ * Rows use event time. For example, a click recorded at 14:07 for a message sent at 09:00 lands in the 14:00 row.
2943
+ *
2944
+ * A single request may span at most 30 days (720 hourly rows); for longer ranges use the daily endpoint, which has a 365-day window. An hourly window longer than 30 days, or a `from` after `to`, returns `422`.
2945
+ *
2946
+ */
2947
+ const getEmailStatsHourly = (options) => (options?.client ?? client).get({
2948
+ security: [{
2949
+ scheme: "bearer",
2950
+ type: "http"
2951
+ }, {
2952
+ in: "cookie",
2953
+ name: "bird_session",
2954
+ type: "apiKey"
2955
+ }],
2956
+ url: "/v1/email/stats/hourly",
2957
+ ...options
2958
+ });
2959
+ /**
2960
+ * Get statistics by tag
2961
+ *
2962
+ * Returns delivery and engagement counts for the requested period, grouped by tag. Use it to compare performance across the tags you set at send time. Rows are ranked by the `sort` metric, `processed` by default, and capped at the requested `limit` (50 by default, 200 at most).
2963
+ *
2964
+ * Rows are computed against event time rather than send time, so engagement received during the period counts even for messages that were sent earlier.
2965
+ *
2966
+ * The window can span at most 365 days. Ask for more and you get a `422`.
2967
+ *
2968
+ */
2969
+ const getEmailStatsByTag = (options) => (options?.client ?? client).get({
2970
+ security: [{
2971
+ scheme: "bearer",
2972
+ type: "http"
2973
+ }, {
2974
+ in: "cookie",
2975
+ name: "bird_session",
2976
+ type: "apiKey"
2977
+ }],
2978
+ url: "/v1/email/stats/tags",
2979
+ ...options
2980
+ });
2981
+ /**
2982
+ * Get aggregate email statistics
2983
+ *
2984
+ * Returns a single-row aggregate across the requested period covering delivery, bounce, complaint, open, and click counts plus the derived rates, along with processing, delivery, and total latency percentiles (p50/p95/p99). Suitable for KPI tiles, campaign reports, and email digests; the daily and hourly endpoints have the same metrics per time bucket.
2985
+ *
2986
+ * The aggregate is computed against event time (not send time), so engagement received during the period for messages sent earlier is included. Rate fields are `null` when their denominator is zero.
2987
+ *
2988
+ * The window grain follows the form of `from` and `to`: calendar days (`YYYY-MM-DD`, up to 365 days) or RFC 3339 instants (hour grain, up to 720 hours, 30 days). A rolling window such as the last 24 hours is a single request. Mixing the two forms returns `422`. Set `timezone` to compute day and hour boundaries in a local zone instead of UTC, and `compare=previous_period` to include the preceding equal-length window in the same response.
2989
+ *
2990
+ */
2991
+ const getEmailStatsSummary = (options) => (options?.client ?? client).get({
2992
+ security: [{
2993
+ scheme: "bearer",
2994
+ type: "http"
2995
+ }, {
2996
+ in: "cookie",
2997
+ name: "bird_session",
2998
+ type: "apiKey"
2999
+ }],
3000
+ url: "/v1/email/stats/summary",
3001
+ ...options
3002
+ });
3003
+ /**
3004
+ * Get statistics by sending IP
3005
+ *
3006
+ * Returns delivery and deliverability counts for the requested period, grouped by the specific IP address used to send each message. Use it to spot a reputation problem on one IP. Block bounces concentrated on a single IP usually mean that IP's reputation has taken a hit, and sorting by `bounces.block` puts those IPs first.
3007
+ *
3008
+ * A sending IP is only known once the receiving mail server reports an outcome: a delivery, a bounce, a deferral, or a late bounce. So this breakdown starts from the delivery stage onward. Accepted, processed, and rejected counts aren't included at all, and neither are engagement counts or processing latency. Complaints and out-of-band bounces aren't attributed to a sending IP either, so `complained` and `oob_bounces` are included but always read `0` here. Bounced, deferred, delivery latency, and total latency are the ones that have real numbers. For workspace-wide figures, use `GET /v1/email/stats/daily`. Rows are computed against event time rather than send time.
3009
+ *
3010
+ * Rows are ranked by the `sort` field, `delivered` by default, and capped at the requested `limit` (50 by default, 200 at most). The window can span at most 365 days. Ask for more and you get a `422`.
3011
+ *
3012
+ */
3013
+ const getEmailStatsBySendingIp = (options) => (options?.client ?? client).get({
3014
+ security: [{
3015
+ scheme: "bearer",
3016
+ type: "http"
3017
+ }, {
3018
+ in: "cookie",
3019
+ name: "bird_session",
3020
+ type: "apiKey"
3021
+ }],
3022
+ url: "/v1/email/stats/sending-ips",
3023
+ ...options
3024
+ });
3025
+ /**
3026
+ * Get statistics by sending domain
3027
+ *
3028
+ * Returns delivery, engagement, and deliverability counts for the requested period, grouped by sending domain: the portion of the `From` address after the `@`. Use it to compare deliverability across multiple verified domains in your workspace, for example transactional versus marketing domains, or sub-domain segregation during IP warming.
3029
+ *
3030
+ * Rows are computed against event time rather than send time, so engagement and bounces received during the period count even for messages that were sent earlier.
3031
+ *
3032
+ * Rows are ranked by the `sort` metric, `processed` by default, and capped at the requested `limit` (50 by default, 200 at most). The window can span at most 365 days. Ask for more and you get a `422`.
3033
+ *
3034
+ */
3035
+ const getEmailStatsBySendingDomain = (options) => (options?.client ?? client).get({
3036
+ security: [{
3037
+ scheme: "bearer",
3038
+ type: "http"
3039
+ }, {
3040
+ in: "cookie",
3041
+ name: "bird_session",
3042
+ type: "apiKey"
3043
+ }],
3044
+ url: "/v1/email/stats/sending-domains",
3045
+ ...options
3046
+ });
3047
+ /**
3048
+ * Get statistics by category
3049
+ *
3050
+ * Returns delivery and engagement counts for the requested period, grouped by category, so you can compare deliverability and engagement between your transactional and marketing traffic. Rows are ranked by the `sort` metric, `processed` by default, and capped at the requested `limit` (50 by default, 200 at most).
3051
+ *
3052
+ * Rows are computed against event time rather than send time, so engagement received during the period counts even for messages that were sent earlier.
3053
+ *
3054
+ * The window can span at most 365 days. Ask for more and you get a `422`.
3055
+ *
3056
+ */
3057
+ const getEmailStatsByCategory = (options) => (options?.client ?? client).get({
3058
+ security: [{
3059
+ scheme: "bearer",
3060
+ type: "http"
3061
+ }, {
3062
+ in: "cookie",
3063
+ name: "bird_session",
3064
+ type: "apiKey"
3065
+ }],
3066
+ url: "/v1/email/stats/categories",
3067
+ ...options
3068
+ });
3069
+ /**
3070
+ * Get statistics by mailbox provider
3071
+ *
3072
+ * Returns delivery, engagement, and deliverability counts for the requested period, grouped by recipient mailbox provider, for example `gmail`, `yahoo`, `microsoft`, or `apple`. Use it to compare how each major inbox provider treats your mail, for example to spot a delivered-rate dip or a complaint spike at one provider before it spreads. For a per-region split within a provider, use the mailbox-provider-region breakdown.
3073
+ *
3074
+ * A recipient's mailbox provider is only known once the receiving mail system reports an outcome, so this breakdown covers the delivery stage onward. Accepted, processed, and rejected counts and processing latency are not included. Rows are computed against event time rather than send time.
3075
+ *
3076
+ * Rows are ranked by the `sort` metric, `delivered` by default, and capped at the requested `limit` (50 by default, 200 at most). The window can span at most 365 days. Ask for more and you get a `422`.
3077
+ *
3078
+ */
3079
+ const getEmailStatsByMailboxProvider = (options) => (options?.client ?? client).get({
3080
+ security: [{
3081
+ scheme: "bearer",
3082
+ type: "http"
3083
+ }, {
3084
+ in: "cookie",
3085
+ name: "bird_session",
3086
+ type: "apiKey"
3087
+ }],
3088
+ url: "/v1/email/stats/mailbox-providers",
3089
+ ...options
3090
+ });
3091
+ /**
3092
+ * Get statistics by mailbox provider region
3093
+ *
3094
+ * Returns delivery, engagement, and deliverability counts for the requested period, grouped by mailbox provider and provider region pair, for example `gmail` in `NA` or `microsoft` in `EU`. The provider region is the regional grouping the receiving mail system reports for the recipient's provider. Pairing it with the provider tells apart a region label that several providers share. Use it to spot a deliverability problem isolated to one provider in one region. For a per-provider view without the region split, use the mailbox-provider breakdown.
3095
+ *
3096
+ * A provider region is only known once the receiving mail system reports an outcome, so this breakdown covers the delivery stage onward. Accepted, processed, and rejected counts and processing latency are not included. Rows are computed against event time rather than send time.
3097
+ *
3098
+ * Rows are ranked by the `sort` metric, `delivered` by default, and capped at the requested `limit` (50 by default, 200 at most). The window can span at most 365 days. Ask for more and you get a `422`.
3099
+ *
3100
+ */
3101
+ const getEmailStatsByMailboxProviderRegion = (options) => (options?.client ?? client).get({
3102
+ security: [{
3103
+ scheme: "bearer",
3104
+ type: "http"
3105
+ }, {
3106
+ in: "cookie",
3107
+ name: "bird_session",
3108
+ type: "apiKey"
3109
+ }],
3110
+ url: "/v1/email/stats/mailbox-provider-regions",
3111
+ ...options
3112
+ });
3113
+ /**
3114
+ * Get statistics by recipient domain
3115
+ *
3116
+ * Returns delivery and engagement counts for the requested period, grouped by recipient mailbox domain: the part of each recipient address after the `@`, for example `gmail.com`, `yahoo.com`, or `outlook.com`. This is the finest-grained deliverability view. Where the mailbox-provider breakdown groups recipients into provider buckets such as `gmail` or `microsoft`, this keys on the exact destination domain. Use it to spot a delivery-rate dip or a complaint spike at a specific domain.
3117
+ *
3118
+ * Rows are ranked by the `sort` metric, `processed` by default, and capped at the requested `limit` (50 by default, 200 at most). Rows are computed against event time rather than send time, so engagement received during the period counts even for messages that were sent earlier.
3119
+ *
3120
+ * The window can span at most 365 days. Ask for more and you get a `422`.
3121
+ *
3122
+ */
3123
+ const getEmailStatsByRecipientDomain = (options) => (options?.client ?? client).get({
3124
+ security: [{
3125
+ scheme: "bearer",
3126
+ type: "http"
3127
+ }, {
3128
+ in: "cookie",
3129
+ name: "bird_session",
3130
+ type: "apiKey"
3131
+ }],
3132
+ url: "/v1/email/stats/recipient-domains",
3133
+ ...options
3134
+ });
3135
+ /**
3136
+ * Get statistics by template
3137
+ *
3138
+ * Returns aggregate delivery and engagement counts grouped by the template each message was sent with, so a template's deliverability and engagement can be compared side by side. Attribution is by the template used at send time; only messages sent with a template appear here, so a workspace that has sent none returns an empty list rather than an error. Each row is keyed by the template ID (`emt_…`); a template deleted after sending still appears by its ID.
3139
+ *
3140
+ * Rows are ranked by the `sort` metric (default `processed`) descending and capped at the requested `limit` (default 50, hard maximum 200). Rows are computed against event time (not send time), so engagement received during the period for messages sent earlier is included.
3141
+ *
3142
+ * The maximum window is 365 days; requesting a longer range returns `422`.
3143
+ *
3144
+ */
3145
+ const getEmailStatsByTemplate = (options) => (options?.client ?? client).get({
3146
+ security: [{
3147
+ scheme: "bearer",
3148
+ type: "http"
3149
+ }, {
3150
+ in: "cookie",
3151
+ name: "bird_session",
3152
+ type: "apiKey"
3153
+ }],
3154
+ url: "/v1/email/stats/templates",
3155
+ ...options
3156
+ });
3157
+ /**
3158
+ * Get engagement by location
3159
+ *
3160
+ * Returns engagement counts (opens and clicks) for the requested period, grouped by the location they were recorded from. Use it to see where your audience engages, for example the top countries by unique opens. The reading location is only known from open and click events, so rows have engagement counts but no delivery counts or rates.
3161
+ *
3162
+ * Use `group_by` to choose the granularity: `country` (the default), `region`, or `city`. Each row has the location hierarchy down to the requested level, so a `city` grouping also reports that row's region and country. Rows are ranked by the `sort` metric, `unique_opens` by default, and capped at the requested `limit` (50 by default, 200 at most).
3163
+ *
3164
+ * Rows are computed against event time rather than send time. The window can span at most 365 days. Ask for more and you get a `422`.
3165
+ *
3166
+ */
3167
+ const getEmailStatsByLocation = (options) => (options?.client ?? client).get({
3168
+ security: [{
3169
+ scheme: "bearer",
3170
+ type: "http"
3171
+ }, {
3172
+ in: "cookie",
3173
+ name: "bird_session",
3174
+ type: "apiKey"
3175
+ }],
3176
+ url: "/v1/email/stats/locations",
3177
+ ...options
3178
+ });
3179
+ /**
3180
+ * Get engagement by email client
3181
+ *
3182
+ * Returns engagement counts (opens and clicks) for the requested period, grouped by the email client, operating system, or device type they were recorded from. Use it for the classic view of opens by mail client, for example the share of opens from Apple Mail compared with Gmail and Outlook. The reading environment is only known from open and click events, so rows have engagement counts but no delivery counts or rates.
3183
+ *
3184
+ * Use `group_by` to choose the facet: `email_client` (the default), `os`, or `device_type`. Each row fills in the facet you chose and leaves the other two `null`. Rows are ranked by the `sort` metric, `unique_opens` by default, and capped at the requested `limit` (50 by default, 200 at most).
3185
+ *
3186
+ * Rows are computed against event time rather than send time. The window can span at most 365 days. Ask for more and you get a `422`.
3187
+ *
3188
+ */
3189
+ const getEmailStatsByClient = (options) => (options?.client ?? client).get({
3190
+ security: [{
3191
+ scheme: "bearer",
3192
+ type: "http"
3193
+ }, {
3194
+ in: "cookie",
3195
+ name: "bird_session",
3196
+ type: "apiKey"
3197
+ }],
3198
+ url: "/v1/email/stats/clients",
3199
+ ...options
3200
+ });
3201
+ /**
3202
+ * Get bounces by SMTP error code
3203
+ *
3204
+ * Returns bounce counts for the requested period, grouped by the SMTP error code the receiving mail server returned. It answers the question of which SMTP responses are driving your bounces. Each row reports how many recipients bounced with that code, plus the hard, soft, admin, block, and undetermined split for that code.
3205
+ *
3206
+ * This failure-only breakdown omits delivered, open, click, and rate fields because bounce codes occur only on bounce events.
3207
+ *
3208
+ * Rows are ranked by the `sort` metric, `bounced` by default, and capped at the requested `limit` (50 by default, 200 at most). They are computed against event time rather than send time. The window can span at most 365 days. Ask for more and you get a `422`.
3209
+ *
3210
+ */
3211
+ const getEmailStatsByBounceCode = (options) => (options?.client ?? client).get({
3212
+ security: [{
3213
+ scheme: "bearer",
3214
+ type: "http"
3215
+ }, {
3216
+ in: "cookie",
3217
+ name: "bird_session",
3218
+ type: "apiKey"
3219
+ }],
3220
+ url: "/v1/email/stats/bounce-codes",
3221
+ ...options
3222
+ });
3223
+ /**
3224
+ * Get complaints by type
3225
+ *
3226
+ * Returns spam-complaint counts for the requested period, grouped by the feedback-loop complaint type the mailbox provider reported, for example `abuse`, `fraud`, or `virus`. Use it to see what kind of complaints your mail attracts.
3227
+ *
3228
+ * This breakdown only covers the complaint side. Each row has the complained count for one type and nothing else, because a complaint type is only ever recorded on a spam-complaint event.
3229
+ *
3230
+ * Rows are ranked by `complained` descending, and capped at the requested `limit` (default 50, hard maximum 200). They are computed against event time rather than send time. The window can span at most 365 days. Ask for more and you get a `422`.
3231
+ *
3232
+ */
3233
+ const getEmailStatsByComplaintType = (options) => (options?.client ?? client).get({
3234
+ security: [{
3235
+ scheme: "bearer",
3236
+ type: "http"
3237
+ }, {
3238
+ in: "cookie",
3239
+ name: "bird_session",
3240
+ type: "apiKey"
3241
+ }],
3242
+ url: "/v1/email/stats/complaint-types",
3243
+ ...options
3244
+ });
3245
+ /**
3246
+ * Get statistics by broadcast
3247
+ *
3248
+ * Returns aggregate delivery and engagement counts grouped by broadcast for the requested period, so each broadcast's deliverability and engagement can be compared side by side. Only messages sent as part of a broadcast appear here. One-off and transactional sends are not included, so a workspace that has not sent broadcasts returns an empty list rather than an error.
3249
+ *
3250
+ * Rows are ranked by the `sort` metric (default `processed`) descending and capped at the requested `limit` (default 50, hard maximum 200). Rows are computed against event time (not send time), so engagement received during the period for messages sent earlier is included.
3251
+ *
3252
+ * The maximum window is 365 days. Requesting a longer range returns a `422`. This breakdown is computed from per-message activity retained for 30 days, so it reflects roughly the last 30 days of activity even when the requested window reaches further back.
3253
+ *
3254
+ */
3255
+ const getEmailStatsByBroadcast = (options) => (options?.client ?? client).get({
3256
+ security: [{
3257
+ scheme: "bearer",
3258
+ type: "http"
3259
+ }, {
3260
+ in: "cookie",
3261
+ name: "bird_session",
3262
+ type: "apiKey"
3263
+ }],
3264
+ url: "/v1/email/stats/broadcasts",
3265
+ ...options
3266
+ });
3267
+ /**
3268
+ * List sending domains
3269
+ *
3270
+ * Returns all sending domains for the current workspace, newest first by default. Each item is the full domain object, including capability statuses and `dns_records`, so no per-domain follow-up read is needed. Filter with `name` to find a specific domain.
3271
+ *
3272
+ */
3273
+ const listDomains = (options) => (options?.client ?? client).get({
3274
+ security: [{
3275
+ scheme: "bearer",
3276
+ type: "http"
3277
+ }, {
3278
+ in: "cookie",
3279
+ name: "bird_session",
3280
+ type: "apiKey"
3281
+ }],
3282
+ url: "/v1/email/domains",
3283
+ ...options
3284
+ });
3285
+ /**
3286
+ * Create a sending domain
3287
+ *
3288
+ * Registers a new sending domain and returns the DNS records to publish
3289
+ * for it. The DKIM TXT record proves ownership, and together with the
3290
+ * return-path CNAME (which also covers SPF, so no separate SPF record is
3291
+ * needed) and a DMARC policy it gates sending. The tracking CNAME is
3292
+ * optional and gates branded link tracking only. Publish the records at
3293
+ * your DNS provider, then check progress with
3294
+ * [Trigger domain verification](/docs/api/reference/verify-domain). Published
3295
+ * records are also re-checked for you automatically. Setup walkthrough:
3296
+ * [Sending domains](/docs/guides/email/sending-domains).
3297
+ *
3298
+ * The domain starts in `pending` status. A domain already registered in
3299
+ * this workspace returns `409`, and creation beyond your organization's
3300
+ * domain quota returns `422` `E10000`. A domain that never verifies
3301
+ * ownership is removed after about 14 days, with a reminder email first.
3302
+ *
3303
+ */
3304
+ const createDomain = (options) => (options.client ?? client).post({
3305
+ security: [{
3306
+ scheme: "bearer",
3307
+ type: "http"
3308
+ }, {
3309
+ in: "cookie",
3310
+ name: "bird_session",
3311
+ type: "apiKey"
3312
+ }],
3313
+ url: "/v1/email/domains",
3314
+ ...options,
3315
+ headers: {
3316
+ "Content-Type": "application/json",
3317
+ ...options.headers
3318
+ }
3319
+ });
3320
+ /**
3321
+ * Delete a sending domain
3322
+ *
3323
+ * Removes the domain and revokes its sender authorization. New sends from a deleted domain are rejected. Historical statistics and events for past sends from this domain are preserved.
3324
+ *
3325
+ */
3326
+ const deleteDomain = (options) => (options.client ?? client).delete({
3327
+ security: [{
3328
+ scheme: "bearer",
3329
+ type: "http"
3330
+ }, {
3331
+ in: "cookie",
3332
+ name: "bird_session",
3333
+ type: "apiKey"
3334
+ }],
3335
+ url: "/v1/email/domains/{domain_id}",
3336
+ ...options
3337
+ });
3338
+ /**
3339
+ * Get a sending domain
3340
+ *
3341
+ * Returns the domain with its capability statuses and every DNS record's current verification state. This read reports the stored result of the last check. To run a fresh DNS check, use [Trigger domain verification](/docs/api/reference/verify-domain).
3342
+ *
3343
+ */
3344
+ const getDomain = (options) => (options.client ?? client).get({
3345
+ security: [{
3346
+ scheme: "bearer",
3347
+ type: "http"
3348
+ }, {
3349
+ in: "cookie",
3350
+ name: "bird_session",
3351
+ type: "apiKey"
3352
+ }],
3353
+ url: "/v1/email/domains/{domain_id}",
3354
+ ...options
3355
+ });
3356
+ /**
3357
+ * Update a sending domain
3358
+ *
3359
+ * Updates settings and configuration on a sending domain. `settings`
3360
+ * changes apply immediately. Changes to `return_path`, `tracking`, or
3361
+ * `dkim` on a verified capability are staged: the current configuration
3362
+ * keeps serving until the new one's DNS records verify, then the change
3363
+ * is promoted automatically. Staged values are visible under
3364
+ * `capabilities.*.pending`. The records to publish appear in
3365
+ * `dns_records` with `state: pending`.
3366
+ *
3367
+ * Invalid combinations are rejected. Enabling tracking toggles without a
3368
+ * tracking domain, or removing the tracking domain while a toggle is on,
3369
+ * returns `409`. Enabling inbound receiving has verification
3370
+ * prerequisites that return `422`. Each rule is detailed on its field.
3371
+ *
3372
+ */
3373
+ const updateDomain = (options) => (options.client ?? client).patch({
3374
+ security: [{
3375
+ scheme: "bearer",
3376
+ type: "http"
3377
+ }, {
3378
+ in: "cookie",
3379
+ name: "bird_session",
3380
+ type: "apiKey"
3381
+ }],
3382
+ url: "/v1/email/domains/{domain_id}",
3383
+ ...options,
3384
+ headers: {
3385
+ "Content-Type": "application/json",
3386
+ ...options.headers
3387
+ }
3388
+ });
3389
+ /**
3390
+ * Verify a domain
3391
+ *
3392
+ * Runs a fresh DNS check across the domain's records (DKIM, return path,
3393
+ * DMARC, tracking, inbound MX, and any staged changes) and returns the
3394
+ * updated domain. Use it for an immediate result after publishing or
3395
+ * correcting records. [Get a sending domain](/docs/api/reference/get-domain)
3396
+ * only reports the last stored result. Published records are also re-checked
3397
+ * for you automatically in the background.
3398
+ *
3399
+ * A `200` with records still `pending` is not a failure: the records were
3400
+ * not found yet, which is normal while DNS propagates (minutes to hours).
3401
+ * Recently verified records are not re-queried, so the call is safe to
3402
+ * repeat while you wait.
3403
+ *
3404
+ */
3405
+ const verifyDomain = (options) => (options.client ?? client).post({
3406
+ security: [{
3407
+ scheme: "bearer",
3408
+ type: "http"
3409
+ }, {
3410
+ in: "cookie",
3411
+ name: "bird_session",
3412
+ type: "apiKey"
3413
+ }],
3414
+ url: "/v1/email/domains/{domain_id}/verify",
3415
+ ...options
3416
+ });
3417
+ /**
3418
+ * List mailboxes
3419
+ *
3420
+ * Returns a paginated list of the workspace's mailboxes, newest first. Search across addresses and display names with `q`, look a mailbox up by its exact address, or filter by lifecycle state or domain.
3421
+ *
3422
+ */
2854
3423
  const listMailboxes = (options) => (options?.client ?? client).get({
2855
3424
  security: [{
2856
3425
  scheme: "bearer",
@@ -2866,7 +3435,7 @@ const listMailboxes = (options) => (options?.client ?? client).get({
2866
3435
  /**
2867
3436
  * Create a mailbox
2868
3437
  *
2869
- * Creates a mailbox. The address is `local_part@domain`. The domain defaults to `inbox.ai`, our shared mailbox domain, where creating the mailbox claims the address for your organization. It is first come, first served, and reserved to your organization even after the mailbox is deleted. You may instead name one of your own domains that is enabled for receiving email. An omitted local part is generated. On a custom domain, addresses of deleted mailboxes are quarantined. The same workspace can rebind one 30 days after deletion, but other workspaces never can.
3438
+ * Creates a mailbox. The address is `local_part@domain`. The domain defaults to `inbox.ai`, Bird's shared mailbox domain, where creating the mailbox claims the address for your organization. It is first come, first served, and reserved to your organization even after the mailbox is deleted. You may instead name one of your own domains that is enabled for receiving email. An omitted local part is generated. On a custom domain, addresses of deleted mailboxes are quarantined. The same workspace can rebind one 30 days after deletion, but other workspaces never can.
2870
3439
  *
2871
3440
  */
2872
3441
  const createMailbox = (options) => (options.client ?? client).post({
@@ -2906,7 +3475,7 @@ const deleteMailbox = (options) => (options.client ?? client).delete({
2906
3475
  /**
2907
3476
  * Get a mailbox
2908
3477
  *
2909
- * Returns a single mailbox by ID. A mailbox deleted within its 30-day restore window is still returned, with a non-null `deleted_at`. Once the window closes it is permanently removed and returns 404.
3478
+ * Returns a single mailbox by ID. A mailbox deleted within its 30-day restore window is still returned, with `deleted_at` set. Once the window closes it is permanently removed and returns `404`.
2910
3479
  *
2911
3480
  */
2912
3481
  const getMailbox = (options) => (options.client ?? client).get({
@@ -2924,7 +3493,7 @@ const getMailbox = (options) => (options.client ?? client).get({
2924
3493
  /**
2925
3494
  * Update a mailbox
2926
3495
  *
2927
- * Updates a mailbox. The address and domain are immutable. Lowering the retention tier deletes any remembered message older than the new cutoff, so that request needs `confirm=true` before it will run.
3496
+ * Updates a mailbox. The address and domain are immutable. Lowering the retention tier deletes any remembered message older than the new cutoff, so the request requires `confirm=true`.
2928
3497
  *
2929
3498
  */
2930
3499
  const updateMailbox = (options) => (options.client ?? client).patch({
@@ -2946,7 +3515,7 @@ const updateMailbox = (options) => (options.client ?? client).patch({
2946
3515
  /**
2947
3516
  * Restore a deleted mailbox
2948
3517
  *
2949
- * Restores a mailbox deleted less than 30 days ago. The address is bound back to the mailbox and starts receiving again, and the remembered messages and conversations are available as before the delete. Once the 30-day window has passed the mailbox and its messages are permanently deleted and can no longer be restored (404). Restoring a mailbox that is not deleted returns a conflict, as does an address that is no longer available.
3518
+ * Restores a mailbox deleted less than 30 days ago. The address is bound back to the mailbox and starts receiving again, and the remembered messages and conversations are available as before the delete. Once the 30-day window has passed the mailbox and its messages are permanently deleted and can no longer be restored (`404`). Restoring a mailbox that is not deleted returns a conflict, as does an address that is no longer available.
2950
3519
  *
2951
3520
  */
2952
3521
  const restoreMailbox = (options) => (options.client ?? client).post({
@@ -2962,13 +3531,13 @@ const restoreMailbox = (options) => (options.client ?? client).post({
2962
3531
  ...options
2963
3532
  });
2964
3533
  /**
2965
- * Mailbox email statistics
3534
+ * Get mailbox email statistics
2966
3535
  *
2967
3536
  * Returns the mailbox's sent and received email statistics over a time window: a period-wide summary plus a bucketed series. Sent-mail metrics have the same delivery, engagement, and latency breakdowns as the email stats endpoints. `received` counts mail that arrived at the mailbox.
2968
3537
  *
2969
3538
  * Rows are bucketed by the time the event happened rather than the time the message was sent, so engagement that arrived during the period for a message sent earlier is counted here. Statistics start when the mailbox starts sending and receiving; the mailbox's all-time `message_count` and `thread_count` live on the mailbox resource itself.
2970
3539
  *
2971
- * `from` and `to` accept either calendar days (YYYY-MM-DD, `day` granularity only) or RFC 3339 instants (`hour` granularity only). Both bounds must use the same form. Window caps depend on `granularity`: 365 days at `day`, 30 days at `hour`. Set `timezone` to report in a local zone instead of UTC.
3540
+ * `from` and `to` accept either calendar days (`YYYY-MM-DD`, `day` granularity only) or RFC 3339 instants (`hour` granularity only). Both bounds must use the same form. Window caps depend on `granularity`: 365 days at `day`, 30 days at `hour`. Set `timezone` to report in a local zone instead of UTC.
2972
3541
  *
2973
3542
  */
2974
3543
  const getMailboxStats = (options) => (options.client ?? client).get({
@@ -3020,7 +3589,7 @@ const listMailboxReceiveRules = (options) => (options.client ?? client).get({
3020
3589
  ...options
3021
3590
  });
3022
3591
  /**
3023
- * Add a receive rule
3592
+ * Create a receive rule
3024
3593
  *
3025
3594
  * Adds an allow or block rule to the mailbox. Rules match the message's envelope sender. Domain entries also match subdomains. Block rules always win, both over allow rules and over the reply admission on allowlist mailboxes. An entry is either allow or block. Rules have no update operation, so a rule that needs the other action is a new rule and the old one is removed. A mailbox holds up to 200 rules.
3026
3595
  *
@@ -3044,7 +3613,7 @@ const createMailboxReceiveRule = (options) => (options.client ?? client).post({
3044
3613
  /**
3045
3614
  * Delete a receive rule
3046
3615
  *
3047
- * Removes a receive rule from the mailbox. There is no update operation for rules, so a rule's allow or block action cannot be changed after it is created.
3616
+ * Removes a receive rule from the mailbox. A rule's allow or block action cannot be changed after creation; delete it and create a replacement.
3048
3617
  *
3049
3618
  */
3050
3619
  const deleteMailboxReceiveRule = (options) => (options.client ?? client).delete({
@@ -3064,9 +3633,9 @@ const deleteMailboxReceiveRule = (options) => (options.client ?? client).delete(
3064
3633
  *
3065
3634
  * Returns a paginated list of conversations across the workspace's mailboxes, most recently active first. `label` selects the view: the inbox (the default when omitted), `archive`, `spam`, `blocked`, or any custom label. You can also filter by mailbox, by linked contact, by participant address, or by a subject substring.
3066
3635
  *
3067
- * To search conversations by their messages' subject and text instead of listing them, use `GET /v1/email/threads/search`.
3068
- *
3069
- * Conversations whose every message has been trashed are left out of the list, and restoring a message brings the conversation back.
3636
+ * This listing filters; it does not search message content.
3637
+ * Conversations whose every message is trashed are excluded; restoring a message
3638
+ * returns the conversation to the list.
3070
3639
  *
3071
3640
  * `before` and `after` filter by time. To page through the results, pass the response cursors back as `starting_after` or `ending_before`.
3072
3641
  *
@@ -3086,7 +3655,7 @@ const listEmailThreads = (options) => (options?.client ?? client).get({
3086
3655
  /**
3087
3656
  * Delete a thread
3088
3657
  *
3089
- * Moves the conversation and all of its messages to the trash. Trashed messages are permanently deleted after 30 days. Pass `permanent=true` to permanently delete the conversation and its messages immediately.
3658
+ * Moves the conversation and all of its messages to the trash. Trashed messages are permanently deleted after 30 days, or sooner if the mailbox's retention period ends first. Pass `permanent=true` to permanently delete the conversation and its messages immediately.
3090
3659
  *
3091
3660
  */
3092
3661
  const deleteEmailThread = (options) => (options.client ?? client).delete({
@@ -3104,7 +3673,7 @@ const deleteEmailThread = (options) => (options.client ?? client).delete({
3104
3673
  /**
3105
3674
  * Get a thread
3106
3675
  *
3107
- * Returns a single conversation. Fetch the messages in the conversation with `GET /v1/email/threads/{thread_id}/messages`. A thread whose retention tier has ended returns `410 Gone`.
3676
+ * Returns a single conversation. Fetch the messages in the conversation with [List messages in a thread](/docs/api/reference/list-email-thread-messages). A thread whose retention tier has ended returns `410 Gone`.
3108
3677
  *
3109
3678
  */
3110
3679
  const getEmailThread = (options) => (options.client ?? client).get({
@@ -3122,7 +3691,7 @@ const getEmailThread = (options) => (options.client ?? client).get({
3122
3691
  /**
3123
3692
  * Update a thread
3124
3693
  *
3125
- * Applies label changes to a conversation, and links or unlinks a contact. Adding `spam` files the conversation, and its received messages, as spam. Adding `archive` files it away without deleting it. Adding `inbox`, or removing `spam`, `blocked`, or `archive`, returns it to the inbox, and its unread count recomputes to match. An archived conversation returns to the inbox by itself when a new message arrives. To block a sender going forward, add a receive rule instead. Any field you leave out stays unchanged.
3694
+ * Applies label changes to a conversation, and links or unlinks a contact. Adding `spam` files the conversation, and its received messages, as spam. Adding `archive` files it away without deleting it. Adding `inbox`, or removing `spam`, `blocked`, or `archive`, returns it to the inbox, and its unread count recomputes to match. An archived conversation returns to the inbox by itself when a new message arrives that isn't spam or blocked; a junk reply or an outbound send leaves it archived. To block a sender going forward, add a receive rule instead. Any field you leave out stays unchanged.
3126
3695
  *
3127
3696
  */
3128
3697
  const updateEmailThread = (options) => (options.client ?? client).patch({
@@ -3184,7 +3753,7 @@ const getEmailThreadMessage = (options) => (options.client ?? client).get({
3184
3753
  /**
3185
3754
  * Get a thread message's original body
3186
3755
  *
3187
- * Returns the original rendered HTML and plain-text body of a message in a conversation. The original body is available for 30 days after the message occurred. After that, this endpoint returns `410 Gone`, but the message's extracted text stays readable on the message itself.
3756
+ * Returns the original rendered HTML and plain-text body of a message in a conversation. The original body is available for 30 days after the message occurred. Later requests return `410 Gone`, while the message's extracted text stays readable on the message itself.
3188
3757
  *
3189
3758
  */
3190
3759
  const getEmailThreadMessageBody = (options) => (options.client ?? client).get({
@@ -3202,7 +3771,7 @@ const getEmailThreadMessageBody = (options) => (options.client ?? client).get({
3202
3771
  /**
3203
3772
  * List a thread message's attachments
3204
3773
  *
3205
- * Returns the attachments on a message in a conversation. Attachment bytes are downloadable for 30 days after the message occurred. After that, this endpoint returns `410 Gone`, but the attachment metadata stays readable on the message's `attachment_manifest`.
3774
+ * Returns the attachments on a message in a conversation. Attachment bytes are downloadable for 30 days after the message occurred. Later requests return `410 Gone`, while the attachment metadata stays readable on the message's `attachment_manifest`.
3206
3775
  *
3207
3776
  */
3208
3777
  const listEmailThreadMessageAttachments = (options) => (options.client ?? client).get({
@@ -3220,7 +3789,7 @@ const listEmailThreadMessageAttachments = (options) => (options.client ?? client
3220
3789
  /**
3221
3790
  * Reply to a thread message
3222
3791
  *
3223
- * Sends a reply to a specific message in a conversation, from the mailbox's own address. Recipients are derived from the message being replied to: its Reply-To address when present, otherwise its From address. Set `reply_all` to also include the original To and Cc recipients. The subject and the threading headers that keep the reply in this conversation are set automatically, and the reply is recorded in the conversation. To reply to a conversation as a whole, target its newest received message.
3792
+ * Sends a reply to a specific message in a conversation, from the mailbox's own address. Recipients are derived from the message being replied to: for a received message, its Reply-To address when present, otherwise its From address; for a message the mailbox sent, its original To recipients. Set `reply_all` to copy the original To and Cc recipients in as `Cc`, leaving out the mailbox's own address. The subject and the threading headers that keep the reply in this conversation are set automatically, and the reply is recorded in the conversation. To reply to a conversation as a whole, target its newest received message.
3224
3793
  *
3225
3794
  */
3226
3795
  const replyEmailThreadMessage = (options) => (options.client ?? client).post({
@@ -3240,9 +3809,9 @@ const replyEmailThreadMessage = (options) => (options.client ?? client).post({
3240
3809
  }
3241
3810
  });
3242
3811
  /**
3243
- * Send a message from a mailbox
3812
+ * Create a message from a mailbox
3244
3813
  *
3245
- * Sends a new message from the mailbox's own address and starts a new conversation with it. The request mirrors the plain send request minus `from`, because the mailbox is who the message comes from. We set the RFC 5322 Message-ID, so later replies from the recipients thread back into the conversation automatically. The send is added to the mailbox's remembered messages and returned as the conversation's first message. A mailbox always sends immediately, so this endpoint does not accept a scheduled send. A suspended mailbox cannot send and returns `403`.
3814
+ * Sends a new message from the mailbox's own address and starts a new conversation with it. The request mirrors the plain send request minus `from`, because the mailbox is who the message comes from. We set the RFC 5322 Message-ID, so later replies from the recipients thread back into the conversation automatically. The send is added to the mailbox's remembered messages and returned as the conversation's first message. A mailbox always sends immediately; scheduled sends are unavailable. A suspended mailbox cannot send and returns `403`.
3246
3815
  *
3247
3816
  */
3248
3817
  const createMailboxMessage = (options) => (options.client ?? client).post({
@@ -3272,10 +3841,9 @@ const createMailboxMessage = (options) => (options.client ?? client).post({
3272
3841
  * - `unread`.
3273
3842
  *
3274
3843
  * Then, every custom label currently in use on its conversations and
3275
- * messages. You apply and remove labels through the conversation and
3276
- * message update endpoints, and that is also what creates or removes a
3277
- * custom label: it exists for as long as at least one message or
3278
- * conversation has it applied.
3844
+ * messages. Apply and remove labels through the conversation and message
3845
+ * update endpoints. These actions also create and remove custom labels. A
3846
+ * custom label exists while at least one message or conversation uses it.
3279
3847
  *
3280
3848
  */
3281
3849
  const listMailboxLabels = (options) => (options.client ?? client).get({
@@ -3293,11 +3861,18 @@ const listMailboxLabels = (options) => (options.client ?? client).get({
3293
3861
  /**
3294
3862
  * List calls
3295
3863
  *
3296
- * Returns a paginated list of the workspace's calls, ordered by start time descending.
3864
+ * Returns a paginated list of the workspace's calls, ordered by start time
3865
+ * descending.
3297
3866
  *
3298
- * The `status` filter selects where in the lifecycle you look, and any combination is a single page: in-flight statuses (`ringing`, `in_progress`), final ones, or both together. Omit it and you get completed calls, which is what this list has always returned.
3867
+ * The `status` filter selects where in the lifecycle you look, and any
3868
+ * combination is a single page: in-flight statuses (`ringing`,
3869
+ * `in_progress`), final ones, or both together. Omit it and you get
3870
+ * completed calls, which is what this list has always returned.
3299
3871
  *
3300
- * A call in flight carries no economics yet: `duration_ms`, `billable_ms`, `ended_at`, and `cost` are null until it ends. It keeps the same `id` throughout, so the same call answers under one identity from the first ring to settlement.
3872
+ * A call in flight carries no economics yet: `duration_ms`, `billable_ms`,
3873
+ * `ended_at`, and `cost` are null until it ends. It keeps the same `id`
3874
+ * throughout, so the same call answers under one identity from the first
3875
+ * ring to settlement.
3301
3876
  *
3302
3877
  */
3303
3878
  const listVoiceCalls = (options) => (options?.client ?? client).get({
@@ -3430,10 +4005,33 @@ var EmailResourceBase = class extends Resource {
3430
4005
  }
3431
4006
  };
3432
4007
  //#endregion
4008
+ //#region src/resources/emailDefaults.ts
4009
+ /**
4010
+ * Merge configured channel defaults under one set of per-call params.
4011
+ *
4012
+ * A field handed no value (`undefined`, or a `null` from a JSON-shaped input)
4013
+ * reads as unset, so its default still fills it. Spreading the params over the
4014
+ * defaults instead would let that no-value win and drop the field off the wire,
4015
+ * which the field-by-field merges in the other SDKs cannot do.
4016
+ *
4017
+ * `accepts` narrows the merge to the fields one body declares, for a request
4018
+ * that rejects a field the send body allows.
4019
+ */
4020
+ function withDefaults(defaults, params, accepts) {
4021
+ if (defaults === void 0) return params;
4022
+ const fill = accepts === void 0 ? { ...defaults } : Object.fromEntries(Object.entries(defaults).filter(([key]) => accepts.includes(key)));
4023
+ const merged = {
4024
+ ...fill,
4025
+ ...params
4026
+ };
4027
+ for (const [key, value] of Object.entries(fill)) if (merged[key] === void 0 || merged[key] === null) merged[key] = value;
4028
+ return merged;
4029
+ }
4030
+ //#endregion
3433
4031
  //#region src/resources/emailStats.gen.ts
3434
4032
  var EmailStatsResource = class extends Resource {
3435
4033
  /**
3436
- * Aggregate email KPIs for one period: sends, delivered, bounces, complaints, opens, clicks, their rates, and latency percentiles. `from`/`to` are both YYYY-MM-DD days or both RFC 3339 instants (hour grain); add `compare=previous_period` for deltas versus the prior window. For a per-day or per-hour series use `email.stats.daily` or `email.stats.hourly`.
4034
+ * Aggregate email KPIs for one period: sends, delivered, bounces, complaints, opens, clicks, their rates, and latency percentiles. The `from` and `to` values are both `YYYY-MM-DD` days or both RFC 3339 instants (hour grain). Add `compare=previous_period` for deltas versus the prior window. For a per-day or per-hour series use `email.stats.daily` or `email.stats.hourly`.
3437
4035
  *
3438
4036
  * @example Summary for a month
3439
4037
  * const s = await bird.email.stats.summary({ from: "2026-05-01", to: "2026-05-31" });
@@ -3513,7 +4111,7 @@ var EmailStatsResource = class extends Resource {
3513
4111
  }));
3514
4112
  }
3515
4113
  /**
3516
- * Delivery and bounce stats grouped by sending IP, with deferral counts alongside them. `sort=bounces.block` surfaces reputation-damaged IPs first. Engagement, accepted, and processed counts aren't available per IP, and complaint and out-of-band bounce counts always read 0 here. For workspace-wide figures, use `email.stats.daily`.
4114
+ * Delivery and bounce stats grouped by sending IP, with deferral counts alongside them. `sort=bounces.block` surfaces reputation-damaged IPs first. Engagement, accepted, and processed counts aren't available per IP, and complaint and out-of-band bounce counts always read `0` here. For workspace-wide figures, use `email.stats.daily`.
3517
4115
  *
3518
4116
  * @example
3519
4117
  * const { data } = await bird.email.stats.bySendingIp({
@@ -3573,7 +4171,7 @@ var EmailStatsResource = class extends Resource {
3573
4171
  }));
3574
4172
  }
3575
4173
  /**
3576
- * Email delivery and engagement stats grouped by recipient mailbox provider, for example `gmail`, `microsoft`, or `yahoo`. It covers the delivery stage onward, so there are no accepted or processed counts. For a per-region split within a provider, use `email.stats.by_mailbox_provider_region`; for exact destination domains instead, use `email.stats.by_recipient_domain`.
4174
+ * Email delivery and engagement stats grouped by recipient mailbox provider, for example `gmail`, `microsoft`, or `yahoo`. It covers the delivery stage onward and omits accepted or processed counts. For a per-region split within a provider, use `email.stats.by_mailbox_provider_region`; for exact destination domains instead, use `email.stats.by_recipient_domain`.
3577
4175
  *
3578
4176
  * @example
3579
4177
  * const { data } = await bird.email.stats.byMailboxProvider({
@@ -3592,7 +4190,7 @@ var EmailStatsResource = class extends Resource {
3592
4190
  }));
3593
4191
  }
3594
4192
  /**
3595
- * Email delivery and engagement stats grouped by a mailbox provider and provider region pair, for example `gmail` in `NA`. It covers the delivery stage onward, so there are no accepted or processed counts. For the provider-level view without the region split, use `email.stats.by_mailbox_provider`.
4193
+ * Email delivery and engagement stats grouped by a mailbox provider and provider region pair, for example `gmail` in `NA`. It covers the delivery stage onward and omits accepted or processed counts. For the provider-level view without the region split, use `email.stats.by_mailbox_provider`.
3596
4194
  *
3597
4195
  * @example
3598
4196
  * const { data } = await bird.email.stats.byMailboxProviderRegion({
@@ -3669,7 +4267,7 @@ var EmailStatsResource = class extends Resource {
3669
4267
  }));
3670
4268
  }
3671
4269
  /**
3672
- * Bounce counts grouped by the SMTP error code the receiving mail server returned. Each row also breaks the bounce down into its hard, soft, admin, block, and undetermined split. There are no delivered, open, or click counts here, because a bounce code only appears on a bounce event. For bounces broken down by destination instead, use `email.stats.by_recipient_domain` or `email.stats.by_mailbox_provider`.
4270
+ * Bounce counts grouped by the SMTP error code the receiving mail server returned. Each row also breaks the bounce down into its hard, soft, admin, block, and undetermined split. It omits delivered, open, and click counts because a bounce code only appears on a bounce event. For bounces broken down by destination instead, use `email.stats.by_recipient_domain` or `email.stats.by_mailbox_provider`.
3673
4271
  *
3674
4272
  * @example
3675
4273
  * const { data } = await bird.email.stats.byBounceCode({
@@ -3689,7 +4287,7 @@ var EmailStatsResource = class extends Resource {
3689
4287
  }));
3690
4288
  }
3691
4289
  /**
3692
- * Spam-complaint counts grouped by the feedback-loop complaint type, for example `abuse`, `fraud`, or `virus`. Complaint side only, so there are no delivery or engagement counts. For complaints broken down by destination instead, use `email.stats.by_mailbox_provider` or `email.stats.by_recipient_domain`.
4290
+ * Spam-complaint counts grouped by the feedback-loop complaint type, for example `abuse`, `fraud`, or `virus`. This complaint-only breakdown omits delivery and engagement counts. For complaints broken down by destination instead, use `email.stats.by_mailbox_provider` or `email.stats.by_recipient_domain`.
3693
4291
  *
3694
4292
  * @example
3695
4293
  * const { data } = await bird.email.stats.byComplaintType({ from: "2026-05-01", to: "2026-05-31" });
@@ -3762,7 +4360,7 @@ var EmailMailboxesResourceBase = class extends Resource {
3762
4360
  }));
3763
4361
  }
3764
4362
  /**
3765
- * Read one mailbox by ID. A mailbox deleted within its 30-day restore window is still returned, with a non-null `deleted_at`. Once that window closes it is gone and this returns 404.
4363
+ * Read one mailbox by ID. A mailbox deleted within its 30-day restore window is still returned, with `deleted_at` set. Once that window closes it is gone and this returns `404`.
3766
4364
  *
3767
4365
  * @example Get a mailbox
3768
4366
  * const mailbox = await bird.email.mailboxes.get("mbx_01abc");
@@ -3810,7 +4408,7 @@ var EmailMailboxesResourceBase = class extends Resource {
3810
4408
  }));
3811
4409
  }
3812
4410
  /**
3813
- * 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.
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`.
3814
4412
  *
3815
4413
  * @example Restore a deleted mailbox
3816
4414
  * const mailbox = await bird.email.mailboxes.restore("mbx_01abc");
@@ -3825,7 +4423,7 @@ var EmailMailboxesResourceBase = class extends Resource {
3825
4423
  }));
3826
4424
  }
3827
4425
  /**
3828
- * Resume a suspended mailbox so it can send and receive again and its conversations 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.
4426
+ * Resume a suspended mailbox so it can send and receive again and its conversations 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`.
3829
4427
  *
3830
4428
  * @example Resume a suspended mailbox
3831
4429
  * const mailbox = await bird.email.mailboxes.resume("mbx_01abc");
@@ -3873,7 +4471,18 @@ var EmailMailboxesResourceBase = class extends Resource {
3873
4471
  };
3874
4472
  //#endregion
3875
4473
  //#region src/resources/emailMailboxesMessages.ts
4474
+ const COMPOSE_FIELDS = [
4475
+ "reply_to",
4476
+ "category",
4477
+ "tags",
4478
+ "metadata"
4479
+ ];
3876
4480
  var EmailMailboxesMessagesResource = class extends Resource {
4481
+ #defaults;
4482
+ constructor(core, client, defaults) {
4483
+ super(core, client);
4484
+ this.#defaults = defaults;
4485
+ }
3877
4486
  /**
3878
4487
  * Send a new email from this mailbox, starting a new conversation.
3879
4488
  *
@@ -3885,10 +4494,11 @@ var EmailMailboxesMessagesResource = class extends Resource {
3885
4494
  * });
3886
4495
  */
3887
4496
  create(mailboxId, params, options) {
4497
+ const body = withDefaults(this.#defaults, params, COMPOSE_FIELDS);
3888
4498
  return this.call("POST", options, ({ signal, headers }) => createMailboxMessage({
3889
4499
  client: this.client,
3890
4500
  path: { mailbox_id: mailboxId },
3891
- body: params,
4501
+ body,
3892
4502
  headers,
3893
4503
  signal
3894
4504
  }));
@@ -3961,10 +4571,10 @@ var EmailMailboxesResource = class extends EmailMailboxesResourceBase {
3961
4571
  messages;
3962
4572
  /** Per-sender allow/block rules — `bird.email.mailboxes.receiveRules.create(...)`, `.list(...)`, `.delete(...)`. */
3963
4573
  receiveRules;
3964
- constructor(...args) {
3965
- super(...args);
3966
- this.messages = new EmailMailboxesMessagesResource(...args);
3967
- this.receiveRules = new EmailMailboxesReceiveRulesResource(...args);
4574
+ constructor(core, client, defaults) {
4575
+ super(core, client);
4576
+ this.messages = new EmailMailboxesMessagesResource(core, client, defaults);
4577
+ this.receiveRules = new EmailMailboxesReceiveRulesResource(core, client);
3968
4578
  }
3969
4579
  };
3970
4580
  //#endregion
@@ -4023,7 +4633,7 @@ var EmailThreadsResourceBase = class extends Resource {
4023
4633
  }));
4024
4634
  }
4025
4635
  /**
4026
- * Move a conversation and all its messages to trash (purged after 30 days), or delete permanently with ?permanent=true.
4636
+ * Move a conversation and all its messages to trash (purged after 30 days), or delete permanently with `?permanent=true`.
4027
4637
  *
4028
4638
  * @example Delete a thread
4029
4639
  * await bird.email.threads.delete("thr_01abc", { permanent: true });
@@ -4042,7 +4652,7 @@ var EmailThreadsResourceBase = class extends Resource {
4042
4652
  //#region src/resources/emailThreadsMessages.gen.ts
4043
4653
  var EmailThreadsMessagesResource = class extends Resource {
4044
4654
  /**
4045
- * 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 extracted plain text.
4655
+ * 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 extracted plain text.
4046
4656
  *
4047
4657
  * @example List a thread's messages
4048
4658
  * for await (const msg of bird.email.threads.messages.list("thr_01abc")) {
@@ -4161,7 +4771,7 @@ var EmailResource = class extends EmailResourceBase {
4161
4771
  super(core, client);
4162
4772
  this.#defaults = defaults;
4163
4773
  this.stats = new EmailStatsResource(core, client);
4164
- this.mailboxes = new EmailMailboxesResource(core, client);
4774
+ this.mailboxes = new EmailMailboxesResource(core, client, defaults);
4165
4775
  this.threads = new EmailThreadsResource(core, client);
4166
4776
  }
4167
4777
  /**
@@ -4229,7 +4839,7 @@ var EmailResource = class extends EmailResourceBase {
4229
4839
  * html: "<p>My first Bird email.</p>",
4230
4840
  * });
4231
4841
  * } catch (err) {
4232
- * if (err instanceof BirdRateLimitError) console.log(`rate limited retry in ${err.retryAfter}s`);
4842
+ * if (err instanceof BirdRateLimitError) console.log(`rate limited; retry in ${err.retryAfter}s`);
4233
4843
  * else if (err instanceof BirdValidationError) console.error(err.details);
4234
4844
  * else if (err instanceof BirdAPIError) console.error(err.code, err.requestId);
4235
4845
  * else throw err;
@@ -4248,10 +4858,7 @@ var EmailResource = class extends EmailResourceBase {
4248
4858
  * else console.log(data.id);
4249
4859
  */
4250
4860
  send(params, options) {
4251
- const body = {
4252
- ...this.#defaults,
4253
- ...params
4254
- };
4861
+ const body = withDefaults(this.#defaults, params);
4255
4862
  return this.call("POST", options, ({ signal, headers }) => createEmailMessage({
4256
4863
  client: this.client,
4257
4864
  body,
@@ -4265,7 +4872,8 @@ var EmailResource = class extends EmailResourceBase {
4265
4872
  * sender, all recipients suppressed, field-level errors) the whole batch is
4266
4873
  * rejected with a `BirdValidationError` and nothing is queued. Resolves with
4267
4874
  * one accepted item per submitted message, in submission order, once the batch
4268
- * is accepted (the API's 202). Channel defaults are applied per item.
4875
+ * is accepted (the API's 202). Channel defaults are applied per item, so a
4876
+ * field set as a default may be omitted from every item (per-item value wins).
4269
4877
  *
4270
4878
  * @example Send a batch of messages
4271
4879
  * const batch = await bird.email.sendBatch([
@@ -4285,10 +4893,7 @@ var EmailResource = class extends EmailResourceBase {
4285
4893
  * for (const item of batch.data) console.log(item.id, item.status);
4286
4894
  */
4287
4895
  sendBatch(params, options) {
4288
- const body = params.map((item) => ({
4289
- ...this.#defaults,
4290
- ...item
4291
- }));
4896
+ const body = params.map((item) => withDefaults(this.#defaults, item));
4292
4897
  return this.call("POST", options, ({ signal, headers }) => createEmailMessageBatch({
4293
4898
  client: this.client,
4294
4899
  body,
@@ -4350,7 +4955,7 @@ var AudiencesResource = class extends Resource {
4350
4955
  }));
4351
4956
  }
4352
4957
  /**
4353
- * Update an audience's name or description. Omitted fields are unchanged; a null description clears it.
4958
+ * Update an audience's name or description. Omitted fields are unchanged; a `null` description clears it.
4354
4959
  *
4355
4960
  * @example Rename an audience
4356
4961
  * await bird.audiences.update("adn_01krdgeqcxet5s7t44vh8rt9mg", { name: "Renamed" });
@@ -4539,7 +5144,7 @@ var DomainsResource = class extends Resource {
4539
5144
  }));
4540
5145
  }
4541
5146
  /**
4542
- * 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.
5147
+ * 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.
4543
5148
  *
4544
5149
  * @example Delete a sending domain by id
4545
5150
  * await bird.domains.delete("dom_01krdgeqcxet5s7t44vh8rt9mg");
@@ -4655,160 +5260,488 @@ var ContactPropertiesResource = class extends Resource {
4655
5260
  //#region src/resources/contacts.gen.ts
4656
5261
  var ContactsResource = class extends Resource {
4657
5262
  /**
4658
- * List the workspace's contacts as a cursor page, newest first. Look one up by exact email, phone_number, or external_id, repeating phone_number to resolve up to 50 numbers in one call (raise limit to match), or search by email, name, or phone substring. Pass include_total for a total count.
5263
+ * List the workspace's contacts as a cursor page, newest first. Look one up by exact email, phone_number, or external_id, repeating phone_number to resolve up to 50 numbers in one call (raise limit to match), or search by email, name, or phone substring. Pass include_total for a total count.
5264
+ *
5265
+ * @example Iterate every contact, or take one page
5266
+ * for await (const contact of bird.contacts.list({ q: "acme.com" })) {
5267
+ * console.log(contact.id, contact.email);
5268
+ * }
5269
+ * const page = await bird.contacts.list({ limit: 50 }); // page.data, page.next_cursor
5270
+ */
5271
+ list(query, options) {
5272
+ return this.paginated("GET", options, ({ signal, headers }, cursor) => listContacts({
5273
+ client: this.client,
5274
+ query: {
5275
+ ...query,
5276
+ starting_after: cursor ?? query?.starting_after
5277
+ },
5278
+ headers,
5279
+ signal
5280
+ }));
5281
+ }
5282
+ /**
5283
+ * Get a single contact by ID. Look up an ID by exact email, phone_number, or external_id with `contacts.list`.
5284
+ *
5285
+ * @example Fetch a contact by id
5286
+ * const contact = await bird.contacts.get("con_01krdgeqcxet5s7t44vh8rt9mg");
5287
+ * console.log(contact.email, contact.first_name);
5288
+ */
5289
+ get(contactId, options) {
5290
+ return this.call("GET", options, ({ signal, headers }) => getContact({
5291
+ client: this.client,
5292
+ path: { contact_id: contactId },
5293
+ headers,
5294
+ signal
5295
+ }));
5296
+ }
5297
+ /**
5298
+ * Create a contact identified by an email address, an E.164 phone number, or both. Fails with a conflict if the email, phone_number, or external_id is already used by another contact. For bulk import or create-or-update semantics use `contacts.batch`.
5299
+ *
5300
+ * @example Create a contact
5301
+ * const contact = await bird.contacts.create({
5302
+ * email: "jane@acme.com",
5303
+ * first_name: "Jane",
5304
+ * });
5305
+ * console.log(contact.id); // "con_…"
5306
+ */
5307
+ create(params = {}, options) {
5308
+ return this.call("POST", options, ({ signal, headers }) => createContact({
5309
+ client: this.client,
5310
+ body: params,
5311
+ headers,
5312
+ signal
5313
+ }));
5314
+ }
5315
+ /**
5316
+ * Update a contact's name, `external_id`, email, `phone_number`, or custom data. Only supplied fields change; custom data keys are merged, with `null` removing a key. A contact keeps at least one identifier: clearing both email and `phone_number` is rejected.
5317
+ *
5318
+ * @example Change a contact's fields
5319
+ * const contact = await bird.contacts.update("con_01krdgeqcxet5s7t44vh8rt9mg", {
5320
+ * first_name: "Jane",
5321
+ * });
5322
+ * console.log(contact.first_name);
5323
+ */
5324
+ update(contactId, params = {}, options) {
5325
+ return this.call("PATCH", options, ({ signal, headers }) => updateContact({
5326
+ client: this.client,
5327
+ path: { contact_id: contactId },
5328
+ body: params,
5329
+ headers,
5330
+ signal
5331
+ }));
5332
+ }
5333
+ /**
5334
+ * Delete a contact and remove it from every audience it belongs to. Suppression records for the address are unaffected.
5335
+ *
5336
+ * @example Delete a contact by id
5337
+ * await bird.contacts.delete("con_01krdgeqcxet5s7t44vh8rt9mg");
5338
+ */
5339
+ delete(contactId, options) {
5340
+ return this.call("DELETE", options, ({ signal, headers }) => deleteContact({
5341
+ client: this.client,
5342
+ path: { contact_id: contactId },
5343
+ headers,
5344
+ signal
5345
+ }));
5346
+ }
5347
+ /**
5348
+ * Create or update up to 1,000 contacts in one request. Match each entry against every supplied identifier (`email`, `phone_number`, and `external_id`), or set `match_on` to use one identifier. Optionally add all successful contacts to up to 10 audiences. Results follow submission order.
5349
+ *
5350
+ * @example Create or update many contacts at once, matched by the identifiers each entry carries
5351
+ * const result = await bird.contacts.batch({
5352
+ * contacts: [{ email: "jane@acme.com", first_name: "Jane" }],
5353
+ * });
5354
+ * for (const item of result.data) {
5355
+ * console.log(item.entry.email, item.status);
5356
+ * }
5357
+ */
5358
+ batch(params, options) {
5359
+ return this.call("POST", options, ({ signal, headers }) => createContactBatch({
5360
+ client: this.client,
5361
+ body: params,
5362
+ headers,
5363
+ signal
5364
+ }));
5365
+ }
5366
+ };
5367
+ //#endregion
5368
+ //#region src/resources/sms.gen.ts
5369
+ var SmsResourceBase = class extends Resource {
5370
+ /**
5371
+ * Get one SMS message by ID: its current delivery status, segment breakdown, cost, and failure detail if it failed.
5372
+ *
5373
+ * @example Read a message back
5374
+ * const msg = await bird.sms.get("sms_abc123");
5375
+ * msg.status; // "accepted" | "delivered" | …
5376
+ */
5377
+ get(messageId, options) {
5378
+ return this.call("GET", options, ({ signal, headers }) => getSmsMessage({
5379
+ client: this.client,
5380
+ path: { message_id: messageId },
5381
+ headers,
5382
+ signal
5383
+ }));
5384
+ }
5385
+ /**
5386
+ * 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.
5387
+ *
5388
+ * @example Iterate outbound messages
5389
+ * for await (const msg of bird.sms.list({ direction: "outbound" })) {
5390
+ * console.log(msg.id, msg.status);
5391
+ * }
5392
+ */
5393
+ list(query, options) {
5394
+ return this.paginated("GET", options, ({ signal, headers }, cursor) => listSmsMessages({
5395
+ client: this.client,
5396
+ query: {
5397
+ ...query,
5398
+ starting_after: cursor ?? query?.starting_after
5399
+ },
5400
+ headers,
5401
+ signal
5402
+ }));
5403
+ }
5404
+ /**
5405
+ * The lifecycle event timeline for one SMS, oldest first: what happened to it and when. Filter with `type` (for example `sms.delivered`) to keep one kind of event. Use `sms.get` for the message's current state and `sms.list` to find its ID.
5406
+ *
5407
+ * @example Read one message's lifecycle timeline
5408
+ * const events = await bird.sms.listEvents("sms_abc123");
5409
+ * for (const event of events.data ?? []) {
5410
+ * console.log(event.type, event.occurred_at);
5411
+ * }
5412
+ */
5413
+ listEvents(messageId, query, options) {
5414
+ return this.call("GET", options, ({ signal, headers }) => listSmsMessageEvents({
5415
+ client: this.client,
5416
+ path: { message_id: messageId },
5417
+ query,
5418
+ headers,
5419
+ signal
5420
+ }));
5421
+ }
5422
+ };
5423
+ //#endregion
5424
+ //#region src/resources/smsStats.gen.ts
5425
+ var SmsStatsResourceBase = class extends Resource {
5426
+ /**
5427
+ * Aggregate SMS KPIs for one period: accepted, sent, delivered, undelivered, failed, rejected and expired counts, the derived delivery and failure rates, and latency percentiles. The `from` and `to` values are both YYYY-MM-DD days or both RFC 3339 instants (hour grain). Add `compare=previous_period` for deltas against the preceding window. For a per-day or per-hour series use `sms.stats.daily` or `sms.stats.hourly`.
5428
+ *
5429
+ * @example Aggregate KPIs for a window
5430
+ * const summary = await bird.sms.stats.summary({
5431
+ * from: "2026-05-01", // both calendar days for a day window, or
5432
+ * to: "2026-05-31", // both RFC 3339 instants for an hour window
5433
+ * });
5434
+ * console.log(summary.delivery, summary.latency);
5435
+ */
5436
+ summary(query, options) {
5437
+ return this.call("GET", options, ({ signal, headers }) => getSmsStatsSummary({
5438
+ client: this.client,
5439
+ query,
5440
+ headers,
5441
+ signal
5442
+ }));
5443
+ }
5444
+ /**
5445
+ * One row of SMS lifecycle counts per calendar day, for charts and trend lines. The window is at most 365 days; set `timezone` to get local calendar days instead of UTC. Rates and latency percentiles are whole-window figures, so read those from `sms.stats.summary`.
5446
+ *
5447
+ * @example One row per calendar day
5448
+ * const stats = await bird.sms.stats.daily({ from: "2026-05-01", to: "2026-05-31" });
5449
+ * for (const point of stats.data ?? []) {
5450
+ * console.log(point.bucket, point.delivery);
5451
+ * }
5452
+ */
5453
+ daily(query, options) {
5454
+ return this.call("GET", options, ({ signal, headers }) => getSmsStatsDaily({
5455
+ client: this.client,
5456
+ query,
5457
+ headers,
5458
+ signal
5459
+ }));
5460
+ }
5461
+ /**
5462
+ * One row of SMS lifecycle counts per hour, for inspecting send rate and deliverability inside a single day. The window is at most 30 days (720 rows) and both bounds round down to the hour. For longer ranges use `sms.stats.daily`.
5463
+ *
5464
+ * @example One row per hour, up to 30 days
5465
+ * const stats = await bird.sms.stats.hourly({
5466
+ * from: "2026-05-30T00:00:00Z",
5467
+ * to: "2026-05-31T00:00:00Z",
5468
+ * });
5469
+ * for (const point of stats.data ?? []) {
5470
+ * console.log(point.bucket, point.delivery);
5471
+ * }
5472
+ */
5473
+ hourly(query, options) {
5474
+ return this.call("GET", options, ({ signal, headers }) => getSmsStatsHourly({
5475
+ client: this.client,
5476
+ query,
5477
+ headers,
5478
+ signal
5479
+ }));
5480
+ }
5481
+ /**
5482
+ * SMS delivery and latency stats grouped by destination country, ranked by the `sort` metric (default `accepted`) and capped by `limit` (default 50, maximum 200). Use it to find where delivery is worst before drilling into `sms.stats.by_error_code`.
5483
+ *
5484
+ * @example Find where delivery is worst
5485
+ * const stats = await bird.sms.stats.byCountry({
5486
+ * from: "2026-05-01",
5487
+ * to: "2026-05-31",
5488
+ * sort: "delivery_rate",
5489
+ * });
5490
+ * for (const row of stats.data ?? []) {
5491
+ * console.log(row.country, row.delivery);
5492
+ * }
5493
+ */
5494
+ byCountry(query, options) {
5495
+ return this.call("GET", options, ({ signal, headers }) => getSmsStatsByCountry({
5496
+ client: this.client,
5497
+ query,
5498
+ headers,
5499
+ signal
5500
+ }));
5501
+ }
5502
+ /**
5503
+ * SMS delivery and latency stats grouped by the carrier that handled the message, ranked by the `sort` metric (default `accepted`) and capped by `limit` (default 50, maximum 200). Use it to compare delivery performance across carriers.
5504
+ *
5505
+ * @example Compare delivery across carriers
5506
+ * const stats = await bird.sms.stats.byCarrier({ from: "2026-05-01", to: "2026-05-31" });
5507
+ * for (const row of stats.data ?? []) {
5508
+ * console.log(row.carrier, row.delivery);
5509
+ * }
5510
+ */
5511
+ byCarrier(query, options) {
5512
+ return this.call("GET", options, ({ signal, headers }) => getSmsStatsByCarrier({
5513
+ client: this.client,
5514
+ query,
5515
+ headers,
5516
+ signal
5517
+ }));
5518
+ }
5519
+ /**
5520
+ * SMS delivery and latency stats grouped by the category you sent under, ranked by the `sort` metric (default `accepted`) and capped by `limit` (default 50, maximum 200).
5521
+ *
5522
+ * @example Split a window by category
5523
+ * const stats = await bird.sms.stats.byCategory({ from: "2026-05-01", to: "2026-05-31" });
5524
+ * for (const row of stats.data ?? []) {
5525
+ * console.log(row.category, row.delivery);
5526
+ * }
5527
+ */
5528
+ byCategory(query, options) {
5529
+ return this.call("GET", options, ({ signal, headers }) => getSmsStatsByCategory({
5530
+ client: this.client,
5531
+ query,
5532
+ headers,
5533
+ signal
5534
+ }));
5535
+ }
5536
+ /**
5537
+ * SMS delivery and latency stats grouped by originator, the sender address messages went out from, ranked by the `sort` metric (default `accepted`) and capped by `limit` (default 50, maximum 200). Use it to compare how your senders perform.
5538
+ *
5539
+ * @example Compare how each sender performs
5540
+ * const stats = await bird.sms.stats.byOriginator({ from: "2026-05-01", to: "2026-05-31" });
5541
+ * for (const row of stats.data ?? []) {
5542
+ * console.log(row.originator, row.delivery);
5543
+ * }
5544
+ */
5545
+ byOriginator(query, options) {
5546
+ return this.call("GET", options, ({ signal, headers }) => getSmsStatsByOriginator({
5547
+ client: this.client,
5548
+ query,
5549
+ headers,
5550
+ signal
5551
+ }));
5552
+ }
5553
+ /**
5554
+ * How many messages ended the period in each lifecycle status: accepted, sent, delivered, undelivered, failed, rejected, expired, ordered by count. The "where did my messages end up" view, suitable for a status-distribution chart.
5555
+ *
5556
+ * @example Where the window's messages ended up
5557
+ * const stats = await bird.sms.stats.byStatus({ from: "2026-05-01", to: "2026-05-31" });
5558
+ * for (const row of stats.data ?? []) {
5559
+ * console.log(row.status, row.count);
5560
+ * }
5561
+ */
5562
+ byStatus(query, options) {
5563
+ return this.call("GET", options, ({ signal, headers }) => getSmsStatsByStatus({
5564
+ client: this.client,
5565
+ query,
5566
+ headers,
5567
+ signal
5568
+ }));
5569
+ }
5570
+ /**
5571
+ * SMS stats grouped by our normalized failure reason, which answers which reasons are driving your failures. The grouping key is the same value as the `error_code` filter on `sms.list`, so a row joins straight to the messages behind it. Ranked by the `sort` metric (default `failed`) and capped by `limit`.
4659
5572
  *
4660
- * @example Iterate every contact, or take one page
4661
- * for await (const contact of bird.contacts.list({ q: "acme.com" })) {
4662
- * console.log(contact.id, contact.email);
5573
+ * @example Which reasons drive failures
5574
+ * const stats = await bird.sms.stats.byErrorCode({ from: "2026-05-01", to: "2026-05-31" });
5575
+ * for (const row of stats.data ?? []) {
5576
+ * // The same value as the error_code filter on bird.sms.list.
5577
+ * console.log(row.error_code, row.delivery);
4663
5578
  * }
4664
- * const page = await bird.contacts.list({ limit: 50 }); // page.data, page.next_cursor
4665
5579
  */
4666
- list(query, options) {
4667
- return this.paginated("GET", options, ({ signal, headers }, cursor) => listContacts({
5580
+ byErrorCode(query, options) {
5581
+ return this.call("GET", options, ({ signal, headers }) => getSmsStatsByErrorCode({
4668
5582
  client: this.client,
4669
- query: {
4670
- ...query,
4671
- starting_after: cursor ?? query?.starting_after
4672
- },
5583
+ query,
4673
5584
  headers,
4674
5585
  signal
4675
5586
  }));
4676
5587
  }
4677
5588
  /**
4678
- * Get a single contact by ID (`con_`-prefixed). Look up an ID by exact email, phone_number, or external_id with `contacts.list`.
5589
+ * SMS delivery and latency stats grouped by tag (`name:value`), ranked by the `sort` metric (default `accepted`) and capped by `limit` (default 50, maximum 200). Only tagged messages appear, and one carrying several tags counts once under each, so rows do not sum to the period total.
4679
5590
  *
4680
- * @example Fetch a contact by id
4681
- * const contact = await bird.contacts.get("con_01krdgeqcxet5s7t44vh8rt9mg");
4682
- * console.log(contact.email, contact.first_name);
5591
+ * @example Compare campaigns and segments
5592
+ * const stats = await bird.sms.stats.byTag({ from: "2026-05-01", to: "2026-05-31" });
5593
+ * for (const row of stats.data ?? []) {
5594
+ * // A message carrying several tags counts once under each, so rows do not sum
5595
+ * // to the period total.
5596
+ * console.log(row.tag, row.delivery);
5597
+ * }
4683
5598
  */
4684
- get(contactId, options) {
4685
- return this.call("GET", options, ({ signal, headers }) => getContact({
5599
+ byTag(query, options) {
5600
+ return this.call("GET", options, ({ signal, headers }) => getSmsStatsByTag({
4686
5601
  client: this.client,
4687
- path: { contact_id: contactId },
5602
+ query,
4688
5603
  headers,
4689
5604
  signal
4690
5605
  }));
4691
5606
  }
5607
+ };
5608
+ //#endregion
5609
+ //#region src/resources/smsStatsInbound.gen.ts
5610
+ var SmsStatsInboundResource = class extends Resource {
4692
5611
  /**
4693
- * Create a contact identified by an email address, an E.164 phone number, or both. Fails with a conflict if the email, phone_number, or external_id is already used by another contact. For bulk import or create-or-update semantics use `contacts.batch`.
5612
+ * Total messages your numbers received over a period. For a breakdown use `sms.stats.inbound.by_country`, `sms.stats.inbound.by_operator`, or `sms.stats.inbound.by_number`.
4694
5613
  *
4695
- * @example Create a contact
4696
- * const contact = await bird.contacts.create({
4697
- * email: "jane@acme.com",
4698
- * first_name: "Jane",
4699
- * });
4700
- * console.log(contact.id); // "con_…"
5614
+ * @example Total messages received
5615
+ * const summary = await bird.sms.stats.inbound.summary({ from: "2026-05-01", to: "2026-05-31" });
5616
+ * console.log(summary.received);
4701
5617
  */
4702
- create(params = {}, options) {
4703
- return this.call("POST", options, ({ signal, headers }) => createContact({
5618
+ summary(query, options) {
5619
+ return this.call("GET", options, ({ signal, headers }) => getSmsInboundStatsSummary({
4704
5620
  client: this.client,
4705
- body: params,
5621
+ query,
4706
5622
  headers,
4707
5623
  signal
4708
5624
  }));
4709
5625
  }
4710
5626
  /**
4711
- * Update a contact's name, external_id, email, phone_number, or custom data. Only supplied fields change; custom data keys are merged, with null removing a key. A contact keeps at least one identifier: clearing both email and phone_number is rejected.
5627
+ * Messages your numbers received, one row per calendar day. Set `timezone` to get local calendar days instead of UTC.
4712
5628
  *
4713
- * @example Change a contact's fields
4714
- * const contact = await bird.contacts.update("con_01krdgeqcxet5s7t44vh8rt9mg", {
4715
- * first_name: "Jane",
4716
- * });
4717
- * console.log(contact.first_name);
5629
+ * @example Received messages per day
5630
+ * const stats = await bird.sms.stats.inbound.daily({ from: "2026-05-01", to: "2026-05-31" });
5631
+ * for (const point of stats.data ?? []) {
5632
+ * console.log(point.bucket, point.received);
5633
+ * }
4718
5634
  */
4719
- update(contactId, params = {}, options) {
4720
- return this.call("PATCH", options, ({ signal, headers }) => updateContact({
5635
+ daily(query, options) {
5636
+ return this.call("GET", options, ({ signal, headers }) => getSmsInboundStatsDaily({
4721
5637
  client: this.client,
4722
- path: { contact_id: contactId },
4723
- body: params,
5638
+ query,
4724
5639
  headers,
4725
5640
  signal
4726
5641
  }));
4727
5642
  }
4728
5643
  /**
4729
- * Delete a contact and remove it from every audience it belongs to. Suppression records for the address are unaffected.
5644
+ * Messages your numbers received, one row per hour, for inspecting inbound volume inside a single day.
4730
5645
  *
4731
- * @example Delete a contact by id
4732
- * await bird.contacts.delete("con_01krdgeqcxet5s7t44vh8rt9mg");
5646
+ * @example Received messages per hour
5647
+ * const stats = await bird.sms.stats.inbound.hourly({
5648
+ * from: "2026-05-30T00:00:00Z",
5649
+ * to: "2026-05-31T00:00:00Z",
5650
+ * });
5651
+ * for (const point of stats.data ?? []) {
5652
+ * console.log(point.bucket, point.received);
5653
+ * }
4733
5654
  */
4734
- delete(contactId, options) {
4735
- return this.call("DELETE", options, ({ signal, headers }) => deleteContact({
5655
+ hourly(query, options) {
5656
+ return this.call("GET", options, ({ signal, headers }) => getSmsInboundStatsHourly({
4736
5657
  client: this.client,
4737
- path: { contact_id: contactId },
5658
+ query,
4738
5659
  headers,
4739
5660
  signal
4740
5661
  }));
4741
5662
  }
4742
5663
  /**
4743
- * Create or update up to 1,000 contacts in one request, each entry matched automatically against every identifier it supplies (email, phone_number, external_id) or, with match_on, by that one field only, and optionally add them all to one or more audiences. Per-contact results are returned in submission order.
5664
+ * Messages your numbers received, grouped by the country of the receiving number.
4744
5665
  *
4745
- * @example Create or update many contacts at once, matched by the identifiers each entry carries
4746
- * const result = await bird.contacts.batch({
4747
- * contacts: [{ email: "jane@acme.com", first_name: "Jane" }],
4748
- * });
4749
- * for (const item of result.data) {
4750
- * console.log(item.entry.email, item.status);
5666
+ * @example Where senders messaged from
5667
+ * const stats = await bird.sms.stats.inbound.byCountry({ from: "2026-05-01", to: "2026-05-31" });
5668
+ * for (const row of stats.data ?? []) {
5669
+ * console.log(row.country, row.received);
4751
5670
  * }
4752
5671
  */
4753
- batch(params, options) {
4754
- return this.call("POST", options, ({ signal, headers }) => createContactBatch({
5672
+ byCountry(query, options) {
5673
+ return this.call("GET", options, ({ signal, headers }) => getSmsInboundStatsByCountry({
4755
5674
  client: this.client,
4756
- body: params,
5675
+ query,
4757
5676
  headers,
4758
5677
  signal
4759
5678
  }));
4760
5679
  }
4761
- };
4762
- //#endregion
4763
- //#region src/resources/sms.gen.ts
4764
- var SmsResourceBase = class extends Resource {
4765
5680
  /**
4766
- * Get one SMS message by id: its current delivery status, segment breakdown, cost, and failure detail if it failed.
5681
+ * Messages your numbers received, grouped by the sender's mobile operator. Messages whose operator the carrier did not report are excluded, so these rows can sum to less than `sms.stats.inbound.summary` for the same period.
4767
5682
  *
4768
- * @example Read a message back
4769
- * const msg = await bird.sms.get("sms_abc123");
4770
- * msg.status; // "accepted" | "delivered" |
5683
+ * @example Received messages per operator
5684
+ * const stats = await bird.sms.stats.inbound.byOperator({ from: "2026-05-01", to: "2026-05-31" });
5685
+ * for (const row of stats.data ?? []) {
5686
+ * // Messages whose operator the carrier did not report are excluded, so these
5687
+ * // rows can sum to less than the inbound summary for the same period.
5688
+ * console.log(row.mcc_mnc, row.received);
5689
+ * }
4771
5690
  */
4772
- get(messageId, options) {
4773
- return this.call("GET", options, ({ signal, headers }) => getSmsMessage({
5691
+ byOperator(query, options) {
5692
+ return this.call("GET", options, ({ signal, headers }) => getSmsInboundStatsByOperator({
4774
5693
  client: this.client,
4775
- path: { message_id: messageId },
5694
+ query,
4776
5695
  headers,
4777
5696
  signal
4778
5697
  }));
4779
5698
  }
4780
5699
  /**
4781
- * 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.
5700
+ * How many messages each of your numbers received, which is the view that shows whether a campaign's reply traffic is landing on the number you expect.
4782
5701
  *
4783
- * @example Iterate outbound messages
4784
- * for await (const msg of bird.sms.list({ direction: "outbound" })) {
4785
- * console.log(msg.id, msg.status);
5702
+ * @example Which number took the traffic
5703
+ * const stats = await bird.sms.stats.inbound.byNumber({ from: "2026-05-01", to: "2026-05-31" });
5704
+ * for (const row of stats.data ?? []) {
5705
+ * console.log(row.number, row.received);
4786
5706
  * }
4787
5707
  */
4788
- list(query, options) {
4789
- return this.paginated("GET", options, ({ signal, headers }, cursor) => listSmsMessages({
5708
+ byNumber(query, options) {
5709
+ return this.call("GET", options, ({ signal, headers }) => getSmsInboundStatsByNumber({
4790
5710
  client: this.client,
4791
- query: {
4792
- ...query,
4793
- starting_after: cursor ?? query?.starting_after
4794
- },
5711
+ query,
4795
5712
  headers,
4796
5713
  signal
4797
5714
  }));
4798
5715
  }
4799
5716
  };
4800
5717
  //#endregion
5718
+ //#region src/resources/smsStats.ts
5719
+ var SmsStatsResource = class extends SmsStatsResourceBase {
5720
+ /** Received-message statistics — `bird.sms.stats.inbound.summary(...)`, `.byNumber(...)`, … */
5721
+ inbound;
5722
+ constructor(core, client) {
5723
+ super(core, client);
5724
+ this.inbound = new SmsStatsInboundResource(core, client);
5725
+ }
5726
+ };
5727
+ //#endregion
4801
5728
  //#region src/resources/sms.ts
4802
5729
  /** Filters and cursor params for `bird.sms.list`. */
4803
5730
  var SmsResource = class extends SmsResourceBase {
5731
+ /** SMS statistics: `bird.sms.stats.summary(...)`, `.daily(...)`, `.inbound.byNumber(...)`, … */
5732
+ stats;
5733
+ constructor(core, client) {
5734
+ super(core, client);
5735
+ this.stats = new SmsStatsResource(core, client);
5736
+ }
4804
5737
  /**
4805
- * Send one SMS to a single recipient. Supply either `text` (with a `category`)
4806
- * or a stored `template` (by `id` or `slug`, with its `parameters`). The
4807
- * result is `accepted`, not yet delivered — read it back with `get` to confirm.
5738
+ * Send one SMS to a single recipient. Supply either `text` (with a `category` and `from`)
5739
+ * or a stored `template` (by `id` or `slug`, with its `parameters`). The API
5740
+ * accepts the message for delivery. Read it back with `get` for the latest status.
4808
5741
  *
4809
5742
  * @example Send free text
4810
5743
  * const msg = await bird.sms.send({
4811
- * from: "MyBrand",
5744
+ * from: "+15557654321",
4812
5745
  * to: "+14155550100",
4813
5746
  * text: "Your verification code is 123456.",
4814
5747
  * category: "authentication",
@@ -4835,8 +5768,18 @@ var SmsResource = class extends SmsResourceBase {
4835
5768
  *
4836
5769
  * @example
4837
5770
  * const result = await bird.sms.sendBatch([
4838
- * { to: "+15551111111", text: "Hi Alice!", category: "marketing" },
4839
- * { to: "+15552222222", text: "Hi Bob!", category: "marketing" },
5771
+ * {
5772
+ * from: "+15557654321",
5773
+ * to: "+15551111111",
5774
+ * text: "Hi Alice!",
5775
+ * category: "marketing",
5776
+ * },
5777
+ * {
5778
+ * from: "+15557654321",
5779
+ * to: "+15552222222",
5780
+ * text: "Hi Bob!",
5781
+ * category: "marketing",
5782
+ * },
4840
5783
  * ]);
4841
5784
  */
4842
5785
  sendBatch(params, options) {
@@ -4849,10 +5792,121 @@ var SmsResource = class extends SmsResourceBase {
4849
5792
  }
4850
5793
  };
4851
5794
  //#endregion
5795
+ //#region src/resources/smsKeywordRules.gen.ts
5796
+ var SmsKeywordRulesResource = class extends Resource {
5797
+ /**
5798
+ * List the default and workspace keyword rules that apply to inbound messages, most specific first. Filter by `country`, `number`, `operation`, or `scope`. Pass `number` to see one number's rules in evaluation order. Default coverage varies by country.
5799
+ */
5800
+ list(query, options) {
5801
+ return this.call("GET", options, ({ signal, headers }) => listSmsKeywordRules({
5802
+ client: this.client,
5803
+ query,
5804
+ headers,
5805
+ signal
5806
+ }));
5807
+ }
5808
+ /**
5809
+ * Read one default or workspace keyword rule. Its ID prefix identifies which kind: a workspace rule can be changed with `sms_keyword_rules.update`, a Bird default cannot.
5810
+ */
5811
+ get(id, options) {
5812
+ return this.call("GET", options, ({ signal, headers }) => getSmsKeywordRule({
5813
+ client: this.client,
5814
+ path: { id },
5815
+ headers,
5816
+ signal
5817
+ }));
5818
+ }
5819
+ /**
5820
+ * Replace the default opt-out, opt-in, or help reply for one country, or add a `custom` keyword. A workspace rule takes precedence over the default for that country. Opt-out and opt-in keywords cannot be assigned to another operation.
5821
+ */
5822
+ create(params, options) {
5823
+ return this.call("POST", options, ({ signal, headers }) => createSmsKeywordRule({
5824
+ client: this.client,
5825
+ body: params,
5826
+ headers,
5827
+ signal
5828
+ }));
5829
+ }
5830
+ /**
5831
+ * Change one of your own keyword rules: its reply, its extra keywords, or its self-managed attestation. Bird's default rules cannot be updated; create your own for that country instead with `sms_keyword_rules.create`. Omitting `keywords` leaves the set alone, while sending an empty list clears your additions back to Bird's.
5832
+ */
5833
+ update(id, params = {}, options) {
5834
+ return this.call("PATCH", options, ({ signal, headers }) => updateSmsKeywordRule({
5835
+ client: this.client,
5836
+ path: { id },
5837
+ body: params,
5838
+ headers,
5839
+ signal
5840
+ }));
5841
+ }
5842
+ /**
5843
+ * Delete one of your own keyword rules, which restores Bird's default for that country and operation. Bird's own rules cannot be deleted.
5844
+ */
5845
+ delete(id, options) {
5846
+ return this.call("DELETE", options, ({ signal, headers }) => deleteSmsKeywordRule({
5847
+ client: this.client,
5848
+ path: { id },
5849
+ headers,
5850
+ signal
5851
+ }));
5852
+ }
5853
+ };
5854
+ //#endregion
5855
+ //#region src/resources/smsSuppressions.gen.ts
5856
+ var SmsSuppressionsResource = class extends Resource {
5857
+ /**
5858
+ * List the workspace's SMS suppressions (sender-and-subscriber pairs blocked from delivery) as a cursor page.
5859
+ */
5860
+ list(query, options) {
5861
+ return this.paginated("GET", options, ({ signal, headers }, cursor) => listSmsSuppressions({
5862
+ client: this.client,
5863
+ query: {
5864
+ ...query,
5865
+ starting_after: cursor ?? query?.starting_after
5866
+ },
5867
+ headers,
5868
+ signal
5869
+ }));
5870
+ }
5871
+ /**
5872
+ * Read one SMS suppression: the sender and subscriber it covers, why messages are stopped, what it blocks, and whether it is still in force. To check whether you may message someone, filter `sms_suppressions.list` by their number instead.
5873
+ */
5874
+ get(suppressionId, options) {
5875
+ return this.call("GET", options, ({ signal, headers }) => getSmsSuppression({
5876
+ client: this.client,
5877
+ path: { suppression_id: suppressionId },
5878
+ headers,
5879
+ signal
5880
+ }));
5881
+ }
5882
+ /**
5883
+ * Stop one of your senders from messaging one subscriber. Covers that sender only; your other senders keep reaching them.
5884
+ */
5885
+ add(params, options) {
5886
+ return this.call("POST", options, ({ signal, headers }) => createSmsSuppression({
5887
+ client: this.client,
5888
+ body: params,
5889
+ headers,
5890
+ signal
5891
+ }));
5892
+ }
5893
+ /**
5894
+ * End a manual SMS suppression, letting that sender message that subscriber again. Only reason `manual` can be ended this way: a subscriber's own stop keyword and a carrier's opt-out are refused.
5895
+ */
5896
+ remove(suppressionId, options) {
5897
+ return this.call("DELETE", options, ({ signal, headers }) => deleteSmsSuppression({
5898
+ client: this.client,
5899
+ path: { suppression_id: suppressionId },
5900
+ headers,
5901
+ signal
5902
+ }));
5903
+ }
5904
+ };
5905
+ //#endregion
4852
5906
  //#region src/resources/smsTemplates.gen.ts
4853
5907
  var SmsTemplatesResource = class extends Resource {
4854
5908
  /**
4855
- * 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.
5909
+ * List the SMS templates available to your workspace, including our built-in templates. Filter by scope, category, or language. The catalog 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.
4856
5910
  *
4857
5911
  * @example List the built-in templates
4858
5912
  * const { data } = await bird.smsTemplates.list({ scope: "system" });
@@ -4867,7 +5921,7 @@ var SmsTemplatesResource = class extends Resource {
4867
5921
  }));
4868
5922
  }
4869
5923
  /**
4870
- * Get one SMS template by its slug or id, including its body and the variables it expects. Fetch it before sms_send to see which parameter keys a template send requires.
5924
+ * Get one SMS template by its slug or ID, including its body and the variables it expects. Fetch it before `sms.send` to see which parameter keys a template send requires.
4871
5925
  *
4872
5926
  * @example Read one template by slug or id
4873
5927
  * const tpl = await bird.smsTemplates.get("bird_otp_verification");
@@ -4886,7 +5940,7 @@ var SmsTemplatesResource = class extends Resource {
4886
5940
  //#region src/resources/whatsapp.gen.ts
4887
5941
  var WhatsappResourceBase = class extends Resource {
4888
5942
  /**
4889
- * 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.
5943
+ * Get one WhatsApp message by id: current delivery status, sent/delivered/read timestamps, the one content it was built from (a template, or free-form text, image, video, audio, sticker, document or location), and failure detail if it failed. For the per-event timeline use whatsapp_list_events.
4890
5944
  *
4891
5945
  * @example Read a message back
4892
5946
  * const msg = await bird.whatsapp.get("wa_abc123");
@@ -4901,7 +5955,7 @@ var WhatsappResourceBase = class extends Resource {
4901
5955
  }));
4902
5956
  }
4903
5957
  /**
4904
- * 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 direction, status, contact phone number, bsuid, template category, or tag. Use whatsapp_get for one message's current state.
5958
+ * List WhatsApp messages, newest first, as a cursor page ({data, next_cursor, …}). Each message carries the one content it was built from: a template, or free-form text, image, video, audio, sticker, document or location. Pass next_cursor back as starting_after to fetch the next page. Filter by direction, status, contact phone number, bsuid, template category, or tag. Use whatsapp_get for one message's current state.
4905
5959
  *
4906
5960
  * @example Iterate delivered messages
4907
5961
  * for await (const msg of bird.whatsapp.list({ status: ["delivered"] })) {
@@ -4920,7 +5974,7 @@ var WhatsappResourceBase = class extends Resource {
4920
5974
  }));
4921
5975
  }
4922
5976
  /**
4923
- * 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.
5977
+ * 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 returns `404`. Use `whatsapp.get` for the condensed current status.
4924
5978
  *
4925
5979
  * @example Read one message's delivery timeline
4926
5980
  * const { data } = await bird.whatsapp.listEvents("wa_abc123");
@@ -4940,10 +5994,11 @@ var WhatsappResourceBase = class extends Resource {
4940
5994
  //#region src/resources/whatsapp.ts
4941
5995
  var WhatsappResource = class extends WhatsappResourceBase {
4942
5996
  /**
4943
- * Send a template message. Bird selects the sender number from the
4944
- * template's category, so there is no sender field on the request. The
4945
- * result is `accepted`, not yet delivered read it back with `get` to
4946
- * confirm.
5997
+ * Send one message, carrying exactly one kind of content: a template, or
5998
+ * free-form `text`, `image`, `video`, `audio`, `sticker`, `document` or
5999
+ * `location`. Every send but a Bird-managed template needs `from`, a number
6000
+ * this workspace owns. The result is `accepted`, not yet delivered — read it
6001
+ * back with `get` to confirm.
4947
6002
  *
4948
6003
  * @example
4949
6004
  * const msg = await bird.whatsapp.send({
@@ -4968,7 +6023,7 @@ var WhatsappResource = class extends WhatsappResourceBase {
4968
6023
  //#region src/resources/voice.gen.ts
4969
6024
  var VoiceResource = class extends Resource {
4970
6025
  /**
4971
- * List the workspace's calls, newest first. Filter to `ringing`/`in_progress` for the calls in progress right now, to final statuses for completed records, or to any mix of the two. Use `from`/`to` for one known party number in international form, and `number` to search either side by fragment. These are per-call records: for rates and totals over a period use voice_stats_summary rather than summing them here, and voice_get to follow one call to settlement.
6026
+ * List the workspace's calls, newest first. Filter to `ringing`/`in_progress` for the calls in progress right now, to final statuses for completed records, or to any mix of the two. Use `from`/`to` for one known party number in international form, and `number` to search either side by fragment. These are per-call records and do not include aggregate rates or totals. Use `voice.get` to follow one call to settlement.
4972
6027
  *
4973
6028
  * @example Iterate the calls happening right now
4974
6029
  * for await (const call of bird.voice.list({ status: ["ringing", "in_progress"] })) {
@@ -4987,7 +6042,7 @@ var VoiceResource = class extends Resource {
4987
6042
  }));
4988
6043
  }
4989
6044
  /**
4990
- * Fetch one call by id, at any point in its lifecycle. A call still ringing or connected carries no economics yet: `duration_ms`, `billable_ms`, `ended_at`, and `cost` are null until it ends, and this same id then answers with the settled record. Poll here to watch one known call; use voice_list to find calls in the first place. When a call was refused, `rejection_reason` names the gate that turned it away.
6045
+ * Fetch one call by ID, at any point in its lifecycle. A call still ringing or connected carries no economics yet: `duration_ms`, `billable_ms`, `ended_at`, and `cost` are null until it ends, and the same ID then returns the settled record. Poll here to watch one known call; use `voice.list` to find calls in the first place. When a call was refused, `rejection_reason` names the gate that turned it away.
4991
6046
  *
4992
6047
  * @example Read one call back
4993
6048
  * const call = await bird.voice.get("vcl_01k0p3v9wera3v6q6xw3e9y2mh");
@@ -5007,7 +6062,7 @@ var VoiceResource = class extends Resource {
5007
6062
  //#region src/resources/verifyVerifications.gen.ts
5008
6063
  var VerifyVerificationsResource = class extends Resource {
5009
6064
  /**
5010
- * Start a verification: generate a one-time passcode and send it to the recipient in `to` (a phone number over the phone channels enabled for its destination country; an email address over email; or both). It is sent over one channel at a time and fails over to the next in the plan, never over two 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, WhatsApp and Telegram delivery all draw on the workspace's balance.
6065
+ * Start a verification and send a one-time passcode to the email address, phone number, or both in `to`. Delivery uses one planned channel at a time and fails over when necessary. Calling again for the same recipient reuses the verification in progress and sends after the resend cooldown. The passcode is never returned; submit the recipient's code with `verify.verifications.check`. SMS, WhatsApp, and Telegram delivery draw on the workspace's balance.
5011
6066
  *
5012
6067
  * @example Start a verification over SMS
5013
6068
  * const verification = await bird.verify.verifications.create({
@@ -5024,7 +6079,7 @@ var VerifyVerificationsResource = class extends Resource {
5024
6079
  }));
5025
6080
  }
5026
6081
  /**
5027
- * 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.
6082
+ * Check a passcode a recipient submitted. Identify the verification by the same `to` recipient used to start it; no verification ID is needed. A wrong or expired code returns HTTP 200 with `success: false` and a `reason` (for example `incorrect_code` or `expired`). 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.
5028
6083
  *
5029
6084
  * @example Check a submitted passcode
5030
6085
  * const result = await bird.verify.verifications.check({
@@ -5042,7 +6097,7 @@ var VerifyVerificationsResource = class extends Resource {
5042
6097
  }));
5043
6098
  }
5044
6099
  /**
5045
- * Advance an in-progress verification to the next channel in its plan and send a fresh passcode there: the "I didn't receive my code" action. The verification is identified by the same `to` recipient used to start it, with no verification id needed. The send bypasses the resend cooldown, and earlier passcodes stay valid. Returns the verification with `last_channel` set to the channel the new code went to; when concurrent advances race for the same recipient, the response reflects committed state: `last_channel` names the most recent completed send, and the racing call that completed the newer send is authoritative. A plan with no further channel returns a 422 named NoNextChannel, after which only re-creating the verification will resend.
6100
+ * Advance an in-progress verification to its next channel and send a fresh passcode. Identify it with the same `to` recipient used to create it; no verification ID is required. This bypasses the resend cooldown, and earlier passcodes remain valid. `last_channel` identifies the most recent completed send. `422 NoNextChannel` means the plan is exhausted; create the verification again to resend on the current channel.
5046
6101
  *
5047
6102
  * @example Send the code again on the next channel
5048
6103
  * const verification = await bird.verify.verifications.nextChannel({
@@ -5264,6 +6319,242 @@ var RealtimeMembersResource = class extends Resource {
5264
6319
  }
5265
6320
  };
5266
6321
  //#endregion
6322
+ //#region src/core/secretbox.gen.ts
6323
+ const SIGMA = new Uint8Array([
6324
+ 101,
6325
+ 120,
6326
+ 112,
6327
+ 97,
6328
+ 110,
6329
+ 100,
6330
+ 32,
6331
+ 51,
6332
+ 50,
6333
+ 45,
6334
+ 98,
6335
+ 121,
6336
+ 116,
6337
+ 101,
6338
+ 32,
6339
+ 107
6340
+ ]);
6341
+ function rotl(x, c) {
6342
+ return x << c | x >>> 32 - c;
6343
+ }
6344
+ function load32(b, i) {
6345
+ return (b[i] | b[i + 1] << 8 | b[i + 2] << 16 | b[i + 3] << 24) >>> 0;
6346
+ }
6347
+ function store32(b, i, v) {
6348
+ b[i] = v & 255;
6349
+ b[i + 1] = v >>> 8 & 255;
6350
+ b[i + 2] = v >>> 16 & 255;
6351
+ b[i + 3] = v >>> 24 & 255;
6352
+ }
6353
+ /**
6354
+ * The Salsa20 core over the 4x4 state built from `key` and a 16-byte `input`.
6355
+ * With `feedForward` this is the Salsa20 block function (stream generation);
6356
+ * without it, the state words at the diagonal and input positions form the
6357
+ * HSalsa20 output used for XSalsa20's subkey derivation.
6358
+ */
6359
+ function salsa20Core(key, input, feedForward) {
6360
+ const j = /* @__PURE__ */ new Int32Array(16);
6361
+ j[0] = load32(SIGMA, 0);
6362
+ j[1] = load32(key, 0);
6363
+ j[2] = load32(key, 4);
6364
+ j[3] = load32(key, 8);
6365
+ j[4] = load32(key, 12);
6366
+ j[5] = load32(SIGMA, 4);
6367
+ j[6] = load32(input, 0);
6368
+ j[7] = load32(input, 4);
6369
+ j[8] = load32(input, 8);
6370
+ j[9] = load32(input, 12);
6371
+ j[10] = load32(SIGMA, 8);
6372
+ j[11] = load32(key, 16);
6373
+ j[12] = load32(key, 20);
6374
+ j[13] = load32(key, 24);
6375
+ j[14] = load32(key, 28);
6376
+ j[15] = load32(SIGMA, 12);
6377
+ let x0 = j[0], x1 = j[1], x2 = j[2], x3 = j[3];
6378
+ let x4 = j[4], x5 = j[5], x6 = j[6], x7 = j[7];
6379
+ let x8 = j[8], x9 = j[9], x10 = j[10], x11 = j[11];
6380
+ let x12 = j[12], x13 = j[13], x14 = j[14], x15 = j[15];
6381
+ for (let round = 0; round < 20; round += 2) {
6382
+ x4 ^= rotl(x0 + x12 | 0, 7);
6383
+ x8 ^= rotl(x4 + x0 | 0, 9);
6384
+ x12 ^= rotl(x8 + x4 | 0, 13);
6385
+ x0 ^= rotl(x12 + x8 | 0, 18);
6386
+ x9 ^= rotl(x5 + x1 | 0, 7);
6387
+ x13 ^= rotl(x9 + x5 | 0, 9);
6388
+ x1 ^= rotl(x13 + x9 | 0, 13);
6389
+ x5 ^= rotl(x1 + x13 | 0, 18);
6390
+ x14 ^= rotl(x10 + x6 | 0, 7);
6391
+ x2 ^= rotl(x14 + x10 | 0, 9);
6392
+ x6 ^= rotl(x2 + x14 | 0, 13);
6393
+ x10 ^= rotl(x6 + x2 | 0, 18);
6394
+ x3 ^= rotl(x15 + x11 | 0, 7);
6395
+ x7 ^= rotl(x3 + x15 | 0, 9);
6396
+ x11 ^= rotl(x7 + x3 | 0, 13);
6397
+ x15 ^= rotl(x11 + x7 | 0, 18);
6398
+ x1 ^= rotl(x0 + x3 | 0, 7);
6399
+ x2 ^= rotl(x1 + x0 | 0, 9);
6400
+ x3 ^= rotl(x2 + x1 | 0, 13);
6401
+ x0 ^= rotl(x3 + x2 | 0, 18);
6402
+ x6 ^= rotl(x5 + x4 | 0, 7);
6403
+ x7 ^= rotl(x6 + x5 | 0, 9);
6404
+ x4 ^= rotl(x7 + x6 | 0, 13);
6405
+ x5 ^= rotl(x4 + x7 | 0, 18);
6406
+ x11 ^= rotl(x10 + x9 | 0, 7);
6407
+ x8 ^= rotl(x11 + x10 | 0, 9);
6408
+ x9 ^= rotl(x8 + x11 | 0, 13);
6409
+ x10 ^= rotl(x9 + x8 | 0, 18);
6410
+ x12 ^= rotl(x15 + x14 | 0, 7);
6411
+ x13 ^= rotl(x12 + x15 | 0, 9);
6412
+ x14 ^= rotl(x13 + x12 | 0, 13);
6413
+ x15 ^= rotl(x14 + x13 | 0, 18);
6414
+ }
6415
+ const x = [
6416
+ x0,
6417
+ x1,
6418
+ x2,
6419
+ x3,
6420
+ x4,
6421
+ x5,
6422
+ x6,
6423
+ x7,
6424
+ x8,
6425
+ x9,
6426
+ x10,
6427
+ x11,
6428
+ x12,
6429
+ x13,
6430
+ x14,
6431
+ x15
6432
+ ];
6433
+ const out = new Uint8Array(feedForward ? 64 : 32);
6434
+ if (feedForward) {
6435
+ for (let i = 0; i < 16; i++) store32(out, 4 * i, x[i] + j[i] | 0);
6436
+ return out;
6437
+ }
6438
+ const picks = [
6439
+ 0,
6440
+ 5,
6441
+ 10,
6442
+ 15,
6443
+ 6,
6444
+ 7,
6445
+ 8,
6446
+ 9
6447
+ ];
6448
+ for (let i = 0; i < 8; i++) store32(out, 4 * i, x[picks[i]]);
6449
+ return out;
6450
+ }
6451
+ /**
6452
+ * The XSalsa20 keystream for a 24-byte nonce: an HSalsa20 subkey from the
6453
+ * nonce's first 16 bytes, then Salsa20 blocks over the remaining 8 bytes plus
6454
+ * a little-endian 64-bit block counter.
6455
+ */
6456
+ function xsalsa20Stream(length, nonce, key) {
6457
+ const subkey = salsa20Core(key, nonce.subarray(0, 16), false);
6458
+ const input = /* @__PURE__ */ new Uint8Array(16);
6459
+ input.set(nonce.subarray(16, 24));
6460
+ const stream = new Uint8Array(length);
6461
+ for (let block = 0; block * 64 < length; block++) {
6462
+ store32(input, 8, block);
6463
+ const chunk = salsa20Core(subkey, input, true);
6464
+ stream.set(chunk.subarray(0, Math.min(64, length - block * 64)), block * 64);
6465
+ }
6466
+ return stream;
6467
+ }
6468
+ const P1305 = (1n << 130n) - 5n;
6469
+ const CLAMP = 21267647620597763993911028882763415551n;
6470
+ const MASK128 = (1n << 128n) - 1n;
6471
+ function leToBigInt(b) {
6472
+ let v = 0n;
6473
+ for (let i = b.length - 1; i >= 0; i--) v = v << 8n | BigInt(b[i]);
6474
+ return v;
6475
+ }
6476
+ function poly1305(msg, key) {
6477
+ const r = leToBigInt(key.subarray(0, 16)) & CLAMP;
6478
+ const s = leToBigInt(key.subarray(16, 32));
6479
+ let acc = 0n;
6480
+ for (let i = 0; i < msg.length; i += 16) {
6481
+ const block = msg.subarray(i, Math.min(i + 16, msg.length));
6482
+ acc = (acc + leToBigInt(block) + (1n << BigInt(8 * block.length))) * r % P1305;
6483
+ }
6484
+ acc = acc + s & MASK128;
6485
+ const tag = /* @__PURE__ */ new Uint8Array(16);
6486
+ for (let i = 0; i < 16; i++) {
6487
+ tag[i] = Number(acc & 255n);
6488
+ acc >>= 8n;
6489
+ }
6490
+ return tag;
6491
+ }
6492
+ /**
6493
+ * Seal `plaintext` under a 24-byte `nonce` and 32-byte `key`, returning the
6494
+ * 16-byte Poly1305 tag followed by the ciphertext (the NaCl box layout).
6495
+ */
6496
+ function seal(plaintext, nonce, key) {
6497
+ const stream = xsalsa20Stream(32 + plaintext.length, nonce, key);
6498
+ const out = new Uint8Array(16 + plaintext.length);
6499
+ for (let i = 0; i < plaintext.length; i++) out[16 + i] = plaintext[i] ^ stream[32 + i];
6500
+ out.set(poly1305(out.subarray(16), stream.subarray(0, 32)));
6501
+ return out;
6502
+ }
6503
+ //#endregion
6504
+ //#region src/core/realtime-crypto.ts
6505
+ const ENCRYPTED_CHANNEL_PREFIX = "private-encrypted-";
6506
+ function isEncryptedChannel(name) {
6507
+ return name.startsWith(ENCRYPTED_CHANNEL_PREFIX);
6508
+ }
6509
+ /**
6510
+ * Decode and validate the configured master key: 32 bytes, base64. Validated
6511
+ * here so a bad key fails with a message naming the config, not a cipher
6512
+ * internals error at publish time.
6513
+ */
6514
+ function decodeMasterKey(masterKey) {
6515
+ if (!masterKey) throw new BirdError("Publishing to a private-encrypted- channel requires the encryption master key. Set `realtime: { encryptionMasterKey }` on the client — generate one as 32 random bytes, base64-encoded.");
6516
+ let decoded = null;
6517
+ try {
6518
+ decoded = Uint8Array.from(atob(masterKey), (c) => c.charCodeAt(0));
6519
+ } catch {
6520
+ decoded = null;
6521
+ }
6522
+ if (!decoded || decoded.length !== 32) throw new BirdError("realtime.encryptionMasterKey must be 32 bytes, base64-encoded.");
6523
+ return decoded;
6524
+ }
6525
+ /** SHA-256(channel_name || master_key) — the channel's secretbox key. */
6526
+ async function deriveSharedSecret(channelName, masterKey) {
6527
+ const channel = new TextEncoder().encode(channelName);
6528
+ const input = new Uint8Array(channel.length + masterKey.length);
6529
+ input.set(channel);
6530
+ input.set(masterKey, channel.length);
6531
+ return new Uint8Array(await crypto.subtle.digest("SHA-256", input));
6532
+ }
6533
+ /** Encrypt an event payload for one encrypted channel. */
6534
+ async function encryptForChannel(channelName, data, masterKey) {
6535
+ const key = await deriveSharedSecret(channelName, masterKey);
6536
+ const nonce = crypto.getRandomValues(/* @__PURE__ */ new Uint8Array(24));
6537
+ const box = seal(new TextEncoder().encode(JSON.stringify(data ?? null)), nonce, key);
6538
+ return {
6539
+ nonce: toBase64(nonce),
6540
+ ciphertext: toBase64(box)
6541
+ };
6542
+ }
6543
+ /** `hex(HMAC-SHA256(secret, payload))` — the channel-auth signature. */
6544
+ async function hmacSha256Hex(secret, payload) {
6545
+ const key = await crypto.subtle.importKey("raw", new TextEncoder().encode(secret), {
6546
+ name: "HMAC",
6547
+ hash: "SHA-256"
6548
+ }, false, ["sign"]);
6549
+ const sig = new Uint8Array(await crypto.subtle.sign("HMAC", key, new TextEncoder().encode(payload)));
6550
+ return Array.from(sig, (b) => b.toString(16).padStart(2, "0")).join("");
6551
+ }
6552
+ function toBase64(bytes) {
6553
+ let raw = "";
6554
+ for (const b of bytes) raw += String.fromCharCode(b);
6555
+ return btoa(raw);
6556
+ }
6557
+ //#endregion
5267
6558
  //#region src/resources/realtime.ts
5268
6559
  /**
5269
6560
  * `bird.realtime` — publish events to a Realtime app's channels and inspect its
@@ -5274,17 +6565,111 @@ var RealtimeResource = class extends RealtimeResourceBase {
5274
6565
  channels;
5275
6566
  /** Members — `bird.realtime.members.send(...)`, `.disconnect(...)`. */
5276
6567
  members;
5277
- constructor(core, client) {
6568
+ #options;
6569
+ constructor(core, client, options) {
5278
6570
  super(core, client);
5279
6571
  this.channels = new RealtimeChannelsResource(core, client);
5280
6572
  this.members = new RealtimeMembersResource(core, client);
6573
+ this.#options = options;
6574
+ }
6575
+ /**
6576
+ * Publish, with end-to-end encryption when the channel asks for it: a
6577
+ * `private-encrypted-` channel's payload is sealed locally under the
6578
+ * configured master key before the request leaves the process. One channel
6579
+ * per encrypted publish — each channel derives its own key, so a fan-out
6580
+ * would deliver ciphertext other channels' subscribers cannot open.
6581
+ *
6582
+ * @example Publish to an encrypted channel
6583
+ * // Client config: realtime: { key, secret, encryptionMasterKey }
6584
+ * await bird.realtime.publish("rap_01krdgeqcxet5s7t44vh8rt9mg", {
6585
+ * event: "order.updated",
6586
+ * channels: ["private-encrypted-orders"],
6587
+ * data: { order_id: "ord_123", status: "shipped" },
6588
+ * });
6589
+ */
6590
+ publish(realtimeAppId, params, options) {
6591
+ const encrypted = params.channels.filter(isEncryptedChannel);
6592
+ if (encrypted.length === 0) return super.publish(realtimeAppId, params, options);
6593
+ if (params.channels.length > 1) throw new BirdError("A publish to a private-encrypted- channel must name exactly that one channel: every channel derives its own key, so a multi-channel publish would hand the other channels undecryptable ciphertext. Publish per channel instead.");
6594
+ const masterKey = decodeMasterKey(this.#options?.encryptionMasterKey);
6595
+ return this.call("POST", options, async ({ signal, headers }) => {
6596
+ const body = {
6597
+ ...params,
6598
+ data: await encryptForChannel(encrypted[0], params.data, masterKey)
6599
+ };
6600
+ return publishRealtimeAppEvent({
6601
+ client: this.client,
6602
+ path: { realtime_app_id: realtimeAppId },
6603
+ body,
6604
+ headers,
6605
+ signal
6606
+ });
6607
+ }, ["RealtimeKey", "RealtimeSecret"]);
6608
+ }
6609
+ /**
6610
+ * Publish a batch, sealing each event addressed to a `private-encrypted-`
6611
+ * channel under that channel's derived key (batch events carry one channel
6612
+ * each, so items encrypt independently).
6613
+ */
6614
+ publishBatch(realtimeAppId, params, options) {
6615
+ if (!params.events.some((e) => isEncryptedChannel(e.channel))) return super.publishBatch(realtimeAppId, params, options);
6616
+ const masterKey = decodeMasterKey(this.#options?.encryptionMasterKey);
6617
+ return this.call("POST", options, async ({ signal, headers }) => {
6618
+ const events = await Promise.all(params.events.map(async (e) => isEncryptedChannel(e.channel) ? {
6619
+ ...e,
6620
+ data: await encryptForChannel(e.channel, e.data, masterKey)
6621
+ } : e));
6622
+ return publishRealtimeAppBatch({
6623
+ client: this.client,
6624
+ path: { realtime_app_id: realtimeAppId },
6625
+ body: {
6626
+ ...params,
6627
+ events
6628
+ },
6629
+ headers,
6630
+ signal
6631
+ });
6632
+ }, ["RealtimeKey", "RealtimeSecret"]);
6633
+ }
6634
+ /**
6635
+ * Sign a channel subscription for the browser client — the body your auth
6636
+ * endpoint returns. Runs locally (no request): the signature is
6637
+ * `HMAC-SHA256(secret, "<connectionId>:<channelName>[:<memberData>]")`,
6638
+ * prefixed with the app key. For a presence channel pass `memberData`, the
6639
+ * exact JSON string carrying `member_id` (and optionally `member_info`) —
6640
+ * it is signed and echoed byte-identical. For a `private-encrypted-`
6641
+ * channel the response also carries the channel's `shared_secret`, derived
6642
+ * from the configured encryption master key.
6643
+ *
6644
+ * @example An Express auth endpoint
6645
+ * app.post("/bird/auth", async (req, res) => {
6646
+ * const { connection_id, channel_name } = req.body;
6647
+ * if (!mayJoin(req.session.user, channel_name)) return res.sendStatus(403);
6648
+ * res.json(
6649
+ * await bird.realtime.authorizeChannel({
6650
+ * connectionId: connection_id,
6651
+ * channelName: channel_name,
6652
+ * }),
6653
+ * );
6654
+ * });
6655
+ */
6656
+ async authorizeChannel(params) {
6657
+ const { key, secret } = this.#options ?? {};
6658
+ if (!key || !secret) throw new BirdError("authorizeChannel signs with the Realtime app credentials. Set `realtime: { key, secret }` on the client.");
6659
+ const out = { auth: `${key}:${await hmacSha256Hex(secret, params.memberData === void 0 ? `${params.connectionId}:${params.channelName}` : `${params.connectionId}:${params.channelName}:${params.memberData}`)}` };
6660
+ if (params.memberData !== void 0) out.member_data = params.memberData;
6661
+ if (isEncryptedChannel(params.channelName)) {
6662
+ const masterKey = decodeMasterKey(this.#options?.encryptionMasterKey);
6663
+ out.shared_secret = toBase64(await deriveSharedSecret(params.channelName, masterKey));
6664
+ }
6665
+ return out;
5281
6666
  }
5282
6667
  };
5283
6668
  //#endregion
5284
6669
  //#region src/resources/lookup.gen.ts
5285
6670
  var LookupResource = class extends Resource {
5286
6671
  /**
5287
- * Look up what a phone number is. Returns the serving network, the issuing network, whether the number was ported, its country, and its line type, free with every call. Pass `type` to buy extra blocks: `classification` (the allocated service of the range, from an intelligence source, reported beside the free `line_type` rather than replacing it), `porting` (whether the number ever moved network, when, and its full history), `presence` (reachable on the network right now), `roaming`, `sim_swap` (when the SIM last changed), and `score` (0-100 credibility). Every requested block reports its own status, and only the ones reading `ok` are billed on top of the lookup. Nothing is sent to the number.
6672
+ * Create a lookup for a phone number's networks, porting state, country, and line type. Pass `type` to request separately billed `classification`, `porting`, `presence`, `roaming`, `sim_swap`, or `score` blocks. Each block reports its own status, and only blocks with an `ok` status add a charge; the lookup does not contact the number.
5288
6673
  *
5289
6674
  * @example Look up a number, buying two extra blocks
5290
6675
  * const answer = await bird.lookup.phoneNumber({
@@ -5304,7 +6689,7 @@ var LookupResource = class extends Resource {
5304
6689
  }));
5305
6690
  }
5306
6691
  /**
5307
- * Look up whether an email address is worth sending to. Returns `result` (the verdict: `valid`; `neutral`, meaning it could not be confirmed either way; `risky`, meaning it will probably accept mail but is likelier than most to bounce or complain; `undeliverable`; or `typo`), `delivery_confidence` (0-100), `flags` (`role`, `disposable`, `free_provider`), `reason` on an undeliverable address (`invalid_syntax`, `invalid_domain`, `invalid_recipient`), and `did_you_mean` when the address looks like a misspelling of a real one. `result` and `reason` are OPEN vocabularies: the values listed here are today's and more may be added, so treat an unrecognized value as a future one rather than an error, falling back on `delivery_confidence`. One address per call. Every answered lookup is billed the same flat amount whatever the verdict, so treat it as a paid call rather than a free check, and use an `Idempotency-Key` so a retry does not buy a second answer. Nothing is sent to the address.
6692
+ * Create a deliverability lookup for one email address. Returns `result`, `delivery_confidence`, address `flags`, an undeliverable `reason`, and `did_you_mean` when a correction is available. Treat unknown `result` and `reason` values as valid additions and use `delivery_confidence` as the fallback; each completed lookup incurs the same charge.
5308
6693
  *
5309
6694
  * @example Check whether an address is worth sending to
5310
6695
  * const answer = await bird.lookup.email({ email: "aisha.khan@example.com" });
@@ -5338,8 +6723,8 @@ function resolveRawRequestUrl(baseUrl, path) {
5338
6723
  return url;
5339
6724
  }
5340
6725
  /**
5341
- * The Bird API client. Construct it with an API key; the region is taken from
5342
- * the key's prefix (`bk_{region}_…`) pass `baseUrl` or `region` to override.
6726
+ * The Bird API client. Construct it with an API key. The region comes from the
6727
+ * key's prefix (`bk_{region}_…`). Pass `baseUrl` or `region` to override it.
5343
6728
  *
5344
6729
  * @example Construct and send
5345
6730
  * const bird = new BirdClient({ apiKey: process.env.BIRD_API_KEY! });
@@ -5351,7 +6736,7 @@ function resolveRawRequestUrl(baseUrl, path) {
5351
6736
  * });
5352
6737
  * console.log(msg.id);
5353
6738
  *
5354
- * @example Channel defaults — set common send fields once; a per-send value always wins
6739
+ * @example Set channel defaults once; a per-send value always wins
5355
6740
  * const bird = new BirdClient({
5356
6741
  * apiKey: process.env.BIRD_API_KEY!,
5357
6742
  * email: { from: "hello@acme.com", category: "transactional" },
@@ -5362,8 +6747,8 @@ function resolveRawRequestUrl(baseUrl, path) {
5362
6747
  * @example All client options
5363
6748
  * const bird = new BirdClient({
5364
6749
  * apiKey: process.env.BIRD_API_KEY!,
5365
- * region: "eu1", // optional override the region from the key prefix
5366
- * baseUrl: "http://localhost:8080", // optional overrides region entirely (local/self-hosted)
6750
+ * region: "eu1", // optional; overrides the region from the key prefix
6751
+ * baseUrl: "http://localhost:8080", // optional; overrides region (local or self-hosted)
5367
6752
  * timeout: 60_000, // per-attempt timeout in ms (default 60_000)
5368
6753
  * maxRetries: 2, // retry budget for transient failures (default 2)
5369
6754
  * });
@@ -5374,31 +6759,35 @@ var BirdClient = class {
5374
6759
  #baseUrl;
5375
6760
  #fetch;
5376
6761
  #headers;
5377
- /** The email channel `bird.email.send(...)`, `.get(...)`, `.list(...)`. */
6762
+ /** Email channel: `bird.email.send(...)`, `.get(...)`, `.list(...)`. */
5378
6763
  email;
5379
- /** The SMS channel `bird.sms.send(...)`, `.get(...)`, `.list(...)`. */
6764
+ /** SMS channel: `bird.sms.send(...)`, `.get(...)`, `.list(...)`. */
5380
6765
  sms;
5381
- /** SMS templates `bird.smsTemplates.list(...)`, `.get(...)`. */
6766
+ /** SMS templates: `bird.smsTemplates.list(...)`, `.get(...)`. */
5382
6767
  smsTemplates;
5383
- /** The WhatsApp channel — `bird.whatsapp.send(...)`, `.get(...)`, `.list(...)`, `.listEvents(...)`. */
6768
+ /** SMS suppressions: `bird.smsSuppressions.list(...)`, `.add(...)`, `.remove(...)`. */
6769
+ smsSuppressions;
6770
+ /** SMS keyword rules: `bird.smsKeywordRules.list(...)`, `.create(...)`, … */
6771
+ smsKeywordRules;
6772
+ /** WhatsApp channel: `bird.whatsapp.send(...)`, `.get(...)`, `.list(...)`, `.listEvents(...)`. */
5384
6773
  whatsapp;
5385
- /** The Voice call log `bird.voice.list(...)`, `.get(...)`. Calls are placed by your own SIP equipment, so this is a read surface. */
6774
+ /** Voice call log: `bird.voice.list(...)`, `.get(...)`. Your SIP equipment places calls, so this is a read surface. */
5386
6775
  voice;
5387
- /** The Verify product — `bird.verify.verifications.create(...)`, `.check(...)`. */
6776
+ /** Verify: `bird.verify.verifications.create(...)`, `.check(...)`. */
5388
6777
  verify;
5389
- /** Contacts `bird.contacts.create(...)`, `.list(...)`, `.get(...)`, `.batch(...)`, … */
6778
+ /** Contacts: `bird.contacts.create(...)`, `.list(...)`, `.get(...)`, `.batch(...)`, … */
5390
6779
  contacts;
5391
- /** Audiences `bird.audiences.create(...)`, `.list(...)`, `.addContacts(...)`, … */
6780
+ /** Audiences: `bird.audiences.create(...)`, `.list(...)`, `.addContacts(...)`, … */
5392
6781
  audiences;
5393
- /** Contact properties `bird.contactProperties.create(...)`, `.list(...)`, `.archive(...)`, … */
6782
+ /** Contact properties: `bird.contactProperties.create(...)`, `.list(...)`, `.archive(...)`, … */
5394
6783
  contactProperties;
5395
- /** Sending domains `bird.domains.create(...)`, `.list(...)`, `.verify(...)`, … */
6784
+ /** Sending domains: `bird.domains.create(...)`, `.list(...)`, `.verify(...)`, … */
5396
6785
  domains;
5397
- /** Recipient intelligence `bird.lookup.email(...)`, `.phoneNumber(...)`. Every answer is billed. */
6786
+ /** Recipient intelligence: `bird.lookup.email(...)`, `.phoneNumber(...)`. Every answer is billed. */
5398
6787
  lookup;
5399
- /** Webhooks `bird.webhooks.unwrap(payload, headers)` verifies an inbound delivery. */
6788
+ /** Webhooks: `bird.webhooks.unwrap(payload, headers)` verifies an inbound delivery. */
5400
6789
  webhooks;
5401
- /** Realtime `bird.realtime.publish(...)`, `.channels.list(...)`, `.members.disconnect(...)`, … */
6790
+ /** Realtime: `bird.realtime.publish(...)`, `.channels.list(...)`, `.members.disconnect(...)`, … */
5402
6791
  realtime;
5403
6792
  constructor(options) {
5404
6793
  const opts = options;
@@ -5407,9 +6796,9 @@ var BirdClient = class {
5407
6796
  this.#headers = {
5408
6797
  ...opts.defaultHeaders,
5409
6798
  Authorization: `Bearer ${opts.apiKey}`,
5410
- "User-Agent": `bird-sdk-js/0.29.0`,
6799
+ "User-Agent": `bird-sdk-js/0.30.0`,
5411
6800
  "Bird-Surface": "sdk-js",
5412
- "Bird-Version": "0.29.0"
6801
+ "Bird-Version": "0.30.0"
5413
6802
  };
5414
6803
  const caller = detectCaller();
5415
6804
  if (caller) this.#headers["Bird-Caller"] = caller;
@@ -5437,6 +6826,8 @@ var BirdClient = class {
5437
6826
  this.email = new EmailResource(this.core, this.#client, opts.email);
5438
6827
  this.sms = new SmsResource(this.core, this.#client);
5439
6828
  this.smsTemplates = new SmsTemplatesResource(this.core, this.#client);
6829
+ this.smsSuppressions = new SmsSuppressionsResource(this.core, this.#client);
6830
+ this.smsKeywordRules = new SmsKeywordRulesResource(this.core, this.#client);
5440
6831
  this.whatsapp = new WhatsappResource(this.core, this.#client);
5441
6832
  this.voice = new VoiceResource(this.core, this.#client);
5442
6833
  this.verify = new VerifyResource(this.core, this.#client);
@@ -5446,7 +6837,7 @@ var BirdClient = class {
5446
6837
  this.domains = new DomainsResource(this.core, this.#client);
5447
6838
  this.lookup = new LookupResource(this.core, this.#client);
5448
6839
  this.webhooks = new WebhooksResource(opts.webhooks);
5449
- this.realtime = new RealtimeResource(this.core, this.#client);
6840
+ this.realtime = new RealtimeResource(this.core, this.#client, opts.realtime);
5450
6841
  }
5451
6842
  /**
5452
6843
  * Escape hatch for endpoints the typed resources don't cover. Runs the full
@@ -5456,7 +6847,7 @@ var BirdClient = class {
5456
6847
  * @throws {TypeError} if `req.path` does not start with exactly one `/` or
5457
6848
  * resolves to a different origin than the configured Bird API base URL.
5458
6849
  *
5459
- * @example Reach an endpoint outside the curated surface you supply the response type
6850
+ * @example Reach an endpoint outside the curated surface. Supply the response type
5460
6851
  * type Suppressions = { data: Array<{ recipient: string }> };
5461
6852
  * const suppressions = await bird.request<Suppressions>({ method: "GET", path: "/v1/email/suppressions" });
5462
6853
  * console.log(suppressions.data.length);
@@ -5550,6 +6941,7 @@ const WebhookEventType = {
5550
6941
  WhatsappDelivered: "whatsapp.delivered",
5551
6942
  WhatsappFailed: "whatsapp.failed",
5552
6943
  WhatsappRead: "whatsapp.read",
6944
+ WhatsappReceived: "whatsapp.received",
5553
6945
  WhatsappRejected: "whatsapp.rejected",
5554
6946
  WhatsappSent: "whatsapp.sent"
5555
6947
  };
@@ -5643,6 +7035,58 @@ const SMSErrorCode = {
5643
7035
  Unreachable: "unreachable"
5644
7036
  };
5645
7037
  /**
7038
+ * Values of SMSKeywordOperation known at this SDK version. The wire value is an open
7039
+ * string: a value added by a newer server deserializes unchanged, so switch on
7040
+ * these with a `default` branch rather than treating the set as closed.
7041
+ */
7042
+ const SMSKeywordOperation = {
7043
+ Custom: "custom",
7044
+ Help: "help",
7045
+ Start: "start",
7046
+ Stop: "stop"
7047
+ };
7048
+ /**
7049
+ * Values of SMSSuppressionCoverage known at this SDK version. The wire value is an open
7050
+ * string: a value added by a newer server deserializes unchanged, so switch on
7051
+ * these with a `default` branch rather than treating the set as closed.
7052
+ */
7053
+ const SMSSuppressionCoverage = {
7054
+ All: "all",
7055
+ NonTransactional: "non_transactional"
7056
+ };
7057
+ /**
7058
+ * Values of SMSSuppressionEndReason known at this SDK version. The wire value is an open
7059
+ * string: a value added by a newer server deserializes unchanged, so switch on
7060
+ * these with a `default` branch rather than treating the set as closed.
7061
+ */
7062
+ const SMSSuppressionEndReason = {
7063
+ ApiKey: "api_key",
7064
+ CarrierCleared: "carrier_cleared",
7065
+ KeywordStart: "keyword_start",
7066
+ User: "user"
7067
+ };
7068
+ /**
7069
+ * Values of SMSSuppressionOrigin known at this SDK version. The wire value is an open
7070
+ * string: a value added by a newer server deserializes unchanged, so switch on
7071
+ * these with a `default` branch rather than treating the set as closed.
7072
+ */
7073
+ const SMSSuppressionOrigin = {
7074
+ ApiKey: "api_key",
7075
+ DlrEvent: "dlr_event",
7076
+ Keyword: "keyword",
7077
+ User: "user"
7078
+ };
7079
+ /**
7080
+ * Values of SMSSuppressionReason known at this SDK version. The wire value is an open
7081
+ * string: a value added by a newer server deserializes unchanged, so switch on
7082
+ * these with a `default` branch rather than treating the set as closed.
7083
+ */
7084
+ const SMSSuppressionReason = {
7085
+ CarrierOptedOut: "carrier_opted_out",
7086
+ KeywordStop: "keyword_stop",
7087
+ Manual: "manual"
7088
+ };
7089
+ /**
5646
7090
  * Values of TemplateLanguageStatus known at this SDK version. The wire value is an open
5647
7091
  * string: a value added by a newer server deserializes unchanged, so switch on
5648
7092
  * these with a `default` branch rather than treating the set as closed.
@@ -5722,6 +7166,7 @@ const WhatsAppEventType = {
5722
7166
  WhatsappDelivered: "whatsapp.delivered",
5723
7167
  WhatsappFailed: "whatsapp.failed",
5724
7168
  WhatsappRead: "whatsapp.read",
7169
+ WhatsappReceived: "whatsapp.received",
5725
7170
  WhatsappRejected: "whatsapp.rejected",
5726
7171
  WhatsappSent: "whatsapp.sent"
5727
7172
  };
@@ -5749,6 +7194,6 @@ const WhatsAppTemplateParameterType = {
5749
7194
  Video: "video"
5750
7195
  };
5751
7196
  //#endregion
5752
- export { BirdAPIError, BirdAuthError, BirdBadRequestError, BirdBillingError, BirdClient, BirdConflictError, BirdConnectionError, BirdError, BirdInternalError, BirdMisdirectedError, BirdNotFoundError, BirdNotImplementedError, BirdPayloadTooLargeError, BirdPermissionError, BirdPreconditionError, BirdRateLimitError, BirdServiceUnavailableError, BirdTimeoutError, BirdValidationError, BirdWebhookVerificationError, EmailEventType, EmailLookupFlag, EmailLookupReason, EmailLookupResult, LookupFlag, LookupPropertyStatus, SMSErrorCode, TemplateLanguageStatus, TemplateStatus, VerificationAttemptFailureReason, VerificationChannel, VerificationTerminalReason, WebhookEventType, WhatsAppErrorCode, WhatsAppEventType, WhatsAppTemplateCategory, WhatsAppTemplateParameterType, baseUrlForRegion, regionFromApiKey };
7197
+ export { BirdAPIError, BirdAuthError, BirdBadRequestError, BirdBillingError, BirdClient, BirdConflictError, BirdConnectionError, BirdError, BirdInternalError, BirdMisdirectedError, BirdNotFoundError, BirdNotImplementedError, BirdPayloadTooLargeError, BirdPermissionError, BirdPreconditionError, BirdRateLimitError, BirdServiceUnavailableError, BirdTimeoutError, BirdValidationError, BirdWebhookVerificationError, EmailEventType, EmailLookupFlag, EmailLookupReason, EmailLookupResult, LookupFlag, LookupPropertyStatus, SMSErrorCode, SMSKeywordOperation, SMSSuppressionCoverage, SMSSuppressionEndReason, SMSSuppressionOrigin, SMSSuppressionReason, TemplateLanguageStatus, TemplateStatus, VerificationAttemptFailureReason, VerificationChannel, VerificationTerminalReason, WebhookEventType, WhatsAppErrorCode, WhatsAppEventType, WhatsAppTemplateCategory, WhatsAppTemplateParameterType, baseUrlForRegion, regionFromApiKey };
5753
7198
 
5754
7199
  //# sourceMappingURL=index.mjs.map