@nurama/sdk 0.0.0-stage → 1.4.1

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.
Files changed (225) hide show
  1. package/LICENSE +202 -0
  2. package/NOTICE +5 -0
  3. package/README.md +1080 -2
  4. package/dist/BotClient.d.ts +66 -0
  5. package/dist/BotClient.d.ts.map +1 -0
  6. package/dist/BotClient.js +68 -0
  7. package/dist/BotClient.js.map +1 -0
  8. package/dist/NuramaClient.d.ts +480 -0
  9. package/dist/NuramaClient.d.ts.map +1 -0
  10. package/dist/NuramaClient.js +902 -0
  11. package/dist/NuramaClient.js.map +1 -0
  12. package/dist/browser/nurama-bot-sdk.js +12051 -0
  13. package/dist/browser/nurama-bot-sdk.min.js +1 -0
  14. package/dist/browser/nurama-sdk.js +12003 -0
  15. package/dist/browser/nurama-sdk.min.js +1 -0
  16. package/dist/routes/ai.d.ts +280 -0
  17. package/dist/routes/ai.d.ts.map +1 -0
  18. package/dist/routes/ai.js +173 -0
  19. package/dist/routes/ai.js.map +1 -0
  20. package/dist/routes/asset.d.ts +493 -0
  21. package/dist/routes/asset.d.ts.map +1 -0
  22. package/dist/routes/asset.js +848 -0
  23. package/dist/routes/asset.js.map +1 -0
  24. package/dist/routes/auth.d.ts +218 -0
  25. package/dist/routes/auth.d.ts.map +1 -0
  26. package/dist/routes/auth.js +454 -0
  27. package/dist/routes/auth.js.map +1 -0
  28. package/dist/routes/blogPosts.d.ts +17 -0
  29. package/dist/routes/blogPosts.d.ts.map +1 -0
  30. package/dist/routes/blogPosts.js +29 -0
  31. package/dist/routes/blogPosts.js.map +1 -0
  32. package/dist/routes/board.d.ts +187 -0
  33. package/dist/routes/board.d.ts.map +1 -0
  34. package/dist/routes/board.js +270 -0
  35. package/dist/routes/board.js.map +1 -0
  36. package/dist/routes/bot.d.ts +202 -0
  37. package/dist/routes/bot.d.ts.map +1 -0
  38. package/dist/routes/bot.js +229 -0
  39. package/dist/routes/bot.js.map +1 -0
  40. package/dist/routes/chat.d.ts +842 -0
  41. package/dist/routes/chat.d.ts.map +1 -0
  42. package/dist/routes/chat.js +863 -0
  43. package/dist/routes/chat.js.map +1 -0
  44. package/dist/routes/chatAi.d.ts +51 -0
  45. package/dist/routes/chatAi.d.ts.map +1 -0
  46. package/dist/routes/chatAi.js +109 -0
  47. package/dist/routes/chatAi.js.map +1 -0
  48. package/dist/routes/config.d.ts +11 -0
  49. package/dist/routes/config.d.ts.map +1 -0
  50. package/dist/routes/config.js +24 -0
  51. package/dist/routes/config.js.map +1 -0
  52. package/dist/routes/convo.d.ts +169 -0
  53. package/dist/routes/convo.d.ts.map +1 -0
  54. package/dist/routes/convo.js +284 -0
  55. package/dist/routes/convo.js.map +1 -0
  56. package/dist/routes/credits.d.ts +82 -0
  57. package/dist/routes/credits.d.ts.map +1 -0
  58. package/dist/routes/credits.js +49 -0
  59. package/dist/routes/credits.js.map +1 -0
  60. package/dist/routes/device.d.ts +74 -0
  61. package/dist/routes/device.d.ts.map +1 -0
  62. package/dist/routes/device.js +122 -0
  63. package/dist/routes/device.js.map +1 -0
  64. package/dist/routes/folder.d.ts +75 -0
  65. package/dist/routes/folder.d.ts.map +1 -0
  66. package/dist/routes/folder.js +99 -0
  67. package/dist/routes/folder.js.map +1 -0
  68. package/dist/routes/invite.d.ts +61 -0
  69. package/dist/routes/invite.d.ts.map +1 -0
  70. package/dist/routes/invite.js +86 -0
  71. package/dist/routes/invite.js.map +1 -0
  72. package/dist/routes/joinLink.d.ts +88 -0
  73. package/dist/routes/joinLink.d.ts.map +1 -0
  74. package/dist/routes/joinLink.js +205 -0
  75. package/dist/routes/joinLink.js.map +1 -0
  76. package/dist/routes/membership.d.ts +116 -0
  77. package/dist/routes/membership.d.ts.map +1 -0
  78. package/dist/routes/membership.js +183 -0
  79. package/dist/routes/membership.js.map +1 -0
  80. package/dist/routes/notification.d.ts +103 -0
  81. package/dist/routes/notification.d.ts.map +1 -0
  82. package/dist/routes/notification.js +89 -0
  83. package/dist/routes/notification.js.map +1 -0
  84. package/dist/routes/oauthGrant.d.ts +45 -0
  85. package/dist/routes/oauthGrant.d.ts.map +1 -0
  86. package/dist/routes/oauthGrant.js +32 -0
  87. package/dist/routes/oauthGrant.js.map +1 -0
  88. package/dist/routes/payment.d.ts +56 -0
  89. package/dist/routes/payment.d.ts.map +1 -0
  90. package/dist/routes/payment.js +78 -0
  91. package/dist/routes/payment.js.map +1 -0
  92. package/dist/routes/product.d.ts +43 -0
  93. package/dist/routes/product.d.ts.map +1 -0
  94. package/dist/routes/product.js +53 -0
  95. package/dist/routes/product.js.map +1 -0
  96. package/dist/routes/project.d.ts +821 -0
  97. package/dist/routes/project.d.ts.map +1 -0
  98. package/dist/routes/project.js +1153 -0
  99. package/dist/routes/project.js.map +1 -0
  100. package/dist/routes/public.d.ts +269 -0
  101. package/dist/routes/public.d.ts.map +1 -0
  102. package/dist/routes/public.js +412 -0
  103. package/dist/routes/public.js.map +1 -0
  104. package/dist/routes/scratch.d.ts +70 -0
  105. package/dist/routes/scratch.d.ts.map +1 -0
  106. package/dist/routes/scratch.js +67 -0
  107. package/dist/routes/scratch.js.map +1 -0
  108. package/dist/routes/settings.d.ts +102 -0
  109. package/dist/routes/settings.d.ts.map +1 -0
  110. package/dist/routes/settings.js +94 -0
  111. package/dist/routes/settings.js.map +1 -0
  112. package/dist/routes/shortlink.d.ts +79 -0
  113. package/dist/routes/shortlink.d.ts.map +1 -0
  114. package/dist/routes/shortlink.js +25 -0
  115. package/dist/routes/shortlink.js.map +1 -0
  116. package/dist/routes/socket.d.ts +108 -0
  117. package/dist/routes/socket.d.ts.map +1 -0
  118. package/dist/routes/socket.js +573 -0
  119. package/dist/routes/socket.js.map +1 -0
  120. package/dist/routes/storage.d.ts +44 -0
  121. package/dist/routes/storage.d.ts.map +1 -0
  122. package/dist/routes/storage.js +49 -0
  123. package/dist/routes/storage.js.map +1 -0
  124. package/dist/routes/subscription.d.ts +184 -0
  125. package/dist/routes/subscription.d.ts.map +1 -0
  126. package/dist/routes/subscription.js +219 -0
  127. package/dist/routes/subscription.js.map +1 -0
  128. package/dist/routes/supportChat.d.ts +40 -0
  129. package/dist/routes/supportChat.d.ts.map +1 -0
  130. package/dist/routes/supportChat.js +53 -0
  131. package/dist/routes/supportChat.js.map +1 -0
  132. package/dist/routes/supportTicket.d.ts +89 -0
  133. package/dist/routes/supportTicket.d.ts.map +1 -0
  134. package/dist/routes/supportTicket.js +54 -0
  135. package/dist/routes/supportTicket.js.map +1 -0
  136. package/dist/routes/tag.d.ts +72 -0
  137. package/dist/routes/tag.d.ts.map +1 -0
  138. package/dist/routes/tag.js +81 -0
  139. package/dist/routes/tag.js.map +1 -0
  140. package/dist/routes/task.d.ts +252 -0
  141. package/dist/routes/task.d.ts.map +1 -0
  142. package/dist/routes/task.js +284 -0
  143. package/dist/routes/task.js.map +1 -0
  144. package/dist/routes/taskRelation.d.ts +80 -0
  145. package/dist/routes/taskRelation.d.ts.map +1 -0
  146. package/dist/routes/taskRelation.js +71 -0
  147. package/dist/routes/taskRelation.js.map +1 -0
  148. package/dist/routes/token.d.ts +97 -0
  149. package/dist/routes/token.d.ts.map +1 -0
  150. package/dist/routes/token.js +73 -0
  151. package/dist/routes/token.js.map +1 -0
  152. package/dist/routes/user.d.ts +112 -0
  153. package/dist/routes/user.d.ts.map +1 -0
  154. package/dist/routes/user.js +151 -0
  155. package/dist/routes/user.js.map +1 -0
  156. package/dist/routes/version.d.ts +42 -0
  157. package/dist/routes/version.d.ts.map +1 -0
  158. package/dist/routes/version.js +38 -0
  159. package/dist/routes/version.js.map +1 -0
  160. package/dist/routes/webhook.d.ts +170 -0
  161. package/dist/routes/webhook.d.ts.map +1 -0
  162. package/dist/routes/webhook.js +173 -0
  163. package/dist/routes/webhook.js.map +1 -0
  164. package/dist/routes/workspace.d.ts +120 -0
  165. package/dist/routes/workspace.d.ts.map +1 -0
  166. package/dist/routes/workspace.js +199 -0
  167. package/dist/routes/workspace.js.map +1 -0
  168. package/dist/utils/uploadSessionManager.d.ts +133 -0
  169. package/dist/utils/uploadSessionManager.d.ts.map +1 -0
  170. package/dist/utils/uploadSessionManager.js +321 -0
  171. package/dist/utils/uploadSessionManager.js.map +1 -0
  172. package/dist/utils/urlParams.d.ts +35 -0
  173. package/dist/utils/urlParams.d.ts.map +1 -0
  174. package/dist/utils/urlParams.js +146 -0
  175. package/dist/utils/urlParams.js.map +1 -0
  176. package/dist/version.d.ts +15 -0
  177. package/dist/version.d.ts.map +1 -0
  178. package/dist/version.js +12 -0
  179. package/dist/version.js.map +1 -0
  180. package/package.json +87 -3
  181. package/src/BotClient.ts +113 -0
  182. package/src/NuramaClient.ts +1253 -0
  183. package/src/bot-browser-entry.js +15 -0
  184. package/src/browser-entry.js +20 -0
  185. package/src/routes/ai.ts +378 -0
  186. package/src/routes/asset.ts +1104 -0
  187. package/src/routes/auth.ts +587 -0
  188. package/src/routes/blogPosts.ts +29 -0
  189. package/src/routes/board.ts +403 -0
  190. package/src/routes/bot.ts +356 -0
  191. package/src/routes/chat.ts +1292 -0
  192. package/src/routes/chatAi.ts +125 -0
  193. package/src/routes/config.ts +31 -0
  194. package/src/routes/convo.ts +321 -0
  195. package/src/routes/credits.ts +112 -0
  196. package/src/routes/device.ts +133 -0
  197. package/src/routes/folder.ts +154 -0
  198. package/src/routes/invite.ts +133 -0
  199. package/src/routes/joinLink.ts +233 -0
  200. package/src/routes/membership.ts +237 -0
  201. package/src/routes/notification.ts +166 -0
  202. package/src/routes/oauthGrant.ts +64 -0
  203. package/src/routes/payment.ts +104 -0
  204. package/src/routes/product.ts +67 -0
  205. package/src/routes/project.ts +1528 -0
  206. package/src/routes/public.ts +496 -0
  207. package/src/routes/scratch.ts +94 -0
  208. package/src/routes/settings.ts +152 -0
  209. package/src/routes/shortlink.ts +90 -0
  210. package/src/routes/socket.ts +757 -0
  211. package/src/routes/storage.ts +83 -0
  212. package/src/routes/subscription.ts +307 -0
  213. package/src/routes/supportChat.ts +62 -0
  214. package/src/routes/supportTicket.ts +114 -0
  215. package/src/routes/tag.ts +131 -0
  216. package/src/routes/task.ts +431 -0
  217. package/src/routes/taskRelation.ts +125 -0
  218. package/src/routes/token.ts +152 -0
  219. package/src/routes/user.ts +214 -0
  220. package/src/routes/version.ts +62 -0
  221. package/src/routes/webhook.ts +295 -0
  222. package/src/routes/workspace.ts +223 -0
  223. package/src/utils/uploadSessionManager.ts +407 -0
  224. package/src/utils/urlParams.ts +181 -0
  225. package/src/version.ts +22 -0
