0
# Comments & Attachments
1
2
Comment and attachment operations for collaboration, communication, and file management within Linear issues and projects.
3
4
## Capabilities
5
6
### Comment Management
7
8
Create, update, and manage comments for issues and other entities.
9
10
```typescript { .api }
11
/**
12
* Get comments with filtering and pagination
13
* @param variables - Query parameters including filters and pagination
14
* @returns Promise resolving to a connection of comments
15
*/
16
comments(variables?: CommentsQueryVariables): LinearFetch<CommentConnection>;
17
18
/**
19
* Get a single comment by ID
20
* @param id - The comment ID
21
* @returns Promise resolving to the comment
22
*/
23
comment(id: string): LinearFetch<Comment>;
24
25
/**
26
* Create a new comment
27
* @param input - Comment creation data
28
* @returns Promise resolving to the creation result
29
*/
30
createComment(input: CommentCreateInput): LinearFetch<CommentPayload>;
31
32
/**
33
* Update an existing comment
34
* @param id - The comment ID to update
35
* @param input - Comment update data
36
* @returns Promise resolving to the update result
37
*/
38
updateComment(id: string, input: CommentUpdateInput): LinearFetch<CommentPayload>;
39
40
/**
41
* Delete a comment
42
* @param id - The comment ID to delete
43
* @returns Promise resolving to the deletion result
44
*/
45
deleteComment(id: string): LinearFetch<DeletePayload>;
46
47
interface CommentCreateInput {
48
/** Comment body in markdown */
49
body: string;
50
/** Issue ID to comment on */
51
issueId?: string;
52
/** Project update ID to comment on */
53
projectUpdateId?: string;
54
/** Document ID to comment on */
55
documentId?: string;
56
/** Parent comment ID for replies */
57
parentId?: string;
58
}
59
60
interface CommentUpdateInput {
61
/** Update comment body */
62
body?: string;
63
}
64
```
65
66
**Usage Examples:**
67
68
```typescript
69
import { LinearClient } from "@linear/sdk";
70
71
const client = new LinearClient({ apiKey: "your-api-key" });
72
73
// Add comment to an issue
74
const newComment = await client.createComment({
75
issueId: "issue-id",
76
body: "This looks good to me! Ready to ship ๐"
77
});
78
79
// Reply to a comment
80
const reply = await client.createComment({
81
issueId: "issue-id",
82
parentId: "parent-comment-id",
83
body: "I agree, let's merge this."
84
});
85
86
// Update comment content
87
const updatedComment = await client.updateComment("comment-id", {
88
body: "Updated comment with additional details"
89
});
90
91
// Get comments for an issue
92
const issueComments = await client.comments({
93
filter: {
94
issue: { id: { eq: "issue-id" } }
95
},
96
orderBy: PaginationOrderBy.CreatedAt
97
});
98
```
99
100
### Attachment Management
101
102
Upload, manage, and associate file attachments with issues and other entities.
103
104
```typescript { .api }
105
/**
106
* Get attachments with filtering and pagination
107
* @param variables - Query parameters including filters and pagination
108
* @returns Promise resolving to a connection of attachments
109
*/
110
attachments(variables?: AttachmentsQueryVariables): LinearFetch<AttachmentConnection>;
111
112
/**
113
* Get a single attachment by ID
114
* @param id - The attachment ID
115
* @returns Promise resolving to the attachment
116
*/
117
attachment(id: string): LinearFetch<Attachment>;
118
119
/**
120
* Create a new attachment
121
* @param input - Attachment creation data
122
* @returns Promise resolving to the creation result
123
*/
124
createAttachment(input: AttachmentCreateInput): LinearFetch<AttachmentPayload>;
125
126
/**
127
* Update an attachment
128
* @param id - The attachment ID to update
129
* @param input - Attachment update data
130
* @returns Promise resolving to the update result
131
*/
132
updateAttachment(id: string, input: AttachmentUpdateInput): LinearFetch<AttachmentPayload>;
133
134
/**
135
* Delete an attachment
136
* @param id - The attachment ID to delete
137
* @returns Promise resolving to the deletion result
138
*/
139
deleteAttachment(id: string): LinearFetch<DeletePayload>;
140
141
interface AttachmentCreateInput {
142
/** Attachment title */
143
title?: string;
144
/** Attachment subtitle */
145
subtitle?: string;
146
/** Attachment URL */
147
url: string;
148
/** Issue ID to attach to */
149
issueId?: string;
150
/** Comment ID to attach to */
151
commentId?: string;
152
/** Project update ID to attach to */
153
projectUpdateId?: string;
154
/** Icon URL for the attachment */
155
iconUrl?: string;
156
/** Metadata about the attachment */
157
metadata?: Record<string, unknown>;
158
}
159
160
interface AttachmentUpdateInput {
161
/** Update attachment title */
162
title?: string;
163
/** Update attachment subtitle */
164
subtitle?: string;
165
/** Update attachment URL */
166
url?: string;
167
/** Update icon URL */
168
iconUrl?: string;
169
/** Update metadata */
170
metadata?: Record<string, unknown>;
171
}
172
```
173
174
**Usage Examples:**
175
176
```typescript
177
// Add a file attachment to an issue
178
const attachment = await client.createAttachment({
179
title: "Design Mockup",
180
subtitle: "Mobile app wireframes",
181
url: "https://example.com/designs/mobile-mockup.fig",
182
issueId: "issue-id",
183
iconUrl: "https://example.com/icons/figma.png",
184
metadata: {
185
fileSize: "2.4MB",
186
fileType: "figma"
187
}
188
});
189
190
// Add screenshot to a comment
191
const screenshot = await client.createAttachment({
192
title: "Bug Screenshot",
193
url: "https://example.com/screenshots/bug-report.png",
194
commentId: "comment-id"
195
});
196
197
// Update attachment metadata
198
const updatedAttachment = await client.updateAttachment("attachment-id", {
199
title: "Updated Design Mockup v2",
200
metadata: {
201
version: "2.0",
202
lastModified: "2024-01-15"
203
}
204
});
205
```
206
207
### File Upload Integration
208
209
Integrate with Linear's file upload system for direct file uploads.
210
211
```typescript { .api }
212
/**
213
* Get file upload URL for direct uploads
214
* @param input - Upload parameters
215
* @returns Promise resolving to upload URL and metadata
216
*/
217
fileUpload(input: FileUploadCreateInput): LinearFetch<UploadPayload>;
218
219
interface FileUploadCreateInput {
220
/** File content type */
221
contentType: string;
222
/** File name */
223
filename: string;
224
/** File size in bytes */
225
size: number;
226
/** Whether file is used for issue attachment */
227
issueId?: string;
228
}
229
230
interface UploadPayload {
231
/** The upload URL for direct upload */
232
uploadUrl: string;
233
/** Asset URL after upload */
234
assetUrl: string;
235
/** Upload headers required */
236
headers?: Record<string, string>;
237
/** Whether upload was successful */
238
success: boolean;
239
}
240
```
241
242
### Reaction Management
243
244
Manage emoji reactions on comments and other content.
245
246
```typescript { .api }
247
/**
248
* Create a reaction on a comment
249
* @param input - Reaction creation data
250
* @returns Promise resolving to the creation result
251
*/
252
createReaction(input: ReactionCreateInput): LinearFetch<ReactionPayload>;
253
254
/**
255
* Delete a reaction
256
* @param id - The reaction ID to delete
257
* @returns Promise resolving to the deletion result
258
*/
259
deleteReaction(id: string): LinearFetch<DeletePayload>;
260
261
interface ReactionCreateInput {
262
/** Comment ID to react to */
263
commentId: string;
264
/** Emoji for the reaction */
265
emoji: string;
266
}
267
```
268
269
## Core Comment & Attachment Types
270
271
```typescript { .api }
272
/** Comment model representing a comment on issues or other entities */
273
class Comment extends Request {
274
/** Unique comment identifier */
275
id: string;
276
/** Comment body in markdown */
277
body: string;
278
/** Comment body rendered as HTML */
279
bodyData: string;
280
/** Comment author */
281
user: User;
282
/** Issue this comment belongs to */
283
issue?: Issue;
284
/** Project update this comment belongs to */
285
projectUpdate?: ProjectUpdate;
286
/** Document this comment belongs to */
287
document?: Document;
288
/** Parent comment for replies */
289
parent?: Comment;
290
/** Child comments (replies) */
291
children: CommentConnection;
292
/** Attachments on this comment */
293
attachments: AttachmentConnection;
294
/** Reactions on this comment */
295
reactions: ReactionConnection;
296
/** Creation timestamp */
297
createdAt: DateTime;
298
/** Last update timestamp */
299
updatedAt: DateTime;
300
/** Last edit timestamp */
301
editedAt?: DateTime;
302
}
303
304
/** Attachment model representing a file or link attachment */
305
class Attachment extends Request {
306
/** Unique attachment identifier */
307
id: string;
308
/** Attachment title */
309
title?: string;
310
/** Attachment subtitle */
311
subtitle?: string;
312
/** Attachment URL */
313
url: string;
314
/** Icon URL */
315
iconUrl?: string;
316
/** Attachment metadata */
317
metadata: Record<string, unknown>;
318
/** Attachment creator */
319
creator: User;
320
/** Issue this attachment belongs to */
321
issue?: Issue;
322
/** Comment this attachment belongs to */
323
comment?: Comment;
324
/** Project update this attachment belongs to */
325
projectUpdate?: ProjectUpdate;
326
/** Creation timestamp */
327
createdAt: DateTime;
328
/** Last update timestamp */
329
updatedAt: DateTime;
330
}
331
332
/** Reaction model representing emoji reactions */
333
class Reaction extends Request {
334
/** Unique reaction identifier */
335
id: string;
336
/** Emoji character */
337
emoji: string;
338
/** User who created the reaction */
339
user: User;
340
/** Comment the reaction is on */
341
comment: Comment;
342
/** Creation timestamp */
343
createdAt: DateTime;
344
}
345
346
/** Response payload for comment mutations */
347
interface CommentPayload {
348
/** The mutated comment */
349
comment?: Comment;
350
/** Whether the mutation was successful */
351
success: boolean;
352
/** Last sync ID */
353
lastSyncId: number;
354
}
355
356
/** Response payload for attachment mutations */
357
interface AttachmentPayload {
358
/** The mutated attachment */
359
attachment?: Attachment;
360
/** Whether the mutation was successful */
361
success: boolean;
362
/** Last sync ID */
363
lastSyncId: number;
364
}
365
366
/** Response payload for reaction mutations */
367
interface ReactionPayload {
368
/** The mutated reaction */
369
reaction?: Reaction;
370
/** Whether the mutation was successful */
371
success: boolean;
372
/** Last sync ID */
373
lastSyncId: number;
374
}
375
376
/** Paginated connection of comments */
377
class CommentConnection extends Connection<Comment> {
378
/** Comments in this page */
379
nodes: Comment[];
380
/** Pagination information */
381
pageInfo: PageInfo;
382
}
383
384
/** Paginated connection of attachments */
385
class AttachmentConnection extends Connection<Attachment> {
386
/** Attachments in this page */
387
nodes: Attachment[];
388
/** Pagination information */
389
pageInfo: PageInfo;
390
}
391
392
/** Paginated connection of reactions */
393
class ReactionConnection extends Connection<Reaction> {
394
/** Reactions in this page */
395
nodes: Reaction[];
396
/** Pagination information */
397
pageInfo: PageInfo;
398
}
399
```