---
sidebar_position: 4
---

# Local REST API

The MetoYou desktop app exposes an optional local HTTP API for scripts and tools. It is implemented in Electron and reads local desktop data.

## Enable the API

1. Open Settings.
2. Open Local API settings.
3. Enable the local server.
4. Choose a port. The default is `17878`.
5. Add trusted signaling server URLs for authentication.
6. Enable Scalar docs if you want `/docs`.
7. Enable Docusaurus docs if you want `/docusaurus`.

By default the server binds to `127.0.0.1`. Only enable LAN exposure when you understand the risk.

## Authentication

Protected routes require a bearer token. Get one by posting username, password, and an allowed signaling server URL.

```bash
curl -s http://127.0.0.1:17878/api/auth/login \
  -H 'Content-Type: application/json' \
  -d '{
    "username": "alice",
    "password": "correct horse battery staple",
    "serverUrl": "https://tojusignal.example.com"
  }'
```

Example response:

```json
{
  "token": "local_4cddf95c5b8c4b6f9e0c",
  "expiresAt": 1777477200000,
  "user": {
    "id": "user-alice-01",
    "username": "alice",
    "displayName": "Alice"
  }
}
```

Use the token:

```bash
curl -s http://127.0.0.1:17878/api/profile \
  -H 'Authorization: Bearer local_4cddf95c5b8c4b6f9e0c'
```

Logout revokes the current token:

```bash
curl -i -X POST http://127.0.0.1:17878/api/auth/logout \
  -H 'Authorization: Bearer local_4cddf95c5b8c4b6f9e0c'
```

## OpenAPI and Scalar

| Route | Auth | Purpose |
| --- | --- | --- |
| `GET /api/openapi.json` | No | OpenAPI 3.1 document. |
| `GET /docs` | No | Scalar API reference when enabled. |

## Public Routes

### GET /api/health

Checks whether the local API server is running.

```bash
curl -s http://127.0.0.1:17878/api/health
```

Example response:

```json
{
  "status": "ok",
  "version": "1.0.0",
  "timestamp": 1777473600000,
  "exposeOnLan": false
}
```

### GET /api/openapi.json

Returns the machine-readable API document.

```bash
curl -s http://127.0.0.1:17878/api/openapi.json
```

### POST /api/auth/login

Issues a local bearer token after credentials are validated by an allowed signaling server.

Request body:

```json
{
  "username": "alice",
  "password": "correct horse battery staple",
  "serverUrl": "https://tojusignal.example.com"
}
```

Common errors:

| Status | Error code | Meaning |
| --- | --- | --- |
| 400 | `INVALID_REQUEST` | Missing username, password, or server URL. |
| 403 | `NO_ALLOWED_SERVERS` | No allowed signaling servers are configured. |
| 403 | `SERVER_NOT_ALLOWED` | The server URL is not in the allowed list. |
| 401 | `INVALID_CREDENTIALS` | Signaling server rejected the login. |
| 502 | `UPSTREAM_UNREACHABLE` | The signaling server could not be reached. |

## Protected Routes

All routes below require:

```http
Authorization: Bearer local_4cddf95c5b8c4b6f9e0c
```

### GET /api/profile

Reads the current local user profile.

```bash
curl -s http://127.0.0.1:17878/api/profile \
  -H 'Authorization: Bearer local_4cddf95c5b8c4b6f9e0c'
```

### GET /api/rooms

Lists rooms known to this device.

```bash
curl -s http://127.0.0.1:17878/api/rooms \
  -H 'Authorization: Bearer local_4cddf95c5b8c4b6f9e0c'
```

### GET `/api/rooms/{roomId}`

Reads one room by id.

```bash
curl -s http://127.0.0.1:17878/api/rooms/room-7ebdde75 \
  -H 'Authorization: Bearer local_4cddf95c5b8c4b6f9e0c'
```

### GET `/api/rooms/{roomId}/users`

Lists users known for a room.

```bash
curl -s http://127.0.0.1:17878/api/rooms/room-7ebdde75/users \
  -H 'Authorization: Bearer local_4cddf95c5b8c4b6f9e0c'
```

