Sessions API
Sessions represent active or historical connections to workspaces. Each session tracks the user, workspace, connection details, and security status.
Session Model
Unique session identifier (UUID v4)
ID of the user who created the session
Email of the user who created the session
ID of the workspace being accessed
Name of the workspace being accessed
Type of the workspace (e.g., “html5”, “rdp”, “linux”)
Session status: "active", "disconnected", "terminated"
Timestamp when the session started (ISO 8601 format)
Timestamp when the session ended (null if still active)
IP address of the session (defaults to “10.0.0.1”)
VPN tunnel status (defaults to “encrypted”)
Whether MFA was verified for this session (defaults to true)
List Sessions
Get all sessions for the authenticated user.
curl https://your-domain.com/api/sessions \
-H "Authorization: Bearer your-token-here"
Response
[
{
"id" : "f47ac10b-58cc-4372-a567-0e02b2c3d479" ,
"user_id" : "a3d2c1b0-9876-4321-abcd-ef1234567890" ,
"user_email" : "john.doe@acme.com" ,
"workspace_id" : "ws-sap-neogenesys" ,
"workspace_name" : "SAP Neogénesys" ,
"workspace_type" : "html5" ,
"status" : "active" ,
"started_at" : "2026-03-05T14:30:00.000Z" ,
"ended_at" : null ,
"ip_address" : "10.0.0.1" ,
"tunnel_status" : "encrypted" ,
"mfa_verified" : true
},
{
"id" : "b2c3d4e5-6789-4abc-def0-123456789abc" ,
"user_id" : "a3d2c1b0-9876-4321-abcd-ef1234567890" ,
"user_email" : "john.doe@acme.com" ,
"workspace_id" : "ws-linux-desktop" ,
"workspace_name" : "Linux Desktop" ,
"workspace_type" : "linux" ,
"status" : "terminated" ,
"started_at" : "2026-03-04T09:15:00.000Z" ,
"ended_at" : "2026-03-04T17:45:00.000Z" ,
"ip_address" : "10.0.0.1" ,
"tunnel_status" : "encrypted" ,
"mfa_verified" : true
}
]
Users can only see their own sessions. The API automatically filters by user_id.
List Active Sessions
Get only currently active sessions for the authenticated user.
curl https://your-domain.com/api/sessions/active \
-H "Authorization: Bearer your-token-here"
Response
Returns an array of sessions with status: "active".
[
{
"id" : "f47ac10b-58cc-4372-a567-0e02b2c3d479" ,
"user_id" : "a3d2c1b0-9876-4321-abcd-ef1234567890" ,
"user_email" : "john.doe@acme.com" ,
"workspace_id" : "ws-sap-neogenesys" ,
"workspace_name" : "SAP Neogénesys" ,
"workspace_type" : "html5" ,
"status" : "active" ,
"started_at" : "2026-03-05T14:30:00.000Z" ,
"ended_at" : null ,
"ip_address" : "10.0.0.1" ,
"tunnel_status" : "encrypted" ,
"mfa_verified" : true
}
]
Create Session
Sessions are automatically created when launching a workspace. See the Workspaces API - Launch Workspace endpoint.
When you call POST /api/workspaces/{workspace_id}/launch, the API:
Creates a new session with the current user’s information
Sets the session status to "active"
Links the session to the workspace
Returns the session ID and connection details
Disconnect Session
Disconnect an active session and mark it as terminated.
curl -X POST https://your-domain.com/api/sessions/f47ac10b-58cc-4372-a567-0e02b2c3d479/disconnect \
-H "Authorization: Bearer your-token-here"
Response
{
"message" : "Session disconnected"
}
Automatic Actions
When a session is disconnected:
Session status is updated to "disconnected"
ended_at timestamp is set to current time
Associated workspace status is set to "available"
Audit log entry is created: "disconnect_session" action
Error Responses
{
"detail" : "Session not found"
}
Session doesn’t exist or doesn’t belong to the authenticated user
Session Status Values
Status Description activeSession is currently running disconnectedSession was manually disconnected terminatedSession was stopped (via workspace stop)
Session Lifecycle
Integration with Workspaces
Sessions are tightly integrated with the Workspaces API:
Creating Sessions
# Launch workspace (creates session)
curl -X POST https://your-domain.com/api/workspaces/ws-linux-desktop/launch \
-H "Authorization: Bearer your-token-here"
Response includes session information:
{
"session_id" : "f47ac10b-58cc-4372-a567-0e02b2c3d479" ,
"workspace" : { ... },
"stream_url" : "/viewer/f47ac10b-58cc-4372-a567-0e02b2c3d479" ,
"tunnel_status" : "encrypted" ,
"security" : { ... }
}
Stopping Workspaces
# Stop workspace (terminates session)
curl -X POST https://your-domain.com/api/workspaces/ws-linux-desktop/stop \
-H "Authorization: Bearer your-token-here"
This automatically:
Finds the active session for that workspace
Sets session status to "terminated"
Sets session ended_at timestamp
Updates workspace status to "available"
Security Features
All sessions enforce:
Encrypted Tunnels All sessions use WireGuard VPN via NetBird
MFA Verification MFA status is tracked per session
Identity Tracking User ID and email recorded for audit
Session Recording All activity can be recorded for compliance
Example: Monitor Active Sessions
import requests
import time
from datetime import datetime, timezone
BASE_URL = "https://your-domain.com/api"
token = "your-token-here"
headers = { "Authorization" : f "Bearer { token } " }
def monitor_sessions ():
"""Monitor active sessions every 30 seconds"""
while True :
response = requests.get( f " { BASE_URL } /sessions/active" , headers = headers)
sessions = response.json()
print ( f " \n [ { datetime.now(timezone.utc) } ] Active Sessions: { len (sessions) } " )
for session in sessions:
started = datetime.fromisoformat(session[ 'started_at' ].replace( 'Z' , '+00:00' ))
duration = datetime.now(timezone.utc) - started
print ( f " - { session[ 'workspace_name' ] } " )
print ( f " Session ID: { session[ 'id' ] } " )
print ( f " Duration: { duration } " )
print ( f " Tunnel: { session[ 'tunnel_status' ] } " )
print ( f " MFA: { 'Verified' if session[ 'mfa_verified' ] else 'Not verified' } " )
time.sleep( 30 )
if __name__ == "__main__" :
monitor_sessions()
Example: Session Cleanup
import requests
from datetime import datetime, timedelta, timezone
BASE_URL = "https://your-domain.com/api"
token = "your-token-here"
headers = { "Authorization" : f "Bearer { token } " }
def cleanup_old_sessions ( max_duration_hours = 8 ):
"""Disconnect sessions running longer than max_duration_hours"""
response = requests.get( f " { BASE_URL } /sessions/active" , headers = headers)
sessions = response.json()
cutoff_time = datetime.now(timezone.utc) - timedelta( hours = max_duration_hours)
for session in sessions:
started = datetime.fromisoformat(session[ 'started_at' ].replace( 'Z' , '+00:00' ))
if started < cutoff_time:
print ( f "Disconnecting old session: { session[ 'workspace_name' ] } " )
requests.post(
f " { BASE_URL } /sessions/ { session[ 'id' ] } /disconnect" ,
headers = headers
)
print ( f " Session { session[ 'id' ] } disconnected" )
if __name__ == "__main__" :
cleanup_old_sessions( max_duration_hours = 8 )