> ## Documentation Index
> Fetch the complete documentation index at: https://docs.visualradioassist.live/llms.txt
> Use this file to discover all available pages before exploring further.

# Legacy routes

> Core v1's /api routes, as the .NET Core answers them, and what changed.

The .NET Core answers the routes of Core v1 on the same paths with the same bodies. Existing integrations, like a Companion page or a radio automation script, keep working after the upgrade.

New integrations should use the [Core API v2 routes](/develop-with-vra/core-control-api/routes): they have device tokens, plain-text twins, clear error codes and more features.

## Routes

**Base URL:** `http://{core_host_ip}:3002`

| Route | Body |
| - | - |
| `GET /api/studio/name` | Studio name, `text/plain` |
| `GET /api/studio/id` | Studio id, `text/plain` |
| `GET /api/state` | JSON, see [The state body](#the-state-body) |
| `GET /api/state/state` | Core instance state, `text/plain`: `ACTIVE`, `DEACTIVATED`, … |
| `GET /api/state/active` | `true` / `false`, `text/plain` |
| `GET /api/state/control/activate` | The new instance state string |
| `GET /api/state/control/deactivate` | The new instance state string |
| `GET /api/state/control/toggle` | The new instance state string |
| `GET /api/studio/control/onair` | `onair` |
| `GET /api/studio/control/deactivate` | `offair` |
| `GET /api/studio/control/offair` | `offair` (same as `deactivate`) |
| `GET /api/studio/control/toggle` | `onair` or `offair`: the new state |
| `POST /api/modules/outputs/control/restart` | `{"ok":true}` |
| `POST /api/modules/control/reload` | The `/api/state` body |
| `POST /api/apps/control/restart` | The `cloud` part of `/api/state` |
| `GET /status` | `{"state":"ACTIVE","active":true,"healthy":true,"ok":true,"status":"ok"}` |
| `GET /status/health` | `{healthy, ok, automations, switchers, automation_link, clients:[{type, id, active}]}` |
| `GET /` | `{version, server, studio:{id, name, type, station}, api:{…}}` |

* `/api/state/control/*` judge on the Core instance state. Toggle deactivates when the state is `ACTIVE` and activates in every other state.
* `/api/studio/control/toggle` treats recording as on air: on air or recording goes off air, off air goes on air.
* `/api/modules/outputs/control/restart` restarts the Output Player apps on this machine.
* `/api/modules/control/reload` pulls the Core configuration from the cloud again.
* `/api/apps/control/restart` restarts the VRA apps the Core manages on this machine.
* `/status`, `/status/health` and `/` need no authentication.

Text answers are `text/plain; charset=utf-8`, JSON answers are compact `application/json; charset=utf-8`. Every answer carries `Cache-Control: no-store`.

```bash theme={null}
curl -H "Authorization: Basic <base64 of EXTERNAL_APP:password>" \
  http://192.168.1.50:3002/api/studio/control/onair
# onair
```

### The state body

`GET /api/state` answers a compatible subset of Core v1's state:

```json theme={null}
{"state":"ACTIVE","active":true,"cloud":{"instance":{"id":"s-01…"},"studio":{"id":"b7e1…","name":"Studio 1","active":1,"activeStation":{"id":"4c2a…","name":"Radio 1"}},"clients":[{"type":"OUTPUT_PLAYER","id":"c-01…","hostname":"studio-pc","active":true}]},"scheduling":{"onair":[{"id":"p-01…","reference_id":null,"title":"Morning Show","start":"2026-10-06T06:00:00.000Z","end":"2026-10-06T09:00:00.000Z","duration":10800000,"rrule":null,"hosts":[{"id":"h-01…","name":"Sam"}],"activeStudio":null}],"upcoming":[]},"switcher":{…},"automation_link":{…},"signals":{…}}
```

* `state`, `active`, `cloud` and `scheduling` are always there.
* `cloud.studio.active` is the studio state number: `0` off air, `1` on air, `2` recording.
* The Core adds the sections it has from its own state snapshot: `switcher`, `automation_link`, `signals`, `audio`, `gpio`, `output`, `automations` and `macro`. Their content follows the .NET Core's state, not Core v1's.

Fields Core v1 sent that are not listed here are not part of the answer. Read what you need from the [v2 routes](/develop-with-vra/core-control-api/routes) instead.

## Authorization

The legacy routes accept device tokens, LAN access and calls from the Core machine itself, like the v2 routes, and also the `EXTERNAL_APP` Basic header while **Allow legacy authorization** is on. That header opens only these routes, never `/api/v2`. A device limited to features needs the Legacy routes feature here. See [Authentication and LAN access](/develop-with-vra/core-control-api/authentication-and-lan-access).

| Situation | Status | Body |
| - | - | - |
| Not authorized | `401` | `Unauthorized`, with `WWW-Authenticate: Basic realm="VRASERVERCOREAPI"` |
| **Legacy routes** feature or the whole API switched off | `403` | `Forbidden` |
| Read-only device on a control route | `403` | `Forbidden` |

The **Legacy routes** feature has its own **Read** and **Control** switch in **Studio settings → Core API → Features**.

## What changed from Core v1

* **Same paths, same bodies.** The routes above answer what Core v1 answered.
* **Refused actions are no longer `200`.** When the Core cannot apply a control route, it answers the current state (the instance state string, or `onair` / `offair`) with an error status: `503` while the Core is starting, `500` when the change failed. Core v1 answered `200` while it was not ready.
* **`/api/studio/control/offair` exists.** The old documentation listed `offair`, Core v1 only answered `deactivate`. Both work now.
* **`/api/state` is a compatible subset.** See [The state body](#the-state-body).
* **Restart routes act on this machine.** `/api/modules/outputs/control/restart` and `/api/apps/control/restart` restart the apps the Core manages on its own machine. On Core v1, the outputs route reloaded the Output Player instances inside the Core; now it restarts the Output Player apps.
* **Device tokens and LAN access work here too.** You can retire the shared `EXTERNAL_APP` header per device.
* **The legacy routes can be switched off** per studio, with the **Legacy routes** feature.

The legacy routes have no plain-text twin and do not take `?wait=` or `?timeout=`.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.