Files
ShadowMountPlus/docs/openapi.yaml
T

1929 lines
57 KiB
YAML

openapi: 3.1.2
info:
title: ShadowMount HTTP API
version: "1"
description: |
HTTP/JSON API exposed by the ShadowMountPlus payload. The service has no
authentication and should only be exposed on a trusted network.
servers:
- url: http://127.0.0.1:10101
description: Default loopback endpoint on the PS5
- url: http://{address}:{port}
description: Configured network endpoint
variables:
address:
default: 192.168.1.50
description: PS5 IPv4 address or hostname
port:
default: "10101"
description: Value of api_port
security: []
tags:
- name: Service
- name: Storage
- name: Scanner
- name: Manual sources
- name: Images
- name: Games
paths:
/:
options:
operationId: preflightIndex
summary: CORS preflight
tags: [Service]
responses:
"204":
$ref: "#/components/responses/Preflight"
get:
operationId: getWebInterface
summary: Get the optional web interface
description: Serves /data/shadowmount/index.html when it is a regular file.
tags: [Service]
responses:
"200":
description: ShadowMount web interface
headers:
Access-Control-Allow-Origin:
$ref: "#/components/headers/AllowOrigin"
content:
text/html:
schema:
type: string
"404":
$ref: "#/components/responses/NotFound"
"500":
$ref: "#/components/responses/InternalError"
/api/v1/version:
options:
operationId: preflightVersion
summary: CORS preflight
tags: [Service]
responses:
"204":
$ref: "#/components/responses/Preflight"
post:
operationId: getVersion
summary: Get API version and capabilities
tags: [Service]
requestBody:
$ref: "#/components/requestBodies/EmptyRequest"
responses:
"200":
$ref: "#/components/responses/VersionSuccess"
"400":
$ref: "#/components/responses/BadRequest"
"411":
$ref: "#/components/responses/LengthRequired"
"413":
$ref: "#/components/responses/PayloadTooLarge"
"415":
$ref: "#/components/responses/UnsupportedMediaType"
"431":
$ref: "#/components/responses/HeadersTooLarge"
"500":
$ref: "#/components/responses/InternalError"
"501":
$ref: "#/components/responses/NotImplemented"
/api/v1/images:
options:
operationId: preflightImages
summary: CORS preflight
tags: [Images]
responses:
"204":
$ref: "#/components/responses/Preflight"
post:
operationId: listImages
summary: Get the complete image snapshot
tags: [Images]
requestBody:
$ref: "#/components/requestBodies/EmptyRequest"
responses:
"200":
$ref: "#/components/responses/ImagesSuccess"
"400":
$ref: "#/components/responses/BadRequest"
"411":
$ref: "#/components/responses/LengthRequired"
"413":
$ref: "#/components/responses/PayloadTooLarge"
"415":
$ref: "#/components/responses/UnsupportedMediaType"
"431":
$ref: "#/components/responses/HeadersTooLarge"
"500":
$ref: "#/components/responses/InternalError"
"501":
$ref: "#/components/responses/NotImplemented"
/api/v1/storage:
options:
operationId: preflightStorage
summary: CORS preflight
tags: [Storage]
responses:
"204":
$ref: "#/components/responses/Preflight"
post:
operationId: getStorageSpace
summary: Get free space for mounted storage filesystems
tags: [Storage]
requestBody:
$ref: "#/components/requestBodies/EmptyRequest"
responses:
"200":
$ref: "#/components/responses/StorageSpaceSuccess"
"400":
$ref: "#/components/responses/BadRequest"
"411":
$ref: "#/components/responses/LengthRequired"
"413":
$ref: "#/components/responses/PayloadTooLarge"
"415":
$ref: "#/components/responses/UnsupportedMediaType"
"431":
$ref: "#/components/responses/HeadersTooLarge"
"500":
$ref: "#/components/responses/InternalError"
"501":
$ref: "#/components/responses/NotImplemented"
/api/v1/scan:
options:
operationId: preflightScan
summary: CORS preflight
tags: [Scanner]
responses:
"204":
$ref: "#/components/responses/Preflight"
post:
operationId: rescan
summary: Queue an immediate full rescan
description: Retry counters are preserved by default. With reset_attempts=true, all title registration/install-remount and path-owned image-mount retry counters are reset immediately before the requested scan starts. If game runtime mounts are busy, the request remains queued until scanning is safe.
tags: [Scanner]
requestBody:
$ref: "#/components/requestBodies/ScanRequest"
responses:
"200":
$ref: "#/components/responses/ScanSuccess"
"400":
$ref: "#/components/responses/BadRequest"
"409":
$ref: "#/components/responses/Busy"
"411":
$ref: "#/components/responses/LengthRequired"
"413":
$ref: "#/components/responses/PayloadTooLarge"
"415":
$ref: "#/components/responses/UnsupportedMediaType"
"431":
$ref: "#/components/responses/HeadersTooLarge"
"500":
$ref: "#/components/responses/InternalError"
"501":
$ref: "#/components/responses/NotImplemented"
/api/v1/manual/list:
options:
operationId: preflightListManualSources
summary: CORS preflight
tags: [Manual sources]
responses:
"204":
$ref: "#/components/responses/Preflight"
post:
operationId: listManualSources
summary: List direct game source paths from manual.lst
description: Entries identify individual game folders or images, not recursive scan roots. Comments and empty lines are omitted.
tags: [Manual sources]
requestBody:
$ref: "#/components/requestBodies/EmptyRequest"
responses:
"200":
$ref: "#/components/responses/ManualListSuccess"
"400":
$ref: "#/components/responses/BadRequest"
"411":
$ref: "#/components/responses/LengthRequired"
"413":
$ref: "#/components/responses/PayloadTooLarge"
"415":
$ref: "#/components/responses/UnsupportedMediaType"
"431":
$ref: "#/components/responses/HeadersTooLarge"
"500":
$ref: "#/components/responses/InternalError"
"501":
$ref: "#/components/responses/NotImplemented"
/api/v1/manual/add:
options:
operationId: preflightAddManualSource
summary: CORS preflight
tags: [Manual sources]
responses:
"204":
$ref: "#/components/responses/Preflight"
post:
operationId: addManualSource
summary: Add a source path to manual.lst
tags: [Manual sources]
requestBody:
$ref: "#/components/requestBodies/ManualPathRequest"
responses:
"200":
$ref: "#/components/responses/ManualUpdateSuccess"
"400":
$ref: "#/components/responses/BadRequest"
"411":
$ref: "#/components/responses/LengthRequired"
"413":
$ref: "#/components/responses/PayloadTooLarge"
"415":
$ref: "#/components/responses/UnsupportedMediaType"
"431":
$ref: "#/components/responses/HeadersTooLarge"
"500":
$ref: "#/components/responses/InternalError"
"501":
$ref: "#/components/responses/NotImplemented"
/api/v1/manual/remove:
options:
operationId: preflightRemoveManualSource
summary: CORS preflight
tags: [Manual sources]
responses:
"204":
$ref: "#/components/responses/Preflight"
post:
operationId: removeManualSource
summary: Remove all matching source lines from manual.lst
tags: [Manual sources]
requestBody:
$ref: "#/components/requestBodies/ManualPathRequest"
responses:
"200":
$ref: "#/components/responses/ManualUpdateSuccess"
"400":
$ref: "#/components/responses/BadRequest"
"411":
$ref: "#/components/responses/LengthRequired"
"413":
$ref: "#/components/responses/PayloadTooLarge"
"415":
$ref: "#/components/responses/UnsupportedMediaType"
"431":
$ref: "#/components/responses/HeadersTooLarge"
"500":
$ref: "#/components/responses/InternalError"
"501":
$ref: "#/components/responses/NotImplemented"
/api/v1/games:
options:
operationId: preflightGames
summary: CORS preflight
tags: [Games]
responses:
"204":
$ref: "#/components/responses/Preflight"
post:
operationId: listGames
summary: Get the complete game snapshot
tags: [Games]
requestBody:
$ref: "#/components/requestBodies/GamesListRequest"
responses:
"200":
$ref: "#/components/responses/GamesSuccess"
"400":
$ref: "#/components/responses/BadRequest"
"411":
$ref: "#/components/responses/LengthRequired"
"413":
$ref: "#/components/responses/PayloadTooLarge"
"415":
$ref: "#/components/responses/UnsupportedMediaType"
"431":
$ref: "#/components/responses/HeadersTooLarge"
"500":
$ref: "#/components/responses/InternalError"
"501":
$ref: "#/components/responses/NotImplemented"
/api/v1/games/info:
options:
operationId: preflightGameInfo
summary: CORS preflight
tags: [Games]
responses:
"204":
$ref: "#/components/responses/Preflight"
post:
operationId: getGameInfo
summary: Get detailed metadata and size for a folder, image or installed PKG
tags: [Games]
requestBody:
$ref: "#/components/requestBodies/TitleRequest"
responses:
"200":
$ref: "#/components/responses/GameInfoSuccess"
"400":
$ref: "#/components/responses/BadRequest"
"404":
$ref: "#/components/responses/NotFound"
"409":
$ref: "#/components/responses/Busy"
"500":
$ref: "#/components/responses/InternalError"
/api/v1/games/fakelib:
options:
operationId: preflightGameFakelib
summary: CORS preflight
tags: [Games]
responses:
"204":
$ref: "#/components/responses/Preflight"
post:
operationId: setGameFakelib
summary: Enable or disable fakelib for a PS5 game on its next launch
tags: [Games]
requestBody:
required: true
content:
application/json:
schema:
type: object
required: [title_id, enabled]
properties:
title_id:
$ref: "#/components/schemas/TitleId"
description: Must identify a PS5 game; homebrew uses its app.db platform.
enabled:
type: boolean
responses:
"200":
description: Per-title policy saved; existing mounts are preserved
content:
application/json:
schema:
type: object
required: [status, title_id, fakelib_enabled, fakelib_effective_enabled, saved, applies_on_next_launch]
properties:
status:
type: integer
const: 0
title_id:
$ref: "#/components/schemas/TitleId"
fakelib_enabled:
type: boolean
fakelib_effective_enabled:
type: boolean
saved:
type: boolean
const: true
applies_on_next_launch:
type: boolean
const: true
"400":
$ref: "#/components/responses/BadRequest"
"404":
$ref: "#/components/responses/NotFound"
"500":
$ref: "#/components/responses/InternalError"
"507":
description: Exclusion list is full; configuration was not changed
/api/v1/games/icon:
get:
operationId: getGameIcon
summary: Stream a game icon or a cached 128x128 thumbnail
tags: [Games]
parameters:
- name: title_id
in: query
required: true
schema:
$ref: "#/components/schemas/TitleId"
- name: size
in: query
required: false
description: Generate and return the cached thumbnail variant
schema:
type: string
enum: [thumb]
responses:
"200":
description: PNG icon
headers:
Access-Control-Allow-Origin:
$ref: "#/components/headers/AllowOrigin"
content:
image/png:
schema:
type: string
format: binary
"400":
$ref: "#/components/responses/BadRequest"
"404":
$ref: "#/components/responses/NotFound"
"500":
$ref: "#/components/responses/InternalError"
/api/v1/settings:
options:
operationId: preflightGetSettings
summary: CORS preflight
tags: [Settings]
responses:
"204":
$ref: "#/components/responses/Preflight"
post:
operationId: getSettings
summary: Read web-managed settings and recursive scan roots
tags: [Settings]
requestBody:
$ref: "#/components/requestBodies/EmptyRequest"
responses:
"200":
description: Current runtime settings
content:
application/json:
schema:
$ref: "#/components/schemas/SettingsResponse"
"400":
$ref: "#/components/responses/BadRequest"
"500":
$ref: "#/components/responses/InternalError"
/api/v1/settings/update:
options:
operationId: preflightUpdateSettings
summary: CORS preflight
tags: [Settings]
responses:
"204":
$ref: "#/components/responses/Preflight"
post:
operationId: updateSettings
summary: Atomically update web-managed config.ini keys
description: Preserves unrelated keys and comments, then queues scanner-owned runtime reload.
tags: [Settings]
requestBody:
required: true
content:
application/json:
schema:
$ref: "#/components/schemas/SettingsUpdateRequest"
responses:
"200":
description: Settings saved and reload queued
"400":
$ref: "#/components/responses/BadRequest"
"403":
$ref: "#/components/responses/Forbidden"
"500":
$ref: "#/components/responses/InternalError"
/api/v1/debug-log:
options:
operationId: preflightGetDebugLog
summary: CORS preflight
tags: [Settings]
responses:
"204":
$ref: "#/components/responses/Preflight"
post:
operationId: getDebugLog
summary: Read a bounded tail of debug.log
tags: [Settings]
requestBody:
required: true
content:
application/json:
schema:
type: object
properties:
max_bytes:
type: integer
minimum: 4096
maximum: 262144
default: 131072
responses:
"200":
description: Debug log tail
content:
application/json:
schema:
$ref: "#/components/schemas/DebugLogResponse"
"400":
$ref: "#/components/responses/BadRequest"
"500":
$ref: "#/components/responses/InternalError"
/api/v1/kernel-log:
options:
operationId: preflightGetKernelLog
summary: CORS preflight
tags: [Settings]
responses:
"204":
$ref: "#/components/responses/Preflight"
post:
operationId: getKernelLog
summary: Read recent events from the SDK log stream used by crash detection
description: Uses the sceKernelDebugGetSdkLogText snapshot shared with crash detection.
tags: [Settings]
requestBody:
required: true
content:
application/json:
schema:
type: object
properties:
max_bytes:
type: integer
minimum: 4096
maximum: 262144
default: 131072
responses:
"200":
description: SDK kernel-log tail
content:
application/json:
schema:
$ref: "#/components/schemas/KernelLogResponse"
"400":
$ref: "#/components/responses/BadRequest"
"403":
$ref: "#/components/responses/Forbidden"
"500":
$ref: "#/components/responses/InternalError"
/api/v1/games/move:
options:
operationId: preflightMoveGameSource
summary: CORS preflight
tags: [Storage]
responses:
"204":
$ref: "#/components/responses/Preflight"
post:
operationId: moveGameSource
summary: Move a game folder or backing image, including across filesystems
tags: [Storage]
requestBody:
$ref: "#/components/requestBodies/StorageDestinationRequest"
responses:
"202":
$ref: "#/components/responses/StorageJobAccepted"
"400":
$ref: "#/components/responses/BadRequest"
"403":
$ref: "#/components/responses/Forbidden"
"404":
$ref: "#/components/responses/NotFound"
"409":
$ref: "#/components/responses/Busy"
"500":
$ref: "#/components/responses/InternalError"
"507":
$ref: "#/components/responses/InsufficientStorage"
/api/v1/games/copy:
options:
operationId: preflightCopyGameSource
summary: CORS preflight
tags: [Storage]
responses:
"204":
$ref: "#/components/responses/Preflight"
post:
operationId: copyGameSource
summary: Copy a game folder or backing image
tags: [Storage]
requestBody:
$ref: "#/components/requestBodies/StorageDestinationRequest"
responses:
"202":
$ref: "#/components/responses/StorageJobAccepted"
"400":
$ref: "#/components/responses/BadRequest"
"403":
$ref: "#/components/responses/Forbidden"
"404":
$ref: "#/components/responses/NotFound"
"409":
$ref: "#/components/responses/Busy"
"500":
$ref: "#/components/responses/InternalError"
"507":
$ref: "#/components/responses/InsufficientStorage"
/api/v1/games/unpack:
options:
operationId: preflightUnpackGameImage
summary: CORS preflight
tags: [Storage]
responses:
"204":
$ref: "#/components/responses/Preflight"
post:
operationId: unpackGameImage
summary: Mount an image read-only and copy its game tree into a folder
tags: [Storage]
requestBody:
required: true
content:
application/json:
schema:
$ref: "#/components/schemas/StorageUnpackRequest"
responses:
"202":
$ref: "#/components/responses/StorageJobAccepted"
"400":
$ref: "#/components/responses/BadRequest"
"403":
$ref: "#/components/responses/Forbidden"
"404":
$ref: "#/components/responses/NotFound"
"409":
$ref: "#/components/responses/Busy"
"500":
$ref: "#/components/responses/InternalError"
"501":
$ref: "#/components/responses/NotImplemented"
"507":
$ref: "#/components/responses/InsufficientStorage"
/api/v1/games/storage/status:
options:
operationId: preflightStorageJobStatus
summary: CORS preflight
tags: [Storage]
responses:
"204":
$ref: "#/components/responses/Preflight"
post:
operationId: getStorageJobStatus
summary: Get the current or last storage job
tags: [Storage]
requestBody:
$ref: "#/components/requestBodies/StorageJobStatusRequest"
responses:
"200":
$ref: "#/components/responses/StorageJobStatusSuccess"
"400":
$ref: "#/components/responses/BadRequest"
"404":
$ref: "#/components/responses/NotFound"
"500":
$ref: "#/components/responses/InternalError"
/api/v1/games/storage/cancel:
options:
operationId: preflightStorageJobCancel
summary: CORS preflight
tags: [Storage]
responses:
"204":
$ref: "#/components/responses/Preflight"
post:
operationId: cancelStorageJob
summary: Cancel an active storage job before its irreversible phase
tags: [Storage]
requestBody:
$ref: "#/components/requestBodies/StorageJobCancelRequest"
responses:
"200":
$ref: "#/components/responses/StorageJobStatusSuccess"
"400":
$ref: "#/components/responses/BadRequest"
"404":
$ref: "#/components/responses/NotFound"
"409":
$ref: "#/components/responses/Busy"
"500":
$ref: "#/components/responses/InternalError"
/api/v1/games/delete:
options:
operationId: preflightDeleteGameSource
summary: CORS preflight
tags: [Storage]
responses:
"204":
$ref: "#/components/responses/Preflight"
post:
operationId: deleteGameSource
summary: Asynchronously delete a game folder or backing image
description: A confirmed request for a cached source that is already absent queues safe scanner reconciliation without starting a storage job or directly uninstalling the title. Absence may also mean disconnected storage. Permission and I/O errors remain failures.
tags: [Storage]
requestBody:
$ref: "#/components/requestBodies/StorageDeleteRequest"
responses:
"200":
description: Source already absent; library reconciliation queued
content:
application/json:
schema:
$ref: "#/components/schemas/MissingSourceResponse"
"202":
$ref: "#/components/responses/StorageJobAccepted"
"400":
$ref: "#/components/responses/BadRequest"
"403":
$ref: "#/components/responses/Forbidden"
"404":
$ref: "#/components/responses/NotFound"
"409":
$ref: "#/components/responses/Busy"
"500":
$ref: "#/components/responses/InternalError"
/api/v1/games/mount:
options:
operationId: preflightMountGame
summary: CORS preflight
tags: [Games]
responses:
"204":
$ref: "#/components/responses/Preflight"
post:
operationId: mountGame
summary: Mount a managed game
tags: [Games]
requestBody:
$ref: "#/components/requestBodies/MountRequest"
responses:
"200":
$ref: "#/components/responses/MountSuccess"
"400":
$ref: "#/components/responses/BadRequest"
"404":
$ref: "#/components/responses/NotFound"
"409":
$ref: "#/components/responses/Busy"
"411":
$ref: "#/components/responses/LengthRequired"
"413":
$ref: "#/components/responses/PayloadTooLarge"
"415":
$ref: "#/components/responses/UnsupportedMediaType"
"431":
$ref: "#/components/responses/HeadersTooLarge"
"500":
$ref: "#/components/responses/InternalError"
"501":
$ref: "#/components/responses/NotImplemented"
/api/v1/games/unmount:
options:
operationId: preflightUnmountGame
summary: CORS preflight
tags: [Games]
responses:
"204":
$ref: "#/components/responses/Preflight"
post:
operationId: unmountGame
summary: Unmount a managed game
tags: [Games]
requestBody:
$ref: "#/components/requestBodies/TitleRequest"
responses:
"200":
$ref: "#/components/responses/UnmountSuccess"
"400":
$ref: "#/components/responses/BadRequest"
"404":
$ref: "#/components/responses/NotFound"
"409":
$ref: "#/components/responses/Busy"
"411":
$ref: "#/components/responses/LengthRequired"
"413":
$ref: "#/components/responses/PayloadTooLarge"
"415":
$ref: "#/components/responses/UnsupportedMediaType"
"431":
$ref: "#/components/responses/HeadersTooLarge"
"500":
$ref: "#/components/responses/InternalError"
"501":
$ref: "#/components/responses/NotImplemented"
/api/v1/games/uninstall:
options:
operationId: preflightUninstallGame
summary: CORS preflight
tags: [Games]
responses:
"204":
$ref: "#/components/responses/Preflight"
post:
operationId: uninstallGame
summary: Request game uninstallation
tags: [Games]
requestBody:
$ref: "#/components/requestBodies/TitleRequest"
responses:
"200":
$ref: "#/components/responses/UninstallSuccess"
"400":
$ref: "#/components/responses/BadRequest"
"404":
$ref: "#/components/responses/NotFound"
"409":
$ref: "#/components/responses/Busy"
"411":
$ref: "#/components/responses/LengthRequired"
"413":
$ref: "#/components/responses/PayloadTooLarge"
"415":
$ref: "#/components/responses/UnsupportedMediaType"
"431":
$ref: "#/components/responses/HeadersTooLarge"
"500":
$ref: "#/components/responses/InternalError"
"501":
$ref: "#/components/responses/NotImplemented"
components:
requestBodies:
EmptyRequest:
required: true
content:
application/json:
schema:
type: object
example: {}
GamesListRequest:
required: true
content:
application/json:
schema:
$ref: "#/components/schemas/GamesListRequest"
ScanRequest:
required: true
content:
application/json:
schema:
$ref: "#/components/schemas/ScanRequest"
TitleRequest:
required: true
content:
application/json:
schema:
$ref: "#/components/schemas/TitleRequest"
MountRequest:
required: true
content:
application/json:
schema:
$ref: "#/components/schemas/MountRequest"
ManualPathRequest:
required: true
content:
application/json:
schema:
$ref: "#/components/schemas/ManualPathRequest"
StorageDestinationRequest:
required: true
content:
application/json:
schema:
$ref: "#/components/schemas/StorageDestinationRequest"
StorageDeleteRequest:
required: true
content:
application/json:
schema:
$ref: "#/components/schemas/StorageDeleteRequest"
StorageJobStatusRequest:
required: true
content:
application/json:
schema:
$ref: "#/components/schemas/StorageJobStatusRequest"
StorageJobCancelRequest:
required: true
content:
application/json:
schema:
$ref: "#/components/schemas/StorageJobCancelRequest"
headers:
AllowOrigin:
description: Browser origins allowed to access the API
schema:
type: string
const: "*"
AllowMethods:
description: Methods allowed by CORS preflight
schema:
type: string
const: GET, POST, OPTIONS
AllowHeaders:
description: Request headers allowed by CORS preflight
schema:
type: string
const: Content-Type
AllowPrivateNetwork:
description: Private Network Access permission
schema:
type: string
const: "true"
MaxAge:
description: Number of seconds for which the preflight may be cached
schema:
type: integer
const: 86400
responses:
Preflight:
description: CORS preflight accepted
headers:
Access-Control-Allow-Origin:
$ref: "#/components/headers/AllowOrigin"
Access-Control-Allow-Methods:
$ref: "#/components/headers/AllowMethods"
Access-Control-Allow-Headers:
$ref: "#/components/headers/AllowHeaders"
Access-Control-Allow-Private-Network:
$ref: "#/components/headers/AllowPrivateNetwork"
Access-Control-Max-Age:
$ref: "#/components/headers/MaxAge"
VersionSuccess:
description: API version and capabilities
headers:
Access-Control-Allow-Origin:
$ref: "#/components/headers/AllowOrigin"
content:
application/json:
schema:
$ref: "#/components/schemas/VersionResponse"
ImagesSuccess:
description: Complete image snapshot
headers:
Access-Control-Allow-Origin:
$ref: "#/components/headers/AllowOrigin"
content:
application/json:
schema:
$ref: "#/components/schemas/ImagesResponse"
StorageSpaceSuccess:
description: Capacity and free space for mounted storage filesystems
headers:
Access-Control-Allow-Origin:
$ref: "#/components/headers/AllowOrigin"
content:
application/json:
schema:
$ref: "#/components/schemas/StorageSpaceResponse"
GamesSuccess:
description: Complete game snapshot
headers:
Access-Control-Allow-Origin:
$ref: "#/components/headers/AllowOrigin"
content:
application/json:
schema:
$ref: "#/components/schemas/GamesResponse"
GameInfoSuccess:
description: Detailed managed game metadata and physical source size
headers:
Access-Control-Allow-Origin:
$ref: "#/components/headers/AllowOrigin"
content:
application/json:
schema:
$ref: "#/components/schemas/GameInfoResponse"
StorageJobAccepted:
description: Copy, move, delete or unpack job accepted for asynchronous execution
headers:
Access-Control-Allow-Origin:
$ref: "#/components/headers/AllowOrigin"
content:
application/json:
schema:
$ref: "#/components/schemas/StorageJobResponse"
StorageJobStatusSuccess:
description: Current or last copy, move, delete or unpack job status
headers:
Access-Control-Allow-Origin:
$ref: "#/components/headers/AllowOrigin"
content:
application/json:
schema:
$ref: "#/components/schemas/StorageJobResponse"
ScanSuccess:
description: Full rescan queued
headers:
Access-Control-Allow-Origin:
$ref: "#/components/headers/AllowOrigin"
content:
application/json:
schema:
$ref: "#/components/schemas/ScanResponse"
ManualUpdateSuccess:
description: manual.lst update completed
headers:
Access-Control-Allow-Origin:
$ref: "#/components/headers/AllowOrigin"
content:
application/json:
schema:
$ref: "#/components/schemas/ManualUpdateResponse"
ManualListSuccess:
description: Parsed manual.lst source paths
headers:
Access-Control-Allow-Origin:
$ref: "#/components/headers/AllowOrigin"
content:
application/json:
schema:
$ref: "#/components/schemas/ManualListResponse"
MountSuccess:
description: Game mounted
headers:
Access-Control-Allow-Origin:
$ref: "#/components/headers/AllowOrigin"
content:
application/json:
schema:
$ref: "#/components/schemas/MountResponse"
UnmountSuccess:
description: Game unmounted
headers:
Access-Control-Allow-Origin:
$ref: "#/components/headers/AllowOrigin"
content:
application/json:
schema:
$ref: "#/components/schemas/UnmountResponse"
UninstallSuccess:
description: Game uninstallation was accepted by AppInstUtil
headers:
Access-Control-Allow-Origin:
$ref: "#/components/headers/AllowOrigin"
content:
application/json:
schema:
$ref: "#/components/schemas/UninstallResponse"
BadRequest:
description: Invalid HTTP request, JSON body or title ID
headers:
Access-Control-Allow-Origin:
$ref: "#/components/headers/AllowOrigin"
content:
application/json:
schema:
$ref: "#/components/schemas/ErrorResponse"
Forbidden:
description: The source or destination is not allowed
headers:
Access-Control-Allow-Origin:
$ref: "#/components/headers/AllowOrigin"
content:
application/json:
schema:
$ref: "#/components/schemas/ErrorResponse"
NotFound:
description: Managed title tracker was not found
headers:
Access-Control-Allow-Origin:
$ref: "#/components/headers/AllowOrigin"
content:
application/json:
schema:
$ref: "#/components/schemas/ErrorResponse"
Busy:
description: Runtime state does not currently permit the operation
headers:
Access-Control-Allow-Origin:
$ref: "#/components/headers/AllowOrigin"
content:
application/json:
schema:
$ref: "#/components/schemas/ErrorResponse"
example:
status: 16
error: Device busy
LengthRequired:
description: Content-Length is required
headers:
Access-Control-Allow-Origin:
$ref: "#/components/headers/AllowOrigin"
content:
application/json:
schema:
$ref: "#/components/schemas/ErrorResponse"
PayloadTooLarge:
description: JSON request body exceeds 4096 bytes
headers:
Access-Control-Allow-Origin:
$ref: "#/components/headers/AllowOrigin"
content:
application/json:
schema:
$ref: "#/components/schemas/ErrorResponse"
UnsupportedMediaType:
description: Content-Type is not application/json
headers:
Access-Control-Allow-Origin:
$ref: "#/components/headers/AllowOrigin"
content:
application/json:
schema:
$ref: "#/components/schemas/ErrorResponse"
HeadersTooLarge:
description: HTTP headers exceed 8192 bytes
headers:
Access-Control-Allow-Origin:
$ref: "#/components/headers/AllowOrigin"
content:
application/json:
schema:
$ref: "#/components/schemas/ErrorResponse"
InternalError:
description: Internal failure
headers:
Access-Control-Allow-Origin:
$ref: "#/components/headers/AllowOrigin"
content:
application/json:
schema:
$ref: "#/components/schemas/ErrorResponse"
NotImplemented:
description: Unsupported transfer encoding or runtime operation
headers:
Access-Control-Allow-Origin:
$ref: "#/components/headers/AllowOrigin"
content:
application/json:
schema:
$ref: "#/components/schemas/ErrorResponse"
InsufficientStorage:
description: The destination filesystem has insufficient free space
headers:
Access-Control-Allow-Origin:
$ref: "#/components/headers/AllowOrigin"
content:
application/json:
schema:
$ref: "#/components/schemas/ErrorResponse"
schemas:
TitleId:
type: string
pattern: "^(CUSA|PPSA|LAPY|FAKE)[0-9]{5}$"
examples: [PPSA12345]
TitleRequest:
type: object
required: [title_id]
properties:
title_id:
$ref: "#/components/schemas/TitleId"
GamesListRequest:
type: object
properties:
include_size:
type: boolean
default: false
description: Calculate every physical source size. Directory traversal can be slow.
ScanRequest:
type: object
properties:
reset_attempts:
type: boolean
default: false
description: Reset title install/mount and image-mount retry counters immediately before this requested full scan starts.
MountRequest:
type: object
required: [title_id]
properties:
title_id:
$ref: "#/components/schemas/TitleId"
mode:
type: string
enum: [ro, rw, r/o, r/w]
description: Optional request-scoped mode for every image layer needed by this mount.
ManualPathRequest:
type: object
required: [path]
properties:
path:
type: string
pattern: "^/.+"
maxLength: 1023
StorageDestinationRequest:
type: object
required: [title_id, destination_dir]
properties:
title_id:
$ref: "#/components/schemas/TitleId"
destination_dir:
type: string
pattern: "^/.+"
maxLength: 1023
description: Existing directory under a configured non-runtime scan root. The original source basename is preserved.
StorageDeleteRequest:
type: object
required: [title_id, confirm]
properties:
title_id:
$ref: "#/components/schemas/TitleId"
confirm:
type: boolean
const: true
StorageUnpackRequest:
type: object
required: [title_id, destination_dir]
properties:
title_id:
$ref: "#/components/schemas/TitleId"
destination_dir:
type: string
pattern: "^/.+"
maxLength: 1023
description: Existing directory under a configured scan root. A TITLE_ID child directory is created.
delete_source:
type: boolean
default: false
description: Delete the backing image only after a complete copy and successful unmount.
StorageJobStatusRequest:
type: object
properties:
job_id:
type: integer
format: int64
minimum: 1
description: Omit to return the current or most recently completed job.
StorageJobCancelRequest:
type: object
required: [job_id]
properties:
job_id:
type: integer
format: int64
minimum: 1
SettingsUpdateRequest:
type: object
required: [debug, quiet_mode, update_emulators, allow_lan_access, fan_target_temperature, scan_paths]
properties:
debug:
type: boolean
quiet_mode:
type: boolean
update_emulators:
type: boolean
auto_update_ampr:
type: boolean
description: Download libSceAmpr.sprx updates from the configured GitHub release URL. Omission preserves the current value for compatibility with older web clients.
auto_remove_missing_games:
type: boolean
description: Remove app registrations whose source remains unavailable. Omission preserves the current value for compatibility with older web clients.
auto_remove_missing_delay_seconds:
type: integer
minimum: 1
maximum: 86400
description: Omission preserves the current value for compatibility with older web clients.
allow_lan_access:
type: boolean
description: Bind to 0.0.0.0 when true or 127.0.0.1 when false.
fan_target_temperature:
type: integer
description: Zero selects system control; otherwise 50 through 91 degrees Celsius.
oneOf:
- const: 0
- minimum: 50
maximum: 91
scan_paths:
type: array
description: Explicit custom roots only. An empty array restores compile-time defaults.
maxItems: 256
items:
type: string
pattern: "^/.+"
maxLength: 1023
SettingsResponse:
allOf:
- $ref: "#/components/schemas/SettingsUpdateRequest"
- type: object
required: [status, api_enabled, scan_path_count]
properties:
status:
type: integer
const: 0
api_enabled:
type: boolean
description: Whether the HTTP API is enabled in config.ini.
scan_path_count:
type: integer
minimum: 0
DebugLogResponse:
type: object
additionalProperties: false
required: [status, file_size, returned_bytes, truncated, content]
properties:
status:
type: integer
const: 0
file_size:
type: integer
format: int64
minimum: 0
returned_bytes:
type: integer
minimum: 0
maximum: 262144
truncated:
type: boolean
content:
type: string
KernelLogResponse:
type: object
additionalProperties: false
required: [status, total_bytes, returned_bytes, truncated, content]
properties:
status:
type: integer
const: 0
total_bytes:
type: integer
minimum: 0
returned_bytes:
type: integer
minimum: 0
maximum: 262144
truncated:
type: boolean
content:
type: string
VersionResponse:
type: object
additionalProperties: false
required: [status, api_version, shadowmount_version, capabilities]
properties:
status:
type: integer
const: 0
api_version:
type: integer
const: 1
shadowmount_version:
type: string
capabilities:
type: array
items:
type: string
enum: [web_ui, storage_space, list_images, list_games, game_info, game_icon, mount_game, unmount_game, uninstall_game, move_game_source, copy_game_source, delete_game_source, unpack_game_image, storage_job_status, storage_job_cancel, list_manual_sources, add_manual_source, remove_manual_source, manage_settings, read_debug_log, read_kernel_log, rescan]
example: [web_ui, storage_space, list_images, list_games, game_info, game_icon, mount_game, unmount_game, uninstall_game, move_game_source, copy_game_source, delete_game_source, unpack_game_image, storage_job_status, storage_job_cancel, list_manual_sources, add_manual_source, remove_manual_source, manage_settings, read_debug_log, read_kernel_log, rescan]
StorageMount:
type: object
additionalProperties: false
required: [source, mount_point, filesystem, total_bytes, free_bytes, available_bytes, used_bytes, read_only]
properties:
source:
type: string
mount_point:
type: string
pattern: "^/"
filesystem:
type: string
total_bytes:
type: integer
format: int64
minimum: 0
free_bytes:
type: integer
format: int64
minimum: 0
available_bytes:
type: integer
format: int64
minimum: 0
used_bytes:
type: integer
format: int64
minimum: 0
read_only:
type: boolean
StorageSpaceResponse:
type: object
additionalProperties: false
required: [status, count, destination_count, mounts, destinations]
properties:
status:
type: integer
const: 0
count:
type: integer
minimum: 0
destination_count:
type: integer
minimum: 0
mounts:
type: array
items:
$ref: "#/components/schemas/StorageMount"
destinations:
type: array
items:
$ref: "#/components/schemas/StorageDestination"
StorageDestination:
type: object
additionalProperties: false
required: [path, source, mount_point, filesystem, total_bytes, free_bytes, available_bytes, used_bytes, read_only]
properties:
path:
type: string
pattern: "^/"
source:
type: string
mount_point:
type: string
pattern: "^/"
filesystem:
type: string
total_bytes:
type: integer
format: int64
minimum: 0
free_bytes:
type: integer
format: int64
minimum: 0
available_bytes:
type: integer
format: int64
minimum: 0
used_bytes:
type: integer
format: int64
minimum: 0
read_only:
type: boolean
Image:
type: object
additionalProperties: false
required:
- path
- mount_point
- size
- mtime_sec
- mtime_nsec
- unit_id
- backend
- complete
- source_available
- mapped
- mounted
properties:
path:
type: string
mount_point:
type: string
size:
type: integer
format: int64
minimum: 0
mtime_sec:
type: integer
format: int64
mtime_nsec:
type: integer
minimum: 0
maximum: 999999999
unit_id:
type: integer
minimum: -1
backend:
type: string
enum: [LVD, MD, UNKNOWN]
complete:
type: boolean
source_available:
type: boolean
mapped:
type: boolean
mounted:
type: boolean
ImagesResponse:
type: object
additionalProperties: false
required: [status, count, images]
properties:
status:
type: integer
const: 0
count:
type: integer
minimum: 0
images:
type: array
items:
$ref: "#/components/schemas/Image"
Game:
type: object
additionalProperties: false
required:
- path
- runtime_path
- source_type
- image_type
- platform
- title_id
- content_id
- title_name
- version
- last_access_time
- install_time
- icon_url
- app_db_size_bytes
- installed
- managed
- mounted
- image_backed
- source_available
- installed_pkg
- can_uninstall
- can_manage_source
- can_toggle_fakelib
- fakelib_enabled
- fakelib_effective_enabled
properties:
path:
type: string
description: Physical game folder, outer backing-image path or installed app.pkg.
runtime_path:
type: string
description: Runtime game directory used by ShadowMount; empty for installed PKGs.
source_type:
type: string
enum: [folder, image, pkg]
image_type:
type: string
enum: ["", ufs, exfatfs, pfs, pfsc, unknown]
platform:
type: string
enum: [ps4, ps5, unknown]
title_id:
$ref: "#/components/schemas/TitleId"
content_id:
type: string
title_name:
type: string
version:
type: string
description: AppInfoJson CONTENT_VERSION (PS5) or APP_VER (PS4), or an empty string when unavailable.
last_access_time:
type: string
description: AppInfoJson #_last_access_time value, falling back to app.db lastAccessTime, or an empty string.
install_time:
type: string
description: AppInfoJson #_install_time value, falling back to app.db installTime, or an empty string.
icon_url:
type: string
description: Relative URL of the icon endpoint, or an empty string.
app_db_size_bytes:
type: integer
format: int64
minimum: 0
installed:
type: boolean
managed:
type: boolean
mounted:
type: boolean
image_backed:
type: boolean
source_available:
type: boolean
installed_pkg:
type: boolean
can_uninstall:
type: boolean
can_manage_source:
type: boolean
description: False for installed PKGs; source mutations are forbidden.
can_toggle_fakelib:
type: boolean
description: True for PS5 games in PKGs, images and folders.
fakelib_enabled:
type: boolean
description: Per-title policy; changes apply on the next launch.
fakelib_effective_enabled:
type: boolean
description: Per-title policy combined with the global backport_fakelib switch.
size_status:
type: integer
minimum: 0
description: errno-style result of optional physical size calculation.
size_bytes:
type: integer
format: int64
minimum: 0
description: Image file size, sum of folder files or installed PKG size from app.db (package file size when unavailable).
status:
type: integer
const: 0
GamesResponse:
type: object
additionalProperties: false
required: [status, count, size_included, games]
properties:
status:
type: integer
const: 0
count:
type: integer
minimum: 0
size_included:
type: boolean
games:
type: array
items:
$ref: "#/components/schemas/Game"
GameInfoResponse:
allOf:
- $ref: "#/components/schemas/Game"
- type: object
required: [status, size_status]
StorageJobResponse:
type: object
additionalProperties: false
required: [status, job_id, operation, state, active, cancellable, cancel_requested, title_id, source_type, source, runtime_source, destination, delete_source, total_bytes, processed_bytes, total_files, processed_files, progress_percent, speed_bytes_per_second, elapsed_ms, affected_titles, result_status, result_error, result_error_reason, scan_queued]
properties:
status:
type: integer
const: 0
job_id:
type: integer
format: int64
minimum: 0
operation:
type: string
enum: ["", move, copy, delete, unpack]
state:
type: string
enum: [idle, preparing, measuring, transferring, deleting, finalizing, completed, failed, cancelled]
active:
type: boolean
cancellable:
type: boolean
cancel_requested:
type: boolean
title_id:
type: string
source_type:
type: string
enum: ["", folder, image]
source:
type: string
runtime_source:
type: string
destination:
type: string
description: Empty for delete jobs.
delete_source:
type: boolean
description: True only for unpack jobs that will remove the image after successful extraction.
total_bytes:
type: integer
format: int64
minimum: 0
processed_bytes:
type: integer
format: int64
minimum: 0
total_files:
type: integer
format: int64
minimum: 0
processed_files:
type: integer
format: int64
minimum: 0
progress_percent:
type: number
format: double
minimum: 0
maximum: 100
speed_bytes_per_second:
type: integer
format: int64
minimum: 0
description: Average processed-byte rate since transfer or deletion began.
elapsed_ms:
type: integer
format: int64
minimum: 0
affected_titles:
type: integer
minimum: 0
result_status:
type: integer
minimum: 0
result_error:
type: string
description: English error text; localized clients should use result_error_reason when available.
result_error_reason:
$ref: "#/components/schemas/OperationErrorReason"
scan_queued:
type: boolean
ScanResponse:
type: object
additionalProperties: false
required: [status, queued, reset_attempts, scan_queued, scan_deferred, scan_deferred_reason]
properties:
status:
type: integer
const: 0
queued:
type: boolean
const: true
reset_attempts:
type: boolean
scan_queued:
type: boolean
const: true
scan_deferred:
type: boolean
description: Whether game runtime or rest mode prevents scanning at response time; queue acceptance does not mean scan completion.
scan_deferred_reason:
type: string
enum: ["", game_active, runtime_prepared, rest_mode]
ManualUpdateResponse:
type: object
additionalProperties: false
required: [status, path, present, changed]
properties:
status:
type: integer
const: 0
path:
type: string
present:
type: boolean
changed:
type: boolean
ManualListResponse:
type: object
additionalProperties: false
required: [status, count, paths]
properties:
status:
type: integer
const: 0
count:
type: integer
minimum: 0
paths:
type: array
items:
type: string
pattern: "^/.+"
MountResponse:
type: object
additionalProperties: false
required: [status, title_id, mounted, mode]
properties:
status:
type: integer
const: 0
title_id:
$ref: "#/components/schemas/TitleId"
mounted:
type: boolean
const: true
mode:
type: string
enum: [default, ro, rw]
UnmountResponse:
type: object
additionalProperties: false
required: [status, title_id, mounted]
properties:
status:
type: integer
const: 0
title_id:
$ref: "#/components/schemas/TitleId"
mounted:
type: boolean
const: false
UninstallResponse:
type: object
additionalProperties: false
required: [status, title_id, uninstall_requested, scan_queued, scan_deferred, scan_deferred_reason]
properties:
status:
type: integer
const: 0
title_id:
$ref: "#/components/schemas/TitleId"
uninstall_requested:
type: boolean
const: true
scan_queued:
type: boolean
description: Full synchronization was queued because the known source was absent before uninstall; retained sources are not immediately rediscovered.
scan_deferred:
type: boolean
scan_deferred_reason:
type: string
enum: ["", game_active, runtime_prepared, rest_mode]
MissingSourceResponse:
type: object
additionalProperties: false
required: [status, title_id, source_missing, scan_queued, scan_deferred, scan_deferred_reason]
properties:
status:
type: integer
const: 0
title_id:
$ref: "#/components/schemas/TitleId"
source_missing:
type: boolean
const: true
scan_queued:
type: boolean
const: true
scan_deferred:
type: boolean
scan_deferred_reason:
type: string
enum: ["", game_active, runtime_prepared, rest_mode]
ErrorResponse:
type: object
additionalProperties: false
required: [status, error]
properties:
status:
type: integer
minimum: 1
description: Positive errno value
error:
type: string
error_reason:
$ref: "#/components/schemas/OperationErrorReason"
OperationErrorReason:
type: string
description: Stable reason code for localized operation errors; empty for generic errno failures.
enum: ["", rest_mode, game_active, install_pending, runtime_prepared, scanner_busy, runtime_busy, title_unmount_busy, image_unmount_busy, unpack_mounted, storage_busy, storage_unavailable]