# FeatherOS endpoints (Client API: account)

> 14 FeatherPanel Client API: account endpoints from user/featheros.php: methods, paths, auth, permissions, rate limits, parameters and responses.

Source: https://featherpanel.com/docs/api/reference/user/featheros/

Defined in [`backend/app/routes/user/featheros.php`](https://github.com/MythicalLTD/FeatherPanel/blob/15b94e9fc9df233123706b47c42728b81e48cb3d/backend/app/routes/user/featheros.php). Authentication used here: **Signed-in user**. Read [Authentication](https://featherpanel.com/docs/api/authentication/) for how to send credentials and [Rate limits and errors](https://featherpanel.com/docs/api/rate-limits-and-errors/) for the response envelope.

Paths, methods, permissions and rate limits come from the route file. Summaries, parameters and response codes come from the OpenAPI annotations on the controllers; endpoints without annotations show only what the route file declares.

## Endpoints

### GET `/api/user/featheros/state`

- Auth: Signed-in user
- Default rate limit: 60 / minute (`user-featheros`)
- Route name: `user-featheros-state-get`
- Controller: [`FeatherOsController::getState`](https://github.com/MythicalLTD/FeatherPanel/blob/15b94e9fc9df233123706b47c42728b81e48cb3d/backend/app/Controllers/User/FeatherOs/FeatherOsController.php)
- [route source](https://github.com/MythicalLTD/FeatherPanel/blob/15b94e9fc9df233123706b47c42728b81e48cb3d/backend/app/routes/user/featheros.php#L26)

**Get FeatherOS desktop state** Saved desktop of the current user: open windows, desktop icon layout, dock, wallpaper and theme. state is null when nothing was saved yet.

```bash
curl -X GET "$PANEL_URL/api/user/featheros/state" \
  -H "Authorization: Bearer $FEATHERPANEL_API_KEY" \
  -H "Accept: application/json"
```

Responses: `200` State retrieved · `401` Unauthorized

### PUT `/api/user/featheros/state`

- Auth: Signed-in user
- Default rate limit: 60 / minute (`user-featheros`)
- Route name: `user-featheros-state-save`
- Controller: [`FeatherOsController::saveState`](https://github.com/MythicalLTD/FeatherPanel/blob/15b94e9fc9df233123706b47c42728b81e48cb3d/backend/app/Controllers/User/FeatherOs/FeatherOsController.php)
- [route source](https://github.com/MythicalLTD/FeatherPanel/blob/15b94e9fc9df233123706b47c42728b81e48cb3d/backend/app/routes/user/featheros.php#L38)

**Save FeatherOS desktop state** Replaces the saved desktop of the current user. Send {"state": {...}}. The document is opaque to the server but limited to 256 KiB.

```bash
curl -X PUT "$PANEL_URL/api/user/featheros/state" \
  -H "Authorization: Bearer $FEATHERPANEL_API_KEY" \
  -H "Accept: application/json"
```

Responses: `200` State saved · `400` Invalid state · `413` State too large

### DELETE `/api/user/featheros/state`

- Auth: Signed-in user
- Default rate limit: 10 / minute (`user-featheros`)
- Route name: `user-featheros-state-reset`
- Controller: [`FeatherOsController::resetState`](https://github.com/MythicalLTD/FeatherPanel/blob/15b94e9fc9df233123706b47c42728b81e48cb3d/backend/app/Controllers/User/FeatherOs/FeatherOsController.php)
- [route source](https://github.com/MythicalLTD/FeatherPanel/blob/15b94e9fc9df233123706b47c42728b81e48cb3d/backend/app/routes/user/featheros.php#L50)

**Reset FeatherOS desktop state** Removes the saved desktop so the next visit starts with the default layout. Notes are kept.

```bash
curl -X DELETE "$PANEL_URL/api/user/featheros/state" \
  -H "Authorization: Bearer $FEATHERPANEL_API_KEY" \
  -H "Accept: application/json"
```

Responses: `200` State reset

### POST `/api/user/featheros/session/acquire`

- Auth: Signed-in user
- Default rate limit: 60 / minute (`user-featheros`)
- Route name: `user-featheros-session-acquire`
- Controller: [`FeatherOsController::acquireSession`](https://github.com/MythicalLTD/FeatherPanel/blob/15b94e9fc9df233123706b47c42728b81e48cb3d/backend/app/Controllers/User/FeatherOs/FeatherOsController.php)
- [route source](https://github.com/MythicalLTD/FeatherPanel/blob/15b94e9fc9df233123706b47c42728b81e48cb3d/backend/app/routes/user/featheros.php#L62)

**Acquire the single FeatherOS session lease** Only one active FeatherOS instance is allowed per user. Pass force=true to take over another tab or device.

```bash
curl -X POST "$PANEL_URL/api/user/featheros/session/acquire" \
  -H "Authorization: Bearer $FEATHERPANEL_API_KEY" \
  -H "Accept: application/json"
```

Responses: `200` Lease acquired · `409` Another session is active

### POST `/api/user/featheros/session/heartbeat`

- Auth: Signed-in user
- Default rate limit: 120 / minute (`user-featheros`)
- Route name: `user-featheros-session-heartbeat`
- Controller: [`FeatherOsController::heartbeatSession`](https://github.com/MythicalLTD/FeatherPanel/blob/15b94e9fc9df233123706b47c42728b81e48cb3d/backend/app/Controllers/User/FeatherOs/FeatherOsController.php)
- [route source](https://github.com/MythicalLTD/FeatherPanel/blob/15b94e9fc9df233123706b47c42728b81e48cb3d/backend/app/routes/user/featheros.php#L74)

**Renew the FeatherOS session lease**

```bash
curl -X POST "$PANEL_URL/api/user/featheros/session/heartbeat" \
  -H "Authorization: Bearer $FEATHERPANEL_API_KEY" \
  -H "Accept: application/json"
```

Responses: `200` Lease renewed · `409` Lease owned by another instance

### POST `/api/user/featheros/session/release`

- Auth: Signed-in user
- Default rate limit: 60 / minute (`user-featheros`)
- Route name: `user-featheros-session-release`
- Controller: [`FeatherOsController::releaseSession`](https://github.com/MythicalLTD/FeatherPanel/blob/15b94e9fc9df233123706b47c42728b81e48cb3d/backend/app/Controllers/User/FeatherOs/FeatherOsController.php)
- [route source](https://github.com/MythicalLTD/FeatherPanel/blob/15b94e9fc9df233123706b47c42728b81e48cb3d/backend/app/routes/user/featheros.php#L86)

**Release the FeatherOS session lease**

```bash
curl -X POST "$PANEL_URL/api/user/featheros/session/release" \
  -H "Authorization: Bearer $FEATHERPANEL_API_KEY" \
  -H "Accept: application/json"
```

Responses: `200` Lease released

### GET `/api/user/featheros/notes`

- Auth: Signed-in user
- Default rate limit: 60 / minute (`user-featheros`)
- Route name: `user-featheros-notes-list`
- Controller: [`FeatherOsController::listNotes`](https://github.com/MythicalLTD/FeatherPanel/blob/15b94e9fc9df233123706b47c42728b81e48cb3d/backend/app/Controllers/User/FeatherOs/FeatherOsController.php)
- [route source](https://github.com/MythicalLTD/FeatherPanel/blob/15b94e9fc9df233123706b47c42728b81e48cb3d/backend/app/routes/user/featheros.php#L98)

**List FeatherOS notes**

```bash
curl -X GET "$PANEL_URL/api/user/featheros/notes" \
  -H "Authorization: Bearer $FEATHERPANEL_API_KEY" \
  -H "Accept: application/json"
```

Responses: `200` Notes retrieved

### POST `/api/user/featheros/notes`

- Auth: Signed-in user
- Default rate limit: 30 / minute (`user-featheros`)
- Route name: `user-featheros-notes-create`
- Controller: [`FeatherOsController::createNote`](https://github.com/MythicalLTD/FeatherPanel/blob/15b94e9fc9df233123706b47c42728b81e48cb3d/backend/app/Controllers/User/FeatherOs/FeatherOsController.php)
- [route source](https://github.com/MythicalLTD/FeatherPanel/blob/15b94e9fc9df233123706b47c42728b81e48cb3d/backend/app/routes/user/featheros.php#L110)

**Create a FeatherOS note** Body: {"title": string, "content": string, "color"?: string, "pinned"?: bool}.

```bash
curl -X POST "$PANEL_URL/api/user/featheros/notes" \
  -H "Authorization: Bearer $FEATHERPANEL_API_KEY" \
  -H "Accept: application/json"
```

Responses: `201` Note created · `400` Invalid note · `409` Note limit reached

### PUT `/api/user/featheros/notes/{id}`

- Auth: Signed-in user
- Default rate limit: 120 / minute (`user-featheros`)
- Route name: `user-featheros-notes-update`
- Controller: [`FeatherOsController::updateNote`](https://github.com/MythicalLTD/FeatherPanel/blob/15b94e9fc9df233123706b47c42728b81e48cb3d/backend/app/Controllers/User/FeatherOs/FeatherOsController.php)
- [route source](https://github.com/MythicalLTD/FeatherPanel/blob/15b94e9fc9df233123706b47c42728b81e48cb3d/backend/app/routes/user/featheros.php#L122)

**Update a FeatherOS note**

| Parameter | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `id` | path | integer | yes |  |

```bash
curl -X PUT "$PANEL_URL/api/user/featheros/notes/$ID" \
  -H "Authorization: Bearer $FEATHERPANEL_API_KEY" \
  -H "Accept: application/json"
```

Responses: `200` Note updated · `404` Note not found

### POST `/api/user/featheros/wallpaper`

- Auth: Signed-in user
- Default rate limit: 10 / minute (`user-featheros`)
- Route name: `user-featheros-wallpaper-upload`
- Controller: [`FeatherOsController::uploadWallpaper`](https://github.com/MythicalLTD/FeatherPanel/blob/15b94e9fc9df233123706b47c42728b81e48cb3d/backend/app/Controllers/User/FeatherOs/FeatherOsController.php)
- [route source](https://github.com/MythicalLTD/FeatherPanel/blob/15b94e9fc9df233123706b47c42728b81e48cb3d/backend/app/routes/user/featheros.php#L139)

**Upload a custom FeatherOS wallpaper** Accepts a JPEG, PNG, GIF or WebP image (max 8 MiB). Stored under /attachments/featheros-wallpapers/ and returned as a URL for the desktop state.

```bash
curl -X POST "$PANEL_URL/api/user/featheros/wallpaper" \
  -H "Authorization: Bearer $FEATHERPANEL_API_KEY" \
  -H "Accept: application/json"
```

Responses: `200` Wallpaper uploaded · `400` Invalid file · `401` Unauthorized

### DELETE `/api/user/featheros/notes/{id}`

- Auth: Signed-in user
- Default rate limit: 30 / minute (`user-featheros`)
- Route name: `user-featheros-notes-delete`
- Controller: [`FeatherOsController::deleteNote`](https://github.com/MythicalLTD/FeatherPanel/blob/15b94e9fc9df233123706b47c42728b81e48cb3d/backend/app/Controllers/User/FeatherOs/FeatherOsController.php)
- [route source](https://github.com/MythicalLTD/FeatherPanel/blob/15b94e9fc9df233123706b47c42728b81e48cb3d/backend/app/routes/user/featheros.php#L151)

**Delete a FeatherOS note**

| Parameter | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `id` | path | integer | yes |  |

```bash
curl -X DELETE "$PANEL_URL/api/user/featheros/notes/$ID" \
  -H "Authorization: Bearer $FEATHERPANEL_API_KEY" \
  -H "Accept: application/json"
```

Responses: `200` Note deleted · `404` Note not found

### GET `/api/user/featheros/trash`

- Auth: Signed-in user
- Default rate limit: 60 / minute (`user-featheros`)
- Route name: `user-featheros-trash-list`
- Controller: [`FeatherOsController::listTrash`](https://github.com/MythicalLTD/FeatherPanel/blob/15b94e9fc9df233123706b47c42728b81e48cb3d/backend/app/Controllers/User/FeatherOs/FeatherOsController.php)
- [route source](https://github.com/MythicalLTD/FeatherPanel/blob/15b94e9fc9df233123706b47c42728b81e48cb3d/backend/app/routes/user/featheros.php#L168)

**List FeatherOS trash entries**

```bash
curl -X GET "$PANEL_URL/api/user/featheros/trash" \
  -H "Authorization: Bearer $FEATHERPANEL_API_KEY" \
  -H "Accept: application/json"
```

### POST `/api/user/featheros/trash`

- Auth: Signed-in user
- Default rate limit: 60 / minute (`user-featheros`)
- Route name: `user-featheros-trash-register`
- Controller: [`FeatherOsController::registerTrash`](https://github.com/MythicalLTD/FeatherPanel/blob/15b94e9fc9df233123706b47c42728b81e48cb3d/backend/app/Controllers/User/FeatherOs/FeatherOsController.php)
- [route source](https://github.com/MythicalLTD/FeatherPanel/blob/15b94e9fc9df233123706b47c42728b81e48cb3d/backend/app/routes/user/featheros.php#L180)

**Register items moved into .featheros-trash**

```bash
curl -X POST "$PANEL_URL/api/user/featheros/trash" \
  -H "Authorization: Bearer $FEATHERPANEL_API_KEY" \
  -H "Accept: application/json"
```

### POST `/api/user/featheros/trash/forget`

- Auth: Signed-in user
- Default rate limit: 60 / minute (`user-featheros`)
- Route name: `user-featheros-trash-forget`
- Controller: [`FeatherOsController::forgetTrash`](https://github.com/MythicalLTD/FeatherPanel/blob/15b94e9fc9df233123706b47c42728b81e48cb3d/backend/app/Controllers/User/FeatherOs/FeatherOsController.php)
- [route source](https://github.com/MythicalLTD/FeatherPanel/blob/15b94e9fc9df233123706b47c42728b81e48cb3d/backend/app/routes/user/featheros.php#L192)

**Drop trash metadata after restore or permanent delete**

```bash
curl -X POST "$PANEL_URL/api/user/featheros/trash/forget" \
  -H "Authorization: Bearer $FEATHERPANEL_API_KEY" \
  -H "Accept: application/json"
```
