@zavudev/sdk 0.59.1 → 0.60.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,20 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.60.0 (unreleased)
4
+
5
+ ### Features
6
+
7
+ * **v2/contacts:** `Contact.whatsapp` (`ContactWhatsapp`: `bsuid`, `username`),
8
+ regenerated from the spec, which already returned it.
9
+
10
+ ### Documentation
11
+
12
+ * **10dlc:** `TenDlcBrandCreateRequest.ein` is required to submit every entity
13
+ type except `SOLE_PROPRIETOR`, and a sole proprietor's `phone` must be a
14
+ mobile number. The `submit` `400` names the missing EIN.
15
+ * **webhooks:** `message.inbound` and `contact.identity_linked` descriptions
16
+ regenerated from the spec (BSUID, `contactId`, `conversationId`).
17
+
3
18
  ## 0.59.1 (unreleased)
4
19
 
5
20
  ### Documentation
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zavudev/sdk",
3
- "version": "0.59.1",
3
+ "version": "0.60.0",
4
4
  "description": "The official TypeScript library for the Zavudev API",
5
5
  "author": "Zavudev <hi@zavu.dev>",
6
6
  "types": "./index.d.ts",
package/src/types.ts CHANGED
@@ -926,11 +926,16 @@ export type TemplateCreateRequestButtonsItemOtpType = 'COPY_CODE' | 'ONE_TAP';
926
926
  * **Inbound events:**
927
927
  * - `message.inbound`: New message received from a contact. `data.conversationId`,
928
928
  * the inbox thread id (deep-link with
929
- * `https://dashboard.zavu.dev/{locale}/inbox?conv={conversationId}`), is sent on
930
- * **email** messages only, and is `null` there on the first message of a
931
- * brand-new thread. On every other channel it is absent: read it from `GET
932
- * /v1/messages/{messageId}`, which always has it, or from `conversation.new` for
933
- * a new contact. Reactions are delivered as `message.inbound` with
929
+ * `https://dashboard.zavu.dev/{locale}/inbox?conv={conversationId}`), is always
930
+ * set: the webhook is sent once the message has been filed in its thread, so the
931
+ * first message of a new thread carries the same id as `conversation.new`.
932
+ * `data.contactId` is the Zavu contact, and unlike `data.from` it does not
933
+ * change when a WhatsApp contact's identifier switches from a business-scoped
934
+ * user ID (BSUID) to a phone number, unless the switch reveals two contacts for
935
+ * one person; they are then merged and `contact.identity_linked` names the one
936
+ * that went away in `mergedContactId`. On WhatsApp, `data.whatsapp` carries the
937
+ * contact's `bsuid` and `username` when known. Reactions carry none of these
938
+ * three. Reactions are delivered as `message.inbound` with
934
939
  * `messageType='reaction'`. When the contact replied to (quoted) an earlier
935
940
  * message, `data.content` carries the reply context: `replyToMessageId`,
936
941
  * `replyToProviderMessageId`, `replyToFrom`, `replyToText`, and
@@ -956,6 +961,21 @@ export type TemplateCreateRequestButtonsItemOtpType = 'COPY_CODE' | 'ONE_TAP';
956
961
  * `https://dashboard.zavu.dev/{locale}/inbox?conv={conversationId}`), the
957
962
  * `phoneNumber` or `email` key, `channel`, `firstMessageId`, `firstMessageText`,
958
963
  * and `profileName`.
964
+ * - `contact.identity_linked`: A WhatsApp contact known by BSUID was tied to a
965
+ * phone number, a contact known by phone received a BSUID, or a contact changed
966
+ * their number. `data` carries `contactId`, `bsuid`, `phoneNumber` and `reason`:
967
+ * `provider_reported` (WhatsApp sent the phone and the BSUID together on an
968
+ * inbound message), `contact_shared` (the contact shared their phone number in
969
+ * reply to a `request_contact_info` message), `phone_changed` (the contact
970
+ * changed their number; `previousPhoneNumber` carries the old one, and `bsuid`
971
+ * is `null` when WhatsApp never reported one for the contact), or
972
+ * `bsuid_changed` (WhatsApp reported a new BSUID for the same number).
973
+ * `contactId` is the contact that remains if two were merged, and
974
+ * `mergedContactId` the one folded into it. `previousBsuid` is a BSUID you may
975
+ * have stored that no longer identifies the contact. Sent once per link, not on
976
+ * every message. `data.from` on `message.inbound` is the phone only when
977
+ * WhatsApp includes it, so it can still be the BSUID afterwards; key on
978
+ * `contactId`.
959
979
  * - `template.status_changed`: WhatsApp template approval status changed. `data`
