{"openapi":"3.1.0","info":{"title":"Yaelix API","version":"1.0.0","description":"The Yaelix REST API allows agents and automations to manage displays, screens, playlists, and content programmatically. Authenticate using an API key in the Authorization header: `Bearer yx_live_<your-key>`. Use optional scopes on API keys for least privilege. Upload media via `/uploads/initiate` and `/uploads/complete`, then create content (optionally with `uploadedFileId`). For safe retries on mutations, send header `Idempotency-Key`.","contact":{"name":"Yaelix Support","url":"https://yaelix.com"}},"servers":[{"url":"/api/v1","description":"Current server"}],"security":[{"ApiKeyAuth":[]}],"tags":[{"name":"Displays","description":"Manage digital signage displays"},{"name":"Screens","description":"Manage screen configurations"},{"name":"Playlists","description":"Manage content playlists"},{"name":"Content","description":"Manage content items (images, videos, websites)"},{"name":"Uploads","description":"Direct upload workflow (presigned PUT to storage)"}],"components":{"securitySchemes":{"ApiKeyAuth":{"type":"http","scheme":"bearer","bearerFormat":"API Key","description":"API key starting with `yx_live_`. Create one in Dashboard > Settings > API Keys."}},"schemas":{"DisplayList":{"type":"array","items":{"$ref":"#/components/schemas/Display"}},"Display":{"type":"object","properties":{"id":{"type":"string","example":"clx1234567890"},"name":{"type":"string","example":"Lobby Display"},"description":{"type":"string","nullable":true,"example":"Main lobby screen"},"location":{"type":"string","nullable":true,"example":"Building A, Floor 1"},"organizationId":{"type":"string"},"isPaired":{"type":"boolean"},"status":{"type":"string","example":"ONLINE"},"orientation":{"type":"string","nullable":true,"example":"LANDSCAPE"},"volume":{"type":"number","nullable":true,"example":80},"brightness":{"type":"number","nullable":true,"example":100},"lastSeenAt":{"type":"string","nullable":true},"createdAt":{"type":"string"},"updatedAt":{"type":"string"}},"required":["id","name","description","location","organizationId","isPaired","status","orientation","volume","brightness","lastSeenAt","createdAt","updatedAt"]},"Error":{"type":"object","properties":{"error":{"type":"string","example":"Not found"}},"required":["error"]},"CreateDisplay":{"type":"object","properties":{"name":{"type":"string","minLength":1,"example":"Lobby Display"},"description":{"type":"string","example":"Main lobby screen"},"location":{"type":"string","example":"Building A, Floor 1"}},"required":["name"]},"UpdateDisplay":{"type":"object","properties":{"name":{"type":"string"},"description":{"type":"string"},"location":{"type":"string"},"orientation":{"type":"string","enum":["LANDSCAPE","PORTRAIT","AUTO"]},"volume":{"type":"number","minimum":0,"maximum":100},"brightness":{"type":"number","minimum":0,"maximum":100}}},"Success":{"type":"object","properties":{"success":{"type":"boolean","example":true}},"required":["success"]},"SendCommand":{"type":"object","properties":{"command":{"type":"string","enum":["reload","refresh","screenshot","skip","pause","resume","volume","mute","brightness","power","reboot","restart","logs","debug"],"example":"reload"},"parameters":{"type":"object","additionalProperties":{"nullable":true}}},"required":["command"]},"PlaylistList":{"type":"array","items":{"$ref":"#/components/schemas/Playlist"}},"Playlist":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string","example":"Default Playlist"},"description":{"type":"string","nullable":true},"organizationId":{"type":"string"},"isActive":{"type":"boolean"},"isDefault":{"type":"boolean"},"shuffleMode":{"type":"string","example":"none"},"duration":{"type":"number"},"schedule":{"nullable":true},"createdAt":{"type":"string"},"updatedAt":{"type":"string"}},"required":["id","name","description","organizationId","isActive","isDefault","shuffleMode","duration","createdAt","updatedAt"]},"CreatePlaylist":{"type":"object","properties":{"name":{"type":"string","minLength":1,"example":"Morning Rotation"},"description":{"type":"string"},"isDefault":{"type":"boolean"},"shuffleMode":{"type":"string","enum":["none","random","daily"]},"isActive":{"type":"boolean"},"items":{"type":"array","items":{"$ref":"#/components/schemas/PlaylistItemInput"}}},"required":["name"]},"PlaylistItemInput":{"type":"object","properties":{"contentId":{"type":"string","nullable":true},"nestedPlaylistId":{"type":"string","nullable":true},"order":{"type":"number","example":1},"duration":{"type":"number","example":10},"transition":{"type":"string","example":"fade"},"settings":{"type":"object","additionalProperties":{"nullable":true}}},"required":["order"]},"UpdatePlaylist":{"type":"object","properties":{"name":{"type":"string"},"description":{"type":"string"},"isActive":{"type":"boolean"},"isDefault":{"type":"boolean"},"shuffleMode":{"type":"string","enum":["none","random","daily"]},"schedule":{"nullable":true},"items":{"type":"array","items":{"$ref":"#/components/schemas/PlaylistItemInput"}}}},"ContentList":{"type":"array","items":{"$ref":"#/components/schemas/Content"}},"Content":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string","example":"Welcome Banner"},"description":{"type":"string","nullable":true},"organizationId":{"type":"string"},"type":{"type":"string","example":"IMAGE"},"url":{"type":"string","nullable":true,"example":"https://cdn.example.com/image.jpg"},"duration":{"type":"number","example":10},"thumbnailUrl":{"type":"string","nullable":true},"fileSize":{"type":"number","nullable":true},"metadata":{"type":"object","nullable":true,"additionalProperties":{"nullable":true}},"tags":{"type":"array","items":{"type":"string"}},"enableCache":{"type":"boolean"},"validFrom":{"type":"string","nullable":true},"validUntil":{"type":"string","nullable":true},"schedule":{"nullable":true},"createdAt":{"type":"string"},"updatedAt":{"type":"string"}},"required":["id","name","description","organizationId","type","url","duration","tags","enableCache","createdAt","updatedAt"]},"CreateContent":{"type":"object","properties":{"name":{"type":"string","minLength":1,"example":"Welcome Banner"},"description":{"type":"string"},"type":{"type":"string","enum":["IMAGE","VIDEO","WEBSITE","HTML","CANVAS"],"example":"IMAGE"},"uploadedFileId":{"type":"string","description":"If provided, the server will look up the uploadedFile and use its url/fileSize defaults.","example":"clx_uploaded_file_id"},"url":{"type":"string"},"fileSize":{"type":"number"},"duration":{"type":"number"},"thumbnailUrl":{"type":"string"},"metadata":{"type":"object","additionalProperties":{"nullable":true}},"tags":{"type":"array","items":{"type":"string"}},"validFrom":{"type":"string","example":"2026-01-01T00:00:00Z"},"validUntil":{"type":"string","example":"2026-12-31T23:59:59Z"},"schedule":{"nullable":true,"description":"Schedule definition (timeRanges)."},"enableCache":{"type":"boolean"}},"required":["name","type"]},"UpdateContent":{"type":"object","properties":{"name":{"type":"string"},"description":{"type":"string"},"url":{"type":"string"},"thumbnailUrl":{"type":"string"},"metadata":{"type":"object","additionalProperties":{"nullable":true}},"tags":{"type":"array","items":{"type":"string"}},"validFrom":{"type":"string"},"validUntil":{"type":"string"},"schedule":{"nullable":true},"enableCache":{"type":"boolean"}}},"ScreenList":{"type":"array","items":{"$ref":"#/components/schemas/Screen"}},"Screen":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string","example":"Lobby Screen"},"description":{"type":"string","nullable":true},"organizationId":{"type":"string"},"playlistId":{"type":"string","nullable":true},"orientation":{"type":"string","example":"landscape"},"createdAt":{"type":"string"},"updatedAt":{"type":"string"}},"required":["id","name","description","organizationId","playlistId","orientation","createdAt","updatedAt"]},"CreateScreen":{"type":"object","properties":{"name":{"type":"string","minLength":1,"example":"Lobby Screen"},"description":{"type":"string"},"playlistId":{"type":"string"}},"required":["name"]},"UpdateScreen":{"type":"object","properties":{"name":{"type":"string"},"description":{"type":"string"},"playlistId":{"type":"string","nullable":true}}},"InitiateUploadResponse":{"type":"object","properties":{"uploadId":{"type":"string"},"uploadUrl":{"type":"string","format":"uri"},"key":{"type":"string"}},"required":["uploadId","uploadUrl","key"]},"InitiateUpload":{"type":"object","properties":{"fileName":{"type":"string","minLength":1},"fileType":{"type":"string","minLength":1,"example":"image/png"},"fileSize":{"type":"integer","minimum":0,"exclusiveMinimum":true},"category":{"type":"string","enum":["IMAGE","VIDEO"]}},"required":["fileName","fileType","fileSize","category"]},"CompleteUploadResponse":{"type":"object","properties":{"id":{"type":"string"},"url":{"type":"string"},"fileName":{"type":"string"},"fileType":{"type":"string"},"fileSize":{"type":"number"},"storageKey":{"type":"string"}},"required":["id","url","fileName","fileType","fileSize","storageKey"]},"CompleteUpload":{"type":"object","properties":{"uploadId":{"type":"string"}},"required":["uploadId"]}},"parameters":{}},"paths":{"/displays":{"get":{"tags":["Displays"],"summary":"List all displays","description":"Returns all displays belonging to the organization associated with the API key.","security":[{"ApiKeyAuth":[]}],"responses":{"200":{"description":"List of displays","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DisplayList"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"post":{"tags":["Displays"],"summary":"Create a display","description":"Creates a new display with a 4-digit pairing code.","security":[{"ApiKeyAuth":[]}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateDisplay"}}}},"responses":{"201":{"description":"Display created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Display"}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/displays/{id}":{"get":{"tags":["Displays"],"summary":"Get a display","description":"Returns a single display by ID.","security":[{"ApiKeyAuth":[]}],"parameters":[{"schema":{"type":"string","example":"clx1234567890"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"Display details","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Display"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"patch":{"tags":["Displays"],"summary":"Update a display","description":"Updates display properties like name, location, orientation, volume, or brightness.","security":[{"ApiKeyAuth":[]}],"parameters":[{"schema":{"type":"string","example":"clx1234567890"},"required":true,"name":"id","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateDisplay"}}}},"responses":{"200":{"description":"Display updated","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Display"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"delete":{"tags":["Displays"],"summary":"Delete a display","description":"Permanently deletes a display.","security":[{"ApiKeyAuth":[]}],"parameters":[{"schema":{"type":"string","example":"clx1234567890"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"Display deleted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Success"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/displays/{id}/command":{"post":{"tags":["Displays"],"summary":"Send a command to a display","description":"Sends a command (reload, screenshot, skip, etc.) to a connected display via WebSocket.","security":[{"ApiKeyAuth":[]}],"parameters":[{"schema":{"type":"string","example":"clx1234567890"},"required":true,"name":"id","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SendCommand"}}}},"responses":{"200":{"description":"Command sent","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Success"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/playlists":{"get":{"tags":["Playlists"],"summary":"List all playlists","description":"Returns all playlists for the organization associated with the API key.","security":[{"ApiKeyAuth":[]}],"responses":{"200":{"description":"List of playlists","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PlaylistList"}}}}}},"post":{"tags":["Playlists"],"summary":"Create a playlist","description":"Creates a new playlist, optionally with items.","security":[{"ApiKeyAuth":[]}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreatePlaylist"}}}},"responses":{"201":{"description":"Playlist created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Playlist"}}}}}}},"/playlists/{id}":{"get":{"tags":["Playlists"],"summary":"Get a playlist","description":"Returns a single playlist with its items.","security":[{"ApiKeyAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"Playlist details","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Playlist"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"patch":{"tags":["Playlists"],"summary":"Update a playlist","description":"Updates playlist properties and optionally replaces all items.","security":[{"ApiKeyAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdatePlaylist"}}}},"responses":{"200":{"description":"Playlist updated","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Playlist"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"delete":{"tags":["Playlists"],"summary":"Delete a playlist","description":"Permanently deletes a playlist and all its items.","security":[{"ApiKeyAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"Playlist deleted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Success"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/content":{"get":{"tags":["Content"],"summary":"List all content","description":"Returns all content items for the organization. Optionally filter by type or tags.","security":[{"ApiKeyAuth":[]}],"parameters":[{"schema":{"type":"string","enum":["IMAGE","VIDEO","WEBSITE","HTML","CANVAS"]},"required":false,"name":"type","in":"query"},{"schema":{"type":"string","description":"Comma-separated list of tags"},"required":false,"description":"Comma-separated list of tags","name":"tags","in":"query"}],"responses":{"200":{"description":"List of content items","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContentList"}}}}}},"post":{"tags":["Content"],"summary":"Create content","description":"Creates a new content item (image, video, website, HTML, or canvas).","security":[{"ApiKeyAuth":[]}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateContent"}}}},"responses":{"201":{"description":"Content created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Content"}}}}}}},"/content/{id}":{"get":{"tags":["Content"],"summary":"Get a content item","description":"Returns a single content item by ID.","security":[{"ApiKeyAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"Content details","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Content"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"patch":{"tags":["Content"],"summary":"Update content","description":"Updates a content item's properties.","security":[{"ApiKeyAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateContent"}}}},"responses":{"200":{"description":"Content updated","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Content"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"delete":{"tags":["Content"],"summary":"Delete content","description":"Permanently deletes a content item. Fails if the content is still used in playlists.","security":[{"ApiKeyAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"Content deleted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Success"}}}},"400":{"description":"Content is in use","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/screens":{"get":{"tags":["Screens"],"summary":"List all screens","description":"Returns all screens for the organization associated with the API key.","security":[{"ApiKeyAuth":[]}],"responses":{"200":{"description":"List of screens","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ScreenList"}}}}}},"post":{"tags":["Screens"],"summary":"Create a screen","description":"Creates a new screen, optionally assigning a playlist.","security":[{"ApiKeyAuth":[]}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateScreen"}}}},"responses":{"201":{"description":"Screen created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Screen"}}}}}}},"/screens/{id}":{"get":{"tags":["Screens"],"summary":"Get a screen","description":"Returns a single screen with its playlist and display assignments.","security":[{"ApiKeyAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"Screen details","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Screen"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"patch":{"tags":["Screens"],"summary":"Update a screen","description":"Updates screen properties like name, description, or playlist.","security":[{"ApiKeyAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateScreen"}}}},"responses":{"200":{"description":"Screen updated","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Screen"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"delete":{"tags":["Screens"],"summary":"Delete a screen","description":"Permanently deletes a screen and its display assignments.","security":[{"ApiKeyAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"Screen deleted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Success"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/screens/{id}/assign-display":{"post":{"tags":["Screens"],"summary":"Assign a display to a screen","description":"Links a display to a screen so it shows the screen's playlist.","security":[{"ApiKeyAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"displayId":{"type":"string","example":"clx1234567890"}},"required":["displayId"]}}}},"responses":{"201":{"description":"Display assigned","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Success"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/uploads/initiate":{"post":{"tags":["Uploads"],"summary":"Initiate a direct upload","description":"Creates a pending upload and returns a presigned PUT URL to upload the file directly to storage. After uploading, call /uploads/complete with the uploadId to finalize and get an uploadedFile id.","security":[{"ApiKeyAuth":[]}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/InitiateUpload"}}}},"responses":{"200":{"description":"Upload initiated","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InitiateUploadResponse"}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/uploads/complete":{"post":{"tags":["Uploads"],"summary":"Complete an upload","description":"Finalizes a pending upload and creates an uploadedFile record. Use the returned uploadedFile id when creating content.","security":[{"ApiKeyAuth":[]}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CompleteUpload"}}}},"responses":{"200":{"description":"Upload completed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CompleteUploadResponse"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}}}}