rusty-telemetry — REST API Reference

# rusty-telemetry — REST API Reference

> **Parent note:** [Sim Racing Telemetry Analysis Platform — Project Plan](joplin://6c0dcb2a567348fd9796f50c790082e4)
> **Repo:** `~/RustroverProjects/rusty-telemetry`
> **Companion:** [racecraft — Vue.js Web Client Notes](joplin://50a09627d5d347009197b94bcee90411)
> **Current version:** v0.6.0

---

## Server Configuration

| Env Var | Purpose | Default |
|---------|---------|---------|
| `RUSTY_TELEMETRY_API_PORT` | REST API server port | `8080` |
| `RUSTY_TELEMETRY_API_HOST` | REST API server bind address | `127.0.0.1` |
| `RUSTY_TELEMETRY_GAME_HOST` | IP of the sim machine (KSUDP handshake target, AC :9996) | `127.0.0.1` |
| `RUSTY_TELEMETRY_LISTEN` | Local bind address for incoming feeds (TT :10101, PCARS :5606) | `0.0.0.0` |
| `RUSTY_TELEMETRY_BIND` | Legacy fallback for both GAME_HOST and LISTEN | — |

---

## Endpoints

### Live Telemetry

| Method | Endpoint | Description |
|--------|----------|-------------|
| GET | `/api/live` | Live telemetry snapshot (all feeds: health, frequency, speed, RPM, gear, inputs, lap time) |

### Recordings

| Method | Endpoint | Description |
|--------|----------|-------------|
| GET | `/api/recordings` | List all recordings |
| POST | `/api/recordings` | Start new recording (JSON: name, game, track, car, use_case, notes — all optional) |
| GET | `/api/recordings/{id}` | Get recording manifest |
| POST | `/api/recordings/stop` | Stop active recording |
| POST | `/api/recordings/{id}/stop` | Stop specific recording |
| DELETE | `/api/recordings/{id}` | Delete recording (removes directory) |
| GET | `/api/recordings/{id}/data/{feed_name}` | Download raw feed binary |

### Metadata

| Method | Endpoint | Description |
|--------|----------|-------------|
| GET | `/api/use-cases` | List valid use cases (shift_points, racing_line, braking_analysis, lap_times, sector_analysis, track_map, general) |
| GET | `/api/games` | List supported games (assetto_corsa, assetto_corsa_competizione, project_cars_1, project_cars_2) |

### Sessions

| Method | Endpoint | Description |
|--------|----------|-------------|
| GET | `/api/sessions` | List all sessions |
| POST | `/api/sessions` | Create analysis session (JSON: use_case, label) |
| GET | `/api/sessions/{id}` | Get session details |
| DELETE | `/api/sessions/{id}` | Delete session |
| POST | `/api/sessions/{id}/complete` | Complete session and auto-analyze |
| GET | `/api/sessions/{id}/analysis` | Get analysis results |
| POST | `/api/sessions/{id}/analyze` | Re-run analysis on completed session |
| POST | `/api/sessions/{id}/reopen` | Re-open a completed session for further recording (v0.6.0) |

### Runs

| Method | Endpoint | Description |
|--------|----------|-------------|
| POST | `/api/sessions/{id}/runs` | Start a run (JSON: feed_name, label, merge_feeds) |
| POST | `/api/sessions/{id}/runs/{run_id}/stop` | Stop a run |
| DELETE | `/api/sessions/{id}/runs/{run_id}` | Delete a run from a session (v0.6.0) |

---

## Request/Response Formats

### Start Recording

```json
// POST /api/recordings
{
  "name": "optional name",
  "game": "assetto_corsa",
  "track": "optional track name",
  "car": "optional car name",
  "use_case": "shift_points",
  "notes": "optional notes"
}
```

### Create Session

```json
// POST /api/sessions
{
  "use_case": "shift_points",
  "label": "optional label"
}
```

### Start Run

```json
// POST /api/sessions/{id}/runs
{
  "feed_name": "ksudp",
  "label": "optional label",
  "merge_feeds": ["telemetry_tool"]
}
```

`merge_feeds` is optional (v0.6.0). When provided, the run merges data from the listed additional feeds with the primary `feed_name`, deduplicating by timestamp.

### Run Response

```json
{
  "id": "uuid",
  "label": "run label",
  "feed_name": "ksudp",
  "status": "recording | stopped",
  "start_marker": 0,
  "end_marker": null,
  "frame_count": 0,
  "data_truncated": false
}
```

### Session Response

```json
{
  "id": "uuid",
  "use_case": "shift_points",
  "label": "session label",
  "status": "active | completed",
  "created_at": "ISO 8601",
  "completed_at": "ISO 8601 | null",
  "runs": [],
  "analysis": null,
  "guidance": "string | null",
  "recording_id": "uuid | null"
}
```

### Delete Run Response

```
// DELETE /api/sessions/{id}/runs/{run_id}
// Returns 204 No Content on success
```

### Reopen Session Response

```
// POST /api/sessions/{id}/reopen
// Returns updated UseCaseSession (status: "active", analysis cleared)
```

---

## UDP Feed Ports

| Port | Feed | Protocol | Status |
|------|------|----------|--------|
| 9996 | KSUDP | AC 3-phase handshake | Optional — handshake to GAME_HOST |
| 10101 | Telemetry Tool | AC binary (357-byte driver struct) | Optional — bind to LISTEN |
| 5606 | PCARS | Binary (auto-detect V1/V2) | Optional — bind to LISTEN |

### Port 9996 (KSUDP) — 3-Phase Handshake Protocol
- AC binds to `0.0.0.0:9996` — accepts handshakes from any IP
- rusty-telemetry sends handshake to `$GAME_HOST:9996`
- AC responds to the source address of the handshake → works across machines
- **Reference**: https://docs.google.com/document/d/1KfkZiIluXZ6mMhLWfDX1qAGbvhGRC3ZUzjVIt5FQpp4/pub

### Port 10101 (Telemetry Tool Plugin) — OPTIONAL
- Config: `<AC>/apps/python/Telemetry_Tool_plugin/config.ini`
- Set `to_ip` to the analysis machine's IP for remote operation
- **Optional** — if rusty-telemetry can't bind :10101, continues without it

### Port 5606 (PCARS) — Bind/Listen
- PCARS sends to a configured target IP:port (default 5606)
- rusty-telemetry binds to `$LISTEN:5606` and listens
- Configure in PCARS: Options → System → UDP Protocol → set target IP/port
- PCARS 1: set format to "Project CARS"
- PCARS 2: set format to "2" for native format, or "1" for PCARS1-compatible
- **Optional** — if bind fails, shows as "not available" and continues

---

## Version History

### v0.6.0 (2026-06-06) — Run Management Enhancements
- `DELETE /api/sessions/{id}/runs/{run_id}` — delete a run
- `POST /api/sessions/{id}/reopen` — reopen completed session
- `POST /api/sessions/{id}/runs` — extended with `merge_feeds` field

### v0.5.0 (2026-06-05) — REST API, Recording Manager, Session Analysis
- Full REST API with recording CRUD, session CRUD, run management, analysis endpoints

### v0.4.1 (2026-06-04) — Remote Operation Support
- Split BIND into GAME_HOST + LISTEN env vars

### v0.4.0 (2026-06-04) — PCARS Support
- Port 5606 parser (V1/V2 auto-detect)

### v0.3.0 (2026-06-04) — TUI + Binary Parsers
- KSUDP handshake fix, Telemetry Tool parser, ring buffer frequency, feed health state machine

---

## Cross-References

- **Main project plan:** [Sim Racing Telemetry Analysis Platform — Project Plan](joplin://6c0dcb2a567348fd9796f50c790082e4)
- **racecraft web client:** [racecraft — Vue.js Web Client Notes](joplin://50a09627d5d347009197b94bcee90411)
- **AC protocol spec:** [Assetto Corsa — UDP Telemetry Protocol Specification](joplin://aed9f3be040943048273a16e05a8100f)
- **ACC protocol spec:** [ACC — UDP Telemetry Protocol Specification](joplin://6ae7005d9810437093d63470cff98b59)
- **Architecture note:** [Architecture & Infrastructure](joplin://c1c3a7b2055642268ab230b95551f470)

---

*Last updated: 2026-06-06 — v0.6.0: run deletion, session reopen, feed merging*

id: 0c837f4e6b7e462a997cbc19e47c864a
parent_id: 0e8e00b432a840628faa4df5bc2068bc
created_time: 2026-06-06T08:09:46.470Z
updated_time: 2026-06-06T08:11:22.097Z
is_conflict: 0
latitude: 0.00000000
longitude: 0.00000000
altitude: 0.0000
author: 
source_url: 
is_todo: 0
todo_due: 0
todo_completed: 0
source: joplin-desktop
source_application: net.cozic.joplin-desktop
application_data: 
order: 1780733386470
user_created_time: 2026-06-06T08:09:46.470Z
user_updated_time: 2026-06-06T08:11:22.097Z
encryption_cipher_text: 
encryption_applied: 0
markup_language: 1
is_shared: 0
share_id: 
conflict_original_id: 
master_key_id: 
user_data: 
deleted_time: 0
type_: 1