960
980
  * carries `templateId`, `name`, `previousStatus`, `currentStatus`,
961
981
  * `rejectionReason`, and `category` — the category Meta currently bills the
@@ -1017,6 +1037,7 @@ export type WebhookEvent =
1017
1037
  | 'message.unsupported'
1018
1038
  | 'broadcast.status_changed'
1019
1039
  | 'conversation.new'
1040
+ | 'contact.identity_linked'
1020
1041
  | 'template.status_changed'
1021
1042
  | 'invitation.status_changed'
1022
1043
  | 'call.initiated'
@@ -1067,14 +1088,29 @@ export interface WebhookMessageData {
1067
1088
  messageType?: MessageType;
1068
1089
  /**
1069
1090
  * ID of the conversation (inbox thread) this message belongs to. Sent on
1070
- * `message.inbound` for **email** messages only; on SMS, WhatsApp, Telegram,
1071
- * Instagram and Messenger it is absent. Use it to deep-link to the dashboard
1072
- * inbox: `https://dashboard.zavu.dev/{locale}/inbox?conv={conversationId}`. On
1073
- * email it is `null` on the first message of a brand-new thread. In every case,
1074
- * fetch it via `GET /v1/messages/{messageId}`, whose `conversationId` is always
1075
- * populated, or take it from the `conversation.new` event for a new contact.
1091
+ * `message.inbound` on every channel, except for reactions. Use it to deep-link to
1092
+ * the dashboard inbox:
1093
+ * `https://dashboard.zavu.dev/{locale}/inbox?conv={conversationId}`. The webhook
1094
+ * is sent once the message has been filed in its thread, so this is always the
1095
+ * thread the message is in: on the first message of a new thread it is the id
1096
+ * `conversation.new` carries, and on the WhatsApp message that ties a BSUID to a
1097
+ * phone number it is the thread that remains once the two are joined.
1076
1098
  */
1077
1099
  conversationId?: string | null;
1100
+ /**
1101
+ * ID of the Zavu contact that sent the message. Sent on `message.inbound` on every
1102
+ * channel, except for reactions. It does not change when a WhatsApp contact's
1103
+ * `from` switches from a business-scoped user ID (BSUID) to a phone number, so use
1104
+ * it, not `from`, as your key for the person. `null` only when no contact could be
1105
+ * resolved.
1106
+ */
1107
+ contactId?: string | null;
1108
+ /**
1109
+ * WhatsApp identity of the sender. Present on WhatsApp `message.inbound` when Zavu
1110
+ * knows the sender's business-scoped user ID (BSUID), and absent otherwise. Same
1111
+ * shape as `whatsapp` on a contact or a conversation.
1112
+ */
1113
+ whatsapp?: WebhookMessageDataWhatsapp;
1078
1114
  /**
1079
1115
  * Text body or media caption. Present on `message.inbound` when the message has
1080
1116
  * text.
@@ -1102,6 +1138,16 @@ export interface WebhookMessageData {
1102
1138
  referral?: AdReferral;
1103
1139
  }
1104
1140
 
1141
+ export interface WebhookMessageDataWhatsapp {
1142
+ /**
1143
+ * Business-scoped user ID. Stable for the person on your WhatsApp Business
1144
+ * Account, whether or not `from` is a phone number.
1145
+ */
1146
+ bsuid: string;
1147
+ /** The WhatsApp username, when the sender has one and Meta reported it. */
1148
+ username?: string;
1149
+ }
1150
+
1105
1151
  /** Webhook configuration for the sender. */