### GET `/api/rooms/{roomId}/messages`

Lists local messages for a room. `limit` defaults to `100` and is clamped from `1` to `500`. `offset` defaults to `0`.

```bash
curl -s 'http://127.0.0.1:17878/api/rooms/room-7ebdde75/messages?limit=50&offset=0' \
  -H 'Authorization: Bearer local_4cddf95c5b8c4b6f9e0c'
```

### GET `/api/rooms/{roomId}/messages/since`

Lists local messages after a required timestamp.

```bash
curl -s 'http://127.0.0.1:17878/api/rooms/room-7ebdde75/messages/since?sinceTimestamp=1777470000000' \
  -H 'Authorization: Bearer local_4cddf95c5b8c4b6f9e0c'
```

### GET `/api/rooms/{roomId}/bans`

Lists active bans for a room.

```bash
curl -s http://127.0.0.1:17878/api/rooms/room-7ebdde75/bans \
  -H 'Authorization: Bearer local_4cddf95c5b8c4b6f9e0c'
```

### GET `/api/rooms/{roomId}/bans/{userId}`

Checks whether a user is banned in a room.

```bash
curl -s http://127.0.0.1:17878/api/rooms/room-7ebdde75/bans/user-muse-01 \
  -H 'Authorization: Bearer local_4cddf95c5b8c4b6f9e0c'
```

Example response:

```json
{ "isBanned": false }
```

### GET `/api/messages/{messageId}`

Reads one local message by id.

```bash
curl -s http://127.0.0.1:17878/api/messages/msg-20260429-001 \
  -H 'Authorization: Bearer local_4cddf95c5b8c4b6f9e0c'
```

### GET `/api/messages/{messageId}/reactions`

Lists reactions for a message.

```bash
curl -s http://127.0.0.1:17878/api/messages/msg-20260429-001/reactions \
  -H 'Authorization: Bearer local_4cddf95c5b8c4b6f9e0c'
```

### GET `/api/messages/{messageId}/attachments`

Lists attachments for a message.

```bash
curl -s http://127.0.0.1:17878/api/messages/msg-20260429-001/attachments \
  -H 'Authorization: Bearer local_4cddf95c5b8c4b6f9e0c'
```

### GET `/api/users/{userId}`

Reads one user by id.

```bash
curl -s http://127.0.0.1:17878/api/users/user-muse-01 \
  -H 'Authorization: Bearer local_4cddf95c5b8c4b6f9e0c'
```

### GET /api/attachments

Lists all attachments stored on this device.

```bash
curl -s http://127.0.0.1:17878/api/attachments \
  -H 'Authorization: Bearer local_4cddf95c5b8c4b6f9e0c'
```

### GET /api/plugin-data

Reads a plugin data value from the local desktop database. `scope` must be `local` or `server`. Provide `serverId` when reading server-scoped data.

```bash
curl -s 'http://127.0.0.1:17878/api/plugin-data?pluginId=example.soundboard&key=favorites&scope=server&serverId=room-7ebdde75' \
  -H 'Authorization: Bearer local_4cddf95c5b8c4b6f9e0c'
```

Example response:

```json
{
  "value": [
    { "label": "Chime", "url": "https://cdn.example.com/chime.wav" }
  ]
}
```

### GET `/api/meta/{key}`

Reads a desktop metadata value by key.

```bash
curl -s http://127.0.0.1:17878/api/meta/metoyou_currentUserId \
  -H 'Authorization: Bearer local_4cddf95c5b8c4b6f9e0c'
```

Example response:

```json
{
  "key": "metoyou_currentUserId",
  "value": "user-alice-01"
}
```

## Data Model Notes

Rooms, users, messages, reactions, attachments, and bans are returned from local desktop persistence. Many schemas allow additional properties because the local database can carry richer app state than the REST docs need to guarantee.

## Security Notes

- Keep the API bound to `127.0.0.1` unless LAN access is required.
- Only add signaling servers you trust to the allowed list.
- Bearer tokens are local to the running desktop app.
- Stop the local API server to clear issued tokens.