0
# Pins
1
2
Pin and unpin messages in channels, and retrieve lists of pinned items. Pinned messages are highlighted items that stay easily accessible at the top of a channel for important information or reference.
3
4
## Capabilities
5
6
### Add Pin
7
8
Pin a message to a channel to highlight it as important.
9
10
```typescript { .api }
11
/**
12
* Pin an item to a channel
13
* @param options - Message parameters to pin
14
* @returns Promise resolving to success confirmation
15
*/
16
pins.add(options: PinsAddArguments): Promise<PinsAddResponse>;
17
18
interface PinsAddArguments extends MessageArgument, TokenOverridable {}
19
20
interface MessageArgument {
21
/** Channel containing the message */
22
channel: string;
23
/** Timestamp of the message to pin */
24
timestamp: string;
25
}
26
27
interface PinsAddResponse extends WebAPICallResult {
28
/** Whether the pin was successfully added */
29
ok: boolean;
30
}
31
```
32
33
**Usage Examples:**
34
35
```typescript
36
import { WebClient } from "@slack/web-api";
37
38
const web = new WebClient(process.env.SLACK_BOT_TOKEN);
39
40
// Pin a message to a channel
41
await web.pins.add({
42
channel: "C1234567890",
43
timestamp: "1234567890.123456"
44
});
45
```
46
47
### List Pins
48
49
Retrieve all pinned items in a specific channel.
50
51
```typescript { .api }
52
/**
53
* List items pinned to a channel
54
* @param options - Channel parameters
55
* @returns Promise resolving to list of pinned items
56
*/
57
pins.list(options: PinsListArguments): Promise<PinsListResponse>;
58
59
interface PinsListArguments extends TokenOverridable {
60
/** Channel to get pinned items for */
61
channel: string;
62
}
63
64
interface PinsListResponse extends WebAPICallResult {
65
/** Array of pinned items */
66
items?: PinnedItem[];
67
/** Total count of pinned items */
68
count?: number;
69
}
70
71
interface PinnedItem {
72
/** Type of pinned item ('message', 'file', etc.) */
73
type?: string;
74
/** Channel ID where item is pinned */
75
channel?: string;
76
/** User who pinned the item */
77
created_by?: string;
78
/** Timestamp when item was pinned */
79
created?: number;
80
/** Message object (if type is 'message') */
81
message?: Message;
82
/** File object (if type is 'file') */
83
file?: File;
84
/** File comment object (if type is 'file_comment') */
85
comment?: FileComment;
86
}
87
```
88
89
**Usage Examples:**
90
91
```typescript
92
// Get all pinned items in a channel
93
const pinnedItems = await web.pins.list({
94
channel: "C1234567890"
95
});
96
97
console.log(`Found ${pinnedItems.count} pinned items`);
98
99
// Process different types of pinned items
100
pinnedItems.items?.forEach(item => {
101
switch (item.type) {
102
case 'message':
103
console.log(`Pinned message: ${item.message?.text}`);
104
break;
105
case 'file':
106
console.log(`Pinned file: ${item.file?.name}`);
107
break;
108
case 'file_comment':
109
console.log(`Pinned file comment: ${item.comment?.comment}`);
110
break;
111
}
112
});
113
```
114
115
### Remove Pin
116
117
Remove a pin from a message in a channel.
118
119
```typescript { .api }
120
/**
121
* Remove a pin from an item in a channel
122
* @param options - Message parameters to unpin
123
* @returns Promise resolving to success confirmation
124
*/
125
pins.remove(options: PinsRemoveArguments): Promise<PinsRemoveResponse>;
126
127
interface PinsRemoveArguments extends MessageArgument, TokenOverridable {}
128
129
interface PinsRemoveResponse extends WebAPICallResult {
130
/** Whether the pin was successfully removed */
131
ok: boolean;
132
}
133
```
134
135
**Usage Examples:**
136
137
```typescript
138
// Remove a pin from a message
139
await web.pins.remove({
140
channel: "C1234567890",
141
timestamp: "1234567890.123456"
142
});
143
144
// Remove all pins from a channel (requires iteration)
145
const pinnedItems = await web.pins.list({
146
channel: "C1234567890"
147
});
148
149
for (const item of pinnedItems.items || []) {
150
if (item.type === 'message' && item.message?.ts) {
151
await web.pins.remove({
152
channel: "C1234567890",
153
timestamp: item.message.ts
154
});
155
}
156
}
157
```
158
159
## Pin Management Patterns
160
161
### Conditional Pinning
162
163
Check if a message is already pinned before adding:
164
165
```typescript
166
const checkAndPin = async (channel: string, timestamp: string) => {
167
const pinnedItems = await web.pins.list({ channel });
168
169
const isAlreadyPinned = pinnedItems.items?.some(
170
item => item.type === 'message' && item.message?.ts === timestamp
171
);
172
173
if (!isAlreadyPinned) {
174
await web.pins.add({ channel, timestamp });
175
console.log('Message pinned successfully');
176
} else {
177
console.log('Message is already pinned');
178
}
179
};
180
```
181
182
### Pin Rotation
183
184
Maintain a maximum number of pins by removing oldest when adding new:
185
186
```typescript
187
const pinWithRotation = async (channel: string, timestamp: string, maxPins = 5) => {
188
const pinnedItems = await web.pins.list({ channel });
189
190
// If at max capacity, remove oldest pin
191
if (pinnedItems.items && pinnedItems.items.length >= maxPins) {
192
const oldestPin = pinnedItems.items
193
.filter(item => item.type === 'message')
194
.sort((a, b) => (a.created || 0) - (b.created || 0))[0];
195
196
if (oldestPin?.message?.ts) {
197
await web.pins.remove({
198
channel,
199
timestamp: oldestPin.message.ts
200
});
201
}
202
}
203
204
// Add new pin
205
await web.pins.add({ channel, timestamp });
206
};
207
```
208
209
## Core Types
210
211
```typescript { .api }
212
interface TokenOverridable {
213
/** Override the default token for this request */
214
token?: string;
215
}
216
217
interface Message {
218
/** Message text content */
219
text?: string;
220
/** Message timestamp */
221
ts?: string;
222
/** User who sent the message */
223
user?: string;
224
/** Message type */
225
type?: string;
226
/** Message subtype */
227
subtype?: string;
228
/** Message attachments */
229
attachments?: MessageAttachment[];
230
/** Message blocks */
231
blocks?: Block[];
232
/** Thread timestamp if message is in a thread */
233
thread_ts?: string;
234
}
235
236
interface File {
237
/** File ID */
238
id?: string;
239
/** File name */
240
name?: string;
241
/** File title */
242
title?: string;
243
/** File size in bytes */
244
size?: number;
245
/** File MIME type */
246
mimetype?: string;
247
/** File URL */
248
url_private?: string;
249
/** User who uploaded the file */
250
user?: string;
251
}
252
253
interface FileComment {
254
/** Comment ID */
255
id?: string;
256
/** Comment text */
257
comment?: string;
258
/** User who created the comment */
259
user?: string;
260
/** Comment timestamp */
261
timestamp?: number;
262
}
263
```