Submit access request
POST/api/access-requests
Authentication: bearer token.
Permission: any signed-in user.
Request body
| Name | Type | Required | Notes |
|---|---|---|---|
serverId | string | Yes | |
reason | string | Yes | At least 10 characters. |
requestedDuration | number | Yes | At least 60. |
requestedPrincipal | string | No | May be null. |
protocol | string | No | Default SSH. |
curl -X POST "https://shellius.example.com/api/access-requests" \
-H "Authorization: Bearer $SHELLIUS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"serverId": "…",
"reason": "…",
"requestedDuration": 0
}'201 Created
{ "success": true, "data": { … } }List requests
GET/api/access-requests
Authentication: bearer token.
Permission: any signed-in user.
Query parameters
| Name | Type | Required | Notes |
|---|---|---|---|
tab | string | No | One of mine, to-review, all. Default mine. |
status | string | No | One of PENDING, APPROVED, DENIED, EXPIRED, REVOKED. |
page | number | No | Default 1. At least 1. |
limit | number | No | Default 25. 1–100. |
curl -X GET "https://shellius.example.com/api/access-requests" \
-H "Authorization: Bearer $SHELLIUS_TOKEN"200 OK
{ "success": true, "data": { … } }Caller's active AR for a server
GET/api/access-requests/by-server/:serverId/active
Authentication: bearer token.
Permission: any signed-in user.
Path parameters
| Name | Type | Notes |
|---|---|---|
serverId | string |
curl -X GET "https://shellius.example.com/api/access-requests/by-server/{serverId}/active" \
-H "Authorization: Bearer $SHELLIUS_TOKEN"200 OK
{ "success": true, "data": { … } }UI intent for one server
GET/api/access-requests/intent
MUST be registered BEFORE /:id so Express doesn't match "intent" as an id.
Authentication: bearer token.
Permission: any signed-in user.
Query parameters
| Name | Type | Required | Notes |
|---|---|---|---|
serverId | — | No |
curl -X GET "https://shellius.example.com/api/access-requests/intent" \
-H "Authorization: Bearer $SHELLIUS_TOKEN"200 OK
{ "success": true, "data": { … } }Bulk intents
GET/api/access-requests/intents
Bulk sibling of /intent MUST be registered BEFORE /:id. Max 50 ids to bound query cost.
Authentication: bearer token.
Permission: any signed-in user.
Query parameters
| Name | Type | Required | Notes |
|---|---|---|---|
serverIds | — | No |
curl -X GET "https://shellius.example.com/api/access-requests/intents" \
-H "Authorization: Bearer $SHELLIUS_TOKEN"200 OK
{ "success": true, "data": { … } }Break glass start
POST/api/access-requests/break-glass/start
Step 1: validate + issue a step-up verification challenge. Grants nothing by itself.
Authentication: bearer token.
Permission: access.break_glass.
Request body
| Name | Type | Required | Notes |
|---|---|---|---|
serverId | string | Yes | |
reason | string | Yes | 20–1000 characters. |
durationSeconds | number | No | At least 300. |
method | string | No | One of totp, email. |
curl -X POST "https://shellius.example.com/api/access-requests/break-glass/start" \
-H "Authorization: Bearer $SHELLIUS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"serverId": "…",
"reason": "…"
}'201 Created
{ "success": true, "data": { … } }Break glass verify
POST/api/access-requests/break-glass/verify
Step 2: burn the challenge against the code and, on success, create the pre-approved AccessRequest.
Authentication: bearer token.
Permission: access.break_glass.
Request body
| Name | Type | Required | Notes |
|---|---|---|---|
challengeId | string | Yes | |
code | string | Yes |
curl -X POST "https://shellius.example.com/api/access-requests/break-glass/verify" \
-H "Authorization: Bearer $SHELLIUS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"challengeId": "…",
"code": "…"
}'201 Created
{ "success": true, "data": { … } }Self-approved emergency access
POST/api/access-requests/break-glass
Authentication: bearer token.
Permission: access.break_glass.
Request body
| Name | Type | Required | Notes |
|---|---|---|---|
serverId | string | Yes | |
reason | string | Yes | 20–1000 characters. |
durationSeconds | number | No | 300–3600. |
curl -X POST "https://shellius.example.com/api/access-requests/break-glass" \
-H "Authorization: Bearer $SHELLIUS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"serverId": "…",
"reason": "…"
}'200 OK
{ "success": true, "data": { … } }Get request
GET/api/access-requests/:id
Requester, reviewer, or admin+ Access control enforced in service via callerId/callerRole.
Authentication: bearer token.
Permission: any signed-in user.
Path parameters
| Name | Type | Notes |
|---|---|---|
id | string |
curl -X GET "https://shellius.example.com/api/access-requests/{id}" \
-H "Authorization: Bearer $SHELLIUS_TOKEN"200 OK
{ "success": true, "data": { … } }Approve/deny a PENDING request
PATCH/api/access-requests/:id/review
Reviewer only (service enforces)
Authentication: bearer token.
Permission: any signed-in user.
Path parameters
| Name | Type | Notes |
|---|---|---|
id | string |
Request body
| Name | Type | Required | Notes |
|---|---|---|---|
decision | string | Yes | One of approve, deny. |
approvedDuration | string | No | At least 60. |
deniedReason | string | Yes | At least 5. |
curl -X PATCH "https://shellius.example.com/api/access-requests/{id}/review" \
-H "Authorization: Bearer $SHELLIUS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"decision": "approve",
"deniedReason": "…"
}'200 OK
{ "success": true, "data": { … } }Revoke request
POST/api/access-requests/:id/revoke
Admin+ OR reviewer (service enforces)
Authentication: bearer token.
Permission: any signed-in user.
Path parameters
| Name | Type | Notes |
|---|---|---|
id | string |
Request body
| Name | Type | Required | Notes |
|---|---|---|---|
reason | string | No | At least 1 characters. |
curl -X POST "https://shellius.example.com/api/access-requests/{id}/revoke" \
-H "Authorization: Bearer $SHELLIUS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"reason": "…"
}'200 OK
{ "success": true, "data": { … } }Ephemeral key + cert download
POST/api/access-requests/:id/ssh-credentials
Requester only SECURITY: This endpoint returns an ephemeral Ed25519 private key. The private key crosses the wire exactly once here and is NEVER stored server-side. Callers must set Cache-Control: no-store on their end; we enforce it here via response headers.
Authentication: bearer token.
Permission: any signed-in user.
Path parameters
| Name | Type | Notes |
|---|---|---|
id | string |
curl -X POST "https://shellius.example.com/api/access-requests/{id}/ssh-credentials" \
-H "Authorization: Bearer $SHELLIUS_TOKEN"200 OK
{ "success": true, "data": { … } }.rdp file for approved RDP request
POST/api/access-requests/:id/rdp-credentials
Requester only.
Authentication: bearer token.
Permission: any signed-in user.
Path parameters
| Name | Type | Notes |
|---|---|---|
id | string |
curl -X POST "https://shellius.example.com/api/access-requests/{id}/rdp-credentials" \
-H "Authorization: Bearer $SHELLIUS_TOKEN"200 OK
{ "success": true, "data": { … } }5-min Guacamole gateway token
POST/api/access-requests/:id/rdp-token
Requester only Returns a short-lived gateway JWT (5 min) that the frontend passes as ?token= on the WebSocket RDP connection.
Authentication: bearer token.
Permission: any signed-in user.
Path parameters
| Name | Type | Notes |
|---|---|---|
id | string |
curl -X POST "https://shellius.example.com/api/access-requests/{id}/rdp-token" \
-H "Authorization: Bearer $SHELLIUS_TOKEN"200 OK
{ "success": true, "data": { … } }Stub web-terminal URL
POST/api/access-requests/:id/connect
Requester only TODO(phase-8): Wire to web terminal WebSocket session. Currently returns a stub URL for the xterm.js terminal page.
Authentication: bearer token.
Permission: any signed-in user.
Path parameters
| Name | Type | Notes |
|---|---|---|
id | string |
curl -X POST "https://shellius.example.com/api/access-requests/{id}/connect" \
-H "Authorization: Bearer $SHELLIUS_TOKEN"200 OK
{ "success": true, "data": { … } }