0
# User Management
1
2
User operations including profile access, team memberships, issue assignments, and organizational data management.
3
4
## Capabilities
5
6
### Core User Operations
7
8
Basic user management operations for accessing user profiles and information.
9
10
```python { .api }
11
def get(self, user_id: str) -> LinearUser:
12
"""
13
Fetch a Linear user by ID with comprehensive user details and organization information.
14
15
Args:
16
user_id: The ID of the user to fetch
17
18
Returns:
19
LinearUser with complete details
20
21
Raises:
22
ValueError: If user not found
23
"""
24
25
def get_all(self) -> Dict[str, LinearUser]:
26
"""
27
Get all users in the organization.
28
29
Returns:
30
Dictionary mapping user IDs to LinearUser objects
31
"""
32
33
def get_me(self) -> LinearUser:
34
"""
35
Get the current user based on the API key.
36
37
Returns:
38
LinearUser object for the authenticated user
39
40
Raises:
41
ValueError: If authentication fails
42
"""
43
```
44
45
Usage examples:
46
47
```python
48
from linear_api import LinearClient
49
50
client = LinearClient()
51
52
# Get current user
53
me = client.users.get_me()
54
print(f"Current user: {me.name} ({me.email})")
55
print(f"Admin: {me.admin}, Active: {me.active}")
56
57
# Get specific user
58
user = client.users.get("user-id")
59
print(f"User: {user.displayName} - {user.email}")
60
61
# Get all organization users
62
all_users = client.users.get_all()
63
print(f"Organization has {len(all_users)} users")
64
```
65
66
### User Discovery
67
68
Find users by various identifiers and attributes.
69
70
```python { .api }
71
def get_email_map(self) -> Dict[str, str]:
72
"""
73
Get a mapping of user IDs to their email addresses.
74
75
Returns:
76
Dictionary mapping user IDs to email addresses
77
"""
78
79
def get_id_by_email(self, email: str) -> str:
80
"""
81
Get a user ID by their email address.
82
83
Args:
84
email: The email address to search for
85
86
Returns:
87
User ID string
88
89
Raises:
90
ValueError: If user not found
91
"""
92
93
def get_id_by_name(self, name: str) -> str:
94
"""
95
Get a user ID by their name (fuzzy match with exact, case-insensitive,
96
and partial matching).
97
98
Args:
99
name: The name to search for
100
101
Returns:
102
User ID string
103
104
Raises:
105
ValueError: If user not found
106
"""
107
```
108
109
Usage examples:
110
111
```python
112
# Get email mapping for all users
113
email_map = client.users.get_email_map()
114
print(f"Found {len(email_map)} users with emails")
115
116
# Find user by email
117
user_id = client.users.get_id_by_email("john.doe@company.com")
118
user = client.users.get(user_id)
119
120
# Find user by name (fuzzy matching)
121
user_id = client.users.get_id_by_name("John Doe")
122
# Also works with partial matches:
123
# user_id = client.users.get_id_by_name("john")
124
# user_id = client.users.get_id_by_name("John")
125
```
126
127
### Issue Management
128
129
Access issues assigned to or created by users.
130
131
```python { .api }
132
def get_assigned_issues(self, user_id: str) -> Dict[str, LinearIssue]:
133
"""
134
Get issues assigned to a user.
135
136
Args:
137
user_id: The ID of the user
138
139
Returns:
140
Dictionary mapping issue IDs to LinearIssue objects
141
"""
142
143
def get_created_issues(self, user_id: str) -> List[Dict[str, Any]]:
144
"""
145
Get issues created by a user with basic issue information.
146
147
Args:
148
user_id: The ID of the user
149
150
Returns:
151
List of issue dictionaries
152
"""
153
```
154
155
Usage examples:
156
157
```python
158
# Get user's assigned issues
159
assigned_issues = client.users.get_assigned_issues("user-id")
160
print(f"User has {len(assigned_issues)} assigned issues")
161
162
# Group by status
163
from collections import defaultdict
164
by_status = defaultdict(list)
165
for issue in assigned_issues.values():
166
by_status[issue.state.name].append(issue)
167
168
print("Issues by status:")
169
for status, issues in by_status.items():
170
print(f" {status}: {len(issues)} issues")
171
172
# Get issues created by user
173
created_issues = client.users.get_created_issues("user-id")
174
print(f"User has created {len(created_issues)} issues")
175
```
176
177
### Team Membership
178
179
Access user team memberships and organizational relationships.
180
181
```python { .api }
182
def get_team_memberships(self, user_id: str) -> List[Dict[str, Any]]:
183
"""
184
Get team memberships for a user with team information included.
185
186
Args:
187
user_id: The ID of the user
188
189
Returns:
190
List of team membership dictionaries
191
"""
192
193
def get_teams(self, user_id: str) -> List[LinearTeam]:
194
"""
195
Get teams that a user is a member of.
196
197
Args:
198
user_id: The ID of the user
199
200
Returns:
201
List of LinearTeam objects
202
"""
203
```
204
205
Usage examples:
206
207
```python
208
# Get user's team memberships
209
memberships = client.users.get_team_memberships("user-id")
210
print(f"User is a member of {len(memberships)} teams")
211
212
for membership in memberships:
213
team_info = membership.get('team', {})
214
is_owner = membership.get('owner', False)
215
print(f" - {team_info.get('name')} {'(Owner)' if is_owner else ''}")
216
217
# Get teams directly
218
teams = client.users.get_teams("user-id")
219
for team in teams:
220
print(f"Team: {team.name} ({team.key})")
221
```
222
223
### Draft Management
224
225
Access document and issue drafts created by users.
226
227
```python { .api }
228
def get_drafts(self, user_id: str) -> List[Draft]:
229
"""
230
Get document drafts created by a user.
231
232
Args:
233
user_id: The ID of the user
234
235
Returns:
236
List of Draft objects
237
"""
238
239
def get_issue_drafts(self, user_id: str) -> List[IssueDraft]:
240
"""
241
Get issue drafts created by a user.
242
243
Args:
244
user_id: The ID of the user
245
246
Returns:
247
List of IssueDraft objects
248
"""
249
```
250
251
Usage examples:
252
253
```python
254
# Get user's document drafts
255
drafts = client.users.get_drafts("user-id")
256
print(f"User has {len(drafts)} document drafts")
257
258
# Get user's issue drafts
259
issue_drafts = client.users.get_issue_drafts("user-id")
260
print(f"User has {len(issue_drafts)} issue drafts")
261
```
262
263
### Cache Management
264
265
Control caching for user-related data.
266
267
```python { .api }
268
def invalidate_cache(self) -> None:
269
"""
270
Invalidate all user-related caches.
271
"""
272
```
273
274
Usage examples:
275
276
```python
277
# Clear user caches
278
client.users.invalidate_cache()
279
```
280
281
## User Properties and Attributes
282
283
The LinearUser model includes comprehensive user information:
284
285
### Core User Fields
286
287
```python
288
user = client.users.get_me()
289
290
# Required fields
291
print(f"ID: {user.id}")
292
print(f"Name: {user.name}")
293
print(f"Display Name: {user.displayName}")
294
print(f"Email: {user.email}")
295
print(f"Created: {user.createdAt}")
296
print(f"Updated: {user.updatedAt}")
297
298
# Boolean status fields
299
print(f"Active: {user.active}")
300
print(f"Admin: {user.admin}")
301
print(f"App User: {user.app}")
302
print(f"Guest: {user.guest}")
303
print(f"Is Me: {user.isMe}")
304
```
305
306
### Optional User Fields
307
308
```python
309
# Optional profile information
310
if user.avatarUrl:
311
print(f"Avatar: {user.avatarUrl}")
312
313
if user.description:
314
print(f"Description: {user.description}")
315
316
if user.timezone:
317
print(f"Timezone: {user.timezone}")
318
319
if user.statusEmoji:
320
print(f"Status: {user.statusEmoji} {user.statusLabel}")
321
322
# Usage statistics
323
if hasattr(user, 'createdIssueCount'):
324
print(f"Created issues: {user.createdIssueCount}")
325
326
# Calendar integration
327
if user.calendarHash:
328
print(f"Calendar hash: {user.calendarHash}")
329
```
330
331
## Advanced User Workflows
332
333
### User Activity Analysis
334
335
```python
336
def analyze_user_activity(user_id: str):
337
user = client.users.get(user_id)
338
assigned_issues = client.users.get_assigned_issues(user_id)
339
created_issues = client.users.get_created_issues(user_id)
340
teams = client.users.get_teams(user_id)
341
342
print(f"User Activity Report: {user.displayName}")
343
print(f"Email: {user.email}")
344
print(f"Status: {'Active' if user.active else 'Inactive'}")
345
print(f"Admin: {'Yes' if user.admin else 'No'}")
346
print(f"Teams: {len(teams)}")
347
print(f"Assigned Issues: {len(assigned_issues)}")
348
print(f"Created Issues: {len(created_issues)}")
349
350
# Analyze assigned issue states
351
if assigned_issues:
352
state_counts = {}
353
for issue in assigned_issues.values():
354
state = issue.state.name
355
state_counts[state] = state_counts.get(state, 0) + 1
356
357
print("\nAssigned Issues by State:")
358
for state, count in state_counts.items():
359
print(f" {state}: {count}")
360
361
# List teams
362
if teams:
363
print("\nTeam Memberships:")
364
for team in teams:
365
print(f" - {team.name} ({team.key})")
366
367
return {
368
"user": user,
369
"team_count": len(teams),
370
"assigned_issues": len(assigned_issues),
371
"created_issues": len(created_issues)
372
}
373
374
# Analyze user activity
375
activity = analyze_user_activity("user-id")
376
```
377
378
### Team Member Directory
379
380
```python
381
def create_team_directory():
382
all_users = client.users.get_all()
383
384
# Filter active users
385
active_users = {uid: user for uid, user in all_users.items() if user.active}
386
387
# Group by team membership
388
team_members = {}
389
390
for user_id, user in active_users.items():
391
teams = client.users.get_teams(user_id)
392
for team in teams:
393
if team.id not in team_members:
394
team_members[team.id] = {
395
'team': team,
396
'members': []
397
}
398
team_members[team.id]['members'].append(user)
399
400
print("Team Directory:")
401
print("=" * 50)
402
403
for team_id, team_data in team_members.items():
404
team = team_data['team']
405
members = team_data['members']
406
407
print(f"\n{team.name} ({team.key})")
408
print("-" * 30)
409
410
# Sort members by name
411
members.sort(key=lambda u: u.displayName.lower())
412
413
for member in members:
414
admin_badge = " [ADMIN]" if member.admin else ""
415
print(f" • {member.displayName} ({member.email}){admin_badge}")
416
417
print(f" Total: {len(members)} members")
418
419
# Create directory
420
create_team_directory()
421
```
422
423
### User Workload Analysis
424
425
```python
426
def analyze_workloads():
427
all_users = client.users.get_all()
428
workloads = []
429
430
for user_id, user in all_users.items():
431
if not user.active:
432
continue
433
434
assigned_issues = client.users.get_assigned_issues(user_id)
435
436
# Calculate workload metrics
437
total_issues = len(assigned_issues)
438
in_progress = sum(1 for issue in assigned_issues.values()
439
if issue.state.type == 'started')
440
441
workloads.append({
442
'user': user,
443
'total_issues': total_issues,
444
'in_progress': in_progress,
445
'workload_score': in_progress + (total_issues * 0.3)
446
})
447
448
# Sort by workload
449
workloads.sort(key=lambda w: w['workload_score'], reverse=True)
450
451
print("User Workload Analysis:")
452
print("=" * 60)
453
print(f"{'Name':<25} {'Total':<8} {'Active':<8} {'Workload':<10}")
454
print("-" * 60)
455
456
for workload in workloads[:20]: # Top 20
457
user = workload['user']
458
print(f"{user.displayName:<25} {workload['total_issues']:<8} "
459
f"{workload['in_progress']:<8} {workload['workload_score']:<10.1f}")
460
461
# Analyze workloads
462
analyze_workloads()
463
```
464
465
### User Search and Filtering
466
467
```python
468
def search_users(query: str, filters: dict = None):
469
"""
470
Search for users with flexible criteria.
471
472
Args:
473
query: Search term for name or email
474
filters: Additional filters (active, admin, teams, etc.)
475
"""
476
all_users = client.users.get_all()
477
results = []
478
479
query_lower = query.lower()
480
481
for user_id, user in all_users.items():
482
# Text search
483
matches_query = (
484
query_lower in user.name.lower() or
485
query_lower in user.displayName.lower() or
486
query_lower in user.email.lower()
487
)
488
489
if not matches_query:
490
continue
491
492
# Apply filters
493
if filters:
494
if 'active' in filters and user.active != filters['active']:
495
continue
496
if 'admin' in filters and user.admin != filters['admin']:
497
continue
498
499
results.append(user)
500
501
# Sort by relevance (exact matches first, then by name)
502
def sort_key(user):
503
exact_name = user.name.lower() == query_lower
504
exact_display = user.displayName.lower() == query_lower
505
exact_email = user.email.lower() == query_lower
506
507
return (not (exact_name or exact_display or exact_email), user.displayName.lower())
508
509
results.sort(key=sort_key)
510
511
print(f"Search results for '{query}':")
512
for user in results[:10]: # Top 10 results
513
status = "Active" if user.active else "Inactive"
514
admin = " [ADMIN]" if user.admin else ""
515
print(f" • {user.displayName} ({user.email}) - {status}{admin}")
516
517
return results
518
519
# Search examples
520
search_users("john") # Find users named John
521
search_users("@company.com") # Find users by email domain
522
search_users("", {'active': True, 'admin': True}) # Find active admins
523
```
524
525
### Organization Metrics
526
527
```python
528
def get_organization_metrics():
529
all_users = client.users.get_all()
530
531
# Calculate metrics
532
total_users = len(all_users)
533
active_users = sum(1 for user in all_users.values() if user.active)
534
admin_users = sum(1 for user in all_users.values() if user.admin)
535
guest_users = sum(1 for user in all_users.values() if user.guest)
536
537
print("Organization User Metrics:")
538
print("=" * 40)
539
print(f"Total Users: {total_users}")
540
print(f"Active Users: {active_users} ({active_users/total_users:.1%})")
541
print(f"Admin Users: {admin_users} ({admin_users/total_users:.1%})")
542
print(f"Guest Users: {guest_users} ({guest_users/total_users:.1%})")
543
print(f"Inactive Users: {total_users - active_users}")
544
545
# Get all teams for team membership analysis
546
all_teams = client.teams.get_all()
547
team_memberships = 0
548
549
for user in all_users.values():
550
if user.active:
551
teams = client.users.get_teams(user.id)
552
team_memberships += len(teams)
553
554
avg_teams = team_memberships / active_users if active_users > 0 else 0
555
print(f"Average teams per active user: {avg_teams:.1f}")
556
557
return {
558
'total': total_users,
559
'active': active_users,
560
'admin': admin_users,
561
'guest': guest_users,
562
'avg_teams_per_user': avg_teams
563
}
564
565
# Get organization metrics
566
metrics = get_organization_metrics()
567
```