1106
1152
  export interface SenderWebhook {
1107
1153
  /** HTTPS URL that will receive webhook events. */
@@ -1374,6 +1420,13 @@ export interface Contact {
1374
1420
  countryCode?: string;
1375
1421
  /** Contact's WhatsApp profile name. Only available for WhatsApp contacts. */
1376
1422
  profileName?: string | null;
1423
+ /**
1424
+ * WhatsApp identity. Present when Zavu has a business-scoped user ID (BSUID) for
1425
+ * the contact, and absent otherwise. A contact with a username can be reached
1426
+ * under its BSUID, its phone number, or both; they are the same contact. Look one
1427
+ * up by BSUID with the `bsuid` query parameter of the list endpoint.
1428
+ */
1429
+ whatsapp?: ContactWhatsapp;
1377
1430
  /** List of available messaging channels for this contact. */
1378
1431
  availableChannels: Array<string>;
1379
1432
  /** Preferred channel for this contact. */
@@ -1387,6 +1440,13 @@ export interface Contact {
1387
1440
  updatedAt?: string;
1388
1441
  }
1389
1442
 
1443
+ export interface ContactWhatsapp {
1444
+ /** Business-scoped user ID. Can be used as `to` when sending. */
1445
+ bsuid: string;
1446
+ /** The WhatsApp username, when Meta reported one. */
1447
+ username?: string;
1448
+ }
1449
+
1390
1450
  export type ContactDefaultChannel =
1391
1451
  | 'sms'
1392
1452
  | 'whatsapp'
@@ -3112,12 +3172,19 @@ export interface TenDlcBrandCreateRequest {
3112
3172
  displayName: string;
3113
3173
  /** Legal company name. */
3114
3174
  companyName?: string;
3115
- /** Employer Identification Number (format: XX-XXXXXXX). */
3175
+ /**
3176
+ * Employer Identification Number (format: XX-XXXXXXX). Required to submit every
3177
+ * entity type except `SOLE_PROPRIETOR`: a brand without it can be created as a
3178
+ * draft, and `POST /v1/10dlc/brands/{brandId}/submit` refuses it with `400`.
3179
+ */
3116
3180
  ein?: string;
3117
3181
  firstName?: string;
3118
3182
  lastName?: string;
3119
3183
  email: string;
3120
- /** Contact phone in E.164 format. */
3184
+ /**
3185
+ * Contact phone in E.164 format. For a `SOLE_PROPRIETOR`, a mobile number: the
3186
+ * carrier texts a verification code to it.
3187
+ */
3121
3188
  phone: string;
3122
3189
  street: string;
3123
3190
  city: string;
@@ -4767,6 +4834,13 @@ export interface ContactsListParams {
4767
4834
  * start a new pagination run when the search term changes.
4768
4835
  */
4769
4836
  search?: string;
4837
+ /**
4838
+ * Exact WhatsApp business-scoped user ID (e.g. `CO.13491208655302741918`). Returns
4839
+ * the contact that holds it, or an empty list. Combines with `phoneNumber` and
4840
+ * `tag` as a filter, and cannot be combined with `search` (400). A value that is
4841
+ * not shaped like a BSUID returns 400.
4842
+ */
4843
+ bsuid?: string;
4770
4844
  /**
4771
4845
  * Tag name. Repeatable: `?tag=vip&tag=chile` returns contacts carrying **every**
4772
4846
  * tag given, not any of them — the same rule the dashboard filter applies.
package/src/v2/types.ts CHANGED
@@ -652,6 +652,13 @@ export interface Contact {
652
652
  countryCode?: string;
653
653
  /** Contact's WhatsApp profile name. Only available for WhatsApp contacts. */
654
654
  profileName?: string | null;
655
+ /**
656
+ * WhatsApp identity. Present when Zavu has a business-scoped user ID (BSUID) for
657
+ * the contact, and absent otherwise. A contact with a username can be reached
658
+ * under its BSUID, its phone number, or both; they are the same contact. Look one
659
+ * up by BSUID with the `bsuid` query parameter of the list endpoint.
660
+ */
661
+ whatsapp?: ContactWhatsapp;
655
662
  /** List of available messaging channels for this contact. */
656
663
  availableChannels: Array<string>;
657
664
  /** Preferred channel for this contact. */
@@ -665,6 +672,13 @@ export interface Contact {
665
672
  updatedAt?: string;
666
673
  }
667
674
 
675
+ export interface ContactWhatsapp {
676
+ /** Business-scoped user ID. Can be used as `to` when sending. */
677
+ bsuid: string;
678
+ /** The WhatsApp username, when Meta reported one. */
679
+ username?: string;
680
+ }
681
+
668
682
  export type ContactDefaultChannel =
669
683
  | 'sms'
670
684
  | 'whatsapp'
@@ -1684,11 +1698,16 @@ export interface TemplateSubmitRequest {
1684
1698
  * **Inbound events:**
1685
1699
  * - `message.inbound`: New message received from a contact. `data.conversationId`,
1686
1700
  * the inbox thread id (deep-link with
1687
- * `https://dashboard.zavu.dev/{locale}/inbox?conv={conversationId}`), is sent on
1688
- * **email** messages only, and is `null` there on the first message of a
1689
- * brand-new thread. On every other channel it is absent: read it from `GET
1690
- * /v2/messages/{messageId}`, which always has it, or from `conversation.new` for
1691
- * a new contact. Reactions are delivered as `message.inbound` with
1701
+ * `https://dashboard.zavu.dev/{locale}/inbox?conv={conversationId}`), is always
1702
+ * set: the webhook is sent once the message has been filed in its thread, so the
1703
+ * first message of a new thread carries the same id as `conversation.new`.
1704
+ * `data.contactId` is the Zavu contact, and unlike `data.from` it does not
1705
+ * change when a WhatsApp contact's identifier switches from a business-scoped
1706
+ * user ID (BSUID) to a phone number, unless the switch reveals two contacts for
1707
+ * one person; they are then merged and `contact.identity_linked` names the one
1708
+ * that went away in `mergedContactId`. On WhatsApp, `data.whatsapp` carries the
1709
+ * contact's `bsuid` and `username` when known. Reactions carry none of these
1710
+ * three. Reactions are delivered as `message.inbound` with
1692
1711
  * `messageType='reaction'`. When the contact replied to (quoted) an earlier
1693
1712
  * message, `data.content` carries the reply context: `replyToMessageId`,
1694
1713
  * `replyToProviderMessageId`, `replyToFrom`, `replyToText`, and
@@ -1714,6 +1733,21 @@ export interface TemplateSubmitRequest {
1714
1733
  * `https://dashboard.zavu.dev/{locale}/inbox?conv={conversationId}`), the
1715
1734
  * `phoneNumber` or `email` key, `channel`, `firstMessageId`, `firstMessageText`,
1716
1735
  * and `profileName`.
1736
+ * - `contact.identity_linked`: A WhatsApp contact known by BSUID was tied to a
1737
+ * phone number, a contact known by phone received a BSUID, or a contact changed
1738
+ * their number. `data` carries `contactId`, `bsuid`, `phoneNumber` and `reason`:
1739
+ * `provider_reported` (WhatsApp sent the phone and the BSUID together on an
1740
+ * inbound message), `contact_shared` (the contact shared their phone number in
1741
+ * reply to a `request_contact_info` message), `phone_changed` (the contact
1742
+ * changed their number; `previousPhoneNumber` carries the old one, and `bsuid`
1743
+ * is `null` when WhatsApp never reported one for the contact), or
1744
+ * `bsuid_changed` (WhatsApp reported a new BSUID for the same number).
1745
+ * `contactId` is the contact that remains if two were merged, and
1746
+ * `mergedContactId` the one folded into it. `previousBsuid` is a BSUID you may
1747
+ * have stored that no longer identifies the contact. Sent once per link, not on
1748
+ * every message. `data.from` on `message.inbound` is the phone only when
1749
+ * WhatsApp includes it, so it can still be the BSUID afterwards; key on
1750
+ * `contactId`.
1717
1751
  * - `template.status_changed`: WhatsApp template approval status changed. `data`
1718
1752
  * carries `templateId`, `name`, `previousStatus`, `currentStatus`,
1719
1753
  * `rejectionReason`, and `category` — the category Meta currently bills the
@@ -1773,6 +1807,7 @@ export type WebhookEvent =
1773
1807
  | 'message.unsupported'
1774
1808
  | 'broadcast.status_changed'
1775
1809
  | 'conversation.new'
1810
+ | 'contact.identity_linked'
1776
1811
  | 'template.status_changed'
1777
1812
  | 'invitation.status_changed'
1778
1813
  | 'call.initiated'
@@ -1805,14 +1840,29 @@ export interface WebhookMessageData {
1805
1840
  messageType?: MessageType;
1806
1841
  /**
1807
1842
  * ID of the conversation (inbox thread) this message belongs to. Sent on
1808
- * `message.inbound` for **email** messages only; on SMS, WhatsApp, Telegram,
1809
- * Instagram and Messenger it is absent. Use it to deep-link to the dashboard
1810
- * inbox: `https://dashboard.zavu.dev/{locale}/inbox?conv={conversationId}`. On
1811
- * email it is `null` on the first message of a brand-new thread. In every case,
1812
- * fetch it via `GET /v2/messages/{messageId}`, whose `conversationId` is always
1813
- * populated, or take it from the `conversation.new` event for a new contact.
1843
+ * `message.inbound` on every channel, except for reactions. Use it to deep-link to
1844
+ * the dashboard inbox:
1845
+ * `https://dashboard.zavu.dev/{locale}/inbox?conv={conversationId}`. The webhook
1846
+ * is sent once the message has been filed in its thread, so this is always the
1847
+ * thread the message is in: on the first message of a new thread it is the id
1848
+ * `conversation.new` carries, and on the WhatsApp message that ties a BSUID to a
1849
+ * phone number it is the thread that remains once the two are joined.
1814
1850
  */
1815
1851
  conversationId?: string | null;
1852
+ /**
1853
+ * ID of the Zavu contact that sent the message. Sent on `message.inbound` on every
1854
+ * channel, except for reactions. It does not change when a WhatsApp contact's
1855
+ * `from` switches from a business-scoped user ID (BSUID) to a phone number, so use
1856
+ * it, not `from`, as your key for the person. `null` only when no contact could be
1857
+ * resolved.
1858
+ */
1859
+ contactId?: string | null;
1860
+ /**
1861
+ * WhatsApp identity of the sender. Present on WhatsApp `message.inbound` when Zavu
1862
+ * knows the sender's business-scoped user ID (BSUID), and absent otherwise. Same
1863
+ * shape as `whatsapp` on a contact or a conversation.
1864
+ */
1865
+ whatsapp?: WebhookMessageDataWhatsapp;
1816
1866
  /**
1817
1867
  * Text body or media caption. Present on `message.inbound` when the message has
1818
1868
  * text.
@@ -1840,6 +1890,16 @@ export interface WebhookMessageData {
1840
1890
  referral?: AdReferral;
1841
1891
  }
1842
1892
 
1893
+ export interface WebhookMessageDataWhatsapp {
1894
+ /**
1895
+ * Business-scoped user ID. Stable for the person on your WhatsApp Business
1896
+ * Account, whether or not `from` is a phone number.
1897
+ */
1898
+ bsuid: string;
1899
+ /** The WhatsApp username, when the sender has one and Meta reported it. */
1900
+ username?: string;
1901
+ }
1902
+
1843
1903
  /**
1844
1904
  * What a `POST` to your /v2 webhook carries. Signed like every Zavu webhook
1845
1905
  * (`X-Zavu-Signature`, with the webhook's `signatureVersion`); the event name is
@@ -2323,6 +2383,13 @@ export interface ConversationsListMessagesParams {
2323
2383
  /** Params for `contacts.list`. */
2324
2384
  export interface ContactsListParams {
2325
2385
  search?: string;
2386
+ /**
2387
+ * Exact WhatsApp business-scoped user ID (e.g. `CO.13491208655302741918`). Returns
2388
+ * the contact that holds it, or an empty list. Combines with `phoneNumber` and
2389
+ * `tag` as a filter, and cannot be combined with `search` (400). A value that is
2390
+ * not shaped like a BSUID returns 400.
2391
+ */
2392
+ bsuid?: string;
2326
2393
  tag?: Array<string>;
2327
2394
  /** @defaultValue `50` */
2328
2395
  limit?: number;
package/src/version.ts CHANGED
@@ -1,3 +1,3 @@
1
1
  // Generated by zavu-codegen from apps/docs/openapi.json. Do not edit: run `bun run codegen`.
2
2
 
3
- export const VERSION = '0.59.1'; // x-release-please-version
3
+ export const VERSION = '0.60.0'; // x-release-please-version
package/types.d.mts CHANGED
@@ -844,11 +844,16 @@ export type TemplateCreateRequestButtonsItemOtpType = 'COPY_CODE' | 'ONE_TAP';
844
844
  * **Inbound events:**
845
845
  * - `message.inbound`: New message received from a contact. `data.conversationId`,
846
846
  * the inbox thread id (deep-link with
847
- * `https://dashboard.zavu.dev/{locale}/inbox?conv={conversationId}`), is sent on
848
- * **email** messages only, and is `null` there on the first message of a
849
- * brand-new thread. On every other channel it is absent: read it from `GET
850
- * /v1/messages/{messageId}`, which always has it, or from `conversation.new` for
851
- * a new contact. Reactions are delivered as `message.inbound` with
847
+ * `https://dashboard.zavu.dev/{locale}/inbox?conv={conversationId}`), is always
848
+ * set: the webhook is sent once the message has been filed in its thread, so the
849
+ * first message of a new thread carries the same id as `conversation.new`.
850
+ * `data.contactId` is the Zavu contact, and unlike `data.from` it does not
851
+ * change when a WhatsApp contact's identifier switches from a business-scoped
852
+ * user ID (BSUID) to a phone number, unless the switch reveals two contacts for
853
+ * one person; they are then merged and `contact.identity_linked` names the one
854
+ * that went away in `mergedContactId`. On WhatsApp, `data.whatsapp` carries the
855
+ * contact's `bsuid` and `username` when known. Reactions carry none of these
856
+ * three. Reactions are delivered as `message.inbound` with
852
857
  * `messageType='reaction'`. When the contact replied to (quoted) an earlier
853
858
  * message, `data.content` carries the reply context: `replyToMessageId`,
854
859
  * `replyToProviderMessageId`, `replyToFrom`, `replyToText`, and
@@ -874,6 +879,21 @@ export type TemplateCreateRequestButtonsItemOtpType = 'COPY_CODE' | 'ONE_TAP';
874
879
  * `https://dashboard.zavu.dev/{locale}/inbox?conv={conversationId}`), the
875
880
  * `phoneNumber` or `email` key, `channel`, `firstMessageId`, `firstMessageText`,
876
881
  * and `profileName`.
882
+ * - `contact.identity_linked`: A WhatsApp contact known by BSUID was tied to a
883
+ * phone number, a contact known by phone received a BSUID, or a contact changed
884
+ * their number. `data` carries `contactId`, `bsuid`, `phoneNumber` and `reason`:
885
+ * `provider_reported` (WhatsApp sent the phone and the BSUID together on an
886
+ * inbound message), `contact_shared` (the contact shared their phone number in
887
+ * reply to a `request_contact_info` message), `phone_changed` (the contact
888
+ * changed their number; `previousPhoneNumber` carries the old one, and `bsuid`
889
+ * is `null` when WhatsApp never reported one for the contact), or
890
+ * `bsuid_changed` (WhatsApp reported a new BSUID for the same number).
891
+ * `contactId` is the contact that remains if two were merged, and
892
+ * `mergedContactId` the one folded into it. `previousBsuid` is a BSUID you may
893
+ * have stored that no longer identifies the contact. Sent once per link, not on
894
+ * every message. `data.from` on `message.inbound` is the phone only when
895
+ * WhatsApp includes it, so it can still be the BSUID afterwards; key on
896
+ * `contactId`.
877
897
  * - `template.status_changed`: WhatsApp template approval status changed. `data`
878
898
  * carries `templateId`, `name`, `previousStatus`, `currentStatus`,
879
899
  * `rejectionReason`, and `category` — the category Meta currently bills the
@@ -924,7 +944,7 @@ export type TemplateCreateRequestButtonsItemOtpType = 'COPY_CODE' | 'ONE_TAP';
924
944
  * - `domain.failed`: A custom email domain failed verification or is partially
925
945
  * verified
926
946
  */
927
- export type WebhookEvent = 'message.queued' | 'message.sent' | 'message.delivered' | 'message.read' | 'message.status' | 'message.failed' | 'message.inbound' | 'message.unsupported' | 'broadcast.status_changed' | 'conversation.new' | 'template.status_changed' | 'invitation.status_changed' | 'call.initiated' | 'call.answered' | 'call.completed' | 'call.failed' | 'domain.verified' | 'domain.failed';
947
+ export type WebhookEvent = 'message.queued' | 'message.sent' | 'message.delivered' | 'message.read' | 'message.status' | 'message.failed' | 'message.inbound' | 'message.unsupported' | 'broadcast.status_changed' | 'conversation.new' | 'contact.identity_linked' | 'template.status_changed' | 'invitation.status_changed' | 'call.initiated' | 'call.answered' | 'call.completed' | 'call.failed' | 'domain.verified' | 'domain.failed';
928
948
  /** Webhook payload structure sent to your endpoint. */
929
949
  export interface WebhookPayload {
930
950
  /** Unique event identifier. */
@@ -967,14 +987,29 @@ export interface WebhookMessageData {
967
987
  messageType?: MessageType;
968
988
  /**
969
989
  * ID of the conversation (inbox thread) this message belongs to. Sent on
970
- * `message.inbound` for **email** messages only; on SMS, WhatsApp, Telegram,
971
- * Instagram and Messenger it is absent. Use it to deep-link to the dashboard
972
- * inbox: `https://dashboard.zavu.dev/{locale}/inbox?conv={conversationId}`. On
973
- * email it is `null` on the first message of a brand-new thread. In every case,
974
- * fetch it via `GET /v1/messages/{messageId}`, whose `conversationId` is always
975
- * populated, or take it from the `conversation.new` event for a new contact.
990
+ * `message.inbound` on every channel, except for reactions. Use it to deep-link to
991
+ * the dashboard inbox:
992
+ * `https://dashboard.zavu.dev/{locale}/inbox?conv={conversationId}`. The webhook
993
+ * is sent once the message has been filed in its thread, so this is always the
994
+ * thread the message is in: on the first message of a new thread it is the id
995
+ * `conversation.new` carries, and on the WhatsApp message that ties a BSUID to a
996
+ * phone number it is the thread that remains once the two are joined.
976
997
  */
977
998
  conversationId?: string | null;
999
+ /**
1000
+ * ID of the Zavu contact that sent the message. Sent on `message.inbound` on every
1001
+ * channel, except for reactions. It does not change when a WhatsApp contact's
1002
+ * `from` switches from a business-scoped user ID (BSUID) to a phone number, so use
1003
+ * it, not `from`, as your key for the person. `null` only when no contact could be
1004
+ * resolved.
1005
+ */
1006
+ contactId?: string | null;
1007
+ /**
1008
+ * WhatsApp identity of the sender. Present on WhatsApp `message.inbound` when Zavu
1009
+ * knows the sender's business-scoped user ID (BSUID), and absent otherwise. Same
1010
+ * shape as `whatsapp` on a contact or a conversation.
1011
+ */
1012
+ whatsapp?: WebhookMessageDataWhatsapp;
978
1013
  /**
979
1014
  * Text body or media caption. Present on `message.inbound` when the message has
980
1015
  * text.
@@ -1001,6 +1036,15 @@ export interface WebhookMessageData {
1001
1036
  */
1002
1037
  referral?: AdReferral;
1003
1038
  }
1039
+ export interface WebhookMessageDataWhatsapp {
1040
+ /**
1041
+ * Business-scoped user ID. Stable for the person on your WhatsApp Business
1042
+ * Account, whether or not `from` is a phone number.
1043
+ */
1044
+ bsuid: string;
1045
+ /** The WhatsApp username, when the sender has one and Meta reported it. */
1046
+ username?: string;
1047
+ }
1004
1048
  /** Webhook configuration for the sender. */
1005
1049
  export interface SenderWebhook {
1006
1050
  /** HTTPS URL that will receive webhook events. */
@@ -1258,6 +1302,13 @@ export interface Contact {
1258
1302
  countryCode?: string;
1259
1303
  /** Contact's WhatsApp profile name. Only available for WhatsApp contacts. */
1260
1304
  profileName?: string | null;
1305
+ /**
1306
+ * WhatsApp identity. Present when Zavu has a business-scoped user ID (BSUID) for
1307
+ * the contact, and absent otherwise. A contact with a username can be reached
1308
+ * under its BSUID, its phone number, or both; they are the same contact. Look one
1309
+ * up by BSUID with the `bsuid` query parameter of the list endpoint.
1310
+ */
1311
+ whatsapp?: ContactWhatsapp;
1261
1312
  /** List of available messaging channels for this contact. */
1262
1313
  availableChannels: Array<string>;
1263
1314
  /** Preferred channel for this contact. */
@@ -1272,6 +1323,12 @@ export interface Contact {
1272
1323
  createdAt: string;
1273
1324
  updatedAt?: string;
1274
1325
  }
1326
+ export interface ContactWhatsapp {
1327
+ /** Business-scoped user ID. Can be used as `to` when sending. */
1328
+ bsuid: string;
1329
+ /** The WhatsApp username, when Meta reported one. */
1330
+ username?: string;
1331
+ }
1275
1332
  export type ContactDefaultChannel = 'sms' | 'whatsapp' | 'telegram' | 'email' | 'instagram' | 'messenger' | 'voice';
1276
1333
  export interface ContactUpdateRequest {
1277
1334
  /**
@@ -2791,12 +2848,19 @@ export interface TenDlcBrandCreateRequest {
2791
2848
  displayName: string;
2792
2849
  /** Legal company name. */
2793
2850
  companyName?: string;
2794
- /** Employer Identification Number (format: XX-XXXXXXX). */
2851
+ /**
2852
+ * Employer Identification Number (format: XX-XXXXXXX). Required to submit every
2853
+ * entity type except `SOLE_PROPRIETOR`: a brand without it can be created as a
2854
+ * draft, and `POST /v1/10dlc/brands/{brandId}/submit` refuses it with `400`.
2855
+ */
2795
2856
  ein?: string;
2796
2857
  firstName?: string;
2797
2858
  lastName?: string;
2798
2859
  email: string;
2799
- /** Contact phone in E.164 format. */
2860
+ /**
2861
+ * Contact phone in E.164 format. For a `SOLE_PROPRIETOR`, a mobile number: the
2862
+ * carrier texts a verification code to it.
2863
+ */
2800
2864
  phone: string;
2801
2865
  street: string;
2802
2866
  city: string;
@@ -4266,6 +4330,13 @@ export interface ContactsListParams {
4266
4330
  * start a new pagination run when the search term changes.
4267
4331
  */
4268
4332
  search?: string;
4333
+ /**
4334
+ * Exact WhatsApp business-scoped user ID (e.g. `CO.13491208655302741918`). Returns
4335
+ * the contact that holds it, or an empty list. Combines with `phoneNumber` and
4336
+ * `tag` as a filter, and cannot be combined with `search` (400). A value that is
4337
+ * not shaped like a BSUID returns 400.
4338
+ */
4339
+ bsuid?: string;
4269
4340
  /**
4270
4341
  * Tag name. Repeatable: `?tag=vip&tag=chile` returns contacts carrying **every**
4271
4342
  * tag given, not any of them — the same rule the dashboard filter applies.