# TorrServer MatriX API Reference

Version: MatriX.141.10
Base URL: `http://{host}:{port}` (default 8090)

## Endpoints

### Health Check
```
GET /echo
→ "MatriX.141.10" (version string)
```

### Torrent Management
```
POST /torrents
Content-Type: application/json

Add:    {"action":"add", "link":"magnet:?xt=urn:btih:HASH", "save_to_db":true}
List:   {"action":"list"}
Get:    {"action":"get", "hash":"HASH"}
Drop:   {"action":"drop", "hash":"HASH"}
Remove: {"action":"rem", "hash":"HASH"}
Edit:   {"action":"set", "hash":"HASH", "title":"..."}
```

### Streaming (NOT query params — path format!)
```
GET /play/{hash}/{file_id}
GET /stream/{hash}/{file_id}
```
- `/play/{hash}/{id}` — with auto-preloading (preferred)
- `/stream/{hash}/{id}` — without auto-preloading
- `file_id` is 1-based from `file_stats[].id`
- Headers: `Range` (byte ranges), `Accept-Ranges: bytes`
- Responses: `video/mp4`, `video/x-matroska`, etc.

### Settings
```
GET  /api/settings   — Get BT config
POST /api/settings   — Update BT config (drops active torrents!)
POST /api/settings/default — Reset to defaults
```

### Cache
```
GET /api/cache?hash=HASH — Piece-level cache info
```

## Torrent Status Object
```json
{
  "stat": 2,
  "stat_string": "Torrent working",
  "hash": "abc123...",
  "name": "Torrent Name",
  "title": "Display Title",
  "total_peers": 42,
  "total_seeders": 40,
  "total_leechers": 2,
  "file_stats": [
    {"id": 1, "path": "folder/file.mp4", "length": 1073741824},
    {"id": 2, "path": "folder/subtitles.srt", "length": 1024}
  ]
}
```

### Status Values
| stat | stat_string | Meaning |
|------|-------------|---------|
| 0 | Torrent in db | Saved to DB, not active |
| 1 | Torrent getting info | Connecting to DHT/trackers |
| 2 | Torrent working | Downloading, streaming possible |

NB: Stat 0 torrents won't start until `GET /play/{hash}/{id}` is called (needs a reader).

## Pitfalls
- **Path format** for streaming: `/play/{hash}/{id}`, NOT `/play?hash=X&file_id=Y`
- **Chicken-and-egg**: TorrServer won't start downloading until someone reads `/play/...`
- **file_id changes**: auto-detect by scanning `file_stats` for `.mp4`/`.mkv` files
- **Content-Type fallback**: if file returns `text/srt` or `text/plain`, try next file_id
- **Settings are destructive**: POST to `/api/settings` drops all active torrents