@@ -0,0 +1,1292 @@
1
+ import NuramaClient from '../NuramaClient.js';
2
+ import {
3
+ type Asset,
4
+ type Chat,
5
+ type ChatMessage,
6
+ type ChatMember,
7
+ type Folder,
8
+ type LinkPreview,
9
+ type Membership,
10
+ type PaginatedResult,
11
+ type CursorPaginatedResult,
12
+ } from '@nurama/types'; // Import pagination types
13
+
14
+ // --- Common Interfaces ---
15
+
16
+ // Base interface for pagination options
17
+ export interface PaginationParams {
18
+ limit?: number;
19
+ paginate?: 'cursor' | 'index'; // Specify pagination type
20
+ // Cursor specific
21
+ cursor?: string;
22
+ paginateReverse?: boolean;
23
+ includeCounts?: boolean;
24
+ includeCursorRecord?: boolean;
25
+ startAt?: string;
26
+ includeStartAtRecord?: boolean;
27
+ // Index specific
28
+ page?: number;
29
+ }
30
+
31
+ export interface SortParams {
32
+ sort?: Record<string, 1 | -1>;
33
+ }
34
+
35
+ export interface DateRangeParams {
36
+ createdBefore?: string | number; // ObjectId or Timestamp
37
+ createdAfter?: string | number; // ObjectId or Timestamp
38
+ updatedBefore?: string | number; // Timestamp (used in getUsersMemberChats)
39
+ }
40
+
41
+ // --- Request Body Interfaces ---
42
+ export interface CreateTopicChatData {
43
+ topicType: 'project' | 'asset';
44
+ topicId: string;
45
+ subject?: string;
46
+ visibility?: 'creator' | 'reviewer';
47
+ }
48
+
49
+ export interface CreateMemberChatData {
50
+ /** Only `workspace` is accepted by the API; `project` is rejected with 400 (project-scoped member chats are no longer created). */
51
+ scopeType: 'workspace' | 'project';
52
+ scopeId: string;
53
+ subject?: string;
54
+ memberIds: string[];
55
+ /** Optional hex colour from the approved palette (see `GET /config`). */
56
+ color?: string;
57
+ }
58
+
59
+ export interface UpdateChatSubjectData {
60
+ subject: string;
61
+ }
62
+
63
+ export interface UpdateMemberChatData {
64
+ subject?: string;
65
+ color?: string;
66
+ }
67
+
68
+ export interface UpdateMemberChatIconData {
69
+ name: string;
70
+ checksum: string;
71
+ sizeInMB: number;
72
+ }
73
+
74
+ export interface MemberIdList {
75
+ memberIds: string[];
76
+ }
77
+
78
+ export interface FileAttachmentData {
79
+ id: number; // Client-side ID
80
+ name: string;
81
+ checksum: string;
82
+ sizeInMB: number;
83
+ }
84
+
85
+ /**
86
+ * Scratch-shape attachment ref — points at bytes already uploaded to a
87
+ * Scratch row. Used by AI Revision (Attach to chat) and the Nurama
88
+ * Support chat (image attachments). The chat-send endpoint accepts
89
+ * either this shape OR the upload-shape (`FileAttachmentData`) in the
90
+ * same `attachments[]` array; `chat.service.createMessage` partitions
91
+ * and routes per-item.
92
+ */
93
+ export interface ScratchAttachmentRef {
94
+ scratchId: string;
95
+ name?: string;
96
+ }
97
+
98
+ // Define annotation types based on backend validation with nested annotation support
99
+ // Percentage-based coordinates (0-100)
100
+ export interface PercentageCoordinates {
101
+ x: number; // 0-100
102
+ y: number; // 0-100
103
+ }
104
+
105
+ // Base annotation properties shared by all annotation types
106
+ export interface BaseAnnotation {
107
+ color?: string;
108
+ frame?: number;
109
+ timestamp?: number;
110
+ startTimestamp?: number;
111
+ endTimestamp?: number;
112
+
113
+ // Fabric.js transform properties (percentage-based storage)
114
+ left?: number; // 0-100
115
+ top?: number; // 0-100
116
+ width?: number; // 0.1-100
117
+ height?: number; // 0.1-100
118
+ scaleX?: number; // 0.01-10
119
+ scaleY?: number; // 0.01-10
120
+ angle?: number; // -360 to 360
121
+ skewX?: number; // -89 to 89
122
+ skewY?: number; // -89 to 89
123
+ flipX?: boolean;
124
+ flipY?: boolean;
125
+ originX?: 'left' | 'center' | 'right';
126
+ originY?: 'top' | 'center' | 'bottom';
127
+ opacity?: number; // 0-1
128
+ visible?: boolean;
129
+
130
+ // Shadow properties
131
+ shadow?: {
132
+ color?: string;
133
+ blur?: number;
134
+ offsetX?: number;
135
+ offsetY?: number;
136
+ };
137
+
138
+ // Enhanced stroke properties
139
+ strokeLineCap?: 'butt' | 'round' | 'square';
140
+ strokeLineJoin?: 'miter' | 'round' | 'bevel';
141
+ strokeMiterLimit?: number;
142
+ strokeDashArray?: number[];
143
+
144
+ // Fill properties
145
+ fillRule?: 'nonzero' | 'evenodd';
146
+ }
147
+
148
+ // Nested annotation types (spatial annotations only, no timestamps or recursive nesting)
149
+ export interface NestedDotAnnotation extends BaseAnnotation {
150
+ type: 'dot';
151
+ coordinates: PercentageCoordinates;
152
+ radius?: number;
153
+ }
154
+
155
+ export interface NestedShapeAnnotation extends BaseAnnotation {
156
+ type: 'rectangle' | 'circle' | 'triangle' | 'arrow' | 'line';
157
+ coordinates: PercentageCoordinates[];
158
+ strokeColor?: string;
159
+ fillColor?: string;
160
+ strokeWidth?: number;
161
+ }
162
+
163
+ export interface NestedTextAnnotation extends BaseAnnotation {
164
+ type: 'text';
165
+ coordinates: PercentageCoordinates;
166
+ content: string;
167
+ fontSize?: number;
168
+ fontFamily?: 'Arial' | 'Helvetica' | 'Times New Roman' | 'Courier New' | 'Georgia' | 'Verdana';
169
+ fontWeight?: 'normal' | 'bold';
170
+ fontStyle?: 'normal' | 'italic';
171
+ textColor?: string;
172
+ }
173
+
174
+ export interface NestedPathAnnotation extends BaseAnnotation {
175
+ type: 'path';
176
+ pathData: string;
177
+ strokeColor?: string;
178
+ strokeWidth?: number;
179
+ }
180
+
181
+ export type NestedAnnotation =
182
+ | NestedDotAnnotation
183
+ | NestedShapeAnnotation
184
+ | NestedTextAnnotation
185
+ | NestedPathAnnotation;
186
+
187
+ // Top-level annotation types (can include nested annotations)
188
+ // IMPORTANT: Nested annotations can ONLY be used when parent has a timestamp
189
+ export interface DotAnnotation extends BaseAnnotation {
190
+ type: 'dot';
191
+ coordinates: PercentageCoordinates;
192
+ radius?: number;
193
+ nestedAnnotations?: NestedAnnotation[];
194
+ }
195
+
196
+ export interface FrameCommentAnnotation extends BaseAnnotation {
197
+ type: 'frameComment';
198
+ nestedAnnotations?: NestedAnnotation[];
199
+ }
200
+
201
+ export interface ShapeAnnotation extends BaseAnnotation {
202
+ type: 'rectangle' | 'circle' | 'triangle' | 'arrow' | 'line';
203
+ coordinates: PercentageCoordinates[];
204
+ strokeColor?: string;
205
+ fillColor?: string;
206
+ strokeWidth?: number;
207
+ nestedAnnotations?: NestedAnnotation[];
208
+ }
209
+
210
+ export interface TextAnnotation extends BaseAnnotation {
211
+ type: 'text';
212
+ coordinates: PercentageCoordinates;
213
+ content: string;
214
+ fontSize?: number;
215
+ fontFamily?: 'Arial' | 'Helvetica' | 'Times New Roman' | 'Courier New' | 'Georgia' | 'Verdana';
216
+ fontWeight?: 'normal' | 'bold';
217
+ fontStyle?: 'normal' | 'italic';
218
+ textColor?: string;
219
+ nestedAnnotations?: NestedAnnotation[];
220
+ }
221
+
222
+ export interface PathAnnotation extends BaseAnnotation {
223
+ type: 'path';
224
+ pathData: string;
225
+ strokeColor?: string;
226
+ strokeWidth?: number;
227
+ nestedAnnotations?: NestedAnnotation[];
228
+ }
229
+
230
+ export type Annotation =
231
+ | DotAnnotation
232
+ | FrameCommentAnnotation
233
+ | ShapeAnnotation
234
+ | TextAnnotation
235
+ | PathAnnotation;
236
+
237
+ export interface CreateMessageData {
238
+ content?: string;
239
+ attachments?: (FileAttachmentData | ScratchAttachmentRef)[];
240
+ replyToId?: string;
241
+ annotations?: Annotation[];
242
+ mentions?: string[];
243
+ assetMentions?: string[];
244
+ folderMentions?: string[];
245
+ submissionMentions?: string[];
246
+ publicMentions?: string[];
247
+ taskMentions?: string[];
248
+ quotes?: string[];
249
+ linkPreviews?: LinkPreview[];
250
+ /**
251
+ * AI-chat only. Sent on the regular chat endpoint when the target
252
+ * chat is an AI topic so the orchestrator gets the page snapshot the
253
+ * user was looking at. Regular chats ignore this field.
254
+ */
255
+ pageContext?: {
256
+ path?: string;
257
+ pageTitle?: string;
258
+ visibleAssetIds?: string[];
259
+ };
260
+ }
261
+
262
+ export interface CreateAssetChatAndMessageData extends CreateMessageData {}
263
+
264
+ export interface ReviseMessageData {
265
+ content?: string;
266
+ mentions?: string[];
267
+ assetMentions?: string[];
268
+ folderMentions?: string[];
269
+ submissionMentions?: string[];
270
+ publicMentions?: string[];
271
+ taskMentions?: string[];
272
+ annotations?: Annotation[];
273
+ quotes?: string[];
274
+ linkPreviews?: LinkPreview[];
275
+ }
276
+
277
+ export interface FetchLinkPreviewsData {
278
+ urls: string[];
279
+ }
280
+
281
+ export interface LinkPreviewResponse {
282
+ previews: LinkPreview[];
283
+ }
284
+
285
+ export interface CreateReactionData {
286
+ emoji: string;
287
+ }
288
+
289
+ // --- Query Parameter Interfaces ---
290
+ export interface GetUsersMemberChatsParams extends PaginationParams, SortParams, DateRangeParams {
291
+ recentMessages?: number;
292
+ scopeId?: string;
293
+ subjectSearch?: string;
294
+ memberSearch?: string;
295
+ archived?: boolean;
296
+ }
297
+
298
+ export interface GetUsersMentionsParams extends PaginationParams, SortParams, DateRangeParams {
299
+ chatId?: string;
300
+ authorId?: string;
301
+ }
302
+
303
+ export interface GetChatByTopicIdParams extends SortParams {
304
+ topicType: 'project' | 'asset' | string; // Allow flexibility
305
+ visibility?: 'creator' | 'reviewer';
306
+ messages?: number;
307
+ replies?: number;
308
+ }
309
+
310
+ export interface GetMessagesParams extends PaginationParams, SortParams, DateRangeParams {
311
+ replies?: number;
312
+ replyLimit?: number;
313
+ replySort?: Record<string, 1 | -1>;
314
+ excludeReplies?: boolean;
315
+ // Search/filter options
316
+ contentSearch?: string;
317
+ authorId?: string;
318
+ type?: 'user' | 'system';
319
+ highlighted?: boolean;
320
+ hasAttachments?: boolean;
321
+ hasAnnotations?: boolean;
322
+ isConvoMessage?: boolean;
323
+ }
324
+
325
+ export interface CreateAssetChatAndMessageParams extends SortParams {
326
+ messages?: number;
327
+ replies?: number;
328
+ }
329
+
330
+ export interface GetMessageParams extends SortParams {
331
+ replies?: number;
332
+ }
333
+
334
+ export interface GetRepliesParams extends PaginationParams, SortParams, DateRangeParams {}
335
+
336
+ export interface GetMentionableAssetsParams extends PaginationParams, SortParams {
337
+ nameSearch?: string;
338
+ }
339
+
340
+ export interface GetMentionableFoldersParams extends PaginationParams, SortParams {
341
+ nameSearch?: string;
342
+ }
343
+
344
+ export interface GetMentionableTasksParams extends PaginationParams, SortParams {
345
+ nameSearch?: string;
346
+ }
347
+
348
+ export interface GetMentionableSubmissionsParams extends PaginationParams, SortParams {
349
+ nameSearch?: string;
350
+ }
351
+
352
+ export interface GetMentionablePublicsParams extends PaginationParams, SortParams {
353
+ nameSearch?: string;
354
+ }
355
+
356
+ /**
357
+ * Mentionable submission entry returned by
358
+ * `getMentionableSubmissions`. Each submission's `id` doubles as the
359
+ * `chatId` (the ChatSubmission row IS the submission chat).
360
+ */
361
+ export interface MentionableSubmission {
362
+ id: string;
363
+ subject: string;
364
+ description: string | null;
365
+ version: string | null;
366
+ status: string;
367
+ totalMessages: number;
368
+ lastMessageAt: string | null;
369
+ publishedAt: string;
370
+ chatId: string;
371
+ creator: { id: string; firstName?: string; lastName?: string; displayName?: string } | null;
372
+ }
373
+
374
+ /**
375
+ * Mentionable public collection entry returned by
376
+ * `getMentionablePublics`. `token` is the URL-safe stable identifier
377
+ * used in the `publicMention:<token>` message-token payload.
378
+ */
379
+ export interface MentionablePublic {
380
+ id: string;
381
+ token: string;
382
+ title: string;
383
+ description: string | null;
384
+ status: string;
385
+ expiresAt: string | null;
386
+ createdAt: string;
387
+ chatId: string | null;
388
+ creator: { id: string; firstName?: string; lastName?: string; displayName?: string } | null;
389
+ }
390
+
391
+ // --- Response Interfaces (using types from nurama-types) ---
392
+ export type ChatResponse = Chat;
393
+ export type MemberChatResponse = ChatMember; // Member chats have their own ChatMember structure
394
+ export type ChatMessageResponse = ChatMessage;
395
+ export type MemberResponse = Membership;
396
+
397
+ /** Addable members for a legacy project-scoped member chat, split by the membership they come from. */
398
+ export interface AddableMembersByScope {
399
+ projectMembership: MemberResponse[];
400
+ workspaceMembership: MemberResponse[];
401
+ }
402
+
403
+ /**
404
+ * One entry of an upload response: the created asset plus the signed upload data the
405
+ * caller uses to PUT the bytes, or a per-file failure (`status: 'fail'` with `error`).
406
+ */
407
+ export interface AttachmentUploadRecord {
408
+ id: number | string;
409
+ name: string;
410
+ status: 'success' | 'fail';
411
+ asset?: Asset;
412
+ signedUrlData?: any;
413
+ uploadChunkSizeInBytes?: number;
414
+ error?: string;
415
+ }
416
+ export type AttachmentResponse = AttachmentUploadRecord;
417
+
418
+ // Combine pagination metadata with a results array
419
+ export type PaginatedResponse<T> = (PaginatedResult | CursorPaginatedResult) & {
420
+ results?: T[];
421
+ };
422
+
423
+ /**
424
+ * Defines chat-related methods for the NuramaClient.
425
+ * @param {NuramaClient} client - The NuramaClient instance.
426
+ * @returns {object} An object containing the chat-related methods.
427
+ */
428
+ export default function createChatMethods(client: NuramaClient) {
429
+ return {
430
+ // --- Topic Chats ---
431
+ /**
432
+ * Creates a topic chat for a project or asset at a given visibility.
433
+ * Requires `canCreateCreatorChat` (visibility `creator`) or `canCreateReviewerChat`
434
+ * (visibility `reviewer`) on the topic resource. Although `visibility` is optional in
435
+ * the type, the permission check only passes when it is one of those two values, so
436
+ * omitting it results in 403.
437
+ * @param {CreateTopicChatData} data - `topicType` (`project` | `asset`), `topicId`, optional `subject` (max 100 chars) and `visibility`.
438
+ * @returns {Promise<ChatResponse>} The created chat.
439
+ */
440
+ async createTopicChat(data: CreateTopicChatData): Promise<ChatResponse> {
441
+ return client._request({
442
+ method: 'POST',
443
+ endpoint: '/v1/chats/topic',
444
+ body: data,
445
+ sendJWT: true,
446
+ });
447
+ },
448
+
449
+ /**
450
+ * Retrieves the topic chat for a project, asset, public release or task, together
451
+ * with its most recent messages and their replies.
452
+ * Requires `canGetCreatorChat` or `canGetReviewerChat` on the chat, matching
453
+ * `params.visibility`. `replies` (default 10, max 100) and `sort` (default `{ id: -1 }`)
454
+ * are honoured, but `messages` is accepted and then not forwarded by the API handler,
455
+ * so 10 recent messages are always returned.
456
+ * @param {string} topicId - The ID of the topic resource (project, asset, public release or task).
457
+ * @param {GetChatByTopicIdParams} params - See GetChatByTopicIdParams. `topicType` is one of `project`, `asset`, `public`, `task`.
458
+ * @returns {Promise<ChatResponse>} The chat, including `recentMessages`.
459
+ * @throws {Error} 'topicId is required.' when `topicId` is falsy.
460
+ */
461
+ async getChatByTopicId(topicId: string, params: GetChatByTopicIdParams): Promise<ChatResponse> {
462
+ if (!topicId) throw new Error('topicId is required.');
463
+ return client._request({
464
+ method: 'GET',
465
+ endpoint: `/v1/chats/topic/${topicId}`,
466
+ params: params,
467
+ sendJWT: true,
468
+ });
469
+ },
470
+
471
+ // --- Member Chats ---
472
+ /**
473
+ * Creates a member ("Team") chat in a workspace with the given members.
474
+ * Only `scopeType: 'workspace'` is accepted by the API: project-scoped member chats
475
+ * are deprecated and `social` is not supported yet, so both are rejected with 400
476
+ * even though the type still allows them. Requires `canCreateWorkspaceMemberChat` on
477
+ * the workspace. The caller is always added as the first member, every member must
478
+ * be chat-eligible in the scope (`membersInvalid` otherwise), and a random approved
479
+ * colour is assigned (the API also accepts an optional `color`, not exposed on this type).
480
+ * @param {CreateMemberChatData} data - `scopeType`, `scopeId`, `memberIds` and optional `subject` (max 100 chars).
481
+ * @returns {Promise<MemberChatResponse>} The created member chat.
482
+ */
483
+ async createMemberChat(data: CreateMemberChatData): Promise<MemberChatResponse> {
484
+ return client._request({
485
+ method: 'POST',
486
+ endpoint: '/v1/chats/member',
487
+ body: data,
488
+ sendJWT: true,
489
+ });
490
+ },
491
+
492
+ /**
493
+ * Lists the member chats the caller belongs to, most recently updated first, each
494
+ * with its recent messages.
495
+ * Defaults to index pagination (`page`, `limit` max 20); pass `paginate: 'cursor'` for
496
+ * cursor pagination. `updatedBefore` is only accepted with index pagination,
497
+ * `recentMessages` caps the messages returned per chat (default and max 20), and
498
+ * `archived` narrows to chats the caller has (`true`) or has not (`false`) archived.
499
+ * `createdBefore` / `createdAfter` from DateRangeParams are not accepted by this
500
+ * endpoint and cause a 400.
501
+ * @param {GetUsersMemberChatsParams} [params] - See GetUsersMemberChatsParams.
502
+ * @returns {Promise<PaginatedResponse<MemberChatResponse>>} A paginated list of member chats.
503
+ */
504
+ async getUsersMemberChats(params?: GetUsersMemberChatsParams): Promise<PaginatedResponse<MemberChatResponse>> {
505
+ return client._request({
506
+ method: 'GET',
507
+ endpoint: '/v1/chats/member',
508
+ params: params,
509
+ sendJWT: true,
510
+ });
511
+ },
512
+
513
+ /**
514
+ * Retrieves a member chat by ID without its messages.
515
+ * The caller must be a member of the chat.
516
+ * @param {string} chatId - The ID of the member chat.
517
+ * @returns {Promise<MemberChatResponse>} The member chat with `participants`, `members` and `icon` populated.
518
+ * @throws {Error} 'chatId is required.' when `chatId` is falsy.
519
+ */
520
+ async getMemberChat(chatId: string): Promise<MemberChatResponse> {
521
+ if (!chatId) throw new Error('chatId is required.');
522
+ return client._request({
523
+ method: 'GET',
524
+ endpoint: `/v1/chats/member/${chatId}`,
525
+ sendJWT: true,
526
+ });
527
+ },
528
+
529
+ /**
530
+ * Retrieves every project topic chat (creator/reviewer) the caller can
531
+ * access across all projects in a workspace, with the latest message and
532
+ * message count for each, ordered by most recent activity. Powers the
533
+ * workspace-level "Project Chat" list.
534
+ * Requires `canGetWorkspace` on the workspace; access to each project's chats is
535
+ * derived from the caller's inherited `canGetCreatorChat` / `canGetReviewerChat`.
536
+ * @param {string} workspaceId - The ID of the workspace.
537
+ * @returns {Promise<Array<object>>} An array of `{ project, visibility, chat }` entries; `chat.recentMessages` holds at most the latest message.
538
+ * @throws {Error} 'workspaceId is required.' when `workspaceId` is falsy.
539
+ */
540
+ async getWorkspaceProjectChats(workspaceId: string): Promise<any[]> {
541
+ if (!workspaceId) throw new Error('workspaceId is required.');
542
+ return client._request({
543
+ method: 'GET',
544
+ endpoint: `/v1/chats/workspace/${workspaceId}/project-chats`,
545
+ sendJWT: true,
546
+ });
547
+ },
548
+
549
+ /**
550
+ * Updates a member chat's subject and/or colour.
551
+ * The caller must be a member of the chat. `subject` is limited to 100 characters
552
+ * and `color` must be one of the approved palette colours.
553
+ * @param {string} chatId - The ID of the member chat.
554
+ * @param {UpdateMemberChatData} data - The new `subject` and/or `color`.
555
+ * @returns {Promise<MemberChatResponse>} The updated member chat.
556
+ * @throws {Error} 'chatId is required.' when `chatId` is falsy.
557
+ */
558
+ async updateMemberChat(chatId: string, data: UpdateMemberChatData): Promise<MemberChatResponse> {
559
+ if (!chatId) throw new Error('chatId is required.');
560
+ return client._request({
561
+ method: 'PUT',
562
+ endpoint: `/v1/chats/member/${chatId}`,
563
+ body: data,
564
+ sendJWT: true,
565
+ });
566
+ },
567
+
568
+ /**
569
+ * Marks a member chat, its messages and its attachments for deletion.
570
+ * Only the chat's creator may delete it; other members receive 403. From the
571
+ * members' perspective the chat disappears immediately; the rows are removed later
572
+ * by the cleanup service.
573
+ * @param {string} chatId - The ID of the member chat.
574
+ * @returns {Promise<void>} Resolves with `null` (the API sends an empty body).
575
+ * @throws {Error} 'chatId is required.' when `chatId` is falsy.
576
+ */
577
+ async deleteMemberChat(chatId: string): Promise<void> {
578
+ if (!chatId) throw new Error('chatId is required.');
579
+ return client._request({
580
+ method: 'DELETE',
581
+ endpoint: `/v1/chats/member/${chatId}`,
582
+ sendJWT: true,
583
+ });
584
+ },
585
+
586
+ /**
587
+ * Archives a member chat for the calling user only.
588
+ * Adds the caller to the chat's `archivedBy` list; other members' view of the chat
589
+ * is unaffected. The caller must be a member of the chat.
590
+ * @param {string} chatId - The ID of the member chat.
591
+ * @returns {Promise<MemberChatResponse>} The updated member chat.
592
+ * @throws {Error} 'chatId is required.' when `chatId` is falsy.
593
+ */
594
+ async archiveMemberChat(chatId: string): Promise<MemberChatResponse> {
595
+ if (!chatId) throw new Error('chatId is required.');
596
+ return client._request({
597
+ method: 'PUT',
598
+ endpoint: `/v1/chats/member/${chatId}/archive`,
599
+ sendJWT: true,
600
+ });
601
+ },
602
+
603
+ /**
604
+ * Unarchives a member chat for the calling user only.
605
+ * Removes the caller from the chat's `archivedBy` list. The caller must be a member
606
+ * of the chat.
607
+ * @param {string} chatId - The ID of the member chat.
608
+ * @returns {Promise<MemberChatResponse>} The updated member chat.
609
+ * @throws {Error} 'chatId is required.' when `chatId` is falsy.
610
+ */
611
+ async unarchiveMemberChat(chatId: string): Promise<MemberChatResponse> {
612
+ if (!chatId) throw new Error('chatId is required.');
613
+ return client._request({
614
+ method: 'PUT',
615
+ endpoint: `/v1/chats/member/${chatId}/unarchive`,
616
+ sendJWT: true,
617
+ });
618
+ },
619
+
620
+ /**
621
+ * Creates an icon asset for a member chat and returns signed upload URLs for it.
622
+ * Any existing icon is marked for deletion. The caller must be a member of the chat;
623
+ * `sizeInMB` is capped at 10 and `name` at 100 characters. Upload the file to the
624
+ * returned `signedUrlData.urls` afterwards, exactly as for any asset upload.
625
+ * @param {string} chatId - The ID of the member chat.
626
+ * @param {UpdateMemberChatIconData} data - `name` (with extension), `checksum` (MD5 or SHA-256) and `sizeInMB`.
627
+ * @returns {Promise<{ chat: MemberChatResponse } & AttachmentUploadRecord>} The updated `chat` plus the created upload record. Note the record's fields (`asset`, `signedUrlData`, `status`, ...) are spread directly onto the response; there is no `iconData` key despite the declared type.
628
+ * @throws {Error} 'chatId is required.' when `chatId` is falsy.
629
+ */
630
+ async updateMemberChatIcon(chatId: string, data: UpdateMemberChatIconData): Promise<{ chat: MemberChatResponse } & AttachmentUploadRecord> {
631
+ if (!chatId) throw new Error('chatId is required.');
632
+ return client._request({
633
+ method: 'PUT',
634
+ endpoint: `/v1/chats/member/${chatId}/icon`,
635
+ body: data,
636
+ sendJWT: true,
637
+ });
638
+ },
639
+
640
+ /**
641
+ * Lists the members that can be added to an existing member chat, based on the chat's
642
+ * scope and the caller's role in it.
643
+ * The caller must be a member of the chat. For workspace-scoped chats the result is a
644
+ * flat array of memberships; for legacy project-scoped chats it is an
645
+ * `AddableMembersByScope` object.
646
+ * @param {string} chatId - The ID of the member chat.
647
+ * @returns {Promise<MemberResponse[] | AddableMembersByScope>} Addable memberships, each with its `user` populated.
648
+ * @throws {Error} 'chatId is required.' when `chatId` is falsy.
649
+ */
650
+ async getAddableMembers(chatId: string): Promise<MemberResponse[] | AddableMembersByScope> {
651
+ if (!chatId) throw new Error('chatId is required.');
652
+ return client._request({
653
+ method: 'GET',
654
+ endpoint: `/v1/chats/member/members/${chatId}`,
655
+ sendJWT: true,
656
+ });
657
+ },
658
+
659
+ /**
660
+ * Lists the members addable to a NEW member chat, by scope, before the chat
661
+ * exists. Use this to populate the create-chat member picker — unlike the
662
+ * raw membership-list endpoints it isn't admin-gated, so non-admin members
663
+ * allowed to start a Team Chat still get the correct list.
664
+ * Requires `canCreateWorkspaceMemberChat` (or `canCreateProjectMemberChat`) on the
665
+ * scope. For `project` scope the result is an `AddableMembersByScope` object; note
666
+ * that project-scoped member chats can no longer be created.
667
+ * @param {'workspace' | 'project'} scopeType - Scope of the chat to create.
668
+ * @param {string} scopeId - ID of the scope resource.
669
+ * @returns {Promise<MemberResponse[] | AddableMembersByScope>} Addable memberships, each with its `user` populated.
670
+ * @throws {Error} 'scopeType is required.' or 'scopeId is required.' when either is falsy.
671
+ */
672
+ async getScopeAddableMembers(
673
+ scopeType: 'workspace' | 'project',
674
+ scopeId: string,
675
+ ): Promise<MemberResponse[] | AddableMembersByScope> {
676
+ if (!scopeType) throw new Error('scopeType is required.');
677
+ if (!scopeId) throw new Error('scopeId is required.');
678
+ return client._request({
679
+ method: 'GET',
680
+ endpoint: '/v1/chats/member/addable',
681
+ params: { scopeType, scopeId },
682
+ sendJWT: true,
683
+ });
684
+ },
685
+
686
+ /**
687
+ * Adds users to a member chat by user ID.
688
+ * The caller must be a member of the chat, and every user must be chat-eligible in
689
+ * the chat's scope (`membersInvalid` otherwise). `memberIds` is not enforced by
690
+ * validation, but the request cannot succeed without it.
691
+ * @param {string} chatId - The ID of the member chat.
692
+ * @param {MemberIdList} data - `memberIds`: the user IDs to add.
693
+ * @returns {Promise<MemberChatResponse>} The updated member chat.
694
+ * @throws {Error} 'chatId is required.' when `chatId` is falsy.
695
+ */
696
+ async addMembers(chatId: string, data: MemberIdList): Promise<MemberChatResponse> {
697
+ if (!chatId) throw new Error('chatId is required.');
698
+ return client._request({
699
+ method: 'PUT',
700
+ endpoint: `/v1/chats/member/members/${chatId}`,
701
+ body: data,
702
+ sendJWT: true,
703
+ });
704
+ },
705
+
706
+ /**
707
+ * Removes users from a member chat by user ID.
708
+ * The caller must be a member of the chat. The chat's creator cannot be removed
709
+ * (`ownerCannotLeaveChat`) and unknown user IDs produce `userNotFound`. Sent as a
710
+ * DELETE with a JSON body.
711
+ * @param {string} chatId - The ID of the member chat.
712
+ * @param {MemberIdList} data - `memberIds`: the user IDs to remove.
713
+ * @returns {Promise<MemberChatResponse>} The updated member chat.
714
+ * @throws {Error} 'chatId is required.' when `chatId` is falsy.
715
+ */
716
+ async removeMembers(chatId: string, data: MemberIdList): Promise<MemberChatResponse> {
717
+ if (!chatId) throw new Error('chatId is required.');
718
+ return client._request({
719
+ method: 'DELETE',
720
+ endpoint: `/v1/chats/member/members/${chatId}`,
721
+ body: data,
722
+ sendJWT: true,
723
+ });
724
+ },
725
+
726
+ // --- Generic Chat Management ---
727
+ /**
728
+ * Retrieves a topic chat (project, asset, task or public) by ID without its messages.
729
+ * Requires `canGetCreatorChat` or `canGetReviewerChat` on the chat, matching its
730
+ * visibility. Only topic chats are served here; member chats are served by
731
+ * `getMemberChat` and a member chat ID yields `chatNotFound`.
732
+ * @param {string} chatId - The ID of the topic chat.
733
+ * @returns {Promise<ChatResponse>} The chat with `participants` populated.
734
+ * @throws {Error} 'chatId is required.' when `chatId` is falsy.
735
+ */
736
+ async getChat(chatId: string): Promise<ChatResponse> {
737
+ if (!chatId) throw new Error('chatId is required.');
738
+ return client._request({
739
+ method: 'GET',
740
+ endpoint: `/v1/chats/${chatId}`,
741
+ sendJWT: true,
742
+ });
743
+ },
744
+
745
+ /**
746
+ * Updates the subject of a topic chat.
747
+ * Requires `canUpdateCreatorChat` or `canUpdateReviewerChat` on the chat, matching
748
+ * its visibility. `subject` is limited to 100 characters. For member chats use
749
+ * `updateMemberChat`.
750
+ * @param {string} chatId - The ID of the topic chat.
751
+ * @param {UpdateChatSubjectData} data - The new `subject`.
752
+ * @returns {Promise<ChatResponse>} The updated chat.
753
+ * @throws {Error} 'chatId is required.' when `chatId` is falsy.
754
+ */
755
+ async updateChatSubject(chatId: string, data: UpdateChatSubjectData): Promise<ChatResponse> {
756
+ if (!chatId) throw new Error('chatId is required.');
757
+ return client._request({
758
+ method: 'PUT',
759
+ endpoint: `/v1/chats/${chatId}`,
760
+ body: data,
761
+ sendJWT: true,
762
+ });
763
+ },
764
+
765
+ /**
766
+ * Marks a topic chat for deletion.
767
+ * In practice this only succeeds for `user`-topic chats owned by the caller: project
768
+ * and asset topic chats are refused with `topicChatsMayNotBeDeleted`, and any other
769
+ * topic type with `unknownError`. Member chats are deleted with `deleteMemberChat`.
770
+ * @param {string} chatId - The ID of the chat.
771
+ * @returns {Promise<void>} Resolves with `null` (the API sends an empty body).
772
+ * @throws {Error} 'chatId is required.' when `chatId` is falsy.
773
+ */
774
+ async deleteChat(chatId: string): Promise<void> {
775
+ if (!chatId) throw new Error('chatId is required.');
776
+ return client._request({
777
+ method: 'DELETE',
778
+ endpoint: `/v1/chats/${chatId}`,
779
+ sendJWT: true,
780
+ });
781
+ },
782
+
783
+ // --- Messages ---
784
+ /**
785
+ * Posts a message to any chat type (topic, member, submission, AI, support).
786
+ * Either `content` (max 10,000 chars) or at least one attachment is required. API
787
+ * tokens need the `chat:write` scope (`tokenScopeMissing` / 403 otherwise); users
788
+ * need message-create permission on the chat, e.g. `canCreateCreatorChatMessage` /
789
+ * `canCreateReviewerChatMessage` for topic chats or membership for member chats.
790
+ * Limits: 6 attachments, 10 of each mention kind, 5 quotes, 5 link previews and
791
+ * 100 annotations. Mentioning users in topic/member/submission chats creates tasks
792
+ * and notifications for them. `pageContext` is only read by AI chats and ignored by
793
+ * every other chat type.
794
+ * @param {string} chatId - The ID of the chat to post in.
795
+ * @param {CreateMessageData} data - See CreateMessageData. `attachments` may mix upload-shape (`FileAttachmentData`) and scratch-shape (`ScratchAttachmentRef`) items.
796
+ * @returns {Promise<ChatMessageResponse>} The created message. When upload-shape attachments were sent it also carries `attachmentData` with the created assets and their signed upload URLs.
797
+ * @throws {Error} 'chatId is required.' when `chatId` is falsy.
798
+ */
799
+ async createMessage(chatId: string, data: CreateMessageData): Promise<ChatMessageResponse> {
800
+ if (!chatId) throw new Error('chatId is required.');
801
+ return client._request({
802
+ method: 'POST',
803
+ endpoint: `/v1/chats/${chatId}/new-message`,
804
+ body: data,
805
+ sendJWT: true,
806
+ });
807
+ },
808
+
809
+ /**
810
+ * Posts a message to an asset's chat at the given visibility, creating the chat first
811
+ * if it does not exist yet (asset chats are normally auto-created, so this mainly
812
+ * covers legacy assets).
813
+ * Only media assets are accepted (`assetInvalidFunctionType` / 404 otherwise).
814
+ * Requires both `canCreate{Creator|Reviewer}Chat` and
815
+ * `canCreate{Creator|Reviewer}ChatMessage` on the asset for the chosen visibility.
816
+ * The body follows the same rules as `createMessage`. The `params` argument is
817
+ * neither validated nor forwarded by the API handler, so the returned chat always
818
+ * carries 10 recent messages with 10 replies each, sorted `{ id: -1 }`.
819
+ * @param {string} assetId - The ID of the media asset.
820
+ * @param {'creator' | 'reviewer'} visibility - Which of the asset's two chats to post in.
821
+ * @param {CreateAssetChatAndMessageData} data - See CreateMessageData.
822
+ * @param {CreateAssetChatAndMessageParams} [params] - Accepted for backwards compatibility only; currently ignored by the API.
823
+ * @returns {Promise<any>} `{ chat, message }`: the chat re-read after the message landed (so `recentMessages` includes it) and the created message, which carries `attachmentData` when upload-shape attachments were sent.
824
+ * @throws {Error} 'assetId is required.' when `assetId` is falsy.
825
+ */
826
+ async createAssetChatAndMessage(assetId: string, visibility: 'creator' | 'reviewer', data: CreateAssetChatAndMessageData, params?: CreateAssetChatAndMessageParams): Promise<any> { // Response combines chat, message, attachmentData
827
+ if (!assetId) throw new Error('assetId is required.');
828
+ return client._request({
829
+ method: 'POST',
830
+ endpoint: `/v1/chats/asset/${assetId}/${visibility}/new-message`,
831
+ body: data,
832
+ params: params, // Params for recent messages/replies included in response
833
+ sendJWT: true,
834
+ });
835
+ },
836
+
837
+ /**
838
+ * Lists a chat's active messages with their recent replies and populated
839
+ * attachments and mentions.
840
+ * Requires read access to the chat (`canGetChat`); API tokens need the `chat:read`
841
+ * scope (`tokenScopeMissing` / 403 otherwise). Defaults to index pagination (`page`,
842
+ * `limit` max 100, sort `{ id: -1 }`); pass `paginate: 'cursor'` for cursor
843
+ * pagination. `createdBefore` / `createdAfter` are only accepted with index
844
+ * pagination and `updatedBefore` is not accepted at all. `replyLimit` (default 10,
845
+ * max 100) sets the replies returned per message; `replies` is a deprecated alias
846
+ * that takes precedence over `replyLimit` whenever it is set to anything other than 10.
847
+ * @param {string} chatId - The ID of the chat.
848
+ * @param {GetMessagesParams} [params] - See GetMessagesParams.
849
+ * @returns {Promise<PaginatedResponse<ChatMessageResponse>>} A paginated list of messages.
850
+ * @throws {Error} 'chatId is required.' when `chatId` is falsy.
851
+ */
852
+ async getMessages(chatId: string, params?: GetMessagesParams): Promise<PaginatedResponse<ChatMessageResponse>> {
853
+ if (!chatId) throw new Error('chatId is required.');
854
+ return client._request({
855
+ method: 'GET',
856
+ endpoint: `/v1/chats/${chatId}/messages`,
857
+ params: params,
858
+ sendJWT: true,
859
+ });
860
+ },
861
+
862
+ /**
863
+ * Retrieves a single message by ID with its most recent replies.
864
+ * Requires read access to the message's chat (`canGetChatMessage`). `replies`
865
+ * defaults to 10 (max 100) and `sort` (default `{ id: -1 }`) orders the included replies.
866
+ * @param {string} messageId - The ID of the message.
867
+ * @param {GetMessageParams} [params] - See GetMessageParams.
868
+ * @returns {Promise<ChatMessageResponse>} The message.
869
+ * @throws {Error} 'messageId is required.' when `messageId` is falsy.
870
+ */
871
+ async getMessage(messageId: string, params?: GetMessageParams): Promise<ChatMessageResponse> {
872
+ if (!messageId) throw new Error('messageId is required.');
873
+ return client._request({
874
+ method: 'GET',
875
+ endpoint: `/v1/chats/message/${messageId}`,
876
+ params: params,
877
+ sendJWT: true,
878
+ });
879
+ },
880
+
881
+ /**
882
+ * Revises a message's content, mentions, quotes, annotations and link previews,
883
+ * keeping the previous version as a revision.
884
+ * Only the author may revise, and in topic/submission chats they also need
885
+ * `canUpdateOwnChatMessage`. Annotations are replaced, not merged: omit
886
+ * `annotations` to keep the current ones, send `[]` to remove them all.
887
+ * `linkPreviews` likewise replaces the stored previews. Same size limits as
888
+ * `createMessage`.
889
+ * @param {string} messageId - The ID of the message to revise.
890
+ * @param {ReviseMessageData} data - See ReviseMessageData.
891
+ * @returns {Promise<ChatMessageResponse>} The revised message.
892
+ * @throws {Error} 'messageId is required.' when `messageId` is falsy.
893
+ */
894
+ async reviseMessage(messageId: string, data: ReviseMessageData): Promise<ChatMessageResponse> {
895
+ if (!messageId) throw new Error('messageId is required.');
896
+ return client._request({
897
+ method: 'PUT',
898
+ endpoint: `/v1/chats/message/${messageId}`,
899
+ body: data,
900
+ sendJWT: true,
901
+ });
902
+ },
903
+
904
+ /**
905
+ * Marks a message for deletion.
906
+ * Only the author may delete, and in topic/submission chats they also need
907
+ * `canDeleteOwnChatMessage`. The row is removed later by the cleanup service.
908
+ * @param {string} messageId - The ID of the message.
909
+ * @returns {Promise<ChatMessageResponse>} The deleted message.
910
+ * @throws {Error} 'messageId is required.' when `messageId` is falsy.
911
+ */
912
+ async deleteMessage(messageId: string): Promise<ChatMessageResponse> {
913
+ if (!messageId) throw new Error('messageId is required.');
914
+ return client._request({
915
+ method: 'DELETE',
916
+ endpoint: `/v1/chats/message/${messageId}`,
917
+ sendJWT: true,
918
+ });
919
+ },
920
+
921
+ // --- Replies ---
922
+ /**
923
+ * Lists the active replies to a message, with attachments populated.
924
+ * Requires read access to the message's chat (`canGetChatMessage`). Defaults to
925
+ * index pagination (`page`, `limit` max 100, sort `{ id: -1 }`); pass
926
+ * `paginate: 'cursor'` for cursor pagination. `createdBefore` / `createdAfter` are
927
+ * only accepted with index pagination and `updatedBefore` is not accepted at all.
928
+ * @param {string} messageId - The ID of the parent message.
929
+ * @param {GetRepliesParams} [params] - See GetRepliesParams.
930
+ * @returns {Promise<PaginatedResponse<ChatMessageResponse>>} A paginated list of replies.
931
+ * @throws {Error} 'messageId is required.' when `messageId` is falsy.
932
+ */
933
+ async getReplies(messageId: string, params?: GetRepliesParams): Promise<PaginatedResponse<ChatMessageResponse>> {
934
+ if (!messageId) throw new Error('messageId is required.');
935
+ return client._request({
936
+ method: 'GET',
937
+ endpoint: `/v1/chats/message/${messageId}/replies`,
938
+ params: params,
939
+ sendJWT: true,
940
+ });
941
+ },
942
+
943
+ // --- Attachments ---
944
+ /**
945
+ * Creates attachment assets for an existing message and returns signed upload URLs
946
+ * for them.
947
+ * Only the message's author may attach, and in topic/submission chats they also
948
+ * need `canCreateAttachment`. Only image and video file names are accepted, each
949
+ * `checksum` must be a 32-64 character hex MD5/SHA-256 digest, `id` must be an
950
+ * integer no greater than 10, and the message may hold at most 6 attachments in
951
+ * total (`exceedsMaxAttachments`). The request is also checked against the
952
+ * workspace storage quota (`uploadRequestExceedsSubscription`).
953
+ * @param {string} messageId - The ID of the message.
954
+ * @param {FileAttachmentData[]} attachments - The files to attach; sent as the raw JSON body array.
955
+ * @returns {Promise<AttachmentResponse[]>} One record per input file: the input item plus `status` and, on success, `asset` and `signedUrlData` (or `error` on failure). Not a bare `Asset` as the declared type suggests.
956
+ * @throws {Error} 'messageId is required.' when `messageId` is falsy.
957
+ */
958
+ async addAttachments(messageId: string, attachments: FileAttachmentData[]): Promise<AttachmentResponse[]> {
959
+ if (!messageId) throw new Error('messageId is required.');
960
+ return client._request({
961
+ method: 'POST',
962
+ endpoint: `/v1/chats/message/${messageId}/attachment/`,
963
+ body: attachments,
964
+ sendJWT: true,
965
+ });
966
+ },
967
+
968
+ /**
969
+ * Removes an attachment from a message and marks the asset for deletion.
970
+ * Only the author may remove attachments, and in topic/submission chats they also
971
+ * need `canDeleteOwnAttachment`. If the message is left with no content and no
972
+ * attachments it is marked for deletion as well, and the deleted message is returned.
973
+ * @param {string} messageId - The ID of the message.
974
+ * @param {string} assetId - The ID of the attached asset to remove.
975
+ * @returns {Promise<ChatMessageResponse>} The updated (or deleted) message.
976
+ * @throws {Error} 'messageId is required.' or 'assetId is required.' when either is falsy.
977
+ */
978
+ async removeAttachment(messageId: string, assetId: string): Promise<ChatMessageResponse> {
979
+ if (!messageId) throw new Error('messageId is required.');
980
+ if (!assetId) throw new Error('assetId is required.');
981
+ return client._request({
982
+ method: 'DELETE',
983
+ endpoint: `/v1/chats/message/${messageId}/attachment/${assetId}`,
984
+ sendJWT: true,
985
+ });
986
+ },
987
+
988
+ // --- Mentions ---
989
+ /**
990
+ * Lists the messages in which the caller was mentioned.
991
+ * Defaults to index pagination (`page`, `limit` max 100, sort `{ id: -1 }`); pass
992
+ * `paginate: 'cursor'` for cursor pagination. Filter with `chatId` and/or
993
+ * `authorId`. `createdBefore` is only accepted with index pagination;
994
+ * `createdAfter` and `updatedBefore` from DateRangeParams are not accepted by this
995
+ * endpoint and cause a 400.
996
+ * @param {GetUsersMentionsParams} [params] - See GetUsersMentionsParams.
997
+ * @returns {Promise<PaginatedResponse<ChatMessageResponse>>} A paginated list of messages.
998
+ */
999
+ async getMentions(params?: GetUsersMentionsParams): Promise<PaginatedResponse<ChatMessageResponse>> {
1000
+ return client._request({
1001
+ method: 'GET',
1002
+ endpoint: '/v1/chats/mentions',
1003
+ params: params,
1004
+ sendJWT: true,
1005
+ });
1006
+ },
1007
+
1008
+ // --- Summaries ---
1009
+
1010
+
1011
+ // --- Reactions ---
1012
+ /**
1013
+ * Adds the caller's emoji reaction to a message, replacing any reaction they already
1014
+ * had on it.
1015
+ * Each user holds at most one reaction per message. Requires message-create
1016
+ * permission on the chat (`canCreateReaction`). `emoji` must be 1-10 characters.
1017
+ * @param {string} messageId - The ID of the message.
1018
+ * @param {CreateReactionData} data - The `emoji` to react with.
1019
+ * @returns {Promise<ChatMessageResponse>} The updated message, including `reactions`.
1020
+ * @throws {Error} 'messageId is required.' when `messageId` is falsy.
1021
+ */
1022
+ async createReaction(messageId: string, data: CreateReactionData): Promise<ChatMessageResponse> {
1023
+ if (!messageId) throw new Error('messageId is required.');
1024
+ return client._request({
1025
+ method: 'POST',
1026
+ endpoint: `/v1/chats/message/${messageId}/reaction`,
1027
+ body: data,
1028
+ sendJWT: true,
1029
+ });
1030
+ },
1031
+
1032
+ /**
1033
+ * Removes the caller's own reaction from a message.
1034
+ * Gated by the same permission as `createReaction`. Calling it when the caller has
1035
+ * no reaction is a no-op that still returns the message.
1036
+ * @param {string} messageId - The ID of the message.
1037
+ * @returns {Promise<ChatMessageResponse>} The updated message.
1038
+ * @throws {Error} 'messageId is required.' when `messageId` is falsy.
1039
+ */
1040
+ async removeReaction(messageId: string): Promise<ChatMessageResponse> {
1041
+ if (!messageId) throw new Error('messageId is required.');
1042
+ return client._request({
1043
+ method: 'DELETE',
1044
+ endpoint: `/v1/chats/message/${messageId}/reaction`,
1045
+ sendJWT: true,
1046
+ });
1047
+ },
1048
+
1049
+ // --- Follow/Unfollow ---
1050
+ /**
1051
+ * Adds the caller to a chat's following list so they are notified about new
1052
+ * messages and updates.
1053
+ * Works with topic, member and submission chats and is idempotent. Requires
1054
+ * message-create permission on the chat (`canCreateChatMessage`).
1055
+ * @param {string} chatId - The ID of the chat to follow.
1056
+ * @returns {Promise<void>} Resolves once followed. The API sends an empty body; re-fetch the chat if you need its `following` list.
1057
+ * @throws {Error} 'chatId is required.' when `chatId` is falsy.
1058
+ */
1059
+ async followChat(chatId: string): Promise<void> {
1060
+ if (!chatId) throw new Error('chatId is required.');
1061
+ await client._request<null>({
1062
+ method: 'PUT',
1063
+ endpoint: `/v1/chats/${chatId}/follow`,
1064
+ sendJWT: true,
1065
+ });
1066
+ },
1067
+
1068
+ /**
1069
+ * Removes the caller from a chat's following list.
1070
+ * Works with topic, member and submission chats and is idempotent. No chat
1071
+ * permission is checked, so users can stop notifications for a chat they have
1072
+ * since lost access to.
1073
+ * @param {string} chatId - The ID of the chat to unfollow.
1074
+ * @returns {Promise<void>} Resolves once unfollowed. The API sends an empty body.
1075
+ * @throws {Error} 'chatId is required.' when `chatId` is falsy.
1076
+ */
1077
+ async unfollowChat(chatId: string): Promise<void> {
1078
+ if (!chatId) throw new Error('chatId is required.');
1079
+ await client._request<null>({
1080
+ method: 'PUT',
1081
+ endpoint: `/v1/chats/${chatId}/unfollow`,
1082
+ sendJWT: true,
1083
+ });
1084
+ },
1085
+
1086
+ // --- Mentionable Assets ---
1087
+ /**
1088
+ * Lists the active assets that can be mentioned (`{{assetMention:assetId}}`) in a chat.
1089
+ * What is returned depends on the chat: project and asset topic chats return the
1090
+ * project's assets at the chat's visibility; project-scoped member chats and
1091
+ * submission chats return all of the project's assets; AI chats return the topic
1092
+ * project's assets filtered to the caller's own visibility tiers; workspace/social
1093
+ * member chats return an empty list. Requires read access to the chat
1094
+ * (`canGetChatMentionableAssets`). Defaults to index pagination (`page`, `limit`
1095
+ * max 100, sort `{ name: 1 }`); pass `paginate: 'cursor'` for cursor pagination.
1096
+ * `startAt` / `includeStartAtRecord` are not accepted here.
1097
+ * @param {string} chatId - The ID of the chat.
1098
+ * @param {GetMentionableAssetsParams} [params] - See GetMentionableAssetsParams. `nameSearch` is a case-insensitive partial match.
1099
+ * @returns {Promise<PaginatedResponse<Asset>>} A paginated list of assets.
1100
+ * @throws {Error} 'chatId is required.' when `chatId` is falsy.
1101
+ */
1102
+ async getMentionableAssets(chatId: string, params?: GetMentionableAssetsParams): Promise<PaginatedResponse<Asset>> {
1103
+ if (!chatId) throw new Error('chatId is required.');
1104
+ return client._request({
1105
+ method: 'GET',
1106
+ endpoint: `/v1/chats/${chatId}/mentionable/assets`,
1107
+ params: params,
1108
+ sendJWT: true,
1109
+ });
1110
+ },
1111
+
1112
+ // --- Mentionable Folders ---
1113
+ /**
1114
+ * Lists the active folders that can be mentioned (`{{folderMention:folderId}}`) in a chat.
1115
+ * What is returned depends on the chat: project and asset topic chats return the
1116
+ * project's folders at the chat's visibility; project-scoped member chats return
1117
+ * all of the project's folders; submission chats return the project's
1118
+ * reviewer-visibility folders; AI chats return the topic project's folders filtered
1119
+ * to the caller's own visibility tiers; workspace/social member chats return an
1120
+ * empty list. Requires read access to the chat (`canGetChatMentionableFolders`).
1121
+ * Defaults to index pagination (`page`, `limit` max 100, sort `{ name: 1 }`); pass
1122
+ * `paginate: 'cursor'` for cursor pagination. `startAt` / `includeStartAtRecord`
1123
+ * are not accepted here.
1124
+ * @param {string} chatId - The ID of the chat.
1125
+ * @param {GetMentionableFoldersParams} [params] - See GetMentionableFoldersParams. `nameSearch` is a case-insensitive partial match.
1126
+ * @returns {Promise<PaginatedResponse<Folder>>} A paginated list of folders.
1127
+ * @throws {Error} 'chatId is required.' when `chatId` is falsy.
1128
+ */
1129
+ async getMentionableFolders(chatId: string, params?: GetMentionableFoldersParams): Promise<PaginatedResponse<Folder>> {
1130
+ if (!chatId) throw new Error('chatId is required.');
1131
+ return client._request({
1132
+ method: 'GET',
1133
+ endpoint: `/v1/chats/${chatId}/mentionable/folders`,
1134
+ params: params,
1135
+ sendJWT: true,
1136
+ });
1137
+ },
1138
+
1139
+ // --- Mentionable Submissions ---
1140
+ /**
1141
+ * Lists the active submissions in a chat's project that can be mentioned
1142
+ * (`{{submissionMention:submissionId}}`).
1143
+ * The project is resolved from the chat (project/asset/task topic chats,
1144
+ * project-scoped member chats, submission chats and project-scoped AI chats); chats
1145
+ * without a project return an empty page. Requires read access to the chat
1146
+ * (`canGetChatMentionableSubmissions`). Index pagination only (`page`, `limit` max
1147
+ * 100, sort `{ createdAt: -1 }`, also sortable by `subject` and `lastMessageAt`);
1148
+ * cursor-pagination params cause a 400.
1149
+ * @param {string} chatId - The ID of the chat.
1150
+ * @param {GetMentionableSubmissionsParams} [params] - See GetMentionableSubmissionsParams. `nameSearch` is a case-insensitive partial match on the subject.
1151
+ * @returns {Promise<PaginatedResponse<MentionableSubmission>>} A paginated list of submissions.
1152
+ * @throws {Error} 'chatId is required.' when `chatId` is falsy.
1153
+ */
1154
+ async getMentionableSubmissions(chatId: string, params?: GetMentionableSubmissionsParams): Promise<PaginatedResponse<MentionableSubmission>> {
1155
+ if (!chatId) throw new Error('chatId is required.');
1156
+ return client._request({
1157
+ method: 'GET',
1158
+ endpoint: `/v1/chats/${chatId}/mentionable/submissions`,
1159
+ params: params,
1160
+ sendJWT: true,
1161
+ });
1162
+ },
1163
+
1164
+ // --- Mentionable Public collections ---
1165
+ /**
1166
+ * Lists the active public releases (share links) owned by a chat's project that can
1167
+ * be mentioned (`{{publicMention:token}}`).
1168
+ * The project is resolved from the chat exactly as for `getMentionableSubmissions`;
1169
+ * chats without a project return an empty page. Requires read access to the chat
1170
+ * (`canGetChatMentionablePublics`). Index pagination only (`page`, `limit` max 100,
1171
+ * sort `{ createdAt: -1 }`, also sortable by `title` and `expires`);
1172
+ * cursor-pagination params cause a 400.
1173
+ * @param {string} chatId - The ID of the chat.
1174
+ * @param {GetMentionablePublicsParams} [params] - See GetMentionablePublicsParams. `nameSearch` is a case-insensitive partial match on the title.
1175
+ * @returns {Promise<PaginatedResponse<MentionablePublic>>} A paginated list of public releases; use each entry's `token` in the mention.
1176
+ * @throws {Error} 'chatId is required.' when `chatId` is falsy.
1177
+ */
1178
+ async getMentionablePublics(chatId: string, params?: GetMentionablePublicsParams): Promise<PaginatedResponse<MentionablePublic>> {
1179
+ if (!chatId) throw new Error('chatId is required.');
1180
+ return client._request({
1181
+ method: 'GET',
1182
+ endpoint: `/v1/chats/${chatId}/mentionable/publics`,
1183
+ params: params,
1184
+ sendJWT: true,
1185
+ });
1186
+ },
1187
+
1188
+ // --- Mentionable Tasks (boards addon required) ---
1189
+ /**
1190
+ * Lists the board tasks that can be mentioned (`{{taskMention:taskId}}`) in a chat.
1191
+ * Requires the workspace to have the `boards` capability (`capabilityNotAvailable`
1192
+ * / 403 otherwise) and read access to the chat (`canGetChatMentionableTasks`).
1193
+ * Project, asset and task topic chats return tasks in the project on boards whose
1194
+ * visibility includes the chat's; project-scoped member chats return every board
1195
+ * task in the project; submission chats return tasks on reviewer-visible boards;
1196
+ * workspace/social member chats return an empty list. Legacy tasks without a board
1197
+ * are never returned. Defaults to index pagination (`page`, `limit` max 100, sort
1198
+ * `{ updatedAt: -1 }`); pass `paginate: 'cursor'` for cursor pagination.
1199
+ * @param {string} chatId - The ID of the chat.
1200
+ * @param {GetMentionableTasksParams} [params] - See GetMentionableTasksParams. `nameSearch` matches a subject substring, an exact task number or an exact task ID.
1201
+ * @returns {Promise<PaginatedResponse<any>>} A paginated list of task summaries (`id`, `subject`, `taskNumber`, `status`, `projectId`, `boardId`, `assignedToId`, `createdAt`, `updatedAt`).
1202
+ * @throws {Error} 'chatId is required.' when `chatId` is falsy.
1203
+ */
1204
+ async getMentionableTasks(chatId: string, params?: GetMentionableTasksParams): Promise<PaginatedResponse<any>> {
1205
+ if (!chatId) throw new Error('chatId is required.');
1206
+ return client._request({
1207
+ method: 'GET',
1208
+ endpoint: `/v1/chats/${chatId}/mentionable/tasks`,
1209
+ params: params,
1210
+ sendJWT: true,
1211
+ });
1212
+ },
1213
+
1214
+ // --- Highlighting ---
1215
+ /**
1216
+ * Highlights a message, recording the caller as the highlighter.
1217
+ * In topic and submission chats this requires `canHighlightMessage` on the chat; in
1218
+ * member chats any member may highlight. For project and asset topic chats a system
1219
+ * message is posted in the project chat of the same visibility, a
1220
+ * `chatHighlightMessage` notification is sent and project members are emailed.
1221
+ * @param {string} messageId - The ID of the message.
1222
+ * @returns {Promise<ChatMessageResponse>} The highlighted message.
1223
+ * @throws {Error} 'messageId is required.' when `messageId` is falsy.
1224
+ */
1225
+ async highlightMessage(messageId: string): Promise<ChatMessageResponse> {
1226
+ if (!messageId) throw new Error('messageId is required.');
1227
+ return client._request({
1228
+ method: 'PUT',
1229
+ endpoint: `/v1/chats/message/${messageId}/highlight`,
1230
+ sendJWT: true,
1231
+ });
1232
+ },
1233
+
1234
+ /**
1235
+ * Removes the highlight from a message.
1236
+ * Clears the highlighter fields and removes the associated system messages and
1237
+ * notification. Same permission as `highlightMessage`.
1238
+ * @param {string} messageId - The ID of the message.
1239
+ * @returns {Promise<ChatMessageResponse>} The unhighlighted message.
1240
+ * @throws {Error} 'messageId is required.' when `messageId` is falsy.
1241
+ */
1242
+ async unhighlightMessage(messageId: string): Promise<ChatMessageResponse> {
1243
+ if (!messageId) throw new Error('messageId is required.');
1244
+ return client._request({
1245
+ method: 'PUT',
1246
+ endpoint: `/v1/chats/message/${messageId}/unhighlight`,
1247
+ sendJWT: true,
1248
+ });
1249
+ },
1250
+
1251
+ // --- Short Links ---
1252
+ /**
1253
+ * Creates a short link for a chat message, or returns the existing one if the
1254
+ * message already has a short link.
1255
+ * Visibility is inherited from the parent chat (`creator` / `reviewer` for topic
1256
+ * chats, `null` for member chats). Requires read access to the message's chat
1257
+ * (`canCreateMessageShortLink`).
1258
+ * @param {string} messageId - The ID of the message.
1259
+ * @returns {Promise<{ code: string; shortUrl: string }>} The 8-character alphanumeric `code` and the complete `shortUrl`.
1260
+ * @throws {Error} 'messageId is required.' when `messageId` is falsy.
1261
+ */
1262
+ async createMessageShortLink(messageId: string): Promise<{ code: string; shortUrl: string }> {
1263
+ if (!messageId) throw new Error('messageId is required.');
1264
+ return client._request({
1265
+ method: 'POST',
1266
+ endpoint: `/v1/chats/message/${messageId}/shortlink`,
1267
+ sendJWT: true,
1268
+ });
1269
+ },
1270
+
1271
+ // --- Link Previews ---
1272
+ /**
1273
+ * Fetches Open Graph / meta-tag preview data for one to five URLs.
1274
+ * Each preview carries an HMAC-SHA256 `signature` that must be passed back
1275
+ * unchanged in `linkPreviews` when creating or revising a message, as the API
1276
+ * verifies it to reject spoofed previews. Duplicate URLs are collapsed and URLs
1277
+ * that fail validation, fetching or SSRF checks are omitted, so `previews` may be
1278
+ * shorter than `urls`. Rate limited to 30 requests per minute per IP.
1279
+ * @param {FetchLinkPreviewsData} data - `urls`: 1-5 absolute http(s) URLs, each at most 2048 characters.
1280
+ * @returns {Promise<LinkPreviewResponse>} `{ previews }`.
1281
+ */
1282
+ async fetchLinkPreviews(data: FetchLinkPreviewsData): Promise<LinkPreviewResponse> {
1283
+ return client._request({
1284
+ method: 'POST',
1285
+ endpoint: '/v1/link-preview',
1286
+ body: data,
1287
+ sendJWT: true,
1288
+ });
1289
+ },
1290
+
1291
+ };
1292
+ }