# Session Management Guide

> Deep dive into creating, managing, and controlling live streaming sessions.

Deep dive into creating, managing, and controlling live streaming sessions.

## Creating a Session

Sessions are the core unit of Synento. Every stream is attached to exactly one session:

```bash
curl -X POST https://api.synento.com/v1/projects/{projectId}/sessions \
  -H "Authorization: Bearer sk_live_xxxxx" \
  -H "Content-Type: application/json" \
  -d '{"name": "Team Standup"}'
```

Response:
```json
{ "data": {
  "id": "sess_abc123",
  "project_id": "proj_xyz789",
  "name": "Team Standup",
  "created_by": "api-key-user",
  "started_at": null,     // set when first participant joins
  "ended_at": null,       // set when last participant leaves
  "created_at": "2025-01-15T10:30:00.000Z"
}, "error": null }
```

### Options

| Field | Required | Default | Description |
|-------|----------|---------|-------------|
| `name` | No | "Untitled session" | Display name for the session |

## Session Lifecycle

```
Created → Waiting for participants...
   ↓ (first join)
Started — Active streaming, recording begins
   ↓ (participant leaves)
Still Started (other participants remain)...
   ↓ (last participant leaves)  
Ended — Recording complete, replay available immediately
```

### Lifecycle Timestamps

| Field | Set When | Value |
|-------|----------|-------|
| `created_at` | Session created via API | ISO 8601 timestamp |
| `started_at` | First participant joins | ISO 8601 timestamp |
| `ended_at` | Last participant leaves | ISO 8601 timestamp |

Duration calculation: `ended_at - started_at` (in milliseconds). Usage tracking records this as `streaming_minutes`.

## Listing Sessions

Retrieve all sessions for a project:

```bash
curl https://api.synento.com/v1/sessions \
  -H "Authorization: Bearer sk_live_xxxxx"
```

Returns sessions sorted by `created_at` DESC. The same endpoint is accessible via SDK:

```typescript
const sessions = await synento.listSessions();
// [{ id, name, startedAt, endedAt, createdAt }, ...]
```

## Getting Session Details

Fetch a single session:

```bash
curl https://api.synento.com/v1/projects/{projectId}/sessions/{sessionId} \
  -H "Authorization: Bearer sk_live_xxxxx"
```

## Connection Tokens

Every participant needs a connection token to join or replay:

### For Live Streaming
```bash
curl -X POST https://api.synento.com/v1/sessions/{sessionId}/connection \
  -H "Authorization: Bearer sk_live_xxxxx" \
  -d '{"user_id": "alice", "focus": ""}'
```

### For Replay Mode
```bash
curl -X POST https://api.synento.com/v1/sessions/{sessionId}/connection \
  -H "Authorization: Bearer sk_live_xxxxx" \
  -d '{"user_id": "viewer", "replay": true, "from_ts": 0, "speed": 1.0}'
```

### Token Connection Parameters

| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `user_id` | string | `"anonymous"` | Participant identifier (appears in chat/media headers) |
| `replay` | boolean | false | If true, enables replay mode instead of live streaming |
| `from_ts` | number (ms) | 0 | Replay start timestamp; use session's `min_ts` from timeline API |
| `speed` | number | 1.0 | Replay speed multiplier (0.25x to 4x) |
| `focus` | string | "" | Focus on a specific stream (user ID or empty for all) |

### Token Response

```json
{ "data": {
  "access_token": "jwt_eyJhbGc...",    // JWT valid for 5 minutes
  "expires_in": 300,                     // seconds until expiry
  "session": "sess_abc123"              // session ID
}, "error": null }
```

The connection token's `access_token` is used to connect via WebSocket:
```javascript
const wsUrl = synento.getWebSocketUrl(sessionId, accessToken, "alice");
// → wss://host/ws?session=sess_abc123&access_token=jwt_eyJhbGc...&user_id=alice
```

## Session Visibility Management

Sessions are private by default. Control who can replay them:

### Toggle Public/Private
```bash
# Make this session publicly accessible (no auth needed for replay)
curl -X PUT https://api.synento.com/v1/sessions/{sessionId}/visibility \
  -H "Authorization: Bearer sk_live_xxxxx" \
  -d '{"is_public": true}'

# Revert to private (only connection token holders can access)
curl -X PUT https://api.synento.com/v1/sessions/{sessionId}/visibility \
  -H "Authorization: Bearer sk_live_xxxxx" \
  -d '{"is_public": false}'
```

### Setting via SDK
```typescript
const result = await synento.setSessionVisibility(sessionId, true);  // make public
```

## Billing & Session Limits

New session creation is checked against billing limits:

- **Free tier**: 300 streaming minutes/month across the organisation
- If exceeded with no active Stripe subscription, new sessions are blocked (402 error)

Check current limits before creating sessions:
```bash
curl https://api.synento.com/v1/billing/limits \
  -H "Authorization: Bearer sk_live_xxxxx"

# Check before every new session in your app
const limits = await synento.getBillingLimits();
if (limits.isBlocked) {
  console.error(limits.statusMessage); // Show user-friendly error to developer
}
```

## Common Patterns

### Create Session, Get Token, Connect (All in One Flow)
```typescript
const session = await synento.createSession({ name: "Team Meeting" });
const token = await synento.createConnectionToken(session.id, { userId: "alice" });

// WebSocket URL
const wsUrl = synento.getWebSocketUrl(session.id, token.accessToken, "alice");

// For embedding in the browser (token generated server-side):
document.getElementById("player").src = wsUrl; // or use Player SDK with access_token
```

### List and Replay All Ended Sessions in a Project
```typescript
const sessions = await synento.listSessions();
for (const session of sessions) {
  if (session.endedAt && !session.isPublic) {
    const token = await synento.createConnectionToken(session.id, { 
      userId: "replay-bot",
      replay: true,
    });
    // Use the token with Player SDK or direct WebSocket for replay...
  }
}
```
