mirror of
https://github.com/Lissy93/dashy.git
synced 2026-07-30 11:06:09 -04:00
📝 Adds docs and swagger spec for API
This commit is contained in:
3
.env
3
.env
@@ -70,6 +70,9 @@
|
||||
# Set to 'true' to enable the REST API for reading / writing config (see docs/api.md)
|
||||
# ENABLE_API=true
|
||||
|
||||
# Optional bearer token granting full API access, as an alternative to Dashy's auth
|
||||
# API_TOKEN=your-long-random-secret
|
||||
|
||||
# Setup any other user defined vars by prepending VITE_APP_ to the var name
|
||||
# VITE_APP_pihole_ip=http://your.pihole.ip
|
||||
# VITE_APP_pihole_key=your_pihole_secret_key
|
||||
|
||||
19
docs/api.md
19
docs/api.md
@@ -18,7 +18,7 @@ Or with `docker run`, pass `-e ENABLE_API=true`. While disabled, all `/api/*` re
|
||||
|
||||
## Authentication
|
||||
|
||||
The API uses Dashy's existing [server-side authentication](/docs/authentication.md). Read endpoints require any authenticated user, and write endpoints require an admin. If no auth is configured, the API is open — the same as Dashy's other endpoints.
|
||||
By default, the API uses Dashy's existing [server-side authentication](/docs/authentication.md). Read endpoints require any authenticated user, and write endpoints require an admin. If no auth is configured, the API is open — the same as Dashy's other endpoints.
|
||||
|
||||
```bash
|
||||
# With HTTP Basic Auth (ENABLE_HTTP_AUTH or BASIC_AUTH_USERNAME / BASIC_AUTH_PASSWORD)
|
||||
@@ -28,6 +28,23 @@ curl -u alice:hunter2 http://localhost:8080/api/config
|
||||
curl -H 'Authorization: Bearer <id-token>' http://localhost:8080/api/config
|
||||
```
|
||||
|
||||
### API token
|
||||
|
||||
If you have no auth configured, or would prefer a dedicated credential for the API, set the `API_TOKEN` environmental variable and send it as a bearer token. A valid token grants full (admin) access, and works alongside any other configured auth method.
|
||||
|
||||
```yaml
|
||||
environment:
|
||||
- ENABLE_API=true
|
||||
- API_TOKEN=your-long-random-secret
|
||||
```
|
||||
|
||||
```bash
|
||||
curl -H 'Authorization: Bearer your-long-random-secret' http://localhost:8080/api/config
|
||||
```
|
||||
|
||||
> [!NOTE]
|
||||
> Setting `API_TOKEN` also secures the API on deployments that have no other auth — anonymous requests are then rejected. Use a long, random value (e.g. `openssl rand -hex 32`) and only send it over HTTPS. The token applies to the API only, not Dashy's other endpoints.
|
||||
|
||||
## Endpoints
|
||||
|
||||
`:filename` is any YAML config file in your user-data directory (e.g. `conf.yml`, or a sub-page like `home-lab.yml`). `:key` is one of the top-level config keys: `pageInfo`, `appConfig`, `sections` or `pages`.
|
||||
|
||||
638
services/api/openapi.yml
Normal file
638
services/api/openapi.yml
Normal file
@@ -0,0 +1,638 @@
|
||||
openapi: 3.1.0
|
||||
|
||||
info:
|
||||
title: Dashy REST API
|
||||
version: 1.0.0
|
||||
summary: Read and write your Dashy config over HTTP.
|
||||
description: |
|
||||
The Dashy API is a simple opt-in REST API for CRUD actions over your config.
|
||||
For full usage guide, examples and architecture, see the [API Docs](https://dashy.to/docs/api).
|
||||
|
||||
<details>
|
||||
<summary>Enabling the API</summary>
|
||||
|
||||
The API is off by default. To enable it, set the `ENABLE_API` env var to true,
|
||||
and restart Dashy.
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary>Authenticating</summary>
|
||||
|
||||
By default, the API will use the same auth system as the rest of your Dashy instance.
|
||||
If you don't have auth configured, or would prefer to use bearer token for the API instead,
|
||||
then you can do so, by setting an `API_TOKEN` environmental variable,
|
||||
and then passing that as a bearer token in the authorization header when making requests,
|
||||
like `curl -H 'Authorization: Bearer <your-long-random-secret>' http://dashy.local/api/config`
|
||||
|
||||
</details>
|
||||
|
||||
> [!IMPORTANT]
|
||||
> There is no warranty. It is your responsibility to correctly configure and protect your instance.
|
||||
> The API is experimental.
|
||||
|
||||
contact:
|
||||
name: GitHub
|
||||
url: https://github.com/Lissy93/dashy
|
||||
license:
|
||||
name: MIT
|
||||
url: https://github.com/Lissy93/dashy/blob/master/LICENSE
|
||||
x-logo:
|
||||
url: https://raw.githubusercontent.com/Lissy93/dashy/master/public/web-icons/dashy-logo.png
|
||||
altText: Dashy
|
||||
href: https://dashy.to
|
||||
|
||||
externalDocs:
|
||||
description: API guide
|
||||
url: https://dashy.to/docs/api
|
||||
|
||||
servers:
|
||||
- url: "{scheme}://{host}/api"
|
||||
description: Your Dashy instance
|
||||
variables:
|
||||
scheme:
|
||||
enum: [http, https]
|
||||
default: http
|
||||
host:
|
||||
default: localhost:4000
|
||||
|
||||
tags:
|
||||
- name: Files
|
||||
description: List, read and replace whole config files.
|
||||
- name: Keys
|
||||
description: Read and replace a single top-level config key.
|
||||
- name: Sections
|
||||
description: Create, read, update and delete sections.
|
||||
- name: Items
|
||||
description: Create, read, update and delete items within a section.
|
||||
|
||||
security:
|
||||
- bearerAuth: []
|
||||
- basicAuth: []
|
||||
- {}
|
||||
|
||||
paths:
|
||||
/config:
|
||||
get:
|
||||
tags: [Files]
|
||||
summary: List config files
|
||||
operationId: listConfigFiles
|
||||
description: Lists every YAML config file in the user-data directory.
|
||||
responses:
|
||||
"200":
|
||||
description: Config files
|
||||
content:
|
||||
application/json:
|
||||
schema: { $ref: "#/components/schemas/FileList" }
|
||||
example: { success: true, files: [conf.yml, home-lab.yml] }
|
||||
"401": { $ref: "#/components/responses/Unauthorized" }
|
||||
"404": { $ref: "#/components/responses/Disabled" }
|
||||
|
||||
/config/{filename}:
|
||||
parameters:
|
||||
- $ref: "#/components/parameters/Filename"
|
||||
get:
|
||||
tags: [Files]
|
||||
summary: Get config file
|
||||
operationId: getConfigFile
|
||||
description: Returns the parsed config file as JSON.
|
||||
responses:
|
||||
"200":
|
||||
description: Parsed config
|
||||
content:
|
||||
application/json:
|
||||
schema: { $ref: "#/components/schemas/Config" }
|
||||
"400": { $ref: "#/components/responses/BadRequest" }
|
||||
"401": { $ref: "#/components/responses/Unauthorized" }
|
||||
"404": { $ref: "#/components/responses/NotFound" }
|
||||
"500": { $ref: "#/components/responses/ParseError" }
|
||||
put:
|
||||
tags: [Files]
|
||||
summary: Replace config file
|
||||
operationId: replaceConfigFile
|
||||
description: |
|
||||
Overwrites the whole file. Writes to `conf.yml` are validated against the
|
||||
config schema; sub-pages are not. A timestamped backup is taken first.
|
||||
requestBody:
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema: { $ref: "#/components/schemas/Config" }
|
||||
example: { pageInfo: { title: My Dashboard }, sections: [] }
|
||||
responses:
|
||||
"200": { $ref: "#/components/responses/Saved" }
|
||||
"400": { $ref: "#/components/responses/BadRequest" }
|
||||
"401": { $ref: "#/components/responses/Unauthorized" }
|
||||
"403": { $ref: "#/components/responses/Forbidden" }
|
||||
"413": { $ref: "#/components/responses/TooLarge" }
|
||||
|
||||
/config/{filename}/{key}:
|
||||
parameters:
|
||||
- $ref: "#/components/parameters/Filename"
|
||||
- $ref: "#/components/parameters/Key"
|
||||
get:
|
||||
tags: [Keys]
|
||||
summary: Get top-level key
|
||||
operationId: getConfigKey
|
||||
description: Returns a single top-level key from the config.
|
||||
responses:
|
||||
"200":
|
||||
description: Key value
|
||||
content:
|
||||
application/json:
|
||||
schema: { $ref: "#/components/schemas/KeyValue" }
|
||||
"400": { $ref: "#/components/responses/BadRequest" }
|
||||
"401": { $ref: "#/components/responses/Unauthorized" }
|
||||
"404": { $ref: "#/components/responses/NotFound" }
|
||||
put:
|
||||
tags: [Keys]
|
||||
summary: Replace top-level key
|
||||
operationId: replaceConfigKey
|
||||
description: Replaces a single top-level key, leaving the rest of the file untouched.
|
||||
requestBody:
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema: { $ref: "#/components/schemas/KeyValue" }
|
||||
example: { theme: nord-frost, layout: auto }
|
||||
responses:
|
||||
"200": { $ref: "#/components/responses/Saved" }
|
||||
"400": { $ref: "#/components/responses/BadRequest" }
|
||||
"401": { $ref: "#/components/responses/Unauthorized" }
|
||||
"403": { $ref: "#/components/responses/Forbidden" }
|
||||
"413": { $ref: "#/components/responses/TooLarge" }
|
||||
|
||||
/config/{filename}/sections:
|
||||
parameters:
|
||||
- $ref: "#/components/parameters/Filename"
|
||||
post:
|
||||
tags: [Sections]
|
||||
summary: Add section
|
||||
operationId: addSection
|
||||
description: Appends a new section. A `name` is required.
|
||||
requestBody:
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema: { $ref: "#/components/schemas/Section" }
|
||||
example: { name: Monitoring, icon: fas fa-chart-line, items: [] }
|
||||
responses:
|
||||
"201":
|
||||
description: Section added
|
||||
content:
|
||||
application/json:
|
||||
schema: { $ref: "#/components/schemas/SectionResult" }
|
||||
"400": { $ref: "#/components/responses/BadRequest" }
|
||||
"401": { $ref: "#/components/responses/Unauthorized" }
|
||||
"403": { $ref: "#/components/responses/Forbidden" }
|
||||
|
||||
/config/{filename}/sections/{sid}:
|
||||
parameters:
|
||||
- $ref: "#/components/parameters/Filename"
|
||||
- $ref: "#/components/parameters/SectionId"
|
||||
get:
|
||||
tags: [Sections]
|
||||
summary: Get section
|
||||
operationId: getSection
|
||||
responses:
|
||||
"200":
|
||||
description: Section
|
||||
content:
|
||||
application/json:
|
||||
schema: { $ref: "#/components/schemas/Section" }
|
||||
"401": { $ref: "#/components/responses/Unauthorized" }
|
||||
"404": { $ref: "#/components/responses/NotFound" }
|
||||
patch:
|
||||
tags: [Sections]
|
||||
summary: Update section
|
||||
operationId: updateSection
|
||||
description: Shallow-merges the supplied fields. Sending `items` replaces the whole array.
|
||||
requestBody:
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema: { $ref: "#/components/schemas/SectionFields" }
|
||||
example: { name: Renamed Section }
|
||||
responses:
|
||||
"200":
|
||||
description: Updated section
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
allOf:
|
||||
- $ref: "#/components/schemas/WriteResult"
|
||||
- type: object
|
||||
properties:
|
||||
section: { $ref: "#/components/schemas/Section" }
|
||||
"400": { $ref: "#/components/responses/BadRequest" }
|
||||
"401": { $ref: "#/components/responses/Unauthorized" }
|
||||
"403": { $ref: "#/components/responses/Forbidden" }
|
||||
"404": { $ref: "#/components/responses/NotFound" }
|
||||
delete:
|
||||
tags: [Sections]
|
||||
summary: Delete section
|
||||
operationId: deleteSection
|
||||
responses:
|
||||
"200": { $ref: "#/components/responses/Saved" }
|
||||
"401": { $ref: "#/components/responses/Unauthorized" }
|
||||
"403": { $ref: "#/components/responses/Forbidden" }
|
||||
"404": { $ref: "#/components/responses/NotFound" }
|
||||
|
||||
/config/{filename}/sections/{sid}/items:
|
||||
parameters:
|
||||
- $ref: "#/components/parameters/Filename"
|
||||
- $ref: "#/components/parameters/SectionId"
|
||||
get:
|
||||
tags: [Items]
|
||||
summary: List items
|
||||
operationId: listItems
|
||||
responses:
|
||||
"200":
|
||||
description: Items in the section
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: array
|
||||
items: { $ref: "#/components/schemas/Item" }
|
||||
"401": { $ref: "#/components/responses/Unauthorized" }
|
||||
"404": { $ref: "#/components/responses/NotFound" }
|
||||
post:
|
||||
tags: [Items]
|
||||
summary: Add item
|
||||
operationId: addItem
|
||||
description: Appends a new item to the section. A `title` is required.
|
||||
requestBody:
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema: { $ref: "#/components/schemas/Item" }
|
||||
example: { title: Grafana, url: https://grafana.local, icon: hl-grafana }
|
||||
responses:
|
||||
"201":
|
||||
description: Item added
|
||||
content:
|
||||
application/json:
|
||||
schema: { $ref: "#/components/schemas/ItemResult" }
|
||||
"400": { $ref: "#/components/responses/BadRequest" }
|
||||
"401": { $ref: "#/components/responses/Unauthorized" }
|
||||
"403": { $ref: "#/components/responses/Forbidden" }
|
||||
"404": { $ref: "#/components/responses/NotFound" }
|
||||
|
||||
/config/{filename}/sections/{sid}/items/{iid}:
|
||||
parameters:
|
||||
- $ref: "#/components/parameters/Filename"
|
||||
- $ref: "#/components/parameters/SectionId"
|
||||
- $ref: "#/components/parameters/ItemId"
|
||||
get:
|
||||
tags: [Items]
|
||||
summary: Get item
|
||||
operationId: getItem
|
||||
responses:
|
||||
"200":
|
||||
description: Item
|
||||
content:
|
||||
application/json:
|
||||
schema: { $ref: "#/components/schemas/Item" }
|
||||
"401": { $ref: "#/components/responses/Unauthorized" }
|
||||
"404": { $ref: "#/components/responses/NotFound" }
|
||||
patch:
|
||||
tags: [Items]
|
||||
summary: Update item
|
||||
operationId: updateItem
|
||||
description: Shallow-merges the supplied fields onto the item.
|
||||
requestBody:
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema: { $ref: "#/components/schemas/ItemFields" }
|
||||
example: { url: https://grafana.example.com }
|
||||
responses:
|
||||
"200":
|
||||
description: Updated item
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
allOf:
|
||||
- $ref: "#/components/schemas/WriteResult"
|
||||
- type: object
|
||||
properties:
|
||||
item: { $ref: "#/components/schemas/Item" }
|
||||
"400": { $ref: "#/components/responses/BadRequest" }
|
||||
"401": { $ref: "#/components/responses/Unauthorized" }
|
||||
"403": { $ref: "#/components/responses/Forbidden" }
|
||||
"404": { $ref: "#/components/responses/NotFound" }
|
||||
delete:
|
||||
tags: [Items]
|
||||
summary: Delete item
|
||||
operationId: deleteItem
|
||||
responses:
|
||||
"200": { $ref: "#/components/responses/Saved" }
|
||||
"401": { $ref: "#/components/responses/Unauthorized" }
|
||||
"403": { $ref: "#/components/responses/Forbidden" }
|
||||
"404": { $ref: "#/components/responses/NotFound" }
|
||||
|
||||
components:
|
||||
securitySchemes:
|
||||
bearerAuth:
|
||||
type: http
|
||||
scheme: bearer
|
||||
description: |
|
||||
Send `Authorization: Bearer <token>`. Use either an `API_TOKEN` (grants full
|
||||
admin access) or, with OIDC/Keycloak, your ID token.
|
||||
basicAuth:
|
||||
type: http
|
||||
scheme: basic
|
||||
description: Dashy's HTTP basic auth (`ENABLE_HTTP_AUTH` users or `BASIC_AUTH_USERNAME`/`PASSWORD`).
|
||||
|
||||
parameters:
|
||||
Filename:
|
||||
name: filename
|
||||
in: path
|
||||
required: true
|
||||
description: A YAML config file in your user-data directory.
|
||||
schema: { type: string, pattern: "^[^/\\\\]+\\.ya?ml$" }
|
||||
example: conf.yml
|
||||
Key:
|
||||
name: key
|
||||
in: path
|
||||
required: true
|
||||
description: A top-level config key.
|
||||
schema: { type: string, enum: [pageInfo, appConfig, sections, pages] }
|
||||
example: appConfig
|
||||
SectionId:
|
||||
name: sid
|
||||
in: path
|
||||
required: true
|
||||
description: Section index (zero-based) or exact `name` (URL-encoded).
|
||||
schema: { type: string }
|
||||
example: "0"
|
||||
ItemId:
|
||||
name: iid
|
||||
in: path
|
||||
required: true
|
||||
description: Item index (zero-based) or exact `title` (URL-encoded).
|
||||
schema: { type: string }
|
||||
example: "0"
|
||||
|
||||
responses:
|
||||
Saved:
|
||||
description: Saved
|
||||
content:
|
||||
application/json:
|
||||
schema: { $ref: "#/components/schemas/WriteResult" }
|
||||
example: { success: true, message: Config has been written to disk }
|
||||
Disabled:
|
||||
description: API not enabled
|
||||
content:
|
||||
application/json:
|
||||
schema: { $ref: "#/components/schemas/Error" }
|
||||
example: { success: false, message: "API not enabled. Set ENABLE_API=true to use the REST API." }
|
||||
BadRequest:
|
||||
description: Invalid filename, key, body or schema
|
||||
content:
|
||||
application/json:
|
||||
schema: { $ref: "#/components/schemas/Error" }
|
||||
example: { success: false, message: "Section must have a 'name'" }
|
||||
Unauthorized:
|
||||
description: Authentication required or invalid
|
||||
content:
|
||||
application/json:
|
||||
schema: { $ref: "#/components/schemas/Error" }
|
||||
example: { success: false, message: Unauthorized }
|
||||
Forbidden:
|
||||
description: Authenticated, but not an admin
|
||||
content:
|
||||
application/json:
|
||||
schema: { $ref: "#/components/schemas/Error" }
|
||||
NotFound:
|
||||
description: File, key, section or item not found
|
||||
content:
|
||||
application/json:
|
||||
schema: { $ref: "#/components/schemas/Error" }
|
||||
example: { success: false, message: conf.yml not found }
|
||||
ParseError:
|
||||
description: File could not be read or parsed
|
||||
content:
|
||||
application/json:
|
||||
schema: { $ref: "#/components/schemas/Error" }
|
||||
TooLarge:
|
||||
description: Body exceeds the size limit (256 KB)
|
||||
content:
|
||||
application/json:
|
||||
schema: { $ref: "#/components/schemas/Error" }
|
||||
|
||||
schemas:
|
||||
Error:
|
||||
type: object
|
||||
properties:
|
||||
success: { type: boolean, enum: [false] }
|
||||
message: { type: string }
|
||||
required: [success, message]
|
||||
WriteResult:
|
||||
type: object
|
||||
properties:
|
||||
success: { type: boolean, enum: [true] }
|
||||
message: { type: string }
|
||||
required: [success, message]
|
||||
FileList:
|
||||
type: object
|
||||
properties:
|
||||
success: { type: boolean, enum: [true] }
|
||||
files:
|
||||
type: array
|
||||
items: { type: string }
|
||||
required: [success, files]
|
||||
SectionResult:
|
||||
allOf:
|
||||
- $ref: "#/components/schemas/WriteResult"
|
||||
- type: object
|
||||
properties:
|
||||
index: { type: integer, description: Array index of the section }
|
||||
section: { $ref: "#/components/schemas/Section" }
|
||||
ItemResult:
|
||||
allOf:
|
||||
- $ref: "#/components/schemas/WriteResult"
|
||||
- type: object
|
||||
properties:
|
||||
index: { type: integer, description: Array index of the item }
|
||||
item: { $ref: "#/components/schemas/Item" }
|
||||
|
||||
Config:
|
||||
type: object
|
||||
description: A full config file. `conf.yml` requires `sections`; sub-pages may hold any subset.
|
||||
additionalProperties: false
|
||||
properties:
|
||||
pageInfo: { $ref: "#/components/schemas/PageInfo" }
|
||||
appConfig: { $ref: "#/components/schemas/AppConfig" }
|
||||
sections:
|
||||
type: array
|
||||
items: { $ref: "#/components/schemas/Section" }
|
||||
pages:
|
||||
type: array
|
||||
items: { $ref: "#/components/schemas/Page" }
|
||||
KeyValue:
|
||||
description: The value of one top-level key.
|
||||
oneOf:
|
||||
- $ref: "#/components/schemas/PageInfo"
|
||||
- $ref: "#/components/schemas/AppConfig"
|
||||
- type: array
|
||||
items: { $ref: "#/components/schemas/Section" }
|
||||
- type: array
|
||||
items: { $ref: "#/components/schemas/Page" }
|
||||
|
||||
PageInfo:
|
||||
type: object
|
||||
description: Branding shown in the header and footer.
|
||||
additionalProperties: false
|
||||
properties:
|
||||
title: { type: string, description: Dashboard title }
|
||||
description: { type: string, description: Sub-title }
|
||||
navLinks: { type: array, description: Header navigation links, items: { type: object } }
|
||||
footer: { type: string, description: Footer HTML or text }
|
||||
logo: { type: string, description: Path or URL to the header logo }
|
||||
favicon: { type: string, description: Path or URL to the favicon }
|
||||
color: { type: string, description: Header text color }
|
||||
|
||||
AppConfig:
|
||||
type: object
|
||||
description: |
|
||||
Global app settings (theme, layout, status checks, auth, etc.). Many fields are
|
||||
supported. See the [configuring docs](https://github.com/Lissy93/dashy/blob/master/docs/configuring.md).
|
||||
properties:
|
||||
theme: { type: string, description: Default theme name }
|
||||
layout: { type: string, enum: [horizontal, vertical, auto, masonry, sidebar], description: Section layout }
|
||||
iconSize: { type: string, enum: [small, medium, large], description: Item icon size }
|
||||
language: { type: string, description: UI language code }
|
||||
startingView: { type: string, enum: [home, default, minimal, workspace], description: Initial view }
|
||||
statusCheck: { type: boolean, description: Enable status checks globally }
|
||||
|
||||
SectionFields:
|
||||
type: object
|
||||
description: Any subset of a section's fields (used for PATCH).
|
||||
additionalProperties: false
|
||||
properties:
|
||||
name:
|
||||
type: string
|
||||
description: Section heading (unique)
|
||||
icon:
|
||||
type: string
|
||||
description: Section icon
|
||||
displayData:
|
||||
type: object
|
||||
description: Per-section display options
|
||||
items:
|
||||
type: array
|
||||
description: The links/apps in this section
|
||||
items: { $ref: "#/components/schemas/Item" }
|
||||
widgets:
|
||||
type: array
|
||||
description: Widgets shown in this section
|
||||
items: { type: object }
|
||||
filteredItems:
|
||||
type: array
|
||||
description: Items pulled from another source
|
||||
items: { type: object }
|
||||
Section:
|
||||
description: A group of items, shown as a card. Requires a `name`.
|
||||
allOf:
|
||||
- $ref: "#/components/schemas/SectionFields"
|
||||
- { type: object, required: [name] }
|
||||
|
||||
ItemFields:
|
||||
type: object
|
||||
description: Any subset of an item's fields (used for PATCH).
|
||||
additionalProperties: false
|
||||
properties:
|
||||
title:
|
||||
type: string
|
||||
description: Display name
|
||||
description:
|
||||
type: string
|
||||
description: Text shown on hover
|
||||
icon:
|
||||
type: string
|
||||
description: "Icon (URL, favicon, font-awesome, etc.)"
|
||||
url:
|
||||
type: string
|
||||
description: Target URL
|
||||
target:
|
||||
type: string
|
||||
enum: [newtab, sametab, parent, top, modal, workspace, clipboard, newwindow]
|
||||
description: How the link opens
|
||||
provider:
|
||||
type: string
|
||||
description: Hosting provider name
|
||||
id:
|
||||
type: string
|
||||
description: Unique identifier
|
||||
tags:
|
||||
type: array
|
||||
description: Tags for filtering
|
||||
items: { type: string }
|
||||
hotkey:
|
||||
type: integer
|
||||
description: Numeric keyboard shortcut
|
||||
rel:
|
||||
type: string
|
||||
description: Anchor rel attribute
|
||||
color:
|
||||
type: string
|
||||
description: Text color
|
||||
backgroundColor:
|
||||
type: string
|
||||
description: Background color
|
||||
displayData:
|
||||
type: object
|
||||
description: Per-item display options
|
||||
subItems:
|
||||
type: array
|
||||
description: Nested child items
|
||||
items: { type: object }
|
||||
statusCheck:
|
||||
type: boolean
|
||||
description: Enable status check for this item
|
||||
statusCheckUrl:
|
||||
type: string
|
||||
description: Override URL to ping
|
||||
statusCheckHeaders:
|
||||
type: object
|
||||
description: Headers sent with the status check
|
||||
statusCheckAllowInsecure:
|
||||
type: boolean
|
||||
description: Allow invalid TLS certs
|
||||
statusCheckAcceptCodes:
|
||||
type: string
|
||||
description: Extra HTTP codes treated as up
|
||||
statusCheckMaxRedirects:
|
||||
type: integer
|
||||
description: Max redirects to follow
|
||||
pingCheckEnabled:
|
||||
type: boolean
|
||||
description: Enable ICMP ping check
|
||||
pingCheckHost:
|
||||
type: string
|
||||
description: Host to ping
|
||||
pingCheckInterval:
|
||||
type: integer
|
||||
description: Ping interval (seconds)
|
||||
pingCheckCount:
|
||||
type: integer
|
||||
description: Number of pings
|
||||
pingCheckTimeout:
|
||||
type: integer
|
||||
description: Ping timeout (ms)
|
||||
Item:
|
||||
description: A single link, app or service. Requires a `title`.
|
||||
allOf:
|
||||
- $ref: "#/components/schemas/ItemFields"
|
||||
- { type: object, required: [title] }
|
||||
|
||||
Page:
|
||||
type: object
|
||||
description: An extra config file loaded as a separate page.
|
||||
additionalProperties: false
|
||||
required: [name, path]
|
||||
properties:
|
||||
name: { type: string, description: Unique page identifier }
|
||||
path: { type: string, description: File name or path of the page's config }
|
||||
displayData: { type: object, description: Page visibility and display options }
|
||||
Reference in New Issue
Block a user