directive @isAuthorized on FIELD_DEFINITION directive @isAdmin on FIELD_DEFINITION scalar Time scalar Any "Used to specify which order to sort items in" enum OrderDirection { "Sort accending A-Z" ASC "Sort decending Z-A" DESC } "Used to specify pagination on a list of items" input Pagination { "How many items to maximally fetch" limit: Int "How many items to skip from the beginning of the query, specified by the `Ordering`" offset: Int } "Used to specify how to sort items" input Ordering { "A column in the database to order by" order_by: String order_direction: OrderDirection } "Credentials used to identify and authenticate a share token" input ShareTokenCredentials { token: String! password: String } type Query { siteInfo: SiteInfo! "List of registered users, must be admin to call" user(order: Ordering, paginate: Pagination): [User!]! @isAdmin "Information about the currently logged in user" myUser: User! @isAuthorized "User preferences for the logged in user" myUserPreferences: UserPreferences! @isAuthorized "List of albums owned by the logged in user." myAlbums( order: Ordering, paginate: Pagination "Return only albums from the root directory of the user" onlyRoot: Boolean "Return also albums with no media directly in them" showEmpty: Boolean "Show only albums having favorites" onlyWithFavorites: Boolean ): [Album!]! @isAuthorized """ Get album by id, user must own the album or be admin If valid tokenCredentials are provided, the album may be retrived without further authentication """ album(id: ID!, tokenCredentials: ShareTokenCredentials): Album! "List of media owned by the logged in user" myMedia(order: Ordering, paginate: Pagination): [Media!]! @isAuthorized """ Get media by id, user must own the media or be admin. If valid tokenCredentials are provided, the media may be retrived without further authentication """ media(id: ID!, tokenCredentials: ShareTokenCredentials): Media! "Get a list of media by their ids, user must own the media or be admin" mediaList(ids: [ID!]!): [Media!]! """ Get a list of media, ordered first by day, then by album if multiple media was found for the same day. """ myTimeline( paginate: Pagination, onlyFavorites: Boolean, "Only fetch media that is older than this date" fromDate: Time ): [Media!]! @isAuthorized "Get media owned by the logged in user, returned in GeoJson format" myMediaGeoJson: Any! @isAuthorized "Get the mapbox api token, returns null if mapbox is not enabled" mapboxToken: String "Fetch a share token containing an `Album` or `Media`" shareToken(credentials: ShareTokenCredentials!): ShareToken! "Check if the `ShareToken` credentials are valid" shareTokenValidatePassword(credentials: ShareTokenCredentials!): Boolean! "Perform a search query on the contents of the media library" search(query: String!, limitMedia: Int, limitAlbums: Int): SearchResult! "Get a list of `FaceGroup`s for the logged in user" myFaceGroups(paginate: Pagination): [FaceGroup!]! @isAuthorized "Get a particular `FaceGroup` specified by its ID" faceGroup(id: ID!): FaceGroup! @isAuthorized } type Mutation { "Authorizes a user and returns a token used to identify the new session" authorizeUser(username: String!, password: String!): AuthorizeResult! "Registers the initial user, can only be called if initialSetup from SiteInfo is true" initialSetupWizard( username: String! password: String! rootPath: String! ): AuthorizeResult "Scan all users for new media" scanAll: ScannerResult! @isAdmin "Scan a single user for new media" scanUser(userId: ID!): ScannerResult! @isAdmin "Generate share token for album" shareAlbum(albumId: ID!, expire: Time, password: String): ShareToken! @isAuthorized "Generate share token for media" shareMedia(mediaId: ID!, expire: Time, password: String): ShareToken! @isAuthorized "Delete a share token by it's token value" deleteShareToken(token: String!): ShareToken! @isAuthorized "Set a password for a token, if null is passed for the password argument, the password will be cleared" protectShareToken(token: String!, password: String): ShareToken! @isAuthorized "Mark or unmark a media as being a favorite" favoriteMedia(mediaId: ID!, favorite: Boolean!): Media! @isAuthorized "Update a user, fields left as `null` will not be changed" updateUser( id: ID! username: String password: String admin: Boolean ): User! @isAdmin "Create a new user" createUser( username: String! password: String admin: Boolean! ): User! @isAdmin "Delete an existing user" deleteUser(id: ID!): User! @isAdmin "Add a root path from where to look for media for the given user, specified by their user id." userAddRootPath(id: ID!, rootPath: String!): Album @isAdmin """ Remove a root path from a user, specified by the id of the user and the top album representing the root path. This album was returned when creating the path using `userAddRootPath`. A list of root paths for a particular user can be retrived from the `User.rootAlbums` path. """ userRemoveRootAlbum(userId: ID!, albumId: ID!): Album @isAdmin """ Set how often, in seconds, the server should automatically scan for new media, a value of 0 will disable periodic scans """ setPeriodicScanInterval(interval: Int!): Int! @isAdmin "Set max number of concurrent scanner jobs running at once" setScannerConcurrentWorkers(workers: Int!): Int! @isAdmin "Set the filter to be used when generating thumbnails" setThumbnailDownsampleMethod(method: ThumbnailFilter!): ThumbnailFilter! @isAdmin "Change user preferences for the logged in user" changeUserPreferences(language: String): UserPreferences! @isAuthorized "Reset the assigned cover photo for an album" resetAlbumCover(albumID: ID!): Album! @isAuthorized "Assign a cover photo to an album" setAlbumCover(coverID: ID!): Album! @isAuthorized "Assign a label to a face group, set label to null to remove the current one" setFaceGroupLabel(faceGroupID: ID!, label: String): FaceGroup! @isAuthorized "Merge two face groups into a single one, all ImageFaces from source will be moved to destination" combineFaceGroups(destinationFaceGroupID: ID!, sourceFaceGroupID: ID!): FaceGroup! @isAuthorized "Move a list of ImageFaces to another face group" moveImageFaces(imageFaceIDs: [ID!]!, destinationFaceGroupID: ID!): FaceGroup! @isAuthorized "Check all unlabeled faces to see if they match a labeled FaceGroup, and move them if they match" recognizeUnlabeledFaces: [ImageFace!]! @isAuthorized "Move a list of ImageFaces to a new face group" detachImageFaces(imageFaceIDs: [ID!]!): FaceGroup! @isAuthorized } type Subscription { notification: Notification! } "Specified the type a particular notification is of" enum NotificationType { "A regular message with no special additions" Message "A notification with an attached progress indicator" Progress "Close a notification with a given key" Close } type Notification { "A key used to identify the notification, new notification updates with the same key, should replace the old notifications" key: String! type: NotificationType! "The text for the title of the notification" header: String! "The text for the body of the notification" content: String! "A value between 0 and 1 when the notification type is `Progress`" progress: Float "Whether or not the message of the notification is positive, the UI might reflect this with a green color" positive: Boolean! "Whether or not the message of the notification is negative, the UI might reflect this with a red color" negative: Boolean! "Time in milliseconds before the notification should close" timeout: Int } type AuthorizeResult { success: Boolean! "A textual status message describing the result, can be used to show an error message when `success` is false" status: String! "An access token used to authenticate new API requests as the newly authorized user. Is present when success is true" token: String } type ScannerResult { finished: Boolean! success: Boolean! progress: Float message: String } "A token used to publicly access an album or media" type ShareToken { id: ID! token: String! "The user who created the token" owner: User! "Optional expire date" expire: Time "Whether or not a password is needed to access the share" hasPassword: Boolean! "The album this token shares" album: Album "The media this token shares" media: Media } "Supported downsampling filters for thumbnail generation" enum ThumbnailFilter { NearestNeighbor, Box, Linear, MitchellNetravali, CatmullRom, Lanczos, } "General information about the site" type SiteInfo { "Whether or not the initial setup wizard should be shown" initialSetup: Boolean! "Whether or not face detection is enabled and working" faceDetectionEnabled: Boolean! "How often automatic scans should be initiated in seconds" periodicScanInterval: Int! @isAdmin "How many max concurrent scanner jobs that should run at once" concurrentWorkers: Int! @isAdmin "The filter to use when generating thumbnails" thumbnailMethod: ThumbnailFilter! @isAdmin } type User { id: ID! username: String! "All albums owned by this user" albums: [Album!]! @isAdmin "Top level albums owned by this user" rootAlbums: [Album!]! @isAdmin "Whether or not the user has admin privileges" admin: Boolean! } "Supported language translations of the user interface" enum LanguageTranslation { English, French, Italian, Swedish, Danish, Spanish, Polish, Ukrainian, German, Russian, TraditionalChinese, SimplifiedChinese, Portuguese, Basque, Turkish } "Preferences for regular users" type UserPreferences { id: ID! language: LanguageTranslation } type Album { id: ID! title: String! "The media inside this album" media( order: Ordering, paginate: Pagination "Return only the favorited media" onlyFavorites: Boolean ): [Media!]! "The albums contained in this album" subAlbums( order: Ordering, paginate: Pagination ): [Album!]! "The album which contains this album" parentAlbum: Album "The user who owns this album" owner: User! "The path on the filesystem of the server, where this album is located" filePath: String! "An image in this album used for previewing this album" thumbnail: Media "A breadcrumb list of all parent albums down to this one" path: [Album!]! "A list of share tokens pointing to this album, owned by the logged in user" shares: [ShareToken!]! } type MediaURL { "URL for previewing the image" url: String! "Width of the image in pixels" width: Int! "Height of the image in pixels" height: Int! "The file size of the resource in bytes" fileSize: Int! } type MediaDownload { "A description of the role of the media file" title: String! mediaUrl: MediaURL! } enum MediaType { Photo Video } type Media { id: ID! title: String! "Local filepath for the media" path: String! "URL to display the media in a smaller resolution" thumbnail: MediaURL "URL to display the photo in full resolution, will be null for videos" highRes: MediaURL "URL to get the video in a web format that can be played in the browser, will be null for photos" videoWeb: MediaURL "The album that holds the media" album: Album! exif: MediaEXIF videoMetadata: VideoMetadata favorite: Boolean! type: MediaType! "The date the image was shot or the date it was imported as a fallback" date: Time! "A short string that can be used to generate a blured version of the media, to show while the original is loading" blurhash: String "A list of share tokens pointing to this media, owned byt the logged in user" shares: [ShareToken!]! "A list of different versions of files for this media that can be downloaded by the user" downloads: [MediaDownload!]! "A list of faces present on the image" faces: [ImageFace!]! } "EXIF metadata from the camera" type MediaEXIF { id: ID! media: Media! "The description of the image" description: String "The model name of the camera" camera: String "The maker of the camera" maker: String "The name of the lens" lens: String dateShot: Time "The exposure time of the image" exposure: Float "The aperature stops of the image" aperture: Float "The ISO setting of the image" iso: Int "The focal length of the lens, when the image was taken" focalLength: Float "A formatted description of the flash settings, when the image was taken" flash: Int "An index describing the mode for adjusting the exposure of the image" exposureProgram: Int "GPS coordinates of where the image was taken" coordinates: Coordinates } type Coordinates { "GPS latitude in degrees" latitude: Float! "GPS longitude in degrees" longitude: Float! } "Metadata specific to video media" type VideoMetadata { id: ID! media: Media! width: Int! height: Int! duration: Float! codec: String framerate: Float bitrate: String colorProfile: String audio: String } type SearchResult { "The string that was searched for" query: String! "A list of albums that matched the query" albums: [Album!]! "A list of media that matched the query" media: [Media!]! } "A group of media from the same album and the same day, that is grouped together in a timeline view" type TimelineGroup { "The full album containing the media in this timeline group" album: Album! "The media contained in this timeline group" media: [Media!]! "The total amount of media in this timeline group" mediaTotal: Int! "The day shared for all media in this timeline group" date: Time! } "A collection of faces of a particular person" type FaceGroup { id: ID! "The name of the person" label: String imageFaces(paginate: Pagination): [ImageFace!]! "The total number of images in this collection" imageFaceCount: Int! } "A single face on a particular image" type ImageFace { id: ID! "A reference to the image the face appears on" media: Media! "A bounding box of where on the image the face is present" rectangle: FaceRectangle! "The `FaceGroup` that contains this `ImageFace`" faceGroup: FaceGroup! } "A bounding box of where a face is present on an image. The values map from 0 to 1 as a fraction of the image width/height" type FaceRectangle { minX: Float! maxX: Float! minY: Float! maxY: Float! }