# HTTP API

The endpoints used by the on-board panel. Everything lives under `http://<board-ip>/api/...` and returns JSON; writes are `POST`. Every path outside `/api` is first matched against routes opened by projects with `cyd.rota`.

## Status and files

| Endpoint | Purpose |
|---|---|
| `GET /api/status` | Jobs (with `mod`), `sys` (heap / DRAM / flash / rssi / temperature), `net`, `autostart`, `rotalar`, `max_jobs`, `max_thread` |
| `GET /api/caps` | Feature map (`OZELLIKLER` + measured capabilities); the panel hides buttons accordingly |
| `GET /api/list` | Project files + `modlar` + `base` (`/projects` or `/sd/projects`) |
| `GET /api/file?name=` | File content |
| `POST /api/save?name=` | Write (body = raw content, streamed) |
| `POST /api/delete?name=` · `POST /api/rename?name=&to=` | |
| `GET /api/docs[?dil=en]` | The on-board handbook (Markdown) |

## Running

| Endpoint | Purpose |
|---|---|
| `POST /api/run?name=[&mod=normal\|thread\|solo]` | Run; `mod` is one-shot |
| `POST /api/stop?name=` · `POST /api/stopall` | Stop |
| `POST /api/mod?name=&mod=` | The file's persistent run mode |
| `POST /api/solo?name=&wifi=0\|1` | Reboot into solo mode (one-shot) |
| `POST /api/autostart?name=&on=0\|1` | Autostart list (multiple) |
| `POST /api/force` | Force a stuck project (reset) |
| `POST /api/eval` | Run the body once |
| `GET /api/rotalar` · `GET /<route>` | Routes opened by projects; the project's handler |

## Log

| Endpoint | Purpose |
|---|---|
| `GET /api/log?since=N[&source=name]` | Live log: `[seq, source, line]` (100-line ring, at most 80 per page) |
| `POST /api/log/clear` | Clear the live log |
| `GET /api/log/file?name=` | The project's persistent log (`/logs/<project>.log`, 8 KB per project) |
| `GET /api/log/files` | Projects that have a log, with sizes |
| `POST /api/log/file/clear?name=` | |

## Settings

| Endpoint | Purpose |
|---|---|
| `GET/POST /api/wifi` | Network settings (an empty password keeps the old one) |
| `GET /api/scan` | Network scan |
| `POST /api/display?rot=0..3&bgr=0\|1&test=1&save=0\|1` | Set the display live |
| `GET/POST /api/depolama[?mod=otomatik\|flash\|sd]` | Where projects live (live switch) |
| `POST /api/tasi?hedef=sd\|flash[&names=a,b]` | Move flash ↔ SD (copy, verify, delete source; refused while a project runs) |
| `POST /api/reset` | Reboot |

## Example

```sh
curl http://192.168.0.217/api/status
curl -X POST --data-binary @hello.py "http://192.168.0.217/api/save?name=hello.py"
curl -X POST "http://192.168.0.217/api/run?name=hello.py"
curl "http://192.168.0.217/api/log?since=0&source=hello.py"
curl -X POST "http://192.168.0.217/api/stop?name=hello.py"
```

## Over the USB bridge

`tools/usb_panel.py` serves the same API over the serial port: frames are `~CYD~id~b64(json{m,p,q,b|f})`, the response is base64-encoded as it is written and streamed as `~CYDR~id~...`; bodies over 384 bytes go as `~CYDB~` chunks and every chunk is acknowledged with `~CYDA~`. On the panel side nothing changes.
