velody/backend/openapi/velody.openapi.json
2026-06-14 09:43:41 +02:00

1043 lines
25 KiB
JSON

{
"openapi": "3.0.0",
"paths": {
"/api/v1/assets/{assetId}/download": {
"get": {
"operationId": "AssetsController_download_v1",
"parameters": [
{
"name": "assetId",
"required": true,
"in": "path",
"schema": {
"type": "string"
}
},
{
"name": "deviceId",
"required": false,
"in": "query",
"description": "Optional client metadata. Authorization: Bearer <deviceAccessToken> is required and determines access.",
"schema": {
"format": "uuid",
"type": "string"
}
}
],
"responses": {
"200": {
"description": "",
"content": {
"audio/mpeg": {
"schema": {
"type": "string",
"format": "binary"
}
}
}
}
},
"security": [
{
"bearer": []
}
],
"tags": [
"assets"
]
}
},
"/api/v1/artwork/{artworkId}/download": {
"get": {
"operationId": "ArtworkController_download_v1",
"parameters": [
{
"name": "artworkId",
"required": true,
"in": "path",
"schema": {
"type": "string"
}
},
{
"name": "deviceId",
"required": false,
"in": "query",
"description": "Optional client metadata. Authorization: Bearer <deviceAccessToken> is required and determines access.",
"schema": {
"format": "uuid",
"type": "string"
}
}
],
"responses": {
"200": {
"description": "",
"content": {
"image/*": {
"schema": {
"type": "string",
"format": "binary"
}
}
}
}
},
"security": [
{
"bearer": []
}
],
"tags": [
"artwork"
]
}
},
"/api/v1/health": {
"get": {
"operationId": "HealthController_getHealth_v1",
"parameters": [],
"responses": {
"200": {
"description": "",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/HealthResponseDto"
}
}
}
}
},
"tags": [
"health"
]
}
},
"/api/v1/devices/register": {
"post": {
"operationId": "DevicesController_register_v1",
"parameters": [],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/RegisterDeviceRequestDto"
}
}
}
},
"responses": {
"201": {
"description": "",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/RegisterDeviceResponseDto"
}
}
}
}
},
"tags": [
"devices"
]
}
},
"/api/v1/devices/heartbeat": {
"post": {
"operationId": "DevicesController_heartbeat_v1",
"parameters": [],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/DeviceHeartbeatRequestDto"
}
}
}
},
"responses": {
"200": {
"description": "",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/DeviceHeartbeatResponseDto"
}
}
}
}
},
"security": [
{
"bearer": []
}
],
"tags": [
"devices"
]
}
},
"/api/v1/uploads/prepare": {
"post": {
"operationId": "UploadsController_prepare_v1",
"parameters": [],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/UploadPrepareRequestDto"
}
}
}
},
"responses": {
"201": {
"description": "",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/UploadPrepareResponseDto"
}
}
}
}
},
"security": [
{
"bearer": []
}
],
"tags": [
"uploads"
]
}
},
"/api/v1/uploads/{uploadId}": {
"get": {
"operationId": "UploadsController_getStatus_v1",
"parameters": [
{
"name": "uploadId",
"required": true,
"in": "path",
"schema": {
"type": "string"
}
}
],
"responses": {
"200": {
"description": "",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/UploadSessionStatusResponseDto"
}
}
}
}
},
"security": [
{
"bearer": []
}
],
"tags": [
"uploads"
]
}
},
"/api/v1/uploads/{uploadId}/file": {
"put": {
"operationId": "UploadsController_uploadFile_v1",
"parameters": [
{
"name": "uploadId",
"required": true,
"in": "path",
"schema": {
"type": "string"
}
}
],
"requestBody": {
"required": true,
"content": {
"audio/mpeg": {
"schema": {
"type": "string",
"format": "binary"
}
},
"audio/mp3": {
"schema": {
"type": "string",
"format": "binary"
}
},
"application/octet-stream": {
"schema": {
"type": "string",
"format": "binary"
}
}
}
},
"responses": {
"200": {
"description": "",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/UploadSessionStatusResponseDto"
}
}
}
}
},
"security": [
{
"bearer": []
}
],
"tags": [
"uploads"
]
}
},
"/api/v1/uploads/{uploadId}/finalize": {
"post": {
"operationId": "UploadsController_finalize_v1",
"parameters": [
{
"name": "uploadId",
"required": true,
"in": "path",
"schema": {
"type": "string"
}
}
],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/UploadFinalizeRequestDto"
}
}
}
},
"responses": {
"200": {
"description": "",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/UploadFinalizeResponseDto"
}
}
}
}
},
"security": [
{
"bearer": []
}
],
"tags": [
"uploads"
]
}
},
"/api/v1/library/tracks": {
"get": {
"operationId": "LibraryController_getTracks_v1",
"parameters": [
{
"name": "deviceId",
"required": false,
"in": "query",
"description": "Optional client metadata. Authorization: Bearer <deviceAccessToken> is required and determines access.",
"schema": {
"format": "uuid",
"type": "string"
}
}
],
"responses": {
"200": {
"description": "",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/LibraryTracksResponseDto"
}
}
}
}
},
"security": [
{
"bearer": []
}
],
"tags": [
"library"
]
}
},
"/api/v1/sync/bootstrap": {
"get": {
"operationId": "SyncController_bootstrap_v1",
"parameters": [
{
"name": "deviceId",
"required": false,
"in": "query",
"description": "Optional client metadata. Authorization: Bearer <deviceAccessToken> is required and determines access.",
"schema": {
"format": "uuid",
"type": "string"
}
}
],
"responses": {
"200": {
"description": "",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/SyncBootstrapResponseDto"
}
}
}
}
},
"security": [
{
"bearer": []
}
],
"tags": [
"sync"
]
}
},
"/api/v1/sync/changes": {
"get": {
"operationId": "SyncController_changes_v1",
"parameters": [
{
"name": "deviceId",
"required": false,
"in": "query",
"description": "Optional client metadata. Authorization: Bearer <deviceAccessToken> is required and determines access.",
"schema": {
"format": "uuid",
"type": "string"
}
},
{
"name": "after",
"required": false,
"in": "query",
"schema": {
"example": "0",
"type": "string"
}
}
],
"responses": {
"200": {
"description": "",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/SyncChangesResponseDto"
}
}
}
}
},
"security": [
{
"bearer": []
}
],
"tags": [
"sync"
]
}
}
},
"info": {
"title": "Velody API",
"description": "Velody Phase 1 foundation API",
"version": "1.0.0",
"contact": {}
},
"tags": [],
"servers": [],
"components": {
"securitySchemes": {
"bearer": {
"scheme": "bearer",
"bearerFormat": "Bearer",
"type": "http",
"description": "Device access token"
}
},
"schemas": {
"HealthDependencyDto": {
"type": "object",
"properties": {
"status": {
"type": "string",
"example": "up"
}
},
"required": [
"status"
]
},
"StorageDependencyDto": {
"type": "object",
"properties": {
"status": {
"type": "string",
"example": "up"
},
"root": {
"type": "string",
"example": "/app/runtime/storage"
}
},
"required": [
"status",
"root"
]
},
"HealthResponseDto": {
"type": "object",
"properties": {
"service": {
"type": "string",
"example": "velody-backend"
},
"version": {
"type": "string",
"example": "0.1.0"
},
"database": {
"$ref": "#/components/schemas/HealthDependencyDto"
},
"storage": {
"$ref": "#/components/schemas/StorageDependencyDto"
},
"serverTime": {
"type": "string",
"example": "2026-05-24T20:00:00.000Z"
}
},
"required": [
"service",
"version",
"database",
"storage",
"serverTime"
]
},
"RegisterDeviceRequestDto": {
"type": "object",
"properties": {
"platform": {
"type": "string",
"enum": [
"MACOS",
"IPHONE"
],
"example": "MACOS"
},
"deviceName": {
"type": "string",
"example": "Diya MacBook Pro"
},
"appVersion": {
"type": "string",
"example": "0.1.0"
}
},
"required": [
"platform",
"deviceName",
"appVersion"
]
},
"RegisterDeviceResponseDto": {
"type": "object",
"properties": {
"deviceId": {
"type": "string",
"format": "uuid"
},
"deviceAccessToken": {
"type": "string",
"description": "Raw device access token returned only during registration. Store it securely."
},
"bootstrapToken": {
"type": "string"
},
"serverTime": {
"type": "string",
"example": "2026-05-24T20:00:00.000Z"
}
},
"required": [
"deviceId",
"deviceAccessToken",
"bootstrapToken",
"serverTime"
]
},
"DeviceHeartbeatRequestDto": {
"type": "object",
"properties": {
"deviceId": {
"type": "string",
"format": "uuid",
"description": "Optional client metadata. Authorization: Bearer <deviceAccessToken> is required and determines access."
},
"appVersion": {
"type": "string",
"example": "0.1.0"
}
},
"required": [
"appVersion"
]
},
"DeviceHeartbeatResponseDto": {
"type": "object",
"properties": {
"ok": {
"type": "boolean",
"example": true
},
"serverTime": {
"type": "string",
"example": "2026-05-24T20:00:00.000Z"
}
},
"required": [
"ok",
"serverTime"
]
},
"UploadPrepareRequestDto": {
"type": "object",
"properties": {
"deviceId": {
"type": "string",
"format": "uuid",
"description": "Optional client metadata. Authorization: Bearer <deviceAccessToken> is required and determines access."
},
"sha256": {
"type": "string",
"example": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
},
"originalFilename": {
"type": "string",
"example": "track.mp3"
},
"sizeBytes": {
"type": "number",
"example": 10485760
}
},
"required": [
"sha256",
"originalFilename",
"sizeBytes"
]
},
"UploadPrepareResponseDto": {
"type": "object",
"properties": {
"status": {
"type": "string",
"enum": [
"exists",
"upload_required"
]
},
"uploadId": {
"type": "string",
"format": "uuid"
},
"nextOffset": {
"type": "number",
"example": 0
},
"trackId": {
"type": "string",
"format": "uuid"
},
"assetId": {
"type": "string",
"format": "uuid"
}
},
"required": [
"status"
]
},
"UploadSessionStatusResponseDto": {
"type": "object",
"properties": {
"uploadId": {
"type": "string",
"format": "uuid"
},
"status": {
"type": "string",
"enum": [
"PENDING",
"READY_TO_UPLOAD",
"COMPLETED",
"FAILED"
]
},
"receivedBytes": {
"type": "string",
"example": 0
},
"expectedSizeBytes": {
"type": "string",
"example": 10485760
},
"nextOffset": {
"type": "string",
"example": 0
},
"finalizedAt": {
"type": "string",
"example": "2026-05-28T12:00:00.000Z"
}
},
"required": [
"uploadId",
"status",
"receivedBytes",
"expectedSizeBytes",
"nextOffset"
]
},
"UploadFinalizeArtworkDto": {
"type": "object",
"properties": {
"dataBase64": {
"type": "string",
"example": "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJ..."
},
"sha256": {
"type": "string",
"example": "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"
},
"mimeType": {
"type": "string",
"enum": [
"image/jpeg",
"image/png"
]
},
"width": {
"type": "number",
"example": 512
},
"height": {
"type": "number",
"example": 512
}
},
"required": [
"dataBase64",
"sha256",
"mimeType"
]
},
"UploadFinalizeRequestDto": {
"type": "object",
"properties": {
"title": {
"type": "string",
"example": "Track Title"
},
"artist": {
"type": "string",
"example": "Track Artist"
},
"album": {
"type": "string",
"example": "Album Title"
},
"durationMs": {
"type": "number",
"example": 245000
},
"artwork": {
"$ref": "#/components/schemas/UploadFinalizeArtworkDto"
}
},
"required": [
"title",
"artist"
]
},
"UploadFinalizeResponseDto": {
"type": "object",
"properties": {
"trackId": {
"type": "string",
"format": "uuid"
},
"assetId": {
"type": "string",
"format": "uuid"
}
},
"required": [
"trackId",
"assetId"
]
},
"RemoteArtworkDto": {
"type": "object",
"properties": {
"artworkId": {
"type": "string",
"format": "uuid"
},
"sha256": {
"type": "string",
"example": "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"
},
"mimeType": {
"type": "string",
"example": "image/jpeg"
},
"width": {
"type": "object",
"example": 512,
"nullable": true
},
"height": {
"type": "object",
"example": 512,
"nullable": true
}
},
"required": [
"artworkId",
"sha256",
"mimeType"
]
},
"RemoteLibraryTrackDto": {
"type": "object",
"properties": {
"trackId": {
"type": "string",
"format": "uuid"
},
"title": {
"type": "string",
"example": "Track Title"
},
"artist": {
"type": "string",
"example": "Track Artist"
},
"durationSeconds": {
"type": "number",
"example": 245
},
"sha256": {
"type": "string",
"example": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
},
"assetId": {
"type": "string",
"format": "uuid"
},
"createdAt": {
"type": "string",
"example": "2026-05-29T08:00:00.000Z"
},
"updatedAt": {
"type": "string",
"example": "2026-05-29T08:05:00.000Z"
},
"artwork": {
"nullable": true,
"type": "object",
"allOf": [
{
"$ref": "#/components/schemas/RemoteArtworkDto"
}
]
}
},
"required": [
"trackId",
"title",
"artist",
"durationSeconds",
"sha256",
"assetId",
"createdAt",
"updatedAt"
]
},
"LibraryTracksResponseDto": {
"type": "object",
"properties": {
"tracks": {
"type": "array",
"items": {
"$ref": "#/components/schemas/RemoteLibraryTrackDto"
}
}
},
"required": [
"tracks"
]
},
"LibraryTrackDto": {
"type": "object",
"properties": {
"id": {
"type": "string",
"format": "uuid"
},
"title": {
"type": "string",
"example": "Placeholder Track"
},
"artist": {
"type": "string",
"example": "Velody"
}
}
},
"SyncEventDto": {
"type": "object",
"properties": {
"entityType": {
"type": "string",
"example": "TRACK"
},
"entityId": {
"type": "string",
"format": "uuid"
},
"action": {
"type": "string",
"example": "CREATED"
},
"eventId": {
"type": "string",
"example": "0"
}
},
"required": [
"entityType",
"entityId",
"action",
"eventId"
]
},
"SyncBootstrapResponseDto": {
"type": "object",
"properties": {
"nextCursor": {
"type": "string",
"example": "0"
},
"tracks": {
"type": "array",
"items": {
"$ref": "#/components/schemas/LibraryTrackDto"
}
},
"events": {
"type": "array",
"items": {
"$ref": "#/components/schemas/SyncEventDto"
}
},
"deletedTrackIds": {
"type": "array",
"items": {
"type": "string"
}
},
"serverTime": {
"type": "string",
"example": "2026-05-24T20:00:00.000Z"
}
},
"required": [
"nextCursor",
"tracks",
"events",
"deletedTrackIds",
"serverTime"
]
},
"SyncChangesResponseDto": {
"type": "object",
"properties": {
"nextCursor": {
"type": "string",
"example": "0"
},
"tracks": {
"type": "array",
"items": {
"$ref": "#/components/schemas/LibraryTrackDto"
}
},
"events": {
"type": "array",
"items": {
"$ref": "#/components/schemas/SyncEventDto"
}
},
"deletedTrackIds": {
"type": "array",
"items": {
"type": "string"
}
},
"serverTime": {
"type": "string",
"example": "2026-05-24T20:00:00.000Z"
}
},
"required": [
"nextCursor",
"tracks",
"events",
"deletedTrackIds",
"serverTime"
]
}
}
}
}