0
# REST API System
1
2
JupyterHub provides a comprehensive REST API for external integration and programmatic management of users, servers, groups, services, and system configuration. The API supports JSON requests/responses and uses token-based authentication.
3
4
## Capabilities
5
6
### Base API Handler
7
8
Foundation class for all REST API endpoints in JupyterHub.
9
10
```python { .api }
11
class APIHandler(BaseHandler):
12
"""
13
Base class for REST API handlers.
14
15
Provides JSON request/response handling, authentication,
16
and common API functionality.
17
"""
18
19
def get_current_user(self):
20
"""
21
Get the current authenticated user.
22
23
Returns:
24
User object if authenticated, None otherwise
25
"""
26
27
def get_current_user_token(self):
28
"""
29
Get the current API token.
30
31
Returns:
32
APIToken object if token auth, None otherwise
33
"""
34
35
def check_xsrf_cookie(self):
36
"""Check XSRF cookie for API requests"""
37
38
def get_json_body(self):
39
"""
40
Parse JSON request body.
41
42
Returns:
43
Parsed JSON data as Python object
44
45
Raises:
46
HTTPError: If JSON is invalid
47
"""
48
49
def write_error(self, status_code, **kwargs):
50
"""
51
Write JSON error response.
52
53
Args:
54
status_code: HTTP status code
55
**kwargs: Additional error context
56
"""
57
```
58
59
### User Management API
60
61
REST endpoints for managing JupyterHub users and their servers.
62
63
```python { .api }
64
# GET /api/users
65
# List all users
66
def get_users() -> List[Dict[str, Any]]:
67
"""
68
Get list of all users.
69
70
Returns:
71
List of user objects with basic information
72
"""
73
74
# GET /api/users/{name}
75
def get_user(name: str) -> Dict[str, Any]:
76
"""
77
Get information about a specific user.
78
79
Args:
80
name: Username
81
82
Returns:
83
User object with servers, groups, and roles
84
"""
85
86
# POST /api/users/{name}
87
def create_user(name: str, admin: bool = False) -> Dict[str, Any]:
88
"""
89
Create a new user.
90
91
Args:
92
name: Username
93
admin: Whether user should be admin
94
95
Returns:
96
Created user object
97
"""
98
99
# PATCH /api/users/{name}
100
def modify_user(name: str, admin: bool = None) -> Dict[str, Any]:
101
"""
102
Modify user properties.
103
104
Args:
105
name: Username
106
admin: Admin status to set
107
108
Returns:
109
Updated user object
110
"""
111
112
# DELETE /api/users/{name}
113
def delete_user(name: str) -> None:
114
"""
115
Delete a user and all their servers.
116
117
Args:
118
name: Username to delete
119
"""
120
121
# POST /api/users/{name}/server
122
def start_user_server(name: str, server_name: str = '') -> Dict[str, Any]:
123
"""
124
Start a user's server.
125
126
Args:
127
name: Username
128
server_name: Named server (empty for default)
129
130
Returns:
131
Server start result
132
"""
133
134
# DELETE /api/users/{name}/server
135
def stop_user_server(name: str, server_name: str = '') -> None:
136
"""
137
Stop a user's server.
138
139
Args:
140
name: Username
141
server_name: Named server (empty for default)
142
"""
143
144
# GET /api/users/{name}/tokens
145
def get_user_tokens(name: str) -> List[Dict[str, Any]]:
146
"""
147
Get user's API tokens.
148
149
Args:
150
name: Username
151
152
Returns:
153
List of token information (without actual token values)
154
"""
155
156
# POST /api/users/{name}/tokens
157
def create_user_token(name: str, expires_in: int = None, note: str = None) -> Dict[str, Any]:
158
"""
159
Create API token for user.
160
161
Args:
162
name: Username
163
expires_in: Token lifetime in seconds
164
note: Token description
165
166
Returns:
167
Token information with actual token value
168
"""
169
```
170
171
### Group Management API
172
173
REST endpoints for managing user groups and group membership.
174
175
```python { .api }
176
# GET /api/groups
177
def get_groups() -> List[Dict[str, Any]]:
178
"""
179
Get list of all groups.
180
181
Returns:
182
List of group objects with member information
183
"""
184
185
# GET /api/groups/{name}
186
def get_group(name: str) -> Dict[str, Any]:
187
"""
188
Get information about a specific group.
189
190
Args:
191
name: Group name
192
193
Returns:
194
Group object with users and roles
195
"""
196
197
# POST /api/groups/{name}
198
def create_group(name: str, users: List[str] = None) -> Dict[str, Any]:
199
"""
200
Create a new group.
201
202
Args:
203
name: Group name
204
users: Initial list of usernames
205
206
Returns:
207
Created group object
208
"""
209
210
# POST /api/groups/{name}/users
211
def add_group_users(name: str, users: List[str]) -> Dict[str, Any]:
212
"""
213
Add users to a group.
214
215
Args:
216
name: Group name
217
users: List of usernames to add
218
219
Returns:
220
Updated group object
221
"""
222
223
# DELETE /api/groups/{name}/users
224
def remove_group_users(name: str, users: List[str]) -> Dict[str, Any]:
225
"""
226
Remove users from a group.
227
228
Args:
229
name: Group name
230
users: List of usernames to remove
231
232
Returns:
233
Updated group object
234
"""
235
236
# DELETE /api/groups/{name}
237
def delete_group(name: str) -> None:
238
"""
239
Delete a group.
240
241
Args:
242
name: Group name to delete
243
"""
244
```
245
246
### Service Management API
247
248
REST endpoints for managing external services integrated with JupyterHub.
249
250
```python { .api }
251
# GET /api/services
252
def get_services() -> List[Dict[str, Any]]:
253
"""
254
Get list of all services.
255
256
Returns:
257
List of service objects
258
"""
259
260
# GET /api/services/{name}
261
def get_service(name: str) -> Dict[str, Any]:
262
"""
263
Get information about a specific service.
264
265
Args:
266
name: Service name
267
268
Returns:
269
Service object with configuration and status
270
"""
271
272
# POST /api/services/{name}
273
def create_service(name: str, url: str, admin: bool = False) -> Dict[str, Any]:
274
"""
275
Register a new service.
276
277
Args:
278
name: Service name
279
url: Service URL
280
admin: Whether service has admin privileges
281
282
Returns:
283
Created service object
284
"""
285
286
# DELETE /api/services/{name}
287
def delete_service(name: str) -> None:
288
"""
289
Unregister a service.
290
291
Args:
292
name: Service name to delete
293
"""
294
```
295
296
### Server Sharing API
297
298
REST endpoints for the server sharing functionality.
299
300
```python { .api }
301
# GET /api/shares/{code}
302
def get_share(code: str) -> Dict[str, Any]:
303
"""
304
Get information about a server share.
305
306
Args:
307
code: Share access code
308
309
Returns:
310
Share information and server details
311
"""
312
313
# POST /api/shares
314
def create_share(server_name: str = '', expires_in: int = None) -> Dict[str, Any]:
315
"""
316
Create a server share.
317
318
Args:
319
server_name: Server to share (empty for default)
320
expires_in: Share lifetime in seconds
321
322
Returns:
323
Share code and access information
324
"""
325
326
# POST /api/shares/{code}/accept
327
def accept_share(code: str) -> Dict[str, Any]:
328
"""
329
Accept a server share invitation.
330
331
Args:
332
code: Share access code
333
334
Returns:
335
Server access information
336
"""
337
```
338
339
### Hub Management API
340
341
REST endpoints for managing the JupyterHub system itself.
342
343
```python { .api }
344
# GET /api/hub/info
345
def get_hub_info() -> Dict[str, Any]:
346
"""
347
Get JupyterHub version and configuration info.
348
349
Returns:
350
Hub version, Python version, and basic config
351
"""
352
353
# POST /api/hub/shutdown
354
def shutdown_hub() -> Dict[str, Any]:
355
"""
356
Shutdown the JupyterHub system.
357
358
Returns:
359
Shutdown confirmation
360
"""
361
362
# GET /api/info
363
def get_info() -> Dict[str, Any]:
364
"""
365
Get general system information.
366
367
Returns:
368
JupyterHub version and basic system info
369
"""
370
```
371
372
### Proxy Management API
373
374
REST endpoints for managing the HTTP proxy component.
375
376
```python { .api }
377
# GET /api/proxy
378
def get_proxy_routes() -> Dict[str, Dict[str, Any]]:
379
"""
380
Get current proxy routing table.
381
382
Returns:
383
Dictionary of routes with target information
384
"""
385
386
# POST /api/proxy
387
def add_proxy_route(path: str, target: str) -> None:
388
"""
389
Add a route to the proxy.
390
391
Args:
392
path: URL path to route
393
target: Target URL to proxy to
394
"""
395
396
# DELETE /api/proxy/{path}
397
def delete_proxy_route(path: str) -> None:
398
"""
399
Remove a route from the proxy.
400
401
Args:
402
path: URL path to remove
403
"""
404
```
405
406
## Usage Examples
407
408
### Authentication
409
410
```python
411
import requests
412
413
# Token-based authentication
414
headers = {
415
'Authorization': f'Bearer {api_token}',
416
'Content-Type': 'application/json'
417
}
418
419
# Make authenticated request
420
response = requests.get(
421
'http://jupyterhub.example.com/api/users',
422
headers=headers
423
)
424
users = response.json()
425
```
426
427
### User Management
428
429
```python
430
# Create a new user
431
response = requests.post(
432
'http://jupyterhub.example.com/api/users/alice',
433
headers=headers,
434
json={'admin': False}
435
)
436
user = response.json()
437
438
# Start user's server
439
response = requests.post(
440
'http://jupyterhub.example.com/api/users/alice/server',
441
headers=headers
442
)
443
444
# Get user information
445
response = requests.get(
446
'http://jupyterhub.example.com/api/users/alice',
447
headers=headers
448
)
449
user_info = response.json()
450
```
451
452
### Group Operations
453
454
```python
455
# Create group with initial users
456
response = requests.post(
457
'http://jupyterhub.example.com/api/groups/students',
458
headers=headers,
459
json={'users': ['alice', 'bob', 'charlie']}
460
)
461
462
# Add users to existing group
463
response = requests.post(
464
'http://jupyterhub.example.com/api/groups/students/users',
465
headers=headers,
466
json={'users': ['david', 'eve']}
467
)
468
```
469
470
### Service Integration
471
472
```python
473
# Register external service
474
response = requests.post(
475
'http://jupyterhub.example.com/api/services/my-service',
476
headers=headers,
477
json={
478
'url': 'http://localhost:8001',
479
'admin': False
480
}
481
)
482
483
# Get service status
484
response = requests.get(
485
'http://jupyterhub.example.com/api/services/my-service',
486
headers=headers
487
)
488
service_info = response.json()
489
```
490
491
### Python Client Library
492
493
```python
494
from jupyterhub.services.auth import HubAuth
495
496
# Initialize Hub authentication
497
auth = HubAuth(
498
api_token='your-api-token',
499
api_url='http://jupyterhub.example.com/hub/api'
500
)
501
502
# Make authenticated requests
503
async def get_users():
504
"""Get all users via API"""
505
response = await auth.api_request('GET', '/users')
506
return response.json()
507
508
async def start_server(username):
509
"""Start user's server"""
510
response = await auth.api_request(
511
'POST',
512
f'/users/{username}/server'
513
)
514
return response.json()
515
```
516
517
## API Response Formats
518
519
### User Object
520
521
```python
522
{
523
"name": "alice",
524
"admin": false,
525
"groups": ["students"],
526
"server": "/user/alice/",
527
"pending": null,
528
"created": "2024-01-01T00:00:00.000000Z",
529
"last_activity": "2024-01-02T12:30:00.000000Z",
530
"servers": {
531
"": {
532
"name": "",
533
"last_activity": "2024-01-02T12:30:00.000000Z",
534
"started": "2024-01-02T12:00:00.000000Z",
535
"pending": null,
536
"ready": true,
537
"state": {},
538
"url": "/user/alice/",
539
"user_options": {},
540
"progress_url": "/hub/api/users/alice/server/progress"
541
}
542
}
543
}
544
```
545
546
### Group Object
547
548
```python
549
{
550
"name": "students",
551
"users": ["alice", "bob", "charlie"],
552
"roles": ["student-role"]
553
}
554
```
555
556
### Service Object
557
558
```python
559
{
560
"name": "announcement-service",
561
"admin": false,
562
"url": "http://localhost:8001",
563
"prefix": "/services/announcement-service",
564
"pid": 12345,
565
"managed": true,
566
"info": {
567
"status": "running"
568
}
569
}
570
```
571
572
## Error Handling
573
574
```python
575
# API error response format
576
{
577
"status": 400,
578
"message": "Bad Request: Invalid user data"
579
}
580
581
# Common HTTP status codes
582
# 200 - Success
583
# 201 - Created
584
# 204 - No Content (successful deletion)
585
# 400 - Bad Request
586
# 401 - Unauthorized
587
# 403 - Forbidden
588
# 404 - Not Found
589
# 409 - Conflict (resource already exists)
590
# 500 - Internal Server Error
591
```