@unboundcx/sdk 4.13.5 → 4.13.7

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@unboundcx/sdk",
3
- "version": "4.13.5",
3
+ "version": "4.13.7",
4
4
  "description": "Official JavaScript SDK for the Unbound API - A comprehensive toolkit for integrating with Unbound's communication, AI, and data management services",
5
5
  "main": "index.js",
6
6
  "type": "module",
package/services/chat.js CHANGED
@@ -1016,15 +1016,16 @@ export class ChatService {
1016
1016
  }
1017
1017
 
1018
1018
  /**
1019
- * Admin: list moderation cases (permanent hide/disposition history).
1019
+ * Admin: list moderation dispositions (permanent per-message
1020
+ * hide/disposition history — one row per message).
1020
1021
  * @param {Object} [params]
1021
1022
  * @param {'open'|'closed'|'all'} [params.status]
1022
1023
  * @param {string} [params.authorId]
1023
- * @param {string} [params.nextId] Pagination cursor (case id)
1024
+ * @param {string} [params.nextId] Pagination cursor (disposition id)
1024
1025
  * @param {number} [params.limit]
1025
1026
  * @returns {Promise<Object>} `{results, hasMore, nextId}`
1026
1027
  */
1027
- async adminListCases({ status, authorId, nextId, limit } = {}) {
1028
+ async adminListDispositions({ status, authorId, nextId, limit } = {}) {
1028
1029
  this.sdk.validateParams(
1029
1030
  { status, authorId, nextId, limit },
1030
1031
  {
@@ -1039,12 +1040,90 @@ export class ChatService {
1039
1040
  if (authorId !== undefined) query.authorId = authorId;
1040
1041
  if (nextId !== undefined) query.nextId = nextId;
1041
1042
  if (limit !== undefined) query.limit = limit;
1043
+ return internalRequest(this.sdk, "/chat/admin/dispositions", "GET", {
1044
+ query,
1045
+ });
1046
+ }
1047
+
1048
+ /**
1049
+ * Admin: get one moderation disposition — hydrated with its message
1050
+ * (content per the usual rules) and reports.
1051
+ * @param {string} id
1052
+ * @returns {Promise<Object>}
1053
+ */
1054
+ async adminGetDisposition(id) {
1055
+ this.sdk.validateParams({ id }, { id: { type: "string", required: true } });
1056
+ return internalRequest(this.sdk, `/chat/admin/dispositions/${id}`, "GET");
1057
+ }
1058
+
1059
+ /**
1060
+ * Admin: list chat cases (multi-message investigations — distinct from
1061
+ * the per-message disposition ledger above).
1062
+ * @param {Object} [params]
1063
+ * @param {'open'|'in_review'|'closed'|'all'} [params.status]
1064
+ * @param {string} [params.category]
1065
+ * @param {string} [params.ownerId]
1066
+ * @param {string} [params.q] Substring match on title
1067
+ * @param {string} [params.nextId] Pagination cursor (case id)
1068
+ * @param {number} [params.limit]
1069
+ * @returns {Promise<Object>} `{results, hasMore, nextId}` — each result
1070
+ * includes `itemCount`, `noteCount`, `lastActivityAt`
1071
+ */
1072
+ async adminListCases({ status, category, ownerId, q, nextId, limit } = {}) {
1073
+ this.sdk.validateParams(
1074
+ { status, category, ownerId, q, nextId, limit },
1075
+ {
1076
+ status: { type: "string", required: false },
1077
+ category: { type: "string", required: false },
1078
+ ownerId: { type: "string", required: false },
1079
+ q: { type: "string", required: false },
1080
+ nextId: { type: "string", required: false },
1081
+ limit: { type: "number", required: false },
1082
+ },
1083
+ );
1084
+ const query = {};
1085
+ if (status !== undefined) query.status = status;
1086
+ if (category !== undefined) query.category = category;
1087
+ if (ownerId !== undefined) query.ownerId = ownerId;
1088
+ if (q !== undefined) query.q = q;
1089
+ if (nextId !== undefined) query.nextId = nextId;
1090
+ if (limit !== undefined) query.limit = limit;
1042
1091
  return internalRequest(this.sdk, "/chat/admin/cases", "GET", { query });
1043
1092
  }
1044
1093
 
1045
1094
  /**
1046
- * Admin: get one moderation case hydrated with its message (content
1047
- * per the usual rules) and reports.
1095
+ * Admin: create a chat case, optionally seeding it with messages
1096
+ * (report ids on those messages are auto-attached to the created item).
1097
+ * @param {Object} params
1098
+ * @param {string} params.title
1099
+ * @param {string} [params.category]
1100
+ * @param {string} [params.description]
1101
+ * @param {string} [params.ownerId]
1102
+ * @param {string[]} [params.messageIds]
1103
+ * @returns {Promise<Object>} the case, plus `items`/`notes`
1104
+ */
1105
+ async adminCreateCase({ title, category, description, ownerId, messageIds }) {
1106
+ this.sdk.validateParams(
1107
+ { title, category, description, ownerId, messageIds },
1108
+ {
1109
+ title: { type: "string", required: true },
1110
+ category: { type: "string", required: false },
1111
+ description: { type: "string", required: false },
1112
+ ownerId: { type: "string", required: false },
1113
+ messageIds: { type: "array", required: false },
1114
+ },
1115
+ );
1116
+ const body = { title };
1117
+ if (category !== undefined) body.category = category;
1118
+ if (description !== undefined) body.description = description;
1119
+ if (ownerId !== undefined) body.ownerId = ownerId;
1120
+ if (messageIds !== undefined) body.messageIds = messageIds;
1121
+ return internalRequest(this.sdk, "/chat/admin/cases", "POST", { body });
1122
+ }
1123
+
1124
+ /**
1125
+ * Admin: get one chat case — hydrated with its items (each with
1126
+ * message/channel/reports/disposition) and its note trail.
1048
1127
  * @param {string} id
1049
1128
  * @returns {Promise<Object>}
1050
1129
  */
@@ -1053,6 +1132,166 @@ export class ChatService {
1053
1132
  return internalRequest(this.sdk, `/chat/admin/cases/${id}`, "GET");
1054
1133
  }
1055
1134
 
1135
+ /**
1136
+ * Admin: update a chat case's fields. `status` may only move between
1137
+ * 'open' and 'in_review' here — use adminCloseCase/adminReopenCase to
1138
+ * close or reopen.
1139
+ * @param {string} id
1140
+ * @param {Object} params
1141
+ * @param {string} [params.title]
1142
+ * @param {string} [params.category]
1143
+ * @param {string} [params.description]
1144
+ * @param {string} [params.ownerId]
1145
+ * @param {'open'|'in_review'} [params.status]
1146
+ * @returns {Promise<Object>}
1147
+ */
1148
+ async adminUpdateCase(id, { title, category, description, ownerId, status } = {}) {
1149
+ this.sdk.validateParams(
1150
+ { id, title, category, description, ownerId, status },
1151
+ {
1152
+ id: { type: "string", required: true },
1153
+ title: { type: "string", required: false },
1154
+ category: { type: "string", required: false },
1155
+ description: { type: "string", required: false },
1156
+ ownerId: { type: "string", required: false },
1157
+ status: { type: "string", required: false },
1158
+ },
1159
+ );
1160
+ const body = {};
1161
+ if (title !== undefined) body.title = title;
1162
+ if (category !== undefined) body.category = category;
1163
+ if (description !== undefined) body.description = description;
1164
+ if (ownerId !== undefined) body.ownerId = ownerId;
1165
+ if (status !== undefined) body.status = status;
1166
+ return internalRequest(this.sdk, `/chat/admin/cases/${id}`, "PATCH", {
1167
+ body,
1168
+ });
1169
+ }
1170
+
1171
+ /**
1172
+ * Admin: attach messages to a case (reportIds auto-filled from each
1173
+ * message's open reports). Messages already on the case are skipped.
1174
+ * @param {string} id
1175
+ * @param {Object} params
1176
+ * @param {string[]} params.messageIds
1177
+ * @returns {Promise<Object>}
1178
+ */
1179
+ async adminAddCaseItems(id, { messageIds }) {
1180
+ this.sdk.validateParams(
1181
+ { id, messageIds },
1182
+ {
1183
+ id: { type: "string", required: true },
1184
+ messageIds: { type: "array", required: true },
1185
+ },
1186
+ );
1187
+ return internalRequest(this.sdk, `/chat/admin/cases/${id}/items`, "POST", {
1188
+ body: { messageIds },
1189
+ });
1190
+ }
1191
+
1192
+ /**
1193
+ * Admin: remove one message from a case.
1194
+ * @param {string} id
1195
+ * @param {string} messageId
1196
+ * @returns {Promise<Object>}
1197
+ */
1198
+ async adminRemoveCaseItem(id, messageId) {
1199
+ this.sdk.validateParams(
1200
+ { id, messageId },
1201
+ {
1202
+ id: { type: "string", required: true },
1203
+ messageId: { type: "string", required: true },
1204
+ },
1205
+ );
1206
+ return internalRequest(
1207
+ this.sdk,
1208
+ `/chat/admin/cases/${id}/items/${messageId}`,
1209
+ "DELETE",
1210
+ );
1211
+ }
1212
+
1213
+ /**
1214
+ * Admin: add a note to a case.
1215
+ * @param {string} id
1216
+ * @param {Object} params
1217
+ * @param {string} params.body
1218
+ * @returns {Promise<Object>}
1219
+ */
1220
+ async adminAddCaseNote(id, { body }) {
1221
+ this.sdk.validateParams(
1222
+ { id, body },
1223
+ {
1224
+ id: { type: "string", required: true },
1225
+ body: { type: "string", required: true },
1226
+ },
1227
+ );
1228
+ return internalRequest(this.sdk, `/chat/admin/cases/${id}/notes`, "POST", {
1229
+ body: { body },
1230
+ });
1231
+ }
1232
+
1233
+ /**
1234
+ * Admin: close a case with a required outcome and note. Appends a
1235
+ * system note to the case.
1236
+ * @param {string} id
1237
+ * @param {Object} params
1238
+ * @param {'no_action'|'warned'|'escalated_hr'|'content_removed'|'other'} params.outcome
1239
+ * @param {string} params.note
1240
+ * @returns {Promise<Object>}
1241
+ */
1242
+ async adminCloseCase(id, { outcome, note }) {
1243
+ this.sdk.validateParams(
1244
+ { id, outcome, note },
1245
+ {
1246
+ id: { type: "string", required: true },
1247
+ outcome: { type: "string", required: true },
1248
+ note: { type: "string", required: true },
1249
+ },
1250
+ );
1251
+ return internalRequest(this.sdk, `/chat/admin/cases/${id}/close`, "POST", {
1252
+ body: { outcome, note },
1253
+ });
1254
+ }
1255
+
1256
+ /**
1257
+ * Admin: reopen a closed case with a required reason. Clears
1258
+ * outcome/closedAt/closedBy/closeNote and appends a system note.
1259
+ * @param {string} id
1260
+ * @param {Object} params
1261
+ * @param {string} params.reason
1262
+ * @returns {Promise<Object>}
1263
+ */
1264
+ async adminReopenCase(id, { reason }) {
1265
+ this.sdk.validateParams(
1266
+ { id, reason },
1267
+ {
1268
+ id: { type: "string", required: true },
1269
+ reason: { type: "string", required: true },
1270
+ },
1271
+ );
1272
+ return internalRequest(this.sdk, `/chat/admin/cases/${id}/reopen`, "POST", {
1273
+ body: { reason },
1274
+ });
1275
+ }
1276
+
1277
+ /**
1278
+ * Admin: list the chat cases a message is linked to (for a report/
1279
+ * flagged-message "Add to case" affordance).
1280
+ * @param {string} messageId
1281
+ * @returns {Promise<Object>} `{results}`
1282
+ */
1283
+ async adminListMessageCases(messageId) {
1284
+ this.sdk.validateParams(
1285
+ { messageId },
1286
+ { messageId: { type: "string", required: true } },
1287
+ );
1288
+ return internalRequest(
1289
+ this.sdk,
1290
+ `/chat/admin/messages/${messageId}/cases`,
1291
+ "GET",
1292
+ );
1293
+ }
1294
+
1056
1295
  /**
1057
1296
  * Admin: audit log of review actions.
1058
1297
  * @returns {Promise<Object>}
@@ -0,0 +1,60 @@
1
+ import { internalRequest } from '../../base.js';
2
+
3
+ /**
4
+ * Account-level email settings (plan §3.3) — auto-create-mailbox policy
5
+ * and the default domain new mailboxes/aliases are suggested on. Exposed
6
+ * as `sdk.messaging.email.settings`.
7
+ */
8
+ export class EmailAccountSettingsService {
9
+ constructor(sdk) {
10
+ this.sdk = sdk;
11
+ }
12
+
13
+ /**
14
+ * Get the account's email settings
15
+ * @returns {Promise<Object>} { autoCreateUserMailbox, userMailboxAddressTemplate, defaultEmailDomainId, updatedAt, updatedBy }
16
+ * @example
17
+ * const settings = await sdk.messaging.email.settings.get();
18
+ */
19
+ async get() {
20
+ return internalRequest(this.sdk, '/messaging/email/settings', 'GET');
21
+ }
22
+
23
+ /**
24
+ * Update the account's email settings (admin only)
25
+ * @param {boolean} [autoCreateUserMailbox] - Auto-create a dedicated mailbox for new users
26
+ * @param {string} [userMailboxAddressTemplate] - Address template, e.g. '{first}.{last}' (tokens: {first},{last},{f},{username})
27
+ * @param {string} [defaultEmailDomainId] - Verified domain used for auto-created mailboxes and alias suggestions
28
+ * @returns {Promise<Object>} { message }
29
+ * @example
30
+ * await sdk.messaging.email.settings.update({
31
+ * autoCreateUserMailbox: true,
32
+ * defaultEmailDomainId: 'domain123',
33
+ * });
34
+ */
35
+ async update({
36
+ autoCreateUserMailbox,
37
+ userMailboxAddressTemplate,
38
+ defaultEmailDomainId,
39
+ } = {}) {
40
+ this.sdk.validateParams(
41
+ { autoCreateUserMailbox, userMailboxAddressTemplate, defaultEmailDomainId },
42
+ {
43
+ autoCreateUserMailbox: { type: 'boolean', required: false },
44
+ userMailboxAddressTemplate: { type: 'string', required: false },
45
+ defaultEmailDomainId: { type: 'string', required: false },
46
+ },
47
+ );
48
+ const body = {};
49
+ if (autoCreateUserMailbox !== undefined)
50
+ body.autoCreateUserMailbox = autoCreateUserMailbox;
51
+ if (userMailboxAddressTemplate !== undefined)
52
+ body.userMailboxAddressTemplate = userMailboxAddressTemplate;
53
+ if (defaultEmailDomainId !== undefined)
54
+ body.defaultEmailDomainId = defaultEmailDomainId;
55
+
56
+ return internalRequest(this.sdk, '/messaging/email/settings', 'PUT', {
57
+ body,
58
+ });
59
+ }
60
+ }
@@ -0,0 +1,69 @@
1
+ import { internalRequest } from '../../base.js';
2
+
3
+ /**
4
+ * Alias suggestion/availability helpers for mailbox creation (plan §4) —
5
+ * mirrors the Extension field UX in UserCreateFormFields.svelte. Exposed
6
+ * as `sdk.messaging.email.mailboxes.aliasSuggest` /
7
+ * `sdk.messaging.email.mailboxes.aliasAvailable`.
8
+ */
9
+ export class EmailAliasSuggestService {
10
+ constructor(sdk) {
11
+ this.sdk = sdk;
12
+ }
13
+
14
+ /**
15
+ * Suggest an available localpart for a user's mailbox on the account's default domain
16
+ * @param {string} [firstName] - User's first name
17
+ * @param {string} [lastName] - User's last name
18
+ * @param {string} [username] - Fallback token source when name parts are missing
19
+ * @returns {Promise<Object>} { localpart, domain, domainId, available: true }
20
+ * @example
21
+ * const suggestion = await sdk.messaging.email.mailboxes.aliasSuggest({
22
+ * firstName: 'Jane',
23
+ * lastName: 'Doe',
24
+ * });
25
+ */
26
+ async suggest({ firstName, lastName, username } = {}) {
27
+ this.sdk.validateParams(
28
+ { firstName, lastName, username },
29
+ {
30
+ firstName: { type: 'string', required: false },
31
+ lastName: { type: 'string', required: false },
32
+ username: { type: 'string', required: false },
33
+ },
34
+ );
35
+ return internalRequest(
36
+ this.sdk,
37
+ '/messaging/email/mailbox/alias-suggest',
38
+ 'GET',
39
+ { query: { firstName, lastName, username } },
40
+ );
41
+ }
42
+
43
+ /**
44
+ * Check whether a localpart is available on a given domain
45
+ * @param {string} localpart - Localpart to check (part before @)
46
+ * @param {string} domainId - Email domain ID
47
+ * @returns {Promise<Object>} { localpart, domainId, available }
48
+ * @example
49
+ * const { available } = await sdk.messaging.email.mailboxes.aliasAvailable({
50
+ * localpart: 'jane.doe',
51
+ * domainId: 'domain123',
52
+ * });
53
+ */
54
+ async available({ localpart, domainId } = {}) {
55
+ this.sdk.validateParams(
56
+ { localpart, domainId },
57
+ {
58
+ localpart: { type: 'string', required: true },
59
+ domainId: { type: 'string', required: true },
60
+ },
61
+ );
62
+ return internalRequest(
63
+ this.sdk,
64
+ '/messaging/email/mailbox/alias-available',
65
+ 'GET',
66
+ { query: { localpart, domainId } },
67
+ );
68
+ }
69
+ }
@@ -0,0 +1,165 @@
1
+ import { internalRequest } from '../../base.js';
2
+
3
+ const VALID_ROLES = ['owner', 'full', 'send', 'read'];
4
+ const VALID_PRINCIPAL_TYPES = ['user', 'group'];
5
+ const VALID_NOTIFY_MODES = ['all', 'important', 'mute'];
6
+
7
+ /**
8
+ * Mailbox access grants (mailboxUsers_acct) — plan §3.2/§4.
9
+ * Exposed on the SDK as `sdk.messaging.email.mailboxes.access`.
10
+ */
11
+ export class EmailMailboxAccessService {
12
+ constructor(sdk) {
13
+ this.sdk = sdk;
14
+ }
15
+
16
+ /**
17
+ * List access grants (users and groups) for a mailbox
18
+ * @param {string} mailboxId - Mailbox ID
19
+ * @returns {Promise<Object>} { mailboxId, access: [{ principalType, principalId, role, name, email?, notifyMode?, ... }] }
20
+ * @example
21
+ * const { access } = await sdk.messaging.email.mailboxes.access.list('mbx123');
22
+ */
23
+ async list(mailboxId) {
24
+ this.sdk.validateParams(
25
+ { mailboxId },
26
+ { mailboxId: { type: 'string', required: true } },
27
+ );
28
+ return internalRequest(
29
+ this.sdk,
30
+ `/messaging/email/mailbox/${mailboxId}/access`,
31
+ 'GET',
32
+ );
33
+ }
34
+
35
+ /**
36
+ * Grant (or update) a user's or group's access to a mailbox
37
+ * @param {string} mailboxId - Mailbox ID
38
+ * @param {string} principalType - 'user' or 'group'
39
+ * @param {string} principalId - User ID or group ID
40
+ * @param {string} role - 'owner', 'full', 'send', or 'read'
41
+ * @param {string} [notifyMode] - 'all', 'important', or 'mute' (user rows only)
42
+ * @param {boolean} [notifyPush] - Push notifications on (user rows only, default true)
43
+ * @param {boolean} [notifyBadge] - Badge count on (user rows only, default true)
44
+ * @param {boolean} [notifySound] - Sound on (user rows only, default false)
45
+ * @returns {Promise<Object>} { mailboxId, principalType, principalId, role }
46
+ * @example
47
+ * await sdk.messaging.email.mailboxes.access.set('mbx123', 'user', 'user456', 'full');
48
+ */
49
+ async set(
50
+ mailboxId,
51
+ principalType,
52
+ principalId,
53
+ role,
54
+ { notifyMode, notifyPush, notifyBadge, notifySound } = {},
55
+ ) {
56
+ this.sdk.validateParams(
57
+ {
58
+ mailboxId,
59
+ principalType,
60
+ principalId,
61
+ role,
62
+ notifyMode,
63
+ notifyPush,
64
+ notifyBadge,
65
+ notifySound,
66
+ },
67
+ {
68
+ mailboxId: { type: 'string', required: true },
69
+ principalType: {
70
+ type: 'string',
71
+ required: true,
72
+ enum: VALID_PRINCIPAL_TYPES,
73
+ },
74
+ principalId: { type: 'string', required: true },
75
+ role: { type: 'string', required: true, enum: VALID_ROLES },
76
+ notifyMode: { type: 'string', required: false, enum: VALID_NOTIFY_MODES },
77
+ notifyPush: { type: 'boolean', required: false },
78
+ notifyBadge: { type: 'boolean', required: false },
79
+ notifySound: { type: 'boolean', required: false },
80
+ },
81
+ );
82
+
83
+ const body = { role };
84
+ if (notifyMode !== undefined) body.notifyMode = notifyMode;
85
+ if (notifyPush !== undefined) body.notifyPush = notifyPush;
86
+ if (notifyBadge !== undefined) body.notifyBadge = notifyBadge;
87
+ if (notifySound !== undefined) body.notifySound = notifySound;
88
+
89
+ return internalRequest(
90
+ this.sdk,
91
+ `/messaging/email/mailbox/${mailboxId}/access/${principalType}/${principalId}`,
92
+ 'PUT',
93
+ { body },
94
+ );
95
+ }
96
+
97
+ /**
98
+ * Remove a user's or group's access grant from a mailbox
99
+ * @param {string} mailboxId - Mailbox ID
100
+ * @param {string} principalType - 'user' or 'group'
101
+ * @param {string} principalId - User ID or group ID
102
+ * @returns {Promise<Object>} { mailboxId, principalType, principalId, message }
103
+ * @example
104
+ * await sdk.messaging.email.mailboxes.access.remove('mbx123', 'user', 'user456');
105
+ */
106
+ async remove(mailboxId, principalType, principalId) {
107
+ this.sdk.validateParams(
108
+ { mailboxId, principalType, principalId },
109
+ {
110
+ mailboxId: { type: 'string', required: true },
111
+ principalType: {
112
+ type: 'string',
113
+ required: true,
114
+ enum: VALID_PRINCIPAL_TYPES,
115
+ },
116
+ principalId: { type: 'string', required: true },
117
+ },
118
+ );
119
+ return internalRequest(
120
+ this.sdk,
121
+ `/messaging/email/mailbox/${mailboxId}/access/${principalType}/${principalId}`,
122
+ 'DELETE',
123
+ );
124
+ }
125
+
126
+ /**
127
+ * Set the caller's own notification preferences for a mailbox
128
+ * @param {string} mailboxId - Mailbox ID
129
+ * @param {string} [notifyMode] - 'all', 'important', or 'mute'
130
+ * @param {boolean} [notifyPush] - Push notifications on
131
+ * @param {boolean} [notifyBadge] - Badge count on
132
+ * @param {boolean} [notifySound] - Sound on
133
+ * @returns {Promise<Object>} Updated access row for the caller
134
+ * @example
135
+ * await sdk.messaging.email.mailboxes.access.setMyNotifications('mbx123', { notifyMode: 'important' });
136
+ */
137
+ async setMyNotifications(
138
+ mailboxId,
139
+ { notifyMode, notifyPush, notifyBadge, notifySound } = {},
140
+ ) {
141
+ this.sdk.validateParams(
142
+ { mailboxId, notifyMode, notifyPush, notifyBadge, notifySound },
143
+ {
144
+ mailboxId: { type: 'string', required: true },
145
+ notifyMode: { type: 'string', required: false, enum: VALID_NOTIFY_MODES },
146
+ notifyPush: { type: 'boolean', required: false },
147
+ notifyBadge: { type: 'boolean', required: false },
148
+ notifySound: { type: 'boolean', required: false },
149
+ },
150
+ );
151
+
152
+ const body = {};
153
+ if (notifyMode !== undefined) body.notifyMode = notifyMode;
154
+ if (notifyPush !== undefined) body.notifyPush = notifyPush;
155
+ if (notifyBadge !== undefined) body.notifyBadge = notifyBadge;
156
+ if (notifySound !== undefined) body.notifySound = notifySound;
157
+
158
+ return internalRequest(
159
+ this.sdk,
160
+ `/messaging/email/mailbox/${mailboxId}/access/me/notifications`,
161
+ 'PUT',
162
+ { body },
163
+ );
164
+ }
165
+ }
@@ -0,0 +1,67 @@
1
+ import { internalRequest } from '../../base.js';
2
+
3
+ const VALID_ROLES = ['owner', 'full', 'send', 'read'];
4
+
5
+ /**
6
+ * Shared mailboxes granted to a group (plan §3.2/§4/§6) — backs
7
+ * Setup → Groups → [id] → Shared mailboxes card. Exposed as
8
+ * `sdk.messaging.email.mailboxes.groupAccess`.
9
+ */
10
+ export class EmailMailboxGroupAccessService {
11
+ constructor(sdk) {
12
+ this.sdk = sdk;
13
+ }
14
+
15
+ /**
16
+ * List mailboxes a group has access to
17
+ * @param {string} groupId - Group ID
18
+ * @returns {Promise<Array>} [{ mailboxId, name, mailbox, role }]
19
+ * @example
20
+ * const mailboxes = await sdk.messaging.email.mailboxes.groupAccess.list('group123');
21
+ */
22
+ async list(groupId) {
23
+ this.sdk.validateParams(
24
+ { groupId },
25
+ { groupId: { type: 'string', required: true } },
26
+ );
27
+ return internalRequest(
28
+ this.sdk,
29
+ `/messaging/email/group/${groupId}/mailboxes`,
30
+ 'GET',
31
+ );
32
+ }
33
+
34
+ /**
35
+ * Replace the full set of mailboxes a group has access to
36
+ * @param {string} groupId - Group ID
37
+ * @param {Array<{mailboxId: string, role: string}>} mailboxes - Desired mailbox/role pairs (role: owner|full|send|read); entries omitted are removed
38
+ * @returns {Promise<Array>} [{ mailboxId, name, mailbox, role }]
39
+ * @example
40
+ * await sdk.messaging.email.mailboxes.groupAccess.set('group123', [
41
+ * { mailboxId: 'mbx1', role: 'full' },
42
+ * { mailboxId: 'mbx2', role: 'read' },
43
+ * ]);
44
+ */
45
+ async set(groupId, mailboxes) {
46
+ this.sdk.validateParams(
47
+ { groupId, mailboxes },
48
+ {
49
+ groupId: { type: 'string', required: true },
50
+ mailboxes: { type: 'array', required: true },
51
+ },
52
+ );
53
+ for (const entry of mailboxes) {
54
+ if (!entry?.mailboxId || !VALID_ROLES.includes(entry.role)) {
55
+ throw new Error(
56
+ `Each mailbox entry requires mailboxId and role in ${VALID_ROLES.join('|')}`,
57
+ );
58
+ }
59
+ }
60
+ return internalRequest(
61
+ this.sdk,
62
+ `/messaging/email/group/${groupId}/mailboxes`,
63
+ 'PUT',
64
+ { body: { mailboxes } },
65
+ );
66
+ }
67
+ }
@@ -0,0 +1,56 @@
1
+ import { internalRequest } from '../../base.js';
2
+
3
+ /**
4
+ * A user's dedicated mailbox (plan §4/§6) — backs Setup → Users →
5
+ * [userId] → Email tab. Exposed as `sdk.messaging.email.mailboxes.forUser`.
6
+ */
7
+ export class EmailMailboxUserService {
8
+ constructor(sdk) {
9
+ this.sdk = sdk;
10
+ }
11
+
12
+ /**
13
+ * Get a user's dedicated mailbox
14
+ * @param {string} userId - User ID
15
+ * @returns {Promise<Object>} Mailbox details, or a 404 if none exists
16
+ * @example
17
+ * const mailbox = await sdk.messaging.email.mailboxes.forUser.get('user123');
18
+ */
19
+ async get(userId) {
20
+ this.sdk.validateParams(
21
+ { userId },
22
+ { userId: { type: 'string', required: true } },
23
+ );
24
+ return internalRequest(
25
+ this.sdk,
26
+ `/messaging/email/mailbox/for-user/${userId}`,
27
+ 'GET',
28
+ );
29
+ }
30
+
31
+ /**
32
+ * Create a dedicated mailbox for a user (manual create / backfill)
33
+ * @param {string} userId - User ID
34
+ * @param {string} [emailAlias] - Localpart to use; defaults to the account's address template
35
+ * @returns {Promise<Object>} { id, userId, type, systemAddress }
36
+ * @example
37
+ * await sdk.messaging.email.mailboxes.forUser.create('user123', { emailAlias: 'j.doe' });
38
+ */
39
+ async create(userId, { emailAlias } = {}) {
40
+ this.sdk.validateParams(
41
+ { userId, emailAlias },
42
+ {
43
+ userId: { type: 'string', required: true },
44
+ emailAlias: { type: 'string', required: false },
45
+ },
46
+ );
47
+ const body = {};
48
+ if (emailAlias !== undefined) body.emailAlias = emailAlias;
49
+ return internalRequest(
50
+ this.sdk,
51
+ `/messaging/email/mailbox/for-user/${userId}`,
52
+ 'POST',
53
+ { body },
54
+ );
55
+ }
56
+ }
@@ -1,7 +1,40 @@
1
1
  import { internalRequest } from '../../base.js';
2
+ import { EmailMailboxAccessService } from './EmailMailboxAccessService.js';
3
+ import { EmailMailboxUserService } from './EmailMailboxUserService.js';
4
+ import { EmailMailboxGroupAccessService } from './EmailMailboxGroupAccessService.js';
5
+ import { EmailAliasSuggestService } from './EmailAliasSuggestService.js';
6
+
2
7
  export class EmailMailboxesService {
3
8
  constructor(sdk) {
4
9
  this.sdk = sdk;
10
+ // Access grants (mailboxUsers_acct) — plan §3.2/§4.
11
+ this.access = new EmailMailboxAccessService(sdk);
12
+ // A user's dedicated mailbox — plan §4/§6.
13
+ this.forUser = new EmailMailboxUserService(sdk);
14
+ // Shared mailboxes granted to a group — plan §3.2/§4/§6.
15
+ this.groupAccess = new EmailMailboxGroupAccessService(sdk);
16
+ this._aliasSuggestService = new EmailAliasSuggestService(sdk);
17
+ }
18
+
19
+ /**
20
+ * Suggest an available mailbox localpart for a user on the account's default domain
21
+ * @param {string} [firstName]
22
+ * @param {string} [lastName]
23
+ * @param {string} [username]
24
+ * @returns {Promise<Object>} { localpart, domain, domainId, available: true }
25
+ */
26
+ aliasSuggest(params) {
27
+ return this._aliasSuggestService.suggest(params);
28
+ }
29
+
30
+ /**
31
+ * Check whether a localpart is available on a given domain
32
+ * @param {string} localpart
33
+ * @param {string} domainId
34
+ * @returns {Promise<Object>} { localpart, domainId, available }
35
+ */
36
+ aliasAvailable(params) {
37
+ return this._aliasSuggestService.available(params);
5
38
  }
6
39
 
7
40
  /**
@@ -15,6 +48,7 @@ export class EmailMailboxesService {
15
48
  * @param {string} [ticketPrefix] - Ticket prefix for engagement sessions (e.g., 'SUP', 'TECH') (optional)
16
49
  * @param {string} [ticketCreateEmailTemplateId] - Email template ID for auto-reply on new tickets (optional)
17
50
  * @param {string} [ticketCreateEmailFrom] - From address for auto-reply emails (optional, defaults to received address)
51
+ * @param {string} [type] - Mailbox type: 'dedicated' (has a primary user) or 'shared' (default)
18
52
  * @returns {Promise<Object>} Created mailbox with system address
19
53
  * @example
20
54
  * // Create basic mailbox
@@ -46,6 +80,7 @@ export class EmailMailboxesService {
46
80
  ticketPrefix,
47
81
  ticketCreateEmailTemplateId,
48
82
  ticketCreateEmailFrom,
83
+ type,
49
84
  ] = arguments;
50
85
  mailboxData = {};
51
86
  if (mailbox !== undefined) mailboxData.mailbox = mailbox;
@@ -60,6 +95,7 @@ export class EmailMailboxesService {
60
95
  mailboxData.ticketCreateEmailTemplateId = ticketCreateEmailTemplateId;
61
96
  if (ticketCreateEmailFrom !== undefined)
62
97
  mailboxData.ticketCreateEmailFrom = ticketCreateEmailFrom;
98
+ if (type !== undefined) mailboxData.type = type;
63
99
  } else {
64
100
  // New API: options object
65
101
  mailboxData = { ...options };
@@ -75,6 +111,7 @@ export class EmailMailboxesService {
75
111
  ticketPrefix: { type: 'string', required: false },
76
112
  ticketCreateEmailTemplateId: { type: 'string', required: false },
77
113
  ticketCreateEmailFrom: { type: 'string', required: false },
114
+ type: { type: 'string', required: false },
78
115
  });
79
116
 
80
117
  const result = await internalRequest(this.sdk, '/messaging/email/mailbox', 'POST', {
@@ -212,6 +249,7 @@ export class EmailMailboxesService {
212
249
  * @param {string} [updates.ticketCreateEmailTemplateId] - Email template ID for auto-reply
213
250
  * @param {string} [updates.ticketCreateEmailFrom] - From address for auto-reply emails
214
251
  * @param {boolean} [updates.isActive] - Whether mailbox is active
252
+ * @param {string} [updates.type] - Mailbox type: 'dedicated' or 'shared'
215
253
  * @returns {Promise<Object>} Update result
216
254
  * @example
217
255
  * // Update mailbox with engagement sessions and queue
@@ -242,6 +280,7 @@ export class EmailMailboxesService {
242
280
  ticketPrefix,
243
281
  ticketCreateEmailTemplateId,
244
282
  ticketCreateEmailFrom,
283
+ type,
245
284
  ] = Array.from(arguments).slice(1);
246
285
  updateData = {};
247
286
  if (mailbox !== undefined) updateData.mailbox = mailbox;
@@ -257,6 +296,7 @@ export class EmailMailboxesService {
257
296
  updateData.ticketCreateEmailTemplateId = ticketCreateEmailTemplateId;
258
297
  if (ticketCreateEmailFrom !== undefined)
259
298
  updateData.ticketCreateEmailFrom = ticketCreateEmailFrom;
299
+ if (type !== undefined) updateData.type = type;
260
300
  } else {
261
301
  // New API: options object
262
302
  updateData = { ...updates };
@@ -276,10 +316,11 @@ export class EmailMailboxesService {
276
316
  ticketCreateEmailTemplateId: { type: 'string', required: false },
277
317
  ticketCreateEmailFrom: { type: 'string', required: false },
278
318
  isActive: { type: 'boolean', required: false },
319
+ type: { type: 'string', required: false },
279
320
  },
280
321
  );
281
322
 
282
- const result = await internalRequest(this.sdk,
323
+ const result = await internalRequest(this.sdk,
283
324
  `/messaging/email/mailbox/${id}`,
284
325
  'PUT',
285
326
  {
@@ -5,6 +5,7 @@ import { EmailMailboxesService } from './EmailMailboxesService.js';
5
5
  import { EmailAnalyticsService } from './EmailAnalyticsService.js';
6
6
  import { EmailQueueService } from './EmailQueueService.js';
7
7
  import { EmailSuppressionService } from './EmailSuppressionService.js';
8
+ import { EmailAccountSettingsService } from './EmailAccountSettingsService.js';
8
9
 
9
10
  import { internalRequest } from '../../base.js';
10
11
  export class EmailService {
@@ -17,6 +18,27 @@ export class EmailService {
17
18
  this.analytics = new EmailAnalyticsService(sdk);
18
19
  this.queue = new EmailQueueService(sdk);
19
20
  this.suppression = new EmailSuppressionService(sdk);
21
+ // Account-level email settings (plan §3.3).
22
+ this.settings = new EmailAccountSettingsService(sdk);
23
+ }
24
+
25
+ /**
26
+ * Assign (or unassign) an email message to a user — shared-inbox "claim" (plan §2b/§4)
27
+ * @param {string} messageId - Email message ID
28
+ * @param {string|null} userId - User ID to assign to, or null to unassign
29
+ * @returns {Promise<Object>} { id, assignedUserId, assignedAt, message }
30
+ * @example
31
+ * await sdk.messaging.email.assign('emailId123', 'user456');
32
+ * await sdk.messaging.email.assign('emailId123', null); // unassign
33
+ */
34
+ async assign(messageId, userId = null) {
35
+ this.sdk.validateParams(
36
+ { messageId },
37
+ { messageId: { type: 'string', required: true } },
38
+ );
39
+ return internalRequest(this.sdk, `/messaging/email/${messageId}/assign`, 'PUT', {
40
+ body: { userId },
41
+ });
20
42
  }
21
43
 
22
44
  /**
@@ -538,6 +560,7 @@ export class EmailService {
538
560
  * @param {string} [filters.sortOrder='desc'] - Sort order: 'asc', 'desc'
539
561
  * @param {number} [filters.limit=25] - Number of results per page (max 200)
540
562
  * @param {number} [filters.offset=0] - Offset for pagination
563
+ * @param {string} [filters.assignedUserId] - Filter by assignment: 'me', 'none', or a specific user ID (plan §2b)
541
564
  * @returns {Promise<Object>} List of email messages with their threads
542
565
  * @example
543
566
  * // Returns messages with nested threads for Gmail-like UI:
@@ -577,6 +600,7 @@ export class EmailService {
577
600
  sortOrder = 'desc',
578
601
  limit = 25,
579
602
  offset = 0,
603
+ assignedUserId,
580
604
  } = {},
581
605
  ) {
582
606
  this.sdk.validateParams(
@@ -589,6 +613,7 @@ export class EmailService {
589
613
  sortOrder,
590
614
  limit,
591
615
  offset,
616
+ assignedUserId,
592
617
  },
593
618
  {
594
619
  mailboxId: { type: 'string', required: true },
@@ -599,11 +624,13 @@ export class EmailService {
599
624
  sortOrder: { type: 'string', required: false },
600
625
  limit: { type: 'number', required: false },
601
626
  offset: { type: 'number', required: false },
627
+ assignedUserId: { type: 'string', required: false },
602
628
  },
603
629
  );
604
630
 
605
631
  const query = { folder, includeDrafts, sortBy, sortOrder, limit, offset };
606
632
  if (search) query.search = search;
633
+ if (assignedUserId) query.assignedUserId = assignedUserId;
607
634
 
608
635
  const params = {
609
636
  query,