{"tags":[{"name":"app"},{"description":"Routes related to user auth","name":"Authentication"},{"description":"Routes related to AuthGroup management.","name":"Auth Groups"},{"description":"Routes related to Binding management.","name":"Bindings"},{"description":"Routes related to exporting objects and history","name":"Export"},{"description":"Routes related to the GraphQL API","name":"GraphQL"},{"description":"Routes related to server health checks","name":"Health"},{"description":"Routes related to Image management","name":"Images"},{"description":"Routes related to quantum sync","name":"Quantum Sync"},{"description":"Routes related to site objects","name":"Site"},{"description":"Routes related to server metadata\/utility","name":"Utility"},{"description":"Routes related to user account management.","name":"Account"},{"description":"Routes related to organization management","name":"Organization"},{"description":"Routes related to PassiveLogic devices","name":"PassiveLogic Device"}],"components":{"examples":{"String":{"value":"some string"},"ChangePasswordData":{"value":{"newPassword":"SandSuxDest0ryAllSand"}},"DeviceLoginResponse":{"value":{"token":"eyJ0eXAiOiJKV1QiLCJhbGciOiJFUzM4NCIsImtpZCI6InBsLUUwOTk2NzlGLTQyNDQtNDA4Ni05NTZBLTg4OUM4QkVCQzg2QSJ9.eyJpc3N1ZXIiOiJQYXNzaXZlTG9naWMiLCJoaXZlSUQiOiJEMjU3M0M2Qy0wQjVBLTRCMzItQjM1Ni00OEEyOTlFRDE0OTMiLCJleHBpcmF0aW9uIjoxNzE0NDA2OTA3LjcyODE1Mywic3ViamVjdCI6IkhpdmUgQXV0aGVudGljYXRpb24iLCJoaXZlU2VyaWFsTnVtYmVyIjoiUTBSWFQyUE1HWCJ9.11Awfpm7Uo1LWBtZTCNn1pxUuliE3lcMF4bIqbJzX87u5zJRFRKqfNWdULlU7mmEq_Fes7CzEvSFmn7wlNLlZxY-T8NKhFq35raskqDW-ZdpXUKRk8aHyWfrCVeFcCZU"}},"KeycloakUserInfo":{"value":{"groups":["sith","empire"],"roles":["admin"],"attributes":{"position":["Dark Lord of the Sith"],"likes":["lightsabers","the Force"]},"firstName":"Anakin","lastName":"Skywalker","username":"darthvader","enabled":true,"access":{"view":true,"manageGroupMembership":true},"email":"darthvader@galactic-empire.com","id":"6BB41259-68CB-4347-A989-DFD3E0903F9F","requiredActions":["UPDATE_PASSWORD","UPDATE_PROFILE"],"emailVerified":true}},"DeleteOrganizationData":{"value":{"orgID":"A0649172-BD54-41D3-A699-734605318890"}},"OrganizationImageData":{"value":{"organizationID":"D7A598BA-F8F8-46E9-AC8E-A75F5D2D02CA","fileType":"svg","image":"PHN2ZyBoZWlnaHQ9IjI0IiB3aWR0aD0iMjQiPjxjaXJjbGUgY3g9IjUwIiBjeT0iNTAiIHI9IjQwIiBzdHJva2U9ImJsYWNrIiBzdHJva2Utd2lkdGg9IjMiIGZpbGw9ImJsdWUiIC8+PC9zdmc+"}},"UploadFileData":{"value":{"file":"PHN2ZyBoZWlnaHQ9IjI0IiB3aWR0aD0iMjQiPjxjaXJjbGUgY3g9IjUwIiBjeT0iNTAiIHI9IjQwIiBzdHJva2U9ImJsYWNrIiBzdHJva2Utd2lkdGg9IjMiIGZpbGw9ImJsdWUiIC8+PC9zdmc+","fileType":"svg","ID":"570A2561-0404-44DA-8CEF-01919AC93EB2"}},"AcceptOrganizationInvite":{"value":{"inviteID":"5E163DE1-ED28-4758-A9F8-D8B634ADEB5B"}},"AuthGroupInviteResponse":{"value":{"inviteID":"91123A34-576B-4D33-A8ED-2C9B060D36A5","message":"Invitation sent."}},"RegisterUserResponse":{"value":{"message":"User registered successfully.","userStatus":"Active","newUserID":{"id":"118C7024-A245-42BD-A33B-CF6480BDAE7A","type":"User"},"refresh":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJQYXNzaXZlTG9naWMiLCJzdWIiOiJBUEkiLCJleHAiOjE1MTYyMzkwMjIsIklEIjoiMjAyZTI0MTEtNjQ5OS00YWJlLTk5MmYtMmZmODU1MWY5NmU5IiwidXNlcklEIjoiMzMwYTFmMjktMTlkMC00Y2M5LWI3MjQtOWJmNDQxNWY4ODY1In0.hyyBxcHBXqYzwZehxqW7aCwfQTlngtCc7gRW31ijK50","token":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJQYXNzaXZlTG9naWMiLCJzdWIiOiJBUEkiLCJleHAiOjE1MTYyMzkwMjIsIklEIjoiMjAyZTI0MTEtNjQ5OS00YWJlLTk5MmYtMmZmODU1MWY5NmU5IiwibmFtZSI6ImRhcnRodmFkZXIiLCJzdGF0dXMiOiJBY3RpdmUifQ.KiI6-jHPAMsDHvyA7U-BaRZ8mZnByF9a1887lVb-1lY"}},"ChangeUserPassword":{"value":{"oldPassword":"Ih8obi-wan!higrndSUXX","newPassword":"SandSuxDest0ryAllSand"}},"UserRegistrationInitiation":{"value":{"email":"darthvader@galactic-empire.com"}},"RequestResetPasswordData":{"value":{"usernameOrEmail":"darthvader@galactic-empire.com"}},"GenericMessageResponse":{"value":{"message":"We will watch your career with great interest."}},"RegisterUserData":{"value":{"acceptMailingList":false,"firstName":"Anakin","username":"0BDDCE1F-0A1A-474F-9C67-D09D57BD1927","lastName":"Skywalker","password":"Ih8obi-wan!higrndSUXX","email":"darthvader@galactic-empire.com","token":"<JWT Token from registration email>","acceptedEULA":true}},"WhoAmIResponse":{"value":{"emailVerified":true,"firstName":"Anakin","userID":"5AAE7EEE-3B8C-4165-ABB2-3B6B37D32961","lastName":"Skywalker","eulaAccepted":true}},"InviteUserToOrganizationData":{"value":{"expiration":"2027-09-04T18:17:01Z","inviteEmail":"mithrawnuruodo@galactic-empire.com","role":"StandardUser","orgID":"B7817895-A584-4562-A922-1FDBBFE31F97"}},"GenerateApiKeyResponse":{"value":{"expiration":841861020173288,"key":"564d9054fb2cf06e3592c8c4fdc1f613822b0de6358d8580a78ae0b204be3f95"}},"BindingUploadResponse":{"value":{"url":"https:\/\/passivelogic.com\/binding\/FEBE95F7-A426-462B-94D3-A25D9488DFF0","message":"Binding object was successfully updated."}},"LoginResponse":{"value":{"refresh":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJQYXNzaXZlTG9naWMiLCJzdWIiOiJBUEkiLCJleHAiOjE1MTYyMzkwMjIsIklEIjoiMjAyZTI0MTEtNjQ5OS00YWJlLTk5MmYtMmZmODU1MWY5NmU5IiwidXNlcklEIjoiMzMwYTFmMjktMTlkMC00Y2M5LWI3MjQtOWJmNDQxNWY4ODY1In0.hyyBxcHBXqYzwZehxqW7aCwfQTlngtCc7gRW31ijK50","token":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJQYXNzaXZlTG9naWMiLCJzdWIiOiJBUEkiLCJleHAiOjE1MTYyMzkwMjIsIklEIjoiMjAyZTI0MTEtNjQ5OS00YWJlLTk5MmYtMmZmODU1MWY5NmU5IiwibmFtZSI6ImRhcnRodmFkZXIiLCJzdGF0dXMiOiJBY3RpdmUifQ.KiI6-jHPAMsDHvyA7U-BaRZ8mZnByF9a1887lVb-1lY","whoAmI":{"emailVerified":true,"firstName":"Anakin","eulaAccepted":true,"lastName":"Skywalker","userID":"BFC7C5F0-ED75-4156-A188-F24147D4CDF6"}}},"RemoveApiKeyRequest":{"value":{"key":"564d9054fb2cf06e3592c8c4fdc1f613822b0de6358d8580a78ae0b204be3f95"}},"AuthGroupRemovalResponse":{"value":{"message":"User has been successfully removed!","userID":"91BB6DF3-7EB3-4418-98CF-D7920654D684","authGroupID":"7A325141-295F-4AB4-9D35-4E46F102EE06"}},"UpdatedUserEmail":{"value":{"newEmail":"emperorpalps@gallactic-empire.com","oldEmail":"sheevpalpatine@old-republic.net","password":"unlimitedP0wuh!!!"}},"OrgInviteResponse":{"value":{"message":"Invitation sent.","inviteID":"1E89D04D-BE96-4E6F-A502-FFFC8555CB00"}},"UploadImageData":{"value":{"fileType":"svg","ID":"1943CA57-1290-4411-A7E3-CE8A5A8BDB6E","image":"PHN2ZyBoZWlnaHQ9IjI0IiB3aWR0aD0iMjQiPjxjaXJjbGUgY3g9IjUwIiBjeT0iNTAiIHI9IjQwIiBzdHJva2U9ImJsYWNrIiBzdHJva2Utd2lkdGg9IjMiIGZpbGw9ImJsdWUiIC8+PC9zdmc+"}},"DeclineOrganizationInvite":{"value":{"inviteID":"150F417B-0E1C-4EA1-8F3E-4C6F0ED35B44"}},"ImageUploadResponse":{"value":{"url":"http:\/\/www.passivelogic.com\/image\/0A7AF633-9A7A-43F4-B699-3004443449FC","message":"Image was succefully updated."}},"InviteUserToAuthGroupData":{"value":{"authGroupID":"29D28D15-B2CB-4683-ACAC-8EABDAA0D4E8","expiration":"2027-09-04T18:17:00Z","role":"StandardUser","inviteEmail":"mithrawnuruodo@galactic-empire.com"}},"ImageData":{"value":{"fileType":"svg","image":"PHN2ZyBoZWlnaHQ9IjI0IiB3aWR0aD0iMjQiPjxjaXJjbGUgY3g9IjUwIiBjeT0iNTAiIHI9IjQwIiBzdHJva2U9ImJsYWNrIiBzdHJva2Utd2lkdGg9IjMiIGZpbGw9ImJsdWUiIC8+PC9zdmc+"}}},"schemas":{"DeviceLoginResponse":{"type":"object","description":"Response to \/api\/device\/login","properties":{"token":{"description":"Signed authentication JWT","type":"string"}},"required":["token"]},"GraphQLRequest":{"type":"object","properties":{"query":{"type":"string"},"variables":{"type":"object","additionalProperties":{"type":"boolean"},"nullable":true},"operationName":{"type":"string","nullable":true}},"required":["query"]},"GraphQLResult":{"type":"object","properties":{"errors":{"nullable":true,"items":{"$ref":"#\/components\/schemas\/GraphQLError"},"type":"array"},"data":{"nullable":true,"type":"boolean"}}},"QuantumObjectType":{"enum":["Adjacency","AllowedQuanta","Analysis","Animation","ApiKey","Artifact","Asset","AuthGroup","Behavior","Binding","Building","Campus","CampusDirectory","CompatibleQuanta","ConnectionNet","ConnectionNode","ConstructionCategory","ControlKnot","Device","DisplayRule","EmailVerification","Equation","Equipment","EquipmentComponent","EquipmentComponentPropertyRouter","EscalationGroup","Event","EventClass","EventHistory","EventRelation","EventType","Floor","GraphVersion","History","Image","ImportedModel","InterfaceAlternate","Invite","Layer","LayerSet","LayerSetJoin","Library","Location","LocationProperty","Manufacturer","Media","MediaComponent","Model","MultifactorAuthentication","NodeSet","NodeSetConnectionNodeJoin","Organization","OrganizationAuthGroupPermission","Prediction","PredictionGroup","Preference","PreferenceGroup","PrivilegeJoin","Procedure","Property","PropertyTagRouter","Quanta","RefreshToken","Relationship","SelectedModel","SessionBinding","SessionEvent","Shape","Site","Subsystem","SubsystemCapability","SubsystemSet","Surface","System","Tag","TagFamily","TypicalConstruction","UnitLookup","UnitPreference","User","UserSession","UserSessionHistory","Vertex","View","WeatherSource","Zone","ZoneGroup","ZoneSubsystem","ZoneSubsystemSet"],"type":"string"},"RegisterUserResponse":{"type":"object","description":"Sent when a new user is successfully registered.","properties":{"token":{"nullable":true,"type":"string","description":"New authentication JWT containing changed information"},"message":{"type":"string","description":"Additional information about the response"},"newUserID":{"$ref":"#\/components\/schemas\/Identifier"},"refresh":{"nullable":true,"type":"string","description":"New refresh JWT"},"userStatus":{"$ref":"#\/components\/schemas\/QuantumUserStatus"}},"required":["message"]},"BindingUploadResponse":{"type":"object","description":"Binding response definition","properties":{"message":{"type":"string","description":"Informative message relating to binding upload. Updated binding url with cache bust."},"url":{"type":"string","nullable":true}},"required":["message"]},"TailscalePostTailnetKeyResponse":{"type":"object","properties":{"keyType":{"type":"string"},"revoked":{"nullable":true,"format":"date-time","type":"string"},"description":{"nullable":true,"type":"string"},"capabilities":{"$ref":"#\/components\/schemas\/TailscaleCapabilities"},"created":{"nullable":true,"format":"date-time","type":"string"},"scopes":{"nullable":true,"type":"array","items":{"type":"string"}},"invalid":{"nullable":true,"type":"boolean"},"expires":{"nullable":true,"format":"date-time","type":"string"},"userId":{"nullable":true,"type":"string"},"expirySeconds":{"format":"int64","type":"integer"},"id":{"type":"string"},"key":{"type":"string"},"tags":{"nullable":true,"type":"array","items":{"type":"string"}}},"required":["capabilities","expirySeconds","id","key","keyType"]},"RemoveApiKeyRequest":{"type":"object","description":"API key to revoke","properties":{"key":{"type":"string","description":"API key to revoke."}},"required":["key"]},"QuantumLensAppStatusResponse":{"type":"object","properties":{"appUpdate":{"nullable":true,"type":"boolean"},"osUpdate":{"nullable":true,"type":"boolean"}}},"ImageData":{"type":"object","description":"Data required to upload image without using an image model.","properties":{"fileType":{"description":"The type of file the given data represents, from a list of allowed files.","type":"string"},"image":{"format":"byte","description":"File data to write to the server. Must be Base64-encoded if sending as JSON.","type":"string"}},"required":["fileType","image"]},"WhoAmIResponse":{"properties":{"eulaAccepted":{"type":"boolean","description":"Flag to mark if the user has acept the terms of the EULA","nullable":true},"lastName":{"type":"string","description":"User's last name","nullable":true},"userID":{"type":"string","description":"Unique ID for the user","format":"uuid"},"firstName":{"type":"string","description":"User's first name","nullable":true},"emailVerified":{"type":"boolean","description":"Flag to mark if the user's email is verified","nullable":true}},"type":"object","description":"Information about the authenticated user","required":["userID"]},"GenericMessageResponse":{"properties":{"message":{"description":"Informative message relating to the specific response","type":"string"}},"type":"object","description":"Generic response information","required":["message"]},"RegisterUserData":{"type":"object","description":"Data required for user registration","properties":{"lastName":{"description":"User's last name","type":"string"},"token":{"type":"string","nullable":true},"password":{"description":"User's password","type":"string"},"acceptedEULA":{"description":"Flag to mark if the user has accepted the EULA","type":"boolean"},"acceptMailingList":{"type":"boolean","description":"Flag to mark if the user wants marketing emails"},"firstName":{"description":"User's first name","type":"string"},"username":{"type":"string","nullable":true},"email":{"description":"User's email","type":"string"},"recaptchaToken":{"type":"string","nullable":true}},"required":["acceptMailingList","acceptedEULA","email","firstName","lastName","password"]},"TailscaleCapabilitiesDevicesCreate":{"type":"object","properties":{"ephemeral":{"type":"boolean"},"tags":{"items":{"type":"string"},"type":"array"},"reusable":{"type":"boolean"},"preauthorized":{"type":"boolean"}},"required":["ephemeral","preauthorized","reusable","tags"]},"JWK":{"properties":{"kty":{"type":"string"}},"type":"object","required":["kty"]},"QuantumRole":{"enum":["PrivilegedUser","ReadOnlyUser","StandardUser","SuperUser"],"type":"string"},"QuantumLensUser":{"type":"object","properties":{"userID":{"format":"uuid","type":"string"},"lastName":{"nullable":true,"type":"string"},"firstName":{"nullable":true,"type":"string"}},"required":["userID"]},"ChangePasswordData":{"type":"object","description":"Information required to change a user's password from the reset password flow","properties":{"confirmNewPassword":{"type":"string","nullable":true},"newPassword":{"type":"string","description":"New password for the user."}},"required":["newPassword"]},"InviteUserToOrganizationData":{"type":"object","description":"Parameters required to invite a user to an organization","properties":{"orgID":{"description":"ID of the organization to which this invite pertains","format":"uuid","type":"string"},"expiration":{"description":"Timestamp at which this invitation will no longer be valid","format":"date-time","nullable":true,"type":"string"},"role":{"$ref":"#\/components\/schemas\/QuantumRole"},"inviteEmail":{"description":"Email to send the invite to","type":"string"}},"required":["inviteEmail","orgID"]},"DeployedOnHiveResponse":{"type":"object","properties":{"runningOnHive":{"type":"boolean"}},"required":["runningOnHive"]},"GraphQLError":{"type":"object","properties":{"locations":{"items":{"$ref":"#\/components\/schemas\/SourceLocation"},"type":"array"},"path":{"items":{"items":{"type":"integer","format":"int64"},"type":"array"},"type":"array"},"message":{"type":"string"},"extensions":{"nullable":true,"additionalProperties":{"type":"boolean"},"type":"object"}},"required":["locations","message","path"]},"RequestResetPasswordData":{"type":"object","description":"Information required to request a password reset.","properties":{"usernameOrEmail":{"description":"Email of the user requesting a reset.","type":"string"}},"required":["usernameOrEmail"]},"KeycloakUserInfo":{"properties":{"roles":{"type":"array","items":{"type":"string"},"description":"Roles for this user","nullable":true},"groups":{"type":"array","items":{"type":"string"},"description":"Groups that this user belongs to","nullable":true},"attributes":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}},"description":"Additional attributes of the user; each attribute can have multiple values","nullable":true},"firstName":{"type":"string","nullable":true,"description":"The user's first (given) name"},"lastName":{"type":"string","nullable":true,"description":"The user's last name (surname)"},"username":{"type":"string","nullable":true,"description":"Unique username for the user"},"enabled":{"type":"boolean","nullable":true,"description":"Active or inactive status for the user"},"access":{"type":"object","additionalProperties":{"type":"boolean"},"description":"Access rights for this user","nullable":true},"email":{"type":"string","description":"Email for the user, also used as the username"},"id":{"type":"string","nullable":true,"description":"Unique ID for the user"},"emailVerified":{"type":"boolean","nullable":true,"description":"Has the email address for this user been verified as valid"},"requiredActions":{"type":"array","items":{"type":"string"},"description":"Actions the user will need to do on next login","nullable":true}},"type":"object","description":"Information for Keycloak about the requested user.","required":["email"]},"DeleteOrganizationData":{"type":"object","description":"Parameters require to delete an organization","properties":{"orgID":{"description":"ID of the organization being deleted","format":"uuid","type":"string"}},"required":["orgID"]},"GenerateApiKeyResponse":{"type":"object","description":"New API key generated for a user.","properties":{"key":{"type":"string","description":"New API key."},"expiration":{"type":"integer","format":"int64","description":"Expiration of the new key."}},"required":["expiration","key"]},"AcceptOrganizationInvite":{"type":"object","description":"Parameters required to accept an organization invite","properties":{"inviteID":{"description":"ID of the invitation being accepted.","format":"uuid","type":"string"}},"required":["inviteID"]},"TailscaleCapabilities":{"type":"object","properties":{"devices":{"$ref":"#\/components\/schemas\/TailscaleCapabilitiesDevices"}},"required":["devices"]},"UploadFileData":{"type":"object","description":"Data required to upload a file binding.","properties":{"fileType":{"description":"The type of file the given data represents.","type":"string"},"file":{"description":"File data to write to the server.","type":"string","format":"byte"},"ID":{"description":"UUID of the quantum binding node that you want to associate this file with.","type":"string","format":"uuid"},"filePath":{"type":"string","nullable":true}},"required":["ID","file","fileType"]},"ImageUploadResponse":{"type":"object","description":"Image response definition","properties":{"message":{"description":"Informative message relating to image upload. Updated image url with cache bust.","type":"string"},"url":{"type":"string","nullable":true}},"required":["message"]},"TailscaleCapabilitiesDevices":{"type":"object","properties":{"create":{"$ref":"#\/components\/schemas\/TailscaleCapabilitiesDevicesCreate"}},"required":["create"]},"InviteUserToAuthGroupData":{"type":"object","description":"Parameters required to invite a user to an organization","properties":{"authGroupID":{"format":"uuid","type":"string","description":"ID of the AuthGroup to which this invite pertains"},"inviteEmail":{"type":"string","description":"Email to send the invite to"},"expiration":{"format":"date-time","nullable":true,"type":"string","description":"Timestamp at which this invitation will no longer be valid"},"role":{"$ref":"#\/components\/schemas\/QuantumRole"}},"required":["authGroupID","inviteEmail"]},"KeycloakCredentialInfo":{"type":"object","properties":{"value":{"nullable":true,"type":"string"},"userLabel":{"nullable":true,"type":"string"},"temporary":{"nullable":true,"type":"boolean"},"createdDate":{"format":"int64","nullable":true,"type":"integer"},"type":{"type":"string"},"id":{"format":"uuid","type":"string"},"priority":{"nullable":true,"format":"int64","type":"integer"},"device":{"nullable":true,"type":"string"}},"required":["id","type"]},"UploadImageData":{"type":"object","description":"Data required to upload an image.","properties":{"filePath":{"nullable":true,"type":"string"},"image":{"format":"byte","type":"string","description":"File data to write to the server. Must be Base64-encoded if sending as JSON."},"fileType":{"type":"string","description":"The type of file the given data represents, from a list of allowed files."},"ID":{"format":"uuid","type":"string","description":"UUID of the quantum image node that you want to associate this image file with."}},"required":["ID","fileType","image"]},"OrgInviteResponse":{"type":"object","description":"Response indicating that an organization invitation was successfully sent.","properties":{"message":{"description":"Message with additional information","type":"string"},"inviteID":{"description":"ID of the invitation generated\/sent","format":"uuid","type":"string"}},"required":["inviteID","message"]},"AuthGroupInviteResponse":{"type":"object","description":"Response indicating that an AuthGroup invitation was successfully sent.","properties":{"inviteID":{"format":"uuid","type":"string","description":"ID of the invitation generated\/sent"},"message":{"type":"string","description":"Message with additional information"}},"required":["inviteID","message"]},"SourceLocation":{"type":"object","properties":{"column":{"type":"integer","format":"int64"},"line":{"type":"integer","format":"int64"}},"required":["column","line"]},"UserRegistrationInitiation":{"properties":{"firstName":{"type":"string","nullable":true},"lastName":{"type":"string","nullable":true},"email":{"description":"Email that is registering for a new account.","type":"string"}},"type":"object","description":"Information for intiating user registration","required":["email"]},"DeclineOrganizationInvite":{"type":"object","description":"Parameters required to decline an organization invite","properties":{"inviteID":{"type":"string","description":"ID of the invitation being declined.","format":"uuid"}},"required":["inviteID"]},"JWKS":{"type":"object","properties":{"keys":{"items":{"$ref":"#\/components\/schemas\/JWK"},"type":"array"}},"required":["keys"]},"ObjectIdentifiers":{"type":"object","properties":{"objectIdentifierMap":{"items":{"$ref":"#\/components\/schemas\/ObjectPair"},"type":"array"}},"required":["objectIdentifierMap"]},"LoginResponse":{"properties":{"whoAmI":{"$ref":"#\/components\/schemas\/WhoAmIResponse"},"token":{"description":"Signed Authentication JWT","type":"string"},"refresh":{"description":"Signed refresh JWT","type":"string"}},"type":"object","description":"Generic response information","required":["refresh","token","whoAmI"]},"QuantumUserStatus":{"enum":["Active","Blocked","Deleted","Locked","Pending","Reset"],"type":"string"},"OrganizationImageData":{"type":"object","description":"Data required to upload a organization image","properties":{"fileType":{"description":"The type of file the given data represents, from a list of allowed files","type":"string"},"image":{"format":"byte","description":"File data to write to the server. Must be Base64-encoded if sending as JSON.","type":"string"},"organizationID":{"format":"uuid","description":"The organization that is associated with this image request.","type":"string"}},"required":["fileType","image","organizationID"]},"MagicLinkResponse":{"properties":{"url":{"type":"string","description":"Url to be used a magic link login.","nullable":true},"message":{"type":"string","description":"Message describing the response type.","nullable":true}},"type":"object","description":"Email for use signing up with a magic link"},"AuthGroupRemovalResponse":{"type":"object","description":"Response indicating that a User has been removed from an AuthGroup.","properties":{"authGroupID":{"type":"string","format":"uuid","description":"ID of the Authgroup the user has been removed from."},"message":{"type":"string","description":"Message with additional information"},"userID":{"type":"string","format":"uuid","description":"ID of the User who has been removed"}},"required":["authGroupID","message","userID"]},"UpdatedUserEmail":{"type":"object","description":"Information for changing a user's email","properties":{"oldEmail":{"type":"string","description":"Previous user email"},"newEmail":{"type":"string","description":"New user email"},"password":{"type":"string","description":"user's password to confirm identity"}},"required":["newEmail","oldEmail","password"]},"ObjectPair":{"type":"object","properties":{"type":{"$ref":"#\/components\/schemas\/QuantumObjectType"},"newID":{"type":"string","format":"uuid"},"oldID":{"type":"string","format":"uuid"}},"required":["newID","oldID","type"]},"QuantumLensResponse":{"type":"object","properties":{"status":{"$ref":"#\/components\/schemas\/QuantumLensAppStatusResponse"},"user":{"$ref":"#\/components\/schemas\/QuantumLensUser"}},"required":["status","user"]},"Identifier":{"type":"object","properties":{"id":{"type":"string"},"type":{"$ref":"#\/components\/schemas\/QuantumObjectType"}},"required":["id","type"]},"ChangeUserPassword":{"type":"object","description":"Information required to change a user's password from the authenticated change password flow","properties":{"oldPassword":{"type":"string","description":"Old password for the user, used to confirm identity."},"newPassword":{"type":"string","description":"New password for the user."}},"required":["newPassword","oldPassword"]}},"securitySchemes":{"Basic Auth - login":{"scheme":"basic","type":"http","description":"Basic authentication used only at login."},"DEPRECATED - PL API Key":{"type":"apiKey","description":"DEPRECATED - PL API Key in Bearer header","name":"Authorization: PL-API-KEY","in":"header"},"PL API Key":{"type":"apiKey","description":"PL API Key in header","name":"PL-API-KEY","in":"header"},"XSRF header":{"type":"apiKey","description":"Authentication using an XSRF protected JWT","name":"X-PL-AUTH","in":"header"}}},"paths":{"\/api\/v0.19\/auth\/offline":{"get":{"tags":["Authentication"],"security":[{"Basic Auth - login":[]},{"XSRF header":[]},{"DEPRECATED - PL API Key":[]},{"PL API Key":[]}],"description":"GET \/auth\/offline"}},"\/api\/v0.19\/organization\/update-logo":{"post":{"security":[{"Basic Auth - login":[]},{"XSRF header":[]},{"DEPRECATED - PL API Key":[]},{"PL API Key":[]}],"responses":{"200":{"description":"OK","content":{"application\/json":{"examples":{"ImageUploadResponse":{"$ref":"#\/components\/examples\/ImageUploadResponse"}},"schema":{"$ref":"#\/components\/schemas\/ImageUploadResponse"}}}}},"operationId":"postApiV0.19OrganizationUpdate-logo","description":"Verifies that the user making the request has sufficient permissions to change the logo for the organization.\nTakes in a new image as the organization's logo. Creates or replaces the previous stored logo.","summary":"Updates the organization's logo","requestBody":{"required":true,"content":{"application\/json":{"examples":{"OrganizationImageData":{"$ref":"#\/components\/examples\/OrganizationImageData"}},"schema":{"$ref":"#\/components\/schemas\/OrganizationImageData"}}}},"tags":["Organization"]}},"\/api\/organization\/delete":{"post":{"security":[{"Basic Auth - login":[]},{"XSRF header":[]},{"DEPRECATED - PL API Key":[]},{"PL API Key":[]}],"responses":{"200":{"content":{"application\/json":{"examples":{"GenericMessageResponse":{"$ref":"#\/components\/examples\/GenericMessageResponse"}},"schema":{"$ref":"#\/components\/schemas\/GenericMessageResponse"}}},"description":"OK"}},"description":"Completely deletes an organization, after verifying that the user making this request has permission to do so.\nSends an email to all other members of the organization informing them that it has been deleted.","operationId":"postApiOrganizationDelete","summary":"Deletes specified organization.","requestBody":{"required":true,"content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/DeleteOrganizationData"},"examples":{"DeleteOrganizationData":{"$ref":"#\/components\/examples\/DeleteOrganizationData"}}}}},"tags":["Organization"]}},"\/api\/v0.20\/organization\/update-image":{"post":{"security":[{"Basic Auth - login":[]},{"XSRF header":[]},{"DEPRECATED - PL API Key":[]},{"PL API Key":[]}],"responses":{"200":{"description":"OK","content":{"application\/json":{"examples":{"ImageUploadResponse":{"$ref":"#\/components\/examples\/ImageUploadResponse"}},"schema":{"$ref":"#\/components\/schemas\/ImageUploadResponse"}}}}},"operationId":"postApiV0.20OrganizationUpdate-image","description":"Verifies that the user making the request has sufficient permissions to change the image for the organization.\nTakes in a new image as the new organization image. Creates or replaces the previously stored image.","summary":"Updates the organization's image","requestBody":{"content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/OrganizationImageData"},"examples":{"OrganizationImageData":{"$ref":"#\/components\/examples\/OrganizationImageData"}}}},"required":true},"tags":["Organization"]}},"\/api\/v0.19\/organization\/delete":{"post":{"security":[{"Basic Auth - login":[]},{"XSRF header":[]},{"DEPRECATED - PL API Key":[]},{"PL API Key":[]}],"responses":{"200":{"description":"OK","content":{"application\/json":{"examples":{"GenericMessageResponse":{"$ref":"#\/components\/examples\/GenericMessageResponse"}},"schema":{"$ref":"#\/components\/schemas\/GenericMessageResponse"}}}}},"operationId":"postApiV0.19OrganizationDelete","description":"Completely deletes an organization, after verifying that the user making this request has permission to do so.\nSends an email to all other members of the organization informing them that it has been deleted.","summary":"Deletes specified organization.","requestBody":{"required":true,"content":{"application\/json":{"examples":{"DeleteOrganizationData":{"$ref":"#\/components\/examples\/DeleteOrganizationData"}},"schema":{"$ref":"#\/components\/schemas\/DeleteOrganizationData"}}}},"tags":["Organization"]}},"\/api\/account\/user\/delete":{"delete":{"description":"Deletes the requesting user if they are not a SuperUser within any organizations.\nOtherwise prompts them to transfer ownership or delete the org before making this request.","security":[{"Basic Auth - login":[]},{"XSRF header":[]},{"DEPRECATED - PL API Key":[]},{"PL API Key":[]}],"tags":["Account"],"summary":"Deletes the user making this request.","operationId":"deleteApiAccountUserDelete","responses":{"200":{"content":{"application\/json":{"examples":{"GenericMessageResponse":{"$ref":"#\/components\/examples\/GenericMessageResponse"}},"schema":{"$ref":"#\/components\/schemas\/GenericMessageResponse"}}},"description":"OK"}}}},"\/api\/v0.19\/auth\/email\/change\/verify":{"get":{"security":[{"Basic Auth - login":[]},{"XSRF header":[]},{"DEPRECATED - PL API Key":[]},{"PL API Key":[]}],"responses":{"200":{"content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/GenericMessageResponse"},"examples":{"GenericMessageResponse":{"$ref":"#\/components\/examples\/GenericMessageResponse"}}}},"description":"OK"}},"description":"DEPRECATED: This endpoint is not available when Keycloak authentication is turned on and will be removed in the future.\n\nVerifies the new email is valid. Updates the user email with the newly validated one.\n\nToken authentication required. Provided by \/api\/v0.19\/auth\/email\/change.","operationId":"getApiV0.19AuthEmailChangeVerify","deprecated":true,"summary":"Verifies and updates new user email","requestBody":{"content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/UpdatedUserEmail"},"examples":{"UpdatedUserEmail":{"$ref":"#\/components\/examples\/UpdatedUserEmail"}}}},"required":true},"tags":["Authentication"]}},"\/api\/v0.20\/auth\/keys":{"get":{"tags":["Authentication"],"operationId":"getApiV0.20AuthKeys","summary":"Returns the public keys used to sign PassiveLogic JSON web tokens.","description":"Returns the public keys used to sign the JSON web tokens so their authenticity can be verified. These are served in the\nstandard JSON Web Key format: https:\/\/www.rfc-editor.org\/rfc\/rfc7517","responses":{"200":{"description":"OK","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/JWKS"}}}}}}},"\/api\/organization\/update-image":{"post":{"security":[{"Basic Auth - login":[]},{"XSRF header":[]},{"DEPRECATED - PL API Key":[]},{"PL API Key":[]}],"responses":{"200":{"description":"OK","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ImageUploadResponse"},"examples":{"ImageUploadResponse":{"$ref":"#\/components\/examples\/ImageUploadResponse"}}}}}},"operationId":"postApiOrganizationUpdate-image","description":"Verifies that the user making the request has sufficient permissions to change the image for the organization.\nTakes in a new image as the new organization image. Creates or replaces the previously stored image.","summary":"Updates the organization's image","requestBody":{"required":true,"content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/OrganizationImageData"},"examples":{"OrganizationImageData":{"$ref":"#\/components\/examples\/OrganizationImageData"}}}}},"tags":["Organization"]}},"\/api\/v0.20\/auth\/zendesk":{"get":{"summary":"Logs a user in to Zendesk using their PL Account","description":"Redirects a user to the PassiveLogic Zendesk portal.\nIf they are already authenticated with their PL account when making this request,\nthey will be automatically logged in to Zendesk as well. Otherwise they will be redirected to the Zendesk login page.\nA `returnTo` query parameter can be used to support deep linking to, for example, specific support articles.","tags":["Authentication"],"operationId":"getApiV0.20AuthZendesk"}},"\/api\/util\/version":{"get":{"deprecated":true,"tags":["Utility"],"summary":"Returns version information","description":"Returns commit hashes & build times for the running build of the webserver and all apps.","operationId":"getApiUtilVersion","responses":{"200":{"content":{"text\/plain":{"schema":{"type":"string"},"examples":{"String":{"$ref":"#\/components\/examples\/String"}}}},"description":"OK"}}}},"\/api\/auth\/zendesk":{"get":{"summary":"Logs a user in to Zendesk using their PL Account","operationId":"getApiAuthZendesk","tags":["Authentication"],"description":"Redirects a user to the PassiveLogic Zendesk portal.\nIf they are already authenticated with their PL account when making this request,\nthey will be automatically logged in to Zendesk as well. Otherwise they will be redirected to the Zendesk login page.\nA `returnTo` query parameter can be used to support deep linking to, for example, specific support articles."}},"\/api\/image\/{imageID}":{"delete":{"security":[{"Basic Auth - login":[]},{"XSRF header":[]},{"DEPRECATED - PL API Key":[]},{"PL API Key":[]}],"responses":{"200":{"description":"OK","content":{"application\/json":{"examples":{"GenericMessageResponse":{"$ref":"#\/components\/examples\/GenericMessageResponse"}},"schema":{"$ref":"#\/components\/schemas\/GenericMessageResponse"}}}}},"description":"Delete the image with the given quantum node ID.\nIf authorized and the given image is found, it will be deleted from the file store and the database.\nThe ID provided must be the ID of the `Image` Quantum node, NOT the name of the image.","operationId":"deleteApiImageByImageID","deprecated":true,"summary":"Delete an image. Deprecated: Delete an image node via the normal GraphQL endpoint or a QuantumSync operation. This route has been deprecated in favor of: POST \/api\/graphql.","parameters":[{"in":"path","required":true,"name":"imageID","schema":{"type":"string"}}],"tags":["Images"]}},"\/api\/meta.json":{"get":{"description":"GET \/api\/meta.json","tags":["api"]}},"\/api\/v0.20\/organization\/join":{"post":{"security":[{"Basic Auth - login":[]},{"XSRF header":[]},{"DEPRECATED - PL API Key":[]},{"PL API Key":[]}],"responses":{"200":{"description":"OK","content":{"application\/json":{"examples":{"GenericMessageResponse":{"$ref":"#\/components\/examples\/GenericMessageResponse"}},"schema":{"$ref":"#\/components\/schemas\/GenericMessageResponse"}}}}},"operationId":"postApiV0.20OrganizationJoin","description":"Adds user to organization based on Organization invite ID.\nRole in organization is determined through Organization invite role, if no role is defined, we default to read-only user.","summary":"Adds a user to an organization","requestBody":{"required":true,"content":{"application\/json":{"examples":{"AcceptOrganizationInvite":{"$ref":"#\/components\/examples\/AcceptOrganizationInvite"}},"schema":{"$ref":"#\/components\/schemas\/AcceptOrganizationInvite"}}}},"tags":["Organization"]}},"\/app\/login\/finish":{"get":{"description":"","operationId":"getAppLoginFinish","summary":"Redirects to external authentication provider (Keycloak).","tags":["app"]}},"\/api\/datasync":{"get":{"description":"Refer to the \/api\/quantumsync route documentation for full details. This route will be removed in the next major version.","tags":["Quantum Sync"],"summary":"QuantumSync API Legacy Route. Use \/api\/quantumsync instead.","operationId":"getApiDatasync","deprecated":true,"security":[{"Basic Auth - login":[]},{"XSRF header":[]},{"DEPRECATED - PL API Key":[]},{"PL API Key":[]}]}},"\/api\/v0.20\/auth\/password\/change":{"get":{"summary":"Redirects the user to the change password flow in the external auth provider (Keycloak).","security":[{"Basic Auth - login":[]},{"XSRF header":[]},{"DEPRECATED - PL API Key":[]},{"PL API Key":[]}],"operationId":"getApiV0.20AuthPasswordChange","tags":["Authentication"],"description":""},"post":{"security":[{"Basic Auth - login":[]},{"XSRF header":[]},{"DEPRECATED - PL API Key":[]},{"PL API Key":[]}],"responses":{"200":{"content":{"application\/json":{"examples":{"GenericMessageResponse":{"$ref":"#\/components\/examples\/GenericMessageResponse"}},"schema":{"$ref":"#\/components\/schemas\/GenericMessageResponse"}}},"description":"OK"}},"operationId":"postApiV0.20AuthPasswordChange","description":"DEPRECATED: This endpoint is not available when Keycloak authentication is turned on and will be removed in the future.\n\nChanges an authenticated user's password to the specified value.","deprecated":true,"summary":"Changes a user's password for an already authenticated user.","requestBody":{"required":true,"content":{"application\/json":{"examples":{"ChangeUserPassword":{"$ref":"#\/components\/examples\/ChangeUserPassword"}},"schema":{"$ref":"#\/components\/schemas\/ChangeUserPassword"}}}},"tags":["Authentication"]}},"\/api\/authgroup\/invite":{"post":{"security":[{"Basic Auth - login":[]},{"XSRF header":[]},{"DEPRECATED - PL API Key":[]},{"PL API Key":[]}],"responses":{"200":{"content":{"application\/json":{"examples":{"AuthGroupInviteResponse":{"$ref":"#\/components\/examples\/AuthGroupInviteResponse"}},"schema":{"$ref":"#\/components\/schemas\/AuthGroupInviteResponse"}}},"description":"OK"}},"operationId":"postApiAuthgroupInvite","description":"Generates and sends an invitation link for the given Site or View (AuthGroup) to the given user email.","summary":"Sends an AuthGroup invite to the given email.","requestBody":{"content":{"application\/json":{"examples":{"InviteUserToAuthGroupData":{"$ref":"#\/components\/examples\/InviteUserToAuthGroupData"}},"schema":{"$ref":"#\/components\/schemas\/InviteUserToAuthGroupData"}}},"required":true},"tags":["Auth Groups"]}},"\/app\/al\/**":{"get":{"tags":["app"],"description":"GET \/app\/al\/**"}},"\/api\/v0.19\/auth\/email\/change":{"post":{"security":[{"Basic Auth - login":[]},{"XSRF header":[]},{"DEPRECATED - PL API Key":[]},{"PL API Key":[]}],"responses":{"200":{"content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/GenericMessageResponse"},"examples":{"GenericMessageResponse":{"$ref":"#\/components\/examples\/GenericMessageResponse"}}}},"description":"OK"}},"operationId":"postApiV0.19AuthEmailChange","description":"DEPRECATED: This endpoint is not available when Keycloak authentication is turned on and will be removed in the future.\n\nSends an update email request to the provided new email address.","deprecated":true,"summary":"Initiates an email change for the current user.","requestBody":{"content":{"application\/json":{"examples":{"UpdatedUserEmail":{"$ref":"#\/components\/examples\/UpdatedUserEmail"}},"schema":{"$ref":"#\/components\/schemas\/UpdatedUserEmail"}}},"required":true},"tags":["Authentication"]}},"\/api\/v0.20\/image\/{imageID}":{"delete":{"security":[{"Basic Auth - login":[]},{"XSRF header":[]},{"DEPRECATED - PL API Key":[]},{"PL API Key":[]}],"responses":{"200":{"content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/GenericMessageResponse"},"examples":{"GenericMessageResponse":{"$ref":"#\/components\/examples\/GenericMessageResponse"}}}},"description":"OK"}},"operationId":"deleteApiV0.20ImageByImageID","description":"Delete the image with the given quantum node ID.\nIf authorized and the given image is found, it will be deleted from the file store and the database.\nThe ID provided must be the ID of the `Image` Quantum node, NOT the name of the image.","deprecated":true,"summary":"Delete an image. Deprecated: Delete an image node via the normal GraphQL endpoint or a QuantumSync operation. This route has been deprecated in favor of: POST \/api\/graphql.","tags":["Images"],"parameters":[{"required":true,"name":"imageID","in":"path","schema":{"type":"string"}}]}},"\/app\/qs\/**":{"get":{"tags":["app"],"description":"GET \/app\/qs\/**"}},"\/api\/v0.19\/auth\/profile\/change":{"get":{"summary":"Redirects the user the change profile flow in the external auth provider (Keycloak).","description":"","tags":["Authentication"],"security":[{"Basic Auth - login":[]},{"XSRF header":[]},{"DEPRECATED - PL API Key":[]},{"PL API Key":[]}],"operationId":"getApiV0.19AuthProfileChange"}},"\/api\/v0.20\/auth\/logout":{"post":{"tags":["Authentication"],"security":[{"Basic Auth - login":[]},{"XSRF header":[]},{"DEPRECATED - PL API Key":[]},{"PL API Key":[]}],"description":"If external auth (Keycloak) is enabled, this initiates the external logout process.\n\nOtherwise, if a cookie keyed by pl-refresh-token is provided in the logout request, that refresh token is revoked.\n\nThe response sets the auth & refresh cookies to empty values & marks them as expired.\nNew tokens must then be generated by the login endpoint.","responses":{"200":{"description":"OK","content":{"application\/json":{"examples":{"GenericMessageResponse":{"$ref":"#\/components\/examples\/GenericMessageResponse"}},"schema":{"$ref":"#\/components\/schemas\/GenericMessageResponse"}}}}},"operationId":"postApiV0.20AuthLogout","summary":"Logs out a user"}},"\/api\/image\/user-avatar":{"post":{"security":[{"Basic Auth - login":[]},{"XSRF header":[]},{"DEPRECATED - PL API Key":[]},{"PL API Key":[]}],"responses":{"200":{"description":"OK","content":{"application\/json":{"examples":{"ImageUploadResponse":{"$ref":"#\/components\/examples\/ImageUploadResponse"}},"schema":{"$ref":"#\/components\/schemas\/ImageUploadResponse"}}}}},"operationId":"postApiImageUser-avatar","description":"Uploads and updates the avatar image URL with the new image URL.","summary":"Update user avatar image","requestBody":{"content":{"application\/json":{"examples":{"ImageData":{"$ref":"#\/components\/examples\/ImageData"}},"schema":{"$ref":"#\/components\/schemas\/ImageData"}}},"required":true},"tags":["Images"]}},"\/app\/as\/**":{"get":{"tags":["app"],"description":"GET \/app\/as\/**"}},"\/api\/v0.20\/account\/eula\/accept":{"post":{"security":[{"Basic Auth - login":[]},{"XSRF header":[]},{"DEPRECATED - PL API Key":[]},{"PL API Key":[]}],"responses":{"200":{"content":{"application\/json":{"examples":{"GenericMessageResponse":{"$ref":"#\/components\/examples\/GenericMessageResponse"}},"schema":{"$ref":"#\/components\/schemas\/GenericMessageResponse"}}},"description":"OK"}},"description":"DEPRECATED: This endpoint is not available when Keycloak authentication is turned on and will be removed in the future.\nDenotes that the current user has accepted the EULA.\nReturns updated access and refresh tokens.","operationId":"postApiV0.20AccountEulaAccept","deprecated":true,"summary":"Accepts EULA for the current user","tags":["Account"]}},"\/api\/v0.20\/device\/tailscale\/authToken":{"get":{"responses":{"200":{"content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/TailscalePostTailnetKeyResponse"}}},"description":"OK"}},"security":[{"Basic Auth - login":[]},{"XSRF header":[]},{"DEPRECATED - PL API Key":[]},{"PL API Key":[]}],"operationId":"getApiV0.20DeviceTailscaleAuthToken","tags":["PassiveLogic Device"],"summary":"Generates an OAuth token for Tailscale","description":"AutToken generated allowing hive's to enroll in our tailnet.\n\nmTLS authentication required."}},"\/api\/v0.19\/auth\/keys":{"get":{"responses":{"200":{"description":"OK","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/JWKS"}}}}},"summary":"Returns the public keys used to sign PassiveLogic JSON web tokens.","operationId":"getApiV0.19AuthKeys","tags":["Authentication"],"description":"Returns the public keys used to sign the JSON web tokens so their authenticity can be verified. These are served in the\nstandard JSON Web Key format: https:\/\/www.rfc-editor.org\/rfc\/rfc7517"}},"\/api\/v0.20\/auth\/offline":{"get":{"security":[{"Basic Auth - login":[]},{"XSRF header":[]},{"DEPRECATED - PL API Key":[]},{"PL API Key":[]}],"description":"GET \/auth\/offline","tags":["Authentication"]}},"\/api\/v0.20\/device\/register":{"post":{"description":"POST \/device\/register","security":[{"Basic Auth - login":[]},{"XSRF header":[]},{"DEPRECATED - PL API Key":[]},{"PL API Key":[]}],"tags":["PassiveLogic Device"]}},"\/api\/v0.20\/quantumsync":{"get":{"operationId":"getApiV0.20Quantumsync","security":[{"Basic Auth - login":[]},{"XSRF header":[]},{"DEPRECATED - PL API Key":[]},{"PL API Key":[]}],"summary":"QuantumSync API over websockets","description":"# Custom QuantumSync\/ShadowClient API:\n\n## QuantumSync QuantumSyncRequestTypes:\n### `start`: authenticates and specifies an initial context. note: the id for start and updateContext is used to key a Dictionary[String:AnyRootedQuantumGraph]\nex)\n```json\n{\n    \"type\": \"start\",\n    \"id\": \"site\",\n    \"appType\":\"BuildingStudio\"\n    \"payload\": {\n        \"authToken\": \"REDACTED\",\n        \"ID\": \"ACAF9E07-5031-4BC2-A8C5-D2C6598D83DE\",\n        \"from\": \"Site\",\n        \"include\": [\n            \"Site\",\n            \"Building\",\n            \"Floor\",\n            \"Zone\"\n    ]\n    }\n}\n```\n\n### `updateContext`: change the current context \/ graph in memory.\nnote: the previous graph\/context can be returned from memory by using updateContext id: <previous id used in start or updateContext>.\nUp to 5 contexts can be loaded before prevention (error) or deleteContext message needed to free up loaded count to load a new context.\n\nex)\n```json\n{\n    \"type\": \"updateContext\",\n    \"id\": \"building\",\n    \"payload\": {\n        \"ID\": \"ACAF9E07-5031-4BC2-A8C5-D2C6598D83DE\",\n        \"from\": \"Building\",\n        \"include\": [\n            \"Site\",\n            \"Floor\",\n            \"Zone\",\n            \"Image\",\n            \"Surface\",\n            \"Adjacency\",\n            \"System\",\n            \"Quanta\",\n            \"Manufacturer\",\n            \"Equipment\",\n            \"Property\",\n            \"Location\"\n        ]\n    }\n}\n```\n\n### `deleteContext`: delete\/clear the context out of memory.\nex)\n```json\n{\n    \"type\": \"deleteContext\",\n    \"id\": \"building\",\n    \"payload\": {}\n}\n```\n\n### `sync`: create\/update\/delete QuantumObjects via a FlatGraphDiff as the payload.\n\nExecuting concurrent sync's is not allowed. If there is a sync already processing and another sync is requested before the response of the first sync is sent, then the 2nd symc will return an error saying there is a sync currently processing, and to wait until its finished before requesting another sync.\n\nex)\n```json\n{\n    \"type\": \"sync\",\n    \"id\": \"F5B6BC51-B991-440C-8ACB-B55C65FD7C24\",\n    \"payload\": {\n        \"added\": [],\n        \"updated\": [\n            {\n                \"description\": null,\n                \"ID\": \"80187B0B-CEEB-488A-A9B7-06784CFB0464\",\n                \"longitude\": null,\n                \"locationPropertyID\": null,\n                \"elevation\": null,\n                \"latitude\": null,\n                \"address\": null,\n                \"timeZone\": null,\n                \"siteIDs\": [\n                    \"7E7E04B4-8F32-4585-839D-E0EFC7BB3544\"\n                ],\n                \"weatherSourceIDs\": [],\n                \"locked\": false,\n                \"authGroupID\": \"A1EBEC59-D887-473F-A5C5-7CBD4ADB2556\",\n                \"__typename\": \"Location\",\n                \"name\": \"foo\"\n            }\n        ],\n        \"removed\": []\n    }\n}\n```\n\n### `syncEphemeral`: create\/update\/delete QuantumObjects via a FlatGraphDiff as the payload, do not write them to the database,\nand discard them at the end of the websocket session.\nex)\n```json\n{\n    \"type\": \"syncEphemeral\",\n    \"id\": \"F5B6BC51-B991-440C-8ACB-B55C65FD7C24\",\n    \"payload\": {\n        \"added\": [],\n        \"updated\": [\n            {\n                \"description\": null,\n                \"ID\": \"80187B0B-CEEB-488A-A9B7-06784CFB0464\",\n                \"longitude\": null,\n                \"locationPropertyID\": null,\n                \"elevation\": null,\n                \"latitude\": null,\n                \"address\": null,\n                \"timeZone\": null,\n                \"siteIDs\": [\n                    \"7E7E04B4-8F32-4585-839D-E0EFC7BB3544\"\n                ],\n                \"weatherSourceIDs\": [],\n                \"locked\": false,\n                \"authGroupID\": \"A1EBEC59-D887-473F-A5C5-7CBD4ADB2556\",\n                \"__typename\": \"Location\",\n                \"name\": \"foo\"\n            }\n        ],\n        \"removed\": []\n    }\n}\n```\n\n### `propertyHistory`: Get history data for a property & listen for updates.\nex)\n```json\n{\n    \"type\": \"propertyHistory\",\n    \"id\": \"propertyHistory1\",\n    \"payload\": {\n        \"propertyIDs\": [\"E585C3B8-F1E5-40D0-83A7-658B248DF103\"],\n        \"startAt\": \"2024-01-01T00:00:00Z\",\n        \"endAt\": \"2024-01-01T01:00:00Z\",\n        \"resample\": {\n            \"interval\": {\n                \"to\": \"minutely\",\n                \"reduceUsing\": \"avg\",\n                \"fillUsing\": \"interpolate\"\n        },\n        \"pollIntervalSec\": 60\n    }\n}\n\n### `propertyHistoryStop`: Stop listening for property history updates\nex)\n```json\n{\n    \"type\": \"propertyHistoryStop\",\n    \"id\": \"propertyHistory1\"\n}\n```\n\n### `writeHistory`: Write historical data to a property\nex)\n```json\n{\n    \"type\": \"writeHistory\",\n    \"id\": \"writeHistory\",\n    \"payload\": {\n        \"histories\": [\n            {\n                \"propertyID\": \"E585C3B8-F1E5-40D0-83A7-658B248DF103\",\n                \"time\": \"2024-01-01T00:00:00Z\",\n                \"value\": 5.0\n            }\n        ]\n    }\n}\n```","tags":["Quantum Sync"]}},"\/app\/**":{"get":{"tags":["app"],"description":"GET \/app\/**"}},"\/api\/v0.19\/account\/credentials":{"get":{"tags":["Account"],"summary":"Retrieves a list of the credentials the current user has enabled.","security":[{"Basic Auth - login":[]},{"XSRF header":[]},{"DEPRECATED - PL API Key":[]},{"PL API Key":[]}],"description":"Retrieves the list of credentials enabled for the current user as reported by Keycloak. Credential types include password,\nTOPT, and passkeys. Note that `createdDate` will be sent as an ISO 8601 formatted string (e.g. 2025-10-10T16:32:11Z). Also note\nthat this API must be called with a properly authenticated JWT.","operationId":"getApiV0.19AccountCredentials","responses":{"200":{"content":{"application\/json":{"schema":{"items":{"$ref":"#\/components\/schemas\/KeycloakCredentialInfo"},"type":"array"}}},"description":"OK"}}}},"\/api\/v0.20\/auth\/register\/initiate":{"post":{"responses":{"200":{"description":"OK","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/GenericMessageResponse"},"examples":{"GenericMessageResponse":{"$ref":"#\/components\/examples\/GenericMessageResponse"}}}}}},"operationId":"postApiV0.20AuthRegisterInitiate","description":"DEPRECATED: This endpoint is not available when Keycloak authentication is turned on and will be removed in the future.\n\nInitiates the PassiveLogic registration process by sending an email to the given user. A user is not stored in the system\nat this point in the process - instead this serves as the initial step proving that a uer has access to the email they\nare signing up with.\n\nEmail will contain a link that holds a signed JWT from us. That JWT is later used to validate and complete registration.\n\nNo authentication required.","deprecated":true,"summary":"Sends an email to begin email verification and registration.","requestBody":{"content":{"application\/json":{"examples":{"UserRegistrationInitiation":{"$ref":"#\/components\/examples\/UserRegistrationInitiation"}},"schema":{"$ref":"#\/components\/schemas\/UserRegistrationInitiation"}}},"required":true},"tags":["Authentication"]}},"\/api\/auth\/login":{"get":{"security":[{"Basic Auth - login":[]},{"XSRF header":[]},{"DEPRECATED - PL API Key":[]},{"PL API Key":[]}],"responses":{"200":{"content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/LoginResponse"},"examples":{"LoginResponse":{"$ref":"#\/components\/examples\/LoginResponse"}}}},"description":"OK"}},"description":"DEPRECATED: This endpoint is not available when Keycloak authentication is turned on and will be removed in the future.\n\nLogs in a user. If multi-factor authentication is enabled, returns a multi-factor token that can be used to\nsend a multi-factor code to the user. Otherwise, sets auth & refresh tokens as cookies and returns a whoami for the\nlogged in user.\n\nBasic authentication required.","deprecated":true,"operationId":"getApiAuthLogin","summary":"Logs in a user","tags":["Authentication"]}},"\/api\/v0.20\/device\/login":{"get":{"description":"Logs in a PassiveLogic device, responding with the authentication token.\n\nmTLS authentication required.","responses":{"200":{"content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/DeviceLoginResponse"},"examples":{"DeviceLoginResponse":{"$ref":"#\/components\/examples\/DeviceLoginResponse"}}}},"description":"OK"}},"tags":["PassiveLogic Device"],"summary":"Logs in a PassiveLogic device","security":[{"Basic Auth - login":[]},{"XSRF header":[]},{"DEPRECATED - PL API Key":[]},{"PL API Key":[]}],"operationId":"getApiV0.20DeviceLogin"}},"\/app\/bs\/**":{"get":{"tags":["app"],"description":"GET \/app\/bs\/**"}},"\/api\/v0.20\/organization\/decline":{"post":{"security":[{"Basic Auth - login":[]},{"XSRF header":[]},{"DEPRECATED - PL API Key":[]},{"PL API Key":[]}],"responses":{"200":{"content":{"application\/json":{"examples":{"GenericMessageResponse":{"$ref":"#\/components\/examples\/GenericMessageResponse"}},"schema":{"$ref":"#\/components\/schemas\/GenericMessageResponse"}}},"description":"OK"}},"description":"Rejects an invitation based on Organization invite ID.\nInvitation is deleted.","operationId":"postApiV0.20OrganizationDecline","summary":"Declines an organization invitation","requestBody":{"content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/DeclineOrganizationInvite"},"examples":{"DeclineOrganizationInvite":{"$ref":"#\/components\/examples\/DeclineOrganizationInvite"}}}},"required":true},"tags":["Organization"]}},"\/api\/v0.20\/authgroup\/remove\/{authGroupID}\/{userID}":{"post":{"security":[{"Basic Auth - login":[]},{"XSRF header":[]},{"DEPRECATED - PL API Key":[]},{"PL API Key":[]}],"responses":{"200":{"description":"OK","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/AuthGroupRemovalResponse"},"examples":{"AuthGroupRemovalResponse":{"$ref":"#\/components\/examples\/AuthGroupRemovalResponse"}}}}}},"operationId":"postApiV0.20AuthgroupRemoveByAuthGroupIDByUserID","description":"Remove a User from an AuthGroup. Users must have PrivilegedUser or greater permissions to remove another user.\nUser can only remove other users with permissions less than or equal to their own permissions. For example: PrivilegedUsers\ncannot remove SuperUsers.","summary":"Removes user from Auth Group","tags":["Auth Groups"],"parameters":[{"required":true,"in":"path","schema":{"type":"string"},"name":"authGroupID"},{"required":true,"in":"path","schema":{"type":"string"},"name":"userID"}]}},"\/app\/devtools\/*":{"get":{"tags":["app"],"description":"GET \/app\/devtools\/*"}},"\/api\/v0.19\/auth\/register\/initiate":{"post":{"responses":{"200":{"description":"OK","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/GenericMessageResponse"},"examples":{"GenericMessageResponse":{"$ref":"#\/components\/examples\/GenericMessageResponse"}}}}}},"operationId":"postApiV0.19AuthRegisterInitiate","description":"DEPRECATED: This endpoint is not available when Keycloak authentication is turned on and will be removed in the future.\n\nInitiates the PassiveLogic registration process by sending an email to the given user. A user is not stored in the system\nat this point in the process - instead this serves as the initial step proving that a uer has access to the email they\nare signing up with.\n\nEmail will contain a link that holds a signed JWT from us. That JWT is later used to validate and complete registration.\n\nNo authentication required.","deprecated":true,"summary":"Sends an email to begin email verification and registration.","requestBody":{"required":true,"content":{"application\/json":{"examples":{"UserRegistrationInitiation":{"$ref":"#\/components\/examples\/UserRegistrationInitiation"}},"schema":{"$ref":"#\/components\/schemas\/UserRegistrationInitiation"}}}},"tags":["Authentication"]}},"\/api\/auth\/magic-link-generate":{"post":{"security":[{"Basic Auth - login":[]},{"XSRF header":[]},{"DEPRECATED - PL API Key":[]},{"PL API Key":[]}],"responses":{"200":{"description":"OK","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/MagicLinkResponse"}}}}},"operationId":"postApiAuthMagic-link-generate","description":"DEPRECATED: This endpoint is not available when Keycloak authentication is turned on and will be removed in the future.\n\nGenerates magic link containing `?token=<signed JWT with user email contained>` and sends it in an email to the user.\nThis is the secure mode and MUST be used in production.\nThis will not return a link to the client.\n\nIf User does not exist in Database, will throw 400 bad request. If user exists, will return 200 ok.\nThese links can then be used to login from GET magic-link-login.","deprecated":true,"summary":"Generates a Magic Link to be used to login.","requestBody":{"required":true,"content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/UserRegistrationInitiation"},"examples":{"UserRegistrationInitiation":{"$ref":"#\/components\/examples\/UserRegistrationInitiation"}}}}},"tags":["Authentication"]}},"\/api\/v0.19\/util\/version":{"get":{"deprecated":true,"operationId":"getApiV0.19UtilVersion","summary":"Returns version information","description":"Returns commit hashes & build times for the running build of the webserver and all apps.","responses":{"200":{"description":"OK","content":{"text\/plain":{"schema":{"type":"string"},"examples":{"String":{"$ref":"#\/components\/examples\/String"}}}}}},"tags":["Utility"]}},"\/api\/v0.20\/tunnel\/{serialNumber}\/**":{"put":{"description":"PUT \/tunnel\/:serialNumber\/**","security":[{"Basic Auth - login":[]},{"XSRF header":[]},{"DEPRECATED - PL API Key":[]},{"PL API Key":[]}],"tags":["tunnel"]},"delete":{"description":"DELETE \/tunnel\/:serialNumber\/**","security":[{"Basic Auth - login":[]},{"XSRF header":[]},{"DEPRECATED - PL API Key":[]},{"PL API Key":[]}],"tags":["tunnel"]},"get":{"description":"GET \/tunnel\/:serialNumber\/**","security":[{"Basic Auth - login":[]},{"XSRF header":[]},{"DEPRECATED - PL API Key":[]},{"PL API Key":[]}],"tags":["tunnel"]},"post":{"description":"POST \/tunnel\/:serialNumber\/**","security":[{"Basic Auth - login":[]},{"XSRF header":[]},{"DEPRECATED - PL API Key":[]},{"PL API Key":[]}],"tags":["tunnel"]}},"\/api\/v0.19\/util\/quantumversion":{"get":{"responses":{"200":{"description":"OK","content":{"text\/plain":{"schema":{"type":"string"},"examples":{"String":{"$ref":"#\/components\/examples\/String"}}}}}},"tags":["Utility"],"summary":"Returns the Quantum Schema version","operationId":"getApiV0.19UtilQuantumversion","description":"Returns the current version of the Quantum schema in use by this webserver as a semantic version."}},"\/api\/v0.20\/image":{"post":{"security":[{"Basic Auth - login":[]},{"XSRF header":[]},{"DEPRECATED - PL API Key":[]},{"PL API Key":[]}],"responses":{"200":{"description":"OK","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ImageUploadResponse"},"examples":{"ImageUploadResponse":{"$ref":"#\/components\/examples\/ImageUploadResponse"}}}}}},"description":"Uploads an image to the server, setting its new stored url & checksum in the database. If an existing ID is given, this will\nattempt an update of the image data. The data may be sent in either multipart\/form-data or JSON format. If using JSON, the\nimage file must be Base64-encoded. Using multipart\/form-data is recommended as it is a more efficient way to transmit binary\ndata.\n\nThis endpoint is intended for associating image file data with an existing `Image` node in the Quantum schema.","operationId":"postApiV0.20Image","summary":"Uploads an image.","requestBody":{"content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/UploadImageData"},"examples":{"UploadImageData":{"$ref":"#\/components\/examples\/UploadImageData"}}},"multipart\/form-data":{"schema":{"$ref":"#\/components\/schemas\/UploadImageData"},"examples":{"UploadImageData":{"$ref":"#\/components\/examples\/UploadImageData"}}}},"required":true},"tags":["Images"]}},"\/api\/auth\/api-key\/remove":{"delete":{"security":[{"Basic Auth - login":[]},{"XSRF header":[]},{"DEPRECATED - PL API Key":[]},{"PL API Key":[]}],"responses":{"200":{"description":"OK","content":{"application\/json":{"examples":{"GenerateApiKeyResponse":{"$ref":"#\/components\/examples\/GenerateApiKeyResponse"}},"schema":{"$ref":"#\/components\/schemas\/GenerateApiKeyResponse"}}}}},"description":"Validates that the given token is linked to the currently authenticated user and removes it if so.","operationId":"deleteApiAuthApi-keyRemove","deprecated":true,"summary":"Removes a given API key for the user. This route has been deprecated in favor of: DELETE \/api\/auth\/api-key.","requestBody":{"required":true,"content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/RemoveApiKeyRequest"},"examples":{"RemoveApiKeyRequest":{"$ref":"#\/components\/examples\/RemoveApiKeyRequest"}}}}},"tags":["Authentication"]},"post":{"security":[{"Basic Auth - login":[]},{"XSRF header":[]},{"DEPRECATED - PL API Key":[]},{"PL API Key":[]}],"responses":{"200":{"content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/GenerateApiKeyResponse"},"examples":{"GenerateApiKeyResponse":{"$ref":"#\/components\/examples\/GenerateApiKeyResponse"}}}},"description":"OK"}},"description":"Validates that the given token is linked to the currently authenticated user and removes it if so.","operationId":"postApiAuthApi-keyRemove","deprecated":true,"summary":"Removes a given API key for the user. This route has been deprecated in favor of: DELETE \/api\/auth\/api-key.","requestBody":{"content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/RemoveApiKeyRequest"},"examples":{"RemoveApiKeyRequest":{"$ref":"#\/components\/examples\/RemoveApiKeyRequest"}}}},"required":true},"tags":["Authentication"]}},"\/api\/v0.20\/health\/liveness":{"get":{"summary":"Liveness check used to determine when webserver should be restarted","description":"See https:\/\/kubernetes.io\/docs\/concepts\/configuration\/liveness-readiness-startup-probes\/#liveness-probe","tags":["Health"],"operationId":"getApiV0.20HealthLiveness","security":[{"Basic Auth - login":[]},{"XSRF header":[]},{"DEPRECATED - PL API Key":[]},{"PL API Key":[]}]}},"\/app\/az\/**":{"get":{"description":"GET \/app\/az\/**","tags":["app"]}},"\/api\/v0.20\/datasync":{"get":{"tags":["Quantum Sync"],"deprecated":true,"security":[{"Basic Auth - login":[]},{"XSRF header":[]},{"DEPRECATED - PL API Key":[]},{"PL API Key":[]}],"description":"Refer to the \/api\/v0.20\/quantumsync route documentation for full details. This route will be removed in the next major version.","summary":"QuantumSync API Legacy Route. Use \/api\/v0.20\/quantumsync instead.","operationId":"getApiV0.20Datasync"}},"\/api\/quantumsync":{"get":{"tags":["Quantum Sync"],"description":"# Custom QuantumSync\/ShadowClient API:\n\n## QuantumSync QuantumSyncRequestTypes:\n### `start`: authenticates and specifies an initial context. note: the id for start and updateContext is used to key a Dictionary[String:AnyRootedQuantumGraph]\nex)\n```json\n{\n    \"type\": \"start\",\n    \"id\": \"site\",\n    \"appType\":\"BuildingStudio\"\n    \"payload\": {\n        \"authToken\": \"REDACTED\",\n        \"ID\": \"ACAF9E07-5031-4BC2-A8C5-D2C6598D83DE\",\n        \"from\": \"Site\",\n        \"include\": [\n            \"Site\",\n            \"Building\",\n            \"Floor\",\n            \"Zone\"\n    ]\n    }\n}\n```\n\n### `updateContext`: change the current context \/ graph in memory.\nnote: the previous graph\/context can be returned from memory by using updateContext id: <previous id used in start or updateContext>.\nUp to 5 contexts can be loaded before prevention (error) or deleteContext message needed to free up loaded count to load a new context.\n\nex)\n```json\n{\n    \"type\": \"updateContext\",\n    \"id\": \"building\",\n    \"payload\": {\n        \"ID\": \"ACAF9E07-5031-4BC2-A8C5-D2C6598D83DE\",\n        \"from\": \"Building\",\n        \"include\": [\n            \"Site\",\n            \"Floor\",\n            \"Zone\",\n            \"Image\",\n            \"Surface\",\n            \"Adjacency\",\n            \"System\",\n            \"Quanta\",\n            \"Manufacturer\",\n            \"Equipment\",\n            \"Property\",\n            \"Location\"\n        ]\n    }\n}\n```\n\n### `deleteContext`: delete\/clear the context out of memory.\nex)\n```json\n{\n    \"type\": \"deleteContext\",\n    \"id\": \"building\",\n    \"payload\": {}\n}\n```\n\n### `sync`: create\/update\/delete QuantumObjects via a FlatGraphDiff as the payload.\n\nExecuting concurrent sync's is not allowed. If there is a sync already processing and another sync is requested before the response of the first sync is sent, then the 2nd symc will return an error saying there is a sync currently processing, and to wait until its finished before requesting another sync.\n\nex)\n```json\n{\n    \"type\": \"sync\",\n    \"id\": \"F5B6BC51-B991-440C-8ACB-B55C65FD7C24\",\n    \"payload\": {\n        \"added\": [],\n        \"updated\": [\n            {\n                \"description\": null,\n                \"ID\": \"80187B0B-CEEB-488A-A9B7-06784CFB0464\",\n                \"longitude\": null,\n                \"locationPropertyID\": null,\n                \"elevation\": null,\n                \"latitude\": null,\n                \"address\": null,\n                \"timeZone\": null,\n                \"siteIDs\": [\n                    \"7E7E04B4-8F32-4585-839D-E0EFC7BB3544\"\n                ],\n                \"weatherSourceIDs\": [],\n                \"locked\": false,\n                \"authGroupID\": \"A1EBEC59-D887-473F-A5C5-7CBD4ADB2556\",\n                \"__typename\": \"Location\",\n                \"name\": \"foo\"\n            }\n        ],\n        \"removed\": []\n    }\n}\n```\n\n### `syncEphemeral`: create\/update\/delete QuantumObjects via a FlatGraphDiff as the payload, do not write them to the database,\nand discard them at the end of the websocket session.\nex)\n```json\n{\n    \"type\": \"syncEphemeral\",\n    \"id\": \"F5B6BC51-B991-440C-8ACB-B55C65FD7C24\",\n    \"payload\": {\n        \"added\": [],\n        \"updated\": [\n            {\n                \"description\": null,\n                \"ID\": \"80187B0B-CEEB-488A-A9B7-06784CFB0464\",\n                \"longitude\": null,\n                \"locationPropertyID\": null,\n                \"elevation\": null,\n                \"latitude\": null,\n                \"address\": null,\n                \"timeZone\": null,\n                \"siteIDs\": [\n                    \"7E7E04B4-8F32-4585-839D-E0EFC7BB3544\"\n                ],\n                \"weatherSourceIDs\": [],\n                \"locked\": false,\n                \"authGroupID\": \"A1EBEC59-D887-473F-A5C5-7CBD4ADB2556\",\n                \"__typename\": \"Location\",\n                \"name\": \"foo\"\n            }\n        ],\n        \"removed\": []\n    }\n}\n```\n\n### `propertyHistory`: Get history data for a property & listen for updates.\nex)\n```json\n{\n    \"type\": \"propertyHistory\",\n    \"id\": \"propertyHistory1\",\n    \"payload\": {\n        \"propertyIDs\": [\"E585C3B8-F1E5-40D0-83A7-658B248DF103\"],\n        \"startAt\": \"2024-01-01T00:00:00Z\",\n        \"endAt\": \"2024-01-01T01:00:00Z\",\n        \"resample\": {\n            \"interval\": {\n                \"to\": \"minutely\",\n                \"reduceUsing\": \"avg\",\n                \"fillUsing\": \"interpolate\"\n        },\n        \"pollIntervalSec\": 60\n    }\n}\n\n### `propertyHistoryStop`: Stop listening for property history updates\nex)\n```json\n{\n    \"type\": \"propertyHistoryStop\",\n    \"id\": \"propertyHistory1\"\n}\n```\n\n### `writeHistory`: Write historical data to a property\nex)\n```json\n{\n    \"type\": \"writeHistory\",\n    \"id\": \"writeHistory\",\n    \"payload\": {\n        \"histories\": [\n            {\n                \"propertyID\": \"E585C3B8-F1E5-40D0-83A7-658B248DF103\",\n                \"time\": \"2024-01-01T00:00:00Z\",\n                \"value\": 5.0\n            }\n        ]\n    }\n}\n```","summary":"QuantumSync API over websockets","operationId":"getApiQuantumsync","security":[{"Basic Auth - login":[]},{"XSRF header":[]},{"DEPRECATED - PL API Key":[]},{"PL API Key":[]}]}},"\/api\/organization\/decline":{"post":{"security":[{"Basic Auth - login":[]},{"XSRF header":[]},{"DEPRECATED - PL API Key":[]},{"PL API Key":[]}],"responses":{"200":{"description":"OK","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/GenericMessageResponse"},"examples":{"GenericMessageResponse":{"$ref":"#\/components\/examples\/GenericMessageResponse"}}}}}},"operationId":"postApiOrganizationDecline","description":"Rejects an invitation based on Organization invite ID.\nInvitation is deleted.","summary":"Declines an organization invitation","requestBody":{"required":true,"content":{"application\/json":{"examples":{"DeclineOrganizationInvite":{"$ref":"#\/components\/examples\/DeclineOrganizationInvite"}},"schema":{"$ref":"#\/components\/schemas\/DeclineOrganizationInvite"}}}},"tags":["Organization"]}},"\/api\/account\/eula\/accept":{"post":{"security":[{"Basic Auth - login":[]},{"XSRF header":[]},{"DEPRECATED - PL API Key":[]},{"PL API Key":[]}],"responses":{"200":{"description":"OK","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/GenericMessageResponse"},"examples":{"GenericMessageResponse":{"$ref":"#\/components\/examples\/GenericMessageResponse"}}}}}},"operationId":"postApiAccountEulaAccept","description":"DEPRECATED: This endpoint is not available when Keycloak authentication is turned on and will be removed in the future.\nDenotes that the current user has accepted the EULA.\nReturns updated access and refresh tokens.","deprecated":true,"summary":"Accepts EULA for the current user","tags":["Account"]}},"\/api\/v0.20\/util\/quantumlens":{"post":{"summary":"QuantumLens (iOS) update & compatibility check","operationId":"postApiV0.20UtilQuantumlens","tags":["Utility"],"responses":{"200":{"description":"OK","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/QuantumLensResponse"}}}}},"security":[{"Basic Auth - login":[]},{"XSRF header":[]},{"DEPRECATED - PL API Key":[]},{"PL API Key":[]}],"description":"Returns the status of the QuantumLens application for the current user.\n\n- `appUpdate`: indicates if a new app version is required (true = forced, false = soft, nil = no update)\n- `osUpdate`: indicates if an iOS update is required (true = update required, nil = compatible)\n- `user`: information about the current user\n\nThis response helps the client determine whether the app or iOS requires an update before continuing."}},"\/api\/v0.19\/auth\/logout":{"post":{"tags":["Authentication"],"summary":"Logs out a user","description":"If external auth (Keycloak) is enabled, this initiates the external logout process.\n\nOtherwise, if a cookie keyed by pl-refresh-token is provided in the logout request, that refresh token is revoked.\n\nThe response sets the auth & refresh cookies to empty values & marks them as expired.\nNew tokens must then be generated by the login endpoint.","operationId":"postApiV0.19AuthLogout","security":[{"Basic Auth - login":[]},{"XSRF header":[]},{"DEPRECATED - PL API Key":[]},{"PL API Key":[]}],"responses":{"200":{"content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/GenericMessageResponse"},"examples":{"GenericMessageResponse":{"$ref":"#\/components\/examples\/GenericMessageResponse"}}}},"description":"OK"}}}},"\/api\/auth\/whoami":{"get":{"description":"Useful to check if a user is authenticated.","security":[{"Basic Auth - login":[]},{"XSRF header":[]},{"DEPRECATED - PL API Key":[]},{"PL API Key":[]}],"operationId":"getApiAuthWhoami","responses":{"200":{"content":{"application\/json":{"examples":{"WhoAmIResponse":{"$ref":"#\/components\/examples\/WhoAmIResponse"}},"schema":{"$ref":"#\/components\/schemas\/WhoAmIResponse"}}},"description":"OK"}},"tags":["Authentication"],"summary":"Returns information about the currently logged in user."}},"\/api\/v0.19\/datasync":{"get":{"operationId":"getApiV0.19Datasync","deprecated":true,"security":[{"Basic Auth - login":[]},{"XSRF header":[]},{"DEPRECATED - PL API Key":[]},{"PL API Key":[]}],"description":"Refer to the \/api\/v0.19\/quantumsync route documentation for full details. This route will be removed in the next major version.","tags":["Quantum Sync"],"summary":"QuantumSync API Legacy Route. Use \/api\/v0.19\/quantumsync instead."}},"\/api\/util\/quantumlens":{"post":{"tags":["Utility"],"operationId":"postApiUtilQuantumlens","security":[{"Basic Auth - login":[]},{"XSRF header":[]},{"DEPRECATED - PL API Key":[]},{"PL API Key":[]}],"summary":"QuantumLens (iOS) update & compatibility check","description":"Returns the status of the QuantumLens application for the current user.\n\n- `appUpdate`: indicates if a new app version is required (true = forced, false = soft, nil = no update)\n- `osUpdate`: indicates if an iOS update is required (true = update required, nil = compatible)\n- `user`: information about the current user\n\nThis response helps the client determine whether the app or iOS requires an update before continuing.","responses":{"200":{"content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/QuantumLensResponse"}}},"description":"OK"}}}},"\/api\/v0.20\/util\/version":{"get":{"summary":"Returns version information","operationId":"getApiV0.20UtilVersion","description":"Returns commit hashes & build times for the running build of the webserver and all apps.","tags":["Utility"],"responses":{"200":{"description":"OK","content":{"text\/plain":{"schema":{"type":"string"},"examples":{"String":{"$ref":"#\/components\/examples\/String"}}}}}},"deprecated":true}},"\/api\/v0.20\/authgroup\/join":{"get":{"security":[{"Basic Auth - login":[]},{"XSRF header":[]},{"DEPRECATED - PL API Key":[]},{"PL API Key":[]}],"responses":{"200":{"content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/GenericMessageResponse"},"examples":{"GenericMessageResponse":{"$ref":"#\/components\/examples\/GenericMessageResponse"}}}},"description":"OK"}},"operationId":"getApiV0.20AuthgroupJoin","description":"DEPRECATED: GET \/api\/authgroup\/join was used to accept a project (auth group) invitation by clicking directly in an email.\nAccepting invitations is now handled by the \/app\/login\/post-auth route provided by the front end, which calls POST\n\/api\/authgroup\/join. This can be removed when any invitations linked to in this way have expired.","summary":"Accepts an AuthGroup Invitation","requestBody":{"required":true,"content":{"application\/json":{"examples":{"AcceptOrganizationInvite":{"$ref":"#\/components\/examples\/AcceptOrganizationInvite"}},"schema":{"$ref":"#\/components\/schemas\/AcceptOrganizationInvite"}}}},"tags":["Auth Groups"]},"post":{"security":[{"Basic Auth - login":[]},{"XSRF header":[]},{"DEPRECATED - PL API Key":[]},{"PL API Key":[]}],"responses":{"200":{"description":"OK","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/GenericMessageResponse"},"examples":{"GenericMessageResponse":{"$ref":"#\/components\/examples\/GenericMessageResponse"}}}}}},"operationId":"postApiV0.20AuthgroupJoin","description":"Used by the front end `\/app\/login\/post-auth` route to accept project (auth group) invitations. The role the user receives in the\nreferenced AuthGroup is determined through AuthGroup invite role; if no role is defined, we default to read-only user.","deprecated":true,"summary":"Accepts an AuthGroup Invitation","requestBody":{"required":true,"content":{"application\/json":{"examples":{"AcceptOrganizationInvite":{"$ref":"#\/components\/examples\/AcceptOrganizationInvite"}},"schema":{"$ref":"#\/components\/schemas\/AcceptOrganizationInvite"}}}},"tags":["Auth Groups"]}},"\/api\/v0.19\/auth\/login":{"get":{"security":[{"Basic Auth - login":[]},{"XSRF header":[]},{"DEPRECATED - PL API Key":[]},{"PL API Key":[]}],"responses":{"200":{"description":"OK","content":{"application\/json":{"examples":{"LoginResponse":{"$ref":"#\/components\/examples\/LoginResponse"}},"schema":{"$ref":"#\/components\/schemas\/LoginResponse"}}}}},"operationId":"getApiV0.19AuthLogin","description":"DEPRECATED: This endpoint is not available when Keycloak authentication is turned on and will be removed in the future.\n\nLogs in a user. If multi-factor authentication is enabled, returns a multi-factor token that can be used to\nsend a multi-factor code to the user. Otherwise, sets auth & refresh tokens as cookies and returns a whoami for the\nlogged in user.\n\nBasic authentication required.","deprecated":true,"summary":"Logs in a user","tags":["Authentication"]}},"\/api\/health\/liveness":{"get":{"tags":["Health"],"summary":"Liveness check used to determine when webserver should be restarted","description":"See https:\/\/kubernetes.io\/docs\/concepts\/configuration\/liveness-readiness-startup-probes\/#liveness-probe","security":[{"Basic Auth - login":[]},{"XSRF header":[]},{"DEPRECATED - PL API Key":[]},{"PL API Key":[]}],"operationId":"getApiHealthLiveness"}},"\/api\/v0.20\/auth\/whoami":{"get":{"operationId":"getApiV0.20AuthWhoami","summary":"Returns information about the currently logged in user.","tags":["Authentication"],"responses":{"200":{"description":"OK","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/WhoAmIResponse"},"examples":{"WhoAmIResponse":{"$ref":"#\/components\/examples\/WhoAmIResponse"}}}}}},"security":[{"Basic Auth - login":[]},{"XSRF header":[]},{"DEPRECATED - PL API Key":[]},{"PL API Key":[]}],"description":"Useful to check if a user is authenticated."}},"\/api\/util\/pl-hardware-info":{"get":{"operationId":"getApiUtilPl-hardware-info","description":"Returns a JSON object where the field 'runningOnHive' will be true if, on the server, the PL_HIVE_REVISION environment variable\nis set to a number greater than or equal to zero.","responses":{"200":{"content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/DeployedOnHiveResponse"}}},"description":"OK"}},"tags":["Utility"],"summary":"Indicates to clients whether or not they are hives serving a webserver."}},"\/api\/v0.20\/util\/ping":{"get":{"tags":["Utility"],"summary":"Keep-alive ping\/pong route","description":"Use to check webserver health or keep connection alive. Returns pong message.","operationId":"getApiV0.20UtilPing","responses":{"200":{"description":"OK","content":{"text\/plain":{"schema":{"type":"string"},"examples":{"String":{"$ref":"#\/components\/examples\/String"}}}}}}}},"\/app\/login\/password":{"get":{"summary":"Redirects to external authentication provider (Keycloak).","description":"","operationId":"getAppLoginPassword","tags":["app"]}},"\/api\/v0.19\/organization\/invite":{"post":{"security":[{"Basic Auth - login":[]},{"XSRF header":[]},{"DEPRECATED - PL API Key":[]},{"PL API Key":[]}],"responses":{"200":{"description":"OK","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/OrgInviteResponse"},"examples":{"OrgInviteResponse":{"$ref":"#\/components\/examples\/OrgInviteResponse"}}}}}},"description":"Generates and sends an invitation link for the given organization to the given user email.","operationId":"postApiV0.19OrganizationInvite","summary":"Sends an organization invite to the given email.","requestBody":{"required":true,"content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/InviteUserToOrganizationData"},"examples":{"InviteUserToOrganizationData":{"$ref":"#\/components\/examples\/InviteUserToOrganizationData"}}}}},"tags":["Organization"]}},"\/api\/auth\/password\/change":{"get":{"tags":["Authentication"],"summary":"Redirects the user to the change password flow in the external auth provider (Keycloak).","description":"","security":[{"Basic Auth - login":[]},{"XSRF header":[]},{"DEPRECATED - PL API Key":[]},{"PL API Key":[]}],"operationId":"getApiAuthPasswordChange"},"post":{"security":[{"Basic Auth - login":[]},{"XSRF header":[]},{"DEPRECATED - PL API Key":[]},{"PL API Key":[]}],"responses":{"200":{"content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/GenericMessageResponse"},"examples":{"GenericMessageResponse":{"$ref":"#\/components\/examples\/GenericMessageResponse"}}}},"description":"OK"}},"description":"DEPRECATED: This endpoint is not available when Keycloak authentication is turned on and will be removed in the future.\n\nChanges an authenticated user's password to the specified value.","operationId":"postApiAuthPasswordChange","deprecated":true,"summary":"Changes a user's password for an already authenticated user.","requestBody":{"content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ChangeUserPassword"},"examples":{"ChangeUserPassword":{"$ref":"#\/components\/examples\/ChangeUserPassword"}}}},"required":true},"tags":["Authentication"]}},"\/app\/login":{"get":{"description":"","operationId":"getAppLogin","tags":["app"],"summary":"Redirects to external authentication provider (Keycloak)."}},"\/api\/v0.20\/graphqlSubscribe":{"get":{"operationId":"getApiV0.20GraphqlSubscribe","description":"Serves the GraphQL API over websockets to support streaming results like subscriptions.\n\nThe following sub-protocols are supported:\n- [graphql-transport-ws](https:\/\/github.com\/enisdenjo\/graphql-ws\/blob\/master\/PROTOCOL.md)\n- [graphql-ws](https:\/\/github.com\/apollographql\/subscriptions-transport-ws\/blob\/master\/PROTOCOL.md)","tags":["GraphQL"],"security":[{"Basic Auth - login":[]},{"XSRF header":[]},{"DEPRECATED - PL API Key":[]},{"PL API Key":[]}],"summary":"GraphQL API over websocket."}},"\/api\/v0.20\/binding":{"post":{"security":[{"Basic Auth - login":[]},{"XSRF header":[]},{"DEPRECATED - PL API Key":[]},{"PL API Key":[]}],"responses":{"200":{"description":"OK","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/BindingUploadResponse"},"examples":{"BindingUploadResponse":{"$ref":"#\/components\/examples\/BindingUploadResponse"}}}}}},"description":"Uploads a file to the server and associates that file with a binding node, setting its new stored URL & checksum in the\ndatabase. The data may be sent in either multipart\/form-data or JSON format. If using JSON, the image file must be\nBase64-encoded. Using multipart\/form-data is recommended as it is a more efficient way to transmit binary data.","operationId":"postApiV0.20Binding","summary":"Uploads a file associated with a binding.","requestBody":{"required":true,"content":{"multipart\/form-data":{"schema":{"$ref":"#\/components\/schemas\/UploadFileData"},"examples":{"UploadFileData":{"$ref":"#\/components\/examples\/UploadFileData"}}},"application\/json":{"schema":{"$ref":"#\/components\/schemas\/UploadFileData"},"examples":{"UploadFileData":{"$ref":"#\/components\/examples\/UploadFileData"}}}}},"tags":["Bindings"]}},"\/api\/v0.19\/util\/pl-hardware-info":{"get":{"summary":"Indicates to clients whether or not they are hives serving a webserver.","tags":["Utility"],"description":"Returns a JSON object where the field 'runningOnHive' will be true if, on the server, the PL_HIVE_REVISION environment variable\nis set to a number greater than or equal to zero.","operationId":"getApiV0.19UtilPl-hardware-info","responses":{"200":{"content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/DeployedOnHiveResponse"}}},"description":"OK"}}}},"\/api\/v0.20\/health\/readiness":{"get":{"description":"See https:\/\/kubernetes.io\/docs\/concepts\/configuration\/liveness-readiness-startup-probes\/#readiness-probe","tags":["Health"],"summary":"Readiness check used to determine if webserver is ready to accept traffic","operationId":"getApiV0.20HealthReadiness","security":[{"Basic Auth - login":[]},{"XSRF header":[]},{"DEPRECATED - PL API Key":[]},{"PL API Key":[]}]}},"\/api\/tunnel\/{serialNumber}\/**":{"put":{"description":"PUT \/tunnel\/:serialNumber\/**","tags":["tunnel"],"security":[{"Basic Auth - login":[]},{"XSRF header":[]},{"DEPRECATED - PL API Key":[]},{"PL API Key":[]}]},"delete":{"description":"DELETE \/tunnel\/:serialNumber\/**","tags":["tunnel"],"security":[{"Basic Auth - login":[]},{"XSRF header":[]},{"DEPRECATED - PL API Key":[]},{"PL API Key":[]}]},"get":{"description":"GET \/tunnel\/:serialNumber\/**","tags":["tunnel"],"security":[{"Basic Auth - login":[]},{"XSRF header":[]},{"DEPRECATED - PL API Key":[]},{"PL API Key":[]}]},"post":{"description":"POST \/tunnel\/:serialNumber\/**","tags":["tunnel"],"security":[{"Basic Auth - login":[]},{"XSRF header":[]},{"DEPRECATED - PL API Key":[]},{"PL API Key":[]}]}},"\/api\/auth\/offline":{"get":{"tags":["Authentication"],"security":[{"Basic Auth - login":[]},{"XSRF header":[]},{"DEPRECATED - PL API Key":[]},{"PL API Key":[]}],"description":"GET \/auth\/offline"}},"\/api\/graphqlSubscribe":{"get":{"summary":"GraphQL API over websocket.","security":[{"Basic Auth - login":[]},{"XSRF header":[]},{"DEPRECATED - PL API Key":[]},{"PL API Key":[]}],"tags":["GraphQL"],"description":"Serves the GraphQL API over websockets to support streaming results like subscriptions.\n\nThe following sub-protocols are supported:\n- [graphql-transport-ws](https:\/\/github.com\/enisdenjo\/graphql-ws\/blob\/master\/PROTOCOL.md)\n- [graphql-ws](https:\/\/github.com\/apollographql\/subscriptions-transport-ws\/blob\/master\/PROTOCOL.md)","operationId":"getApiGraphqlSubscribe"}},"\/api\/v0.20\/auth\/login":{"get":{"security":[{"Basic Auth - login":[]},{"XSRF header":[]},{"DEPRECATED - PL API Key":[]},{"PL API Key":[]}],"responses":{"200":{"description":"OK","content":{"application\/json":{"examples":{"LoginResponse":{"$ref":"#\/components\/examples\/LoginResponse"}},"schema":{"$ref":"#\/components\/schemas\/LoginResponse"}}}}},"operationId":"getApiV0.20AuthLogin","deprecated":true,"description":"DEPRECATED: This endpoint is not available when Keycloak authentication is turned on and will be removed in the future.\n\nLogs in a user. If multi-factor authentication is enabled, returns a multi-factor token that can be used to\nsend a multi-factor code to the user. Otherwise, sets auth & refresh tokens as cookies and returns a whoami for the\nlogged in user.\n\nBasic authentication required.","summary":"Logs in a user","tags":["Authentication"]}},"\/api\/v0.20\/authgroup\/invite":{"post":{"security":[{"Basic Auth - login":[]},{"XSRF header":[]},{"DEPRECATED - PL API Key":[]},{"PL API Key":[]}],"responses":{"200":{"content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/AuthGroupInviteResponse"},"examples":{"AuthGroupInviteResponse":{"$ref":"#\/components\/examples\/AuthGroupInviteResponse"}}}},"description":"OK"}},"description":"Generates and sends an invitation link for the given Site or View (AuthGroup) to the given user email.","operationId":"postApiV0.20AuthgroupInvite","summary":"Sends an AuthGroup invite to the given email.","requestBody":{"required":true,"content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/InviteUserToAuthGroupData"},"examples":{"InviteUserToAuthGroupData":{"$ref":"#\/components\/examples\/InviteUserToAuthGroupData"}}}}},"tags":["Auth Groups"]}},"\/api\/v0.20\/organization\/invite":{"post":{"security":[{"Basic Auth - login":[]},{"XSRF header":[]},{"DEPRECATED - PL API Key":[]},{"PL API Key":[]}],"responses":{"200":{"content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/OrgInviteResponse"},"examples":{"OrgInviteResponse":{"$ref":"#\/components\/examples\/OrgInviteResponse"}}}},"description":"OK"}},"description":"Generates and sends an invitation link for the given organization to the given user email.","operationId":"postApiV0.20OrganizationInvite","summary":"Sends an organization invite to the given email.","requestBody":{"content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/InviteUserToOrganizationData"},"examples":{"InviteUserToOrganizationData":{"$ref":"#\/components\/examples\/InviteUserToOrganizationData"}}}},"required":true},"tags":["Organization"]}},"\/api\/v0.20\/auth\/verify":{"get":{"operationId":"getApiV0.20AuthVerify","tags":["Authentication"],"parameters":[{"example":"darthvader@galactic-empire.com","description":"User's email to confirm as verified","in":"query","required":true,"name":"email","schema":{"type":"string"}}],"summary":"Redirects user to login","description":"Redirects user to `\/api\/v0.20\/auth\/login`, passing along the provided valid jwt and email.\n\nExists in this form for backward compatibility."}},"\/api\/util\/externalauthconfig":{"get":{"responses":{"200":{"content":{"text\/plain":{"schema":{"type":"string"},"examples":{"String":{"$ref":"#\/components\/examples\/String"}}}},"description":"OK"}},"operationId":"getApiUtilExternalauthconfig","tags":["Utility"],"summary":"Provides information about the external auth configuration","description":"Use to check whether or not external auth (i.e. Keycloak) is enabled, and if so what the public settings are."}},"\/api\/v0.20\/auth\/register":{"post":{"responses":{"200":{"content":{"application\/json":{"examples":{"RegisterUserResponse":{"$ref":"#\/components\/examples\/RegisterUserResponse"}},"schema":{"$ref":"#\/components\/schemas\/RegisterUserResponse"}}},"description":"OK"}},"operationId":"postApiV0.20AuthRegister","description":"DEPRECATED: This endpoint is not available when Keycloak authentication is turned on and will be removed in the future.\n\nCreates a new user based on the provided information. Requires jwt obtained via email from\n`\/api\/v0.20\/auth\/register\/initiate`. The user status is set to `Active` and immediately logged in.\n\n\n\nRegistration token is required when email verification is enforced, as indicated by a failed response to this endpoint","deprecated":true,"summary":"Registers a new user","requestBody":{"content":{"application\/json":{"examples":{"RegisterUserData":{"$ref":"#\/components\/examples\/RegisterUserData"}},"schema":{"$ref":"#\/components\/schemas\/RegisterUserData"}}},"required":true},"tags":["Authentication"]}},"\/api\/v0.19\/auth\/kc\/{user}":{"get":{"security":[{"Basic Auth - login":[]},{"XSRF header":[]},{"DEPRECATED - PL API Key":[]},{"PL API Key":[]}],"responses":{"200":{"description":"OK","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/KeycloakUserInfo"},"examples":{"KeycloakUserInfo":{"$ref":"#\/components\/examples\/KeycloakUserInfo"}}}}}},"operationId":"getApiV0.19AuthKcByUser","description":"Enables migrating users to Keycloak by providing an API endpoint for retrieving user information. This\ninformation is then saved to Keycloak's own database.","summary":"Retrieves user information for Keycloak","parameters":[{"name":"user","schema":{"type":"string"},"in":"path","required":true}],"tags":["Authentication"]},"post":{"security":[{"Basic Auth - login":[]},{"XSRF header":[]},{"DEPRECATED - PL API Key":[]},{"PL API Key":[]}],"responses":{"200":{"description":"OK","content":{"application\/json":{"examples":{"GenericMessageResponse":{"$ref":"#\/components\/examples\/GenericMessageResponse"}},"schema":{"$ref":"#\/components\/schemas\/GenericMessageResponse"}}}}},"operationId":"postApiV0.19AuthKcByUser","description":"Allows the Keycloak migration plugin to validate a user's password. Once validated, the password is saved\nto Keycloak's database and is subsequently no longer validated using this API.","summary":"Validates a user's password","parameters":[{"name":"user","schema":{"type":"string"},"in":"path","required":true}],"tags":["Authentication"]}},"\/api\/util\/ping":{"get":{"responses":{"200":{"content":{"text\/plain":{"schema":{"type":"string"},"examples":{"String":{"$ref":"#\/components\/examples\/String"}}}},"description":"OK"}},"tags":["Utility"],"summary":"Keep-alive ping\/pong route","description":"Use to check webserver health or keep connection alive. Returns pong message.","operationId":"getApiUtilPing"}},"\/api\/v0.19\/account\/user\/delete":{"delete":{"tags":["Account"],"responses":{"200":{"description":"OK","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/GenericMessageResponse"},"examples":{"GenericMessageResponse":{"$ref":"#\/components\/examples\/GenericMessageResponse"}}}}}},"summary":"Deletes the user making this request.","description":"Deletes the requesting user if they are not a SuperUser within any organizations.\nOtherwise prompts them to transfer ownership or delete the org before making this request.","operationId":"deleteApiV0.19AccountUserDelete","security":[{"Basic Auth - login":[]},{"XSRF header":[]},{"DEPRECATED - PL API Key":[]},{"PL API Key":[]}]}},"\/app\/login\/reset":{"get":{"tags":["app"],"description":"","operationId":"getAppLoginReset","summary":"Redirects to external authentication provider (Keycloak)."}},"\/api\/v0.20\/export\/property\/history":{"get":{"description":"Returns a string representation of property history values in CSV format from the given properties.\nreturns in the following headers:\nTime,Equipment name,Property name,Unit,Value\n\nTime returned in ISO8601 string format","summary":"Exports CSV formatted property history data","operationId":"getApiV0.20ExportPropertyHistory","security":[{"Basic Auth - login":[]},{"XSRF header":[]},{"DEPRECATED - PL API Key":[]},{"PL API Key":[]}],"tags":["Export"],"responses":{"200":{"content":{"text\/plain":{"examples":{"String":{"$ref":"#\/components\/examples\/String"}},"schema":{"type":"string"}}},"description":"OK"}}}},"\/api\/account\/credentials":{"get":{"operationId":"getApiAccountCredentials","summary":"Retrieves a list of the credentials the current user has enabled.","description":"Retrieves the list of credentials enabled for the current user as reported by Keycloak. Credential types include password,\nTOPT, and passkeys. Note that `createdDate` will be sent as an ISO 8601 formatted string (e.g. 2025-10-10T16:32:11Z). Also note\nthat this API must be called with a properly authenticated JWT.","responses":{"200":{"description":"OK","content":{"application\/json":{"schema":{"items":{"$ref":"#\/components\/schemas\/KeycloakCredentialInfo"},"type":"array"}}}}},"security":[{"Basic Auth - login":[]},{"XSRF header":[]},{"DEPRECATED - PL API Key":[]},{"PL API Key":[]}],"tags":["Account"]}},"\/api\/v0.20\/organization\/delete":{"post":{"responses":{"200":{"content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/GenericMessageResponse"},"examples":{"GenericMessageResponse":{"$ref":"#\/components\/examples\/GenericMessageResponse"}}}},"description":"OK"}},"summary":"Deletes specified organization.","description":"Completely deletes an organization, after verifying that the user making this request has permission to do so.\nSends an email to all other members of the organization informing them that it has been deleted.","operationId":"postApiV0.20OrganizationDelete","tags":["Organization"],"requestBody":{"required":true,"content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/DeleteOrganizationData"},"examples":{"DeleteOrganizationData":{"$ref":"#\/components\/examples\/DeleteOrganizationData"}}}}},"security":[{"Basic Auth - login":[]},{"XSRF header":[]},{"DEPRECATED - PL API Key":[]},{"PL API Key":[]}]}},"\/api\/v0.20\/auth\/password\/reset":{"post":{"responses":{"200":{"content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/GenericMessageResponse"},"examples":{"GenericMessageResponse":{"$ref":"#\/components\/examples\/GenericMessageResponse"}}}},"description":"OK"}},"description":"DEPRECATED: This endpoint is not available when Keycloak authentication is turned on and will be removed in the future.\n\nInitiates a password reset for the given user, sending them an email with a password reset link authenticated to their\naccount only.","operationId":"postApiV0.20AuthPasswordReset","deprecated":true,"summary":"Initiates a password reset.","requestBody":{"content":{"application\/json":{"examples":{"RequestResetPasswordData":{"$ref":"#\/components\/examples\/RequestResetPasswordData"}},"schema":{"$ref":"#\/components\/schemas\/RequestResetPasswordData"}}},"required":true},"tags":["Authentication"]}},"\/api\/auth\/logout":{"post":{"summary":"Logs out a user","description":"If external auth (Keycloak) is enabled, this initiates the external logout process.\n\nOtherwise, if a cookie keyed by pl-refresh-token is provided in the logout request, that refresh token is revoked.\n\nThe response sets the auth & refresh cookies to empty values & marks them as expired.\nNew tokens must then be generated by the login endpoint.","tags":["Authentication"],"responses":{"200":{"description":"OK","content":{"application\/json":{"examples":{"GenericMessageResponse":{"$ref":"#\/components\/examples\/GenericMessageResponse"}},"schema":{"$ref":"#\/components\/schemas\/GenericMessageResponse"}}}}},"security":[{"Basic Auth - login":[]},{"XSRF header":[]},{"DEPRECATED - PL API Key":[]},{"PL API Key":[]}],"operationId":"postApiAuthLogout"}},"\/api\/auth\/kc\/{user}":{"get":{"parameters":[{"in":"path","schema":{"type":"string"},"name":"user","required":true}],"responses":{"200":{"content":{"application\/json":{"examples":{"KeycloakUserInfo":{"$ref":"#\/components\/examples\/KeycloakUserInfo"}},"schema":{"$ref":"#\/components\/schemas\/KeycloakUserInfo"}}},"description":"OK"}},"summary":"Retrieves user information for Keycloak","operationId":"getApiAuthKcByUser","description":"Enables migrating users to Keycloak by providing an API endpoint for retrieving user information. This\ninformation is then saved to Keycloak's own database.","tags":["Authentication"],"security":[{"Basic Auth - login":[]},{"XSRF header":[]},{"DEPRECATED - PL API Key":[]},{"PL API Key":[]}]},"post":{"parameters":[{"in":"path","schema":{"type":"string"},"name":"user","required":true}],"responses":{"200":{"description":"OK","content":{"application\/json":{"examples":{"GenericMessageResponse":{"$ref":"#\/components\/examples\/GenericMessageResponse"}},"schema":{"$ref":"#\/components\/schemas\/GenericMessageResponse"}}}}},"summary":"Validates a user's password","operationId":"postApiAuthKcByUser","description":"Allows the Keycloak migration plugin to validate a user's password. Once validated, the password is saved\nto Keycloak's database and is subsequently no longer validated using this API.","tags":["Authentication"],"security":[{"Basic Auth - login":[]},{"XSRF header":[]},{"DEPRECATED - PL API Key":[]},{"PL API Key":[]}]}},"\/api\/authgroup\/remove\/{authGroupID}\/{userID}":{"post":{"security":[{"Basic Auth - login":[]},{"XSRF header":[]},{"DEPRECATED - PL API Key":[]},{"PL API Key":[]}],"responses":{"200":{"description":"OK","content":{"application\/json":{"examples":{"AuthGroupRemovalResponse":{"$ref":"#\/components\/examples\/AuthGroupRemovalResponse"}},"schema":{"$ref":"#\/components\/schemas\/AuthGroupRemovalResponse"}}}}},"operationId":"postApiAuthgroupRemoveByAuthGroupIDByUserID","description":"Remove a User from an AuthGroup. Users must have PrivilegedUser or greater permissions to remove another user.\nUser can only remove other users with permissions less than or equal to their own permissions. For example: PrivilegedUsers\ncannot remove SuperUsers.","summary":"Removes user from Auth Group","parameters":[{"in":"path","name":"authGroupID","schema":{"type":"string"},"required":true},{"in":"path","name":"userID","schema":{"type":"string"},"required":true}],"tags":["Auth Groups"]}},"\/api\/auth\/register\/initiate":{"post":{"responses":{"200":{"content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/GenericMessageResponse"},"examples":{"GenericMessageResponse":{"$ref":"#\/components\/examples\/GenericMessageResponse"}}}},"description":"OK"}},"description":"DEPRECATED: This endpoint is not available when Keycloak authentication is turned on and will be removed in the future.\n\nInitiates the PassiveLogic registration process by sending an email to the given user. A user is not stored in the system\nat this point in the process - instead this serves as the initial step proving that a uer has access to the email they\nare signing up with.\n\nEmail will contain a link that holds a signed JWT from us. That JWT is later used to validate and complete registration.\n\nNo authentication required.","operationId":"postApiAuthRegisterInitiate","deprecated":true,"summary":"Sends an email to begin email verification and registration.","requestBody":{"content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/UserRegistrationInitiation"},"examples":{"UserRegistrationInitiation":{"$ref":"#\/components\/examples\/UserRegistrationInitiation"}}}},"required":true},"tags":["Authentication"]}},"\/api\/organization\/join":{"post":{"security":[{"Basic Auth - login":[]},{"XSRF header":[]},{"DEPRECATED - PL API Key":[]},{"PL API Key":[]}],"responses":{"200":{"description":"OK","content":{"application\/json":{"examples":{"GenericMessageResponse":{"$ref":"#\/components\/examples\/GenericMessageResponse"}},"schema":{"$ref":"#\/components\/schemas\/GenericMessageResponse"}}}}},"operationId":"postApiOrganizationJoin","description":"Adds user to organization based on Organization invite ID.\nRole in organization is determined through Organization invite role, if no role is defined, we default to read-only user.","summary":"Adds a user to an organization","requestBody":{"required":true,"content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/AcceptOrganizationInvite"},"examples":{"AcceptOrganizationInvite":{"$ref":"#\/components\/examples\/AcceptOrganizationInvite"}}}}},"tags":["Organization"]}},"\/app\/login\/eula":{"get":{"summary":"Redirects to external authentication provider (Keycloak).","tags":["app"],"description":"","operationId":"getAppLoginEula"}},"\/api\/v0.19\/graphqlSubscribe":{"get":{"tags":["GraphQL"],"summary":"GraphQL API over websocket.","operationId":"getApiV0.19GraphqlSubscribe","description":"Serves the GraphQL API over websockets to support streaming results like subscriptions.\n\nThe following sub-protocols are supported:\n- [graphql-transport-ws](https:\/\/github.com\/enisdenjo\/graphql-ws\/blob\/master\/PROTOCOL.md)\n- [graphql-ws](https:\/\/github.com\/apollographql\/subscriptions-transport-ws\/blob\/master\/PROTOCOL.md)","security":[{"Basic Auth - login":[]},{"XSRF header":[]},{"DEPRECATED - PL API Key":[]},{"PL API Key":[]}]}},"\/api\/v0.20\/auth\/email\/change\/verify":{"get":{"security":[{"Basic Auth - login":[]},{"XSRF header":[]},{"DEPRECATED - PL API Key":[]},{"PL API Key":[]}],"responses":{"200":{"description":"OK","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/GenericMessageResponse"},"examples":{"GenericMessageResponse":{"$ref":"#\/components\/examples\/GenericMessageResponse"}}}}}},"description":"DEPRECATED: This endpoint is not available when Keycloak authentication is turned on and will be removed in the future.\n\nVerifies the new email is valid. Updates the user email with the newly validated one.\n\nToken authentication required. Provided by \/api\/v0.20\/auth\/email\/change.","operationId":"getApiV0.20AuthEmailChangeVerify","deprecated":true,"summary":"Verifies and updates new user email","requestBody":{"content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/UpdatedUserEmail"},"examples":{"UpdatedUserEmail":{"$ref":"#\/components\/examples\/UpdatedUserEmail"}}}},"required":true},"tags":["Authentication"]}},"\/":{"get":{"description":"GET \/","tags":[""]}},"\/api\/device\/login":{"get":{"description":"Logs in a PassiveLogic device, responding with the authentication token.\n\nmTLS authentication required.","tags":["PassiveLogic Device"],"summary":"Logs in a PassiveLogic device","operationId":"getApiDeviceLogin","responses":{"200":{"content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/DeviceLoginResponse"},"examples":{"DeviceLoginResponse":{"$ref":"#\/components\/examples\/DeviceLoginResponse"}}}},"description":"OK"}},"security":[{"Basic Auth - login":[]},{"XSRF header":[]},{"DEPRECATED - PL API Key":[]},{"PL API Key":[]}]}},"\/api\/auth\/password\/reset":{"post":{"responses":{"200":{"content":{"application\/json":{"examples":{"GenericMessageResponse":{"$ref":"#\/components\/examples\/GenericMessageResponse"}},"schema":{"$ref":"#\/components\/schemas\/GenericMessageResponse"}}},"description":"OK"}},"description":"DEPRECATED: This endpoint is not available when Keycloak authentication is turned on and will be removed in the future.\n\nInitiates a password reset for the given user, sending them an email with a password reset link authenticated to their\naccount only.","operationId":"postApiAuthPasswordReset","deprecated":true,"summary":"Initiates a password reset.","requestBody":{"content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/RequestResetPasswordData"},"examples":{"RequestResetPasswordData":{"$ref":"#\/components\/examples\/RequestResetPasswordData"}}}},"required":true},"tags":["Authentication"]}},"\/api\/v0.20\/auth\/profile\/change":{"get":{"summary":"Redirects the user the change profile flow in the external auth provider (Keycloak).","description":"","security":[{"Basic Auth - login":[]},{"XSRF header":[]},{"DEPRECATED - PL API Key":[]},{"PL API Key":[]}],"tags":["Authentication"],"operationId":"getApiV0.20AuthProfileChange"}},"\/api\/v0.20\/auth\/kc\/{user}":{"get":{"security":[{"Basic Auth - login":[]},{"XSRF header":[]},{"DEPRECATED - PL API Key":[]},{"PL API Key":[]}],"responses":{"200":{"description":"OK","content":{"application\/json":{"examples":{"KeycloakUserInfo":{"$ref":"#\/components\/examples\/KeycloakUserInfo"}},"schema":{"$ref":"#\/components\/schemas\/KeycloakUserInfo"}}}}},"description":"Enables migrating users to Keycloak by providing an API endpoint for retrieving user information. This\ninformation is then saved to Keycloak's own database.","operationId":"getApiV0.20AuthKcByUser","summary":"Retrieves user information for Keycloak","tags":["Authentication"],"parameters":[{"in":"path","schema":{"type":"string"},"name":"user","required":true}]},"post":{"security":[{"Basic Auth - login":[]},{"XSRF header":[]},{"DEPRECATED - PL API Key":[]},{"PL API Key":[]}],"responses":{"200":{"description":"OK","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/GenericMessageResponse"},"examples":{"GenericMessageResponse":{"$ref":"#\/components\/examples\/GenericMessageResponse"}}}}}},"description":"Allows the Keycloak migration plugin to validate a user's password. Once validated, the password is saved\nto Keycloak's database and is subsequently no longer validated using this API.","operationId":"postApiV0.20AuthKcByUser","summary":"Validates a user's password","tags":["Authentication"],"parameters":[{"in":"path","schema":{"type":"string"},"name":"user","required":true}]}},"\/api\/v0.20\/auth\/magic-link-login":{"get":{"security":[{"Basic Auth - login":[]},{"XSRF header":[]},{"DEPRECATED - PL API Key":[]},{"PL API Key":[]}],"responses":{"200":{"content":{"application\/json":{"examples":{"GenericMessageResponse":{"$ref":"#\/components\/examples\/GenericMessageResponse"}},"schema":{"$ref":"#\/components\/schemas\/GenericMessageResponse"}}},"description":"OK"}},"description":"DEPRECATED: This endpoint is not available when Keycloak authentication is turned on and will be removed in the future.\n\nRequires a magic login link containing containing `?token=<signed JWT with user email contained>`.\nThis is the secure mode and MUST be used in production.","operationId":"getApiV0.20AuthMagic-link-login","deprecated":true,"summary":"Logs in a user using Magic Link generated by POST magic-link-generate","tags":["Authentication"]}},"\/api\/auth\/password\/reset\/change":{"post":{"security":[{"Basic Auth - login":[]},{"XSRF header":[]},{"DEPRECATED - PL API Key":[]},{"PL API Key":[]}],"responses":{"200":{"description":"OK","content":{"application\/json":{"examples":{"GenericMessageResponse":{"$ref":"#\/components\/examples\/GenericMessageResponse"}},"schema":{"$ref":"#\/components\/schemas\/GenericMessageResponse"}}}}},"description":"DEPRECATED: This endpoint is not available when Keycloak authentication is turned on and will be removed in the future.\n\nChanges a user's password to the specified value, reached from password reset flow.\n\nToken authentication required, only using the authentication JWT decoded from the password reset URL sent to a user\nfrom a reset initiation.","operationId":"postApiAuthPasswordResetChange","deprecated":true,"summary":"Changes a user's password from the password reset flow.","requestBody":{"content":{"application\/json":{"examples":{"ChangePasswordData":{"$ref":"#\/components\/examples\/ChangePasswordData"}},"schema":{"$ref":"#\/components\/schemas\/ChangePasswordData"}}},"required":true},"tags":["Authentication"]}},"\/api\/v0.19\/auth\/password\/change":{"get":{"tags":["Authentication"],"operationId":"getApiV0.19AuthPasswordChange","summary":"Redirects the user to the change password flow in the external auth provider (Keycloak).","security":[{"Basic Auth - login":[]},{"XSRF header":[]},{"DEPRECATED - PL API Key":[]},{"PL API Key":[]}],"description":""},"post":{"security":[{"Basic Auth - login":[]},{"XSRF header":[]},{"DEPRECATED - PL API Key":[]},{"PL API Key":[]}],"responses":{"200":{"description":"OK","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/GenericMessageResponse"},"examples":{"GenericMessageResponse":{"$ref":"#\/components\/examples\/GenericMessageResponse"}}}}}},"operationId":"postApiV0.19AuthPasswordChange","description":"DEPRECATED: This endpoint is not available when Keycloak authentication is turned on and will be removed in the future.\n\nChanges an authenticated user's password to the specified value.","deprecated":true,"summary":"Changes a user's password for an already authenticated user.","requestBody":{"required":true,"content":{"application\/json":{"examples":{"ChangeUserPassword":{"$ref":"#\/components\/examples\/ChangeUserPassword"}},"schema":{"$ref":"#\/components\/schemas\/ChangeUserPassword"}}}},"tags":["Authentication"]}},"\/api\/v0.20\/authgroup\/decline":{"post":{"security":[{"Basic Auth - login":[]},{"XSRF header":[]},{"DEPRECATED - PL API Key":[]},{"PL API Key":[]}],"responses":{"200":{"content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/GenericMessageResponse"},"examples":{"GenericMessageResponse":{"$ref":"#\/components\/examples\/GenericMessageResponse"}}}},"description":"OK"}},"description":"Rejects an invitation based on AuthGroup invite ID.\nInvitation is deleted.","operationId":"postApiV0.20AuthgroupDecline","summary":"Declines an AuthGroup invitation","requestBody":{"content":{"application\/json":{"examples":{"DeclineOrganizationInvite":{"$ref":"#\/components\/examples\/DeclineOrganizationInvite"}},"schema":{"$ref":"#\/components\/schemas\/DeclineOrganizationInvite"}}},"required":true},"tags":["Auth Groups"]}},"\/api\/v0.19\/auth\/verify":{"get":{"summary":"Redirects user to login","description":"Redirects user to `\/api\/v0.19\/auth\/login`, passing along the provided valid jwt and email.\n\nExists in this form for backward compatibility.","operationId":"getApiV0.19AuthVerify","parameters":[{"in":"query","required":true,"description":"User's email to confirm as verified","schema":{"type":"string"},"name":"email","example":"darthvader@galactic-empire.com"}],"tags":["Authentication"]}},"\/api\/v0.19\/graphql":{"get":{"security":[{"Basic Auth - login":[]},{"XSRF header":[]},{"DEPRECATED - PL API Key":[]},{"PL API Key":[]}],"responses":{"200":{"content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/GraphQLResult"}}},"description":"OK"}},"operationId":"getApiV0.19Graphql","description":"Serves the GraphQL API. For more details, see [graphql.org](https:\/\/graphql.org\/learn\/serving-over-http\/#get-request)","externalDocs":{"description":"GraphQL documentation.","url":"https:\/\/graphql.org\/learn\/serving-over-http\/#get-request"},"summary":"GraphQL API","parameters":[{"required":true,"schema":{"type":"string"},"in":"query","name":"query"},{"required":false,"schema":{"nullable":true,"type":"string"},"in":"query","name":"operationName"},{"required":false,"schema":{"additionalProperties":{"type":"boolean"},"type":"object","nullable":true},"in":"query","example":{},"name":"variables"}],"tags":["GraphQL"]},"post":{"security":[{"Basic Auth - login":[]},{"XSRF header":[]},{"DEPRECATED - PL API Key":[]},{"PL API Key":[]}],"responses":{"200":{"description":"OK","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/GraphQLResult"}}}}},"operationId":"postApiV0.19Graphql","description":"Serves the GraphQL API. For more details, see [graphql.org](https:\/\/graphql.org\/learn\/serving-over-http\/#post-request)","externalDocs":{"description":"GraphQL documentation.","url":"https:\/\/graphql.org\/learn\/serving-over-http\/#post-request"},"summary":"GraphQL API","requestBody":{"content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/GraphQLRequest"}}},"required":true},"tags":["GraphQL"]}},"\/api\/organization\/invite":{"post":{"security":[{"Basic Auth - login":[]},{"XSRF header":[]},{"DEPRECATED - PL API Key":[]},{"PL API Key":[]}],"responses":{"200":{"content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/OrgInviteResponse"},"examples":{"OrgInviteResponse":{"$ref":"#\/components\/examples\/OrgInviteResponse"}}}},"description":"OK"}},"description":"Generates and sends an invitation link for the given organization to the given user email.","operationId":"postApiOrganizationInvite","summary":"Sends an organization invite to the given email.","requestBody":{"content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/InviteUserToOrganizationData"},"examples":{"InviteUserToOrganizationData":{"$ref":"#\/components\/examples\/InviteUserToOrganizationData"}}}},"required":true},"tags":["Organization"]}},"\/api\/auth\/keys":{"get":{"summary":"Returns the public keys used to sign PassiveLogic JSON web tokens.","description":"Returns the public keys used to sign the JSON web tokens so their authenticity can be verified. These are served in the\nstandard JSON Web Key format: https:\/\/www.rfc-editor.org\/rfc\/rfc7517","operationId":"getApiAuthKeys","tags":["Authentication"],"responses":{"200":{"content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/JWKS"}}},"description":"OK"}}}},"\/api\/v0.19\/health\/readiness":{"get":{"security":[{"Basic Auth - login":[]},{"XSRF header":[]},{"DEPRECATED - PL API Key":[]},{"PL API Key":[]}],"summary":"Readiness check used to determine if webserver is ready to accept traffic","description":"See https:\/\/kubernetes.io\/docs\/concepts\/configuration\/liveness-readiness-startup-probes\/#readiness-probe","operationId":"getApiV0.19HealthReadiness","tags":["Health"]}},"\/api\/v0.20\/util\/pl-hardware-info":{"get":{"summary":"Indicates to clients whether or not they are hives serving a webserver.","operationId":"getApiV0.20UtilPl-hardware-info","tags":["Utility"],"responses":{"200":{"content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/DeployedOnHiveResponse"}}},"description":"OK"}},"description":"Returns a JSON object where the field 'runningOnHive' will be true if, on the server, the PL_HIVE_REVISION environment variable\nis set to a number greater than or equal to zero."}},"\/api\/v0.20\/site\/copy":{"post":{"security":[{"Basic Auth - login":[]},{"XSRF header":[]},{"DEPRECATED - PL API Key":[]},{"PL API Key":[]}],"responses":{"200":{"description":"OK","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ObjectIdentifiers"}}}}},"description":"Copies Project from one organization to a target organization given a project Identifier.\nAll UUID's are created new for the copied project.\nReturns a mapping of old identifiers and new identifiers of the given project.\nHistory data is NOT copied unless startDate and endDate are provided.\nHistory copy will take time to complete in the background and there will be no indication of success.","operationId":"postApiV0.20SiteCopy","summary":"Copy Project from one organization to another","tags":["Site"],"parameters":[{"schema":{"type":"string","format":"uuid"},"in":"query","description":"Organization to copy the given site into.","name":"targetOrganizationID","required":true},{"schema":{"type":"string","format":"uuid"},"in":"query","description":"Site to copy.","name":"siteID","required":true},{"schema":{"nullable":true,"type":"string"},"in":"query","description":"Optionally change the copied site name.","name":"siteName","required":false},{"schema":{"nullable":true,"type":"string"},"in":"query","description":"Optionally change the copied site directory.","name":"siteDirectory","required":false},{"schema":{"type":"string","nullable":true},"in":"query","description":"Date to start copying history from. Required to export all history.","name":"startDate","required":false},{"schema":{"type":"string","nullable":true},"in":"query","description":"Date to end copying history at. Required to export all history.","name":"endDate","required":false}]}},"\/api\/v0.20\/image\/user-avatar":{"post":{"security":[{"Basic Auth - login":[]},{"XSRF header":[]},{"DEPRECATED - PL API Key":[]},{"PL API Key":[]}],"responses":{"200":{"content":{"application\/json":{"examples":{"ImageUploadResponse":{"$ref":"#\/components\/examples\/ImageUploadResponse"}},"schema":{"$ref":"#\/components\/schemas\/ImageUploadResponse"}}},"description":"OK"}},"operationId":"postApiV0.20ImageUser-avatar","description":"Uploads and updates the avatar image URL with the new image URL.","summary":"Update user avatar image","requestBody":{"content":{"application\/json":{"examples":{"ImageData":{"$ref":"#\/components\/examples\/ImageData"}},"schema":{"$ref":"#\/components\/schemas\/ImageData"}}},"required":true},"tags":["Images"]}},"\/api\/v0.19\/organization\/decline":{"post":{"security":[{"Basic Auth - login":[]},{"XSRF header":[]},{"DEPRECATED - PL API Key":[]},{"PL API Key":[]}],"responses":{"200":{"content":{"application\/json":{"examples":{"GenericMessageResponse":{"$ref":"#\/components\/examples\/GenericMessageResponse"}},"schema":{"$ref":"#\/components\/schemas\/GenericMessageResponse"}}},"description":"OK"}},"description":"Rejects an invitation based on Organization invite ID.\nInvitation is deleted.","operationId":"postApiV0.19OrganizationDecline","summary":"Declines an organization invitation","requestBody":{"required":true,"content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/DeclineOrganizationInvite"},"examples":{"DeclineOrganizationInvite":{"$ref":"#\/components\/examples\/DeclineOrganizationInvite"}}}}},"tags":["Organization"]}},"\/api\/v0.19\/organization\/update-image":{"post":{"security":[{"Basic Auth - login":[]},{"XSRF header":[]},{"DEPRECATED - PL API Key":[]},{"PL API Key":[]}],"responses":{"200":{"description":"OK","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ImageUploadResponse"},"examples":{"ImageUploadResponse":{"$ref":"#\/components\/examples\/ImageUploadResponse"}}}}}},"operationId":"postApiV0.19OrganizationUpdate-image","description":"Verifies that the user making the request has sufficient permissions to change the image for the organization.\nTakes in a new image as the new organization image. Creates or replaces the previously stored image.","summary":"Updates the organization's image","requestBody":{"required":true,"content":{"application\/json":{"examples":{"OrganizationImageData":{"$ref":"#\/components\/examples\/OrganizationImageData"}},"schema":{"$ref":"#\/components\/schemas\/OrganizationImageData"}}}},"tags":["Organization"]}},"\/api\/v0.19\/health\/liveness":{"get":{"tags":["Health"],"description":"See https:\/\/kubernetes.io\/docs\/concepts\/configuration\/liveness-readiness-startup-probes\/#liveness-probe","security":[{"Basic Auth - login":[]},{"XSRF header":[]},{"DEPRECATED - PL API Key":[]},{"PL API Key":[]}],"summary":"Liveness check used to determine when webserver should be restarted","operationId":"getApiV0.19HealthLiveness"}},"\/api\/v0.19\/auth\/magic-link-generate":{"post":{"security":[{"Basic Auth - login":[]},{"XSRF header":[]},{"DEPRECATED - PL API Key":[]},{"PL API Key":[]}],"responses":{"200":{"description":"OK","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/MagicLinkResponse"}}}}},"description":"DEPRECATED: This endpoint is not available when Keycloak authentication is turned on and will be removed in the future.\n\nGenerates magic link containing `?token=<signed JWT with user email contained>` and sends it in an email to the user.\nThis is the secure mode and MUST be used in production.\nThis will not return a link to the client.\n\nIf User does not exist in Database, will throw 400 bad request. If user exists, will return 200 ok.\nThese links can then be used to login from GET magic-link-login.","operationId":"postApiV0.19AuthMagic-link-generate","deprecated":true,"summary":"Generates a Magic Link to be used to login.","requestBody":{"content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/UserRegistrationInitiation"},"examples":{"UserRegistrationInitiation":{"$ref":"#\/components\/examples\/UserRegistrationInitiation"}}}},"required":true},"tags":["Authentication"]}},"\/api\/authgroup\/decline":{"post":{"security":[{"Basic Auth - login":[]},{"XSRF header":[]},{"DEPRECATED - PL API Key":[]},{"PL API Key":[]}],"responses":{"200":{"description":"OK","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/GenericMessageResponse"},"examples":{"GenericMessageResponse":{"$ref":"#\/components\/examples\/GenericMessageResponse"}}}}}},"operationId":"postApiAuthgroupDecline","description":"Rejects an invitation based on AuthGroup invite ID.\nInvitation is deleted.","summary":"Declines an AuthGroup invitation","requestBody":{"content":{"application\/json":{"examples":{"DeclineOrganizationInvite":{"$ref":"#\/components\/examples\/DeclineOrganizationInvite"}},"schema":{"$ref":"#\/components\/schemas\/DeclineOrganizationInvite"}}},"required":true},"tags":["Auth Groups"]}},"\/app\/login\/verify":{"get":{"summary":"Redirects to external authentication provider (Keycloak).","tags":["app"],"operationId":"getAppLoginVerify","description":""}},"\/api\/v0.20\/auth\/api-key\/remove":{"delete":{"security":[{"Basic Auth - login":[]},{"XSRF header":[]},{"DEPRECATED - PL API Key":[]},{"PL API Key":[]}],"responses":{"200":{"description":"OK","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/GenerateApiKeyResponse"},"examples":{"GenerateApiKeyResponse":{"$ref":"#\/components\/examples\/GenerateApiKeyResponse"}}}}}},"operationId":"deleteApiV0.20AuthApi-keyRemove","description":"Validates that the given token is linked to the currently authenticated user and removes it if so.","deprecated":true,"summary":"Removes a given API key for the user. This route has been deprecated in favor of: DELETE \/api\/v0.20\/auth\/api-key.","requestBody":{"content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/RemoveApiKeyRequest"},"examples":{"RemoveApiKeyRequest":{"$ref":"#\/components\/examples\/RemoveApiKeyRequest"}}}},"required":true},"tags":["Authentication"]},"post":{"security":[{"Basic Auth - login":[]},{"XSRF header":[]},{"DEPRECATED - PL API Key":[]},{"PL API Key":[]}],"responses":{"200":{"description":"OK","content":{"application\/json":{"examples":{"GenerateApiKeyResponse":{"$ref":"#\/components\/examples\/GenerateApiKeyResponse"}},"schema":{"$ref":"#\/components\/schemas\/GenerateApiKeyResponse"}}}}},"operationId":"postApiV0.20AuthApi-keyRemove","description":"Validates that the given token is linked to the currently authenticated user and removes it if so.","deprecated":true,"summary":"Removes a given API key for the user. This route has been deprecated in favor of: DELETE \/api\/v0.20\/auth\/api-key.","requestBody":{"content":{"application\/json":{"examples":{"RemoveApiKeyRequest":{"$ref":"#\/components\/examples\/RemoveApiKeyRequest"}},"schema":{"$ref":"#\/components\/schemas\/RemoveApiKeyRequest"}}},"required":true},"tags":["Authentication"]}},"\/api\/v0.19\/auth\/whoami":{"get":{"operationId":"getApiV0.19AuthWhoami","responses":{"200":{"content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/WhoAmIResponse"},"examples":{"WhoAmIResponse":{"$ref":"#\/components\/examples\/WhoAmIResponse"}}}},"description":"OK"}},"summary":"Returns information about the currently logged in user.","security":[{"Basic Auth - login":[]},{"XSRF header":[]},{"DEPRECATED - PL API Key":[]},{"PL API Key":[]}],"tags":["Authentication"],"description":"Useful to check if a user is authenticated."}},"\/api\/v0.19\/quantumsync":{"get":{"description":"# Custom QuantumSync\/ShadowClient API:\n\n## QuantumSync QuantumSyncRequestTypes:\n### `start`: authenticates and specifies an initial context. note: the id for start and updateContext is used to key a Dictionary[String:AnyRootedQuantumGraph]\nex)\n```json\n{\n    \"type\": \"start\",\n    \"id\": \"site\",\n    \"appType\":\"BuildingStudio\"\n    \"payload\": {\n        \"authToken\": \"REDACTED\",\n        \"ID\": \"ACAF9E07-5031-4BC2-A8C5-D2C6598D83DE\",\n        \"from\": \"Site\",\n        \"include\": [\n            \"Site\",\n            \"Building\",\n            \"Floor\",\n            \"Zone\"\n    ]\n    }\n}\n```\n\n### `updateContext`: change the current context \/ graph in memory.\nnote: the previous graph\/context can be returned from memory by using updateContext id: <previous id used in start or updateContext>.\nUp to 5 contexts can be loaded before prevention (error) or deleteContext message needed to free up loaded count to load a new context.\n\nex)\n```json\n{\n    \"type\": \"updateContext\",\n    \"id\": \"building\",\n    \"payload\": {\n        \"ID\": \"ACAF9E07-5031-4BC2-A8C5-D2C6598D83DE\",\n        \"from\": \"Building\",\n        \"include\": [\n            \"Site\",\n            \"Floor\",\n            \"Zone\",\n            \"Image\",\n            \"Surface\",\n            \"Adjacency\",\n            \"System\",\n            \"Quanta\",\n            \"Manufacturer\",\n            \"Equipment\",\n            \"Property\",\n            \"Location\"\n        ]\n    }\n}\n```\n\n### `deleteContext`: delete\/clear the context out of memory.\nex)\n```json\n{\n    \"type\": \"deleteContext\",\n    \"id\": \"building\",\n    \"payload\": {}\n}\n```\n\n### `sync`: create\/update\/delete QuantumObjects via a FlatGraphDiff as the payload.\n\nExecuting concurrent sync's is not allowed. If there is a sync already processing and another sync is requested before the response of the first sync is sent, then the 2nd symc will return an error saying there is a sync currently processing, and to wait until its finished before requesting another sync.\n\nex)\n```json\n{\n    \"type\": \"sync\",\n    \"id\": \"F5B6BC51-B991-440C-8ACB-B55C65FD7C24\",\n    \"payload\": {\n        \"added\": [],\n        \"updated\": [\n            {\n                \"description\": null,\n                \"ID\": \"80187B0B-CEEB-488A-A9B7-06784CFB0464\",\n                \"longitude\": null,\n                \"locationPropertyID\": null,\n                \"elevation\": null,\n                \"latitude\": null,\n                \"address\": null,\n                \"timeZone\": null,\n                \"siteIDs\": [\n                    \"7E7E04B4-8F32-4585-839D-E0EFC7BB3544\"\n                ],\n                \"weatherSourceIDs\": [],\n                \"locked\": false,\n                \"authGroupID\": \"A1EBEC59-D887-473F-A5C5-7CBD4ADB2556\",\n                \"__typename\": \"Location\",\n                \"name\": \"foo\"\n            }\n        ],\n        \"removed\": []\n    }\n}\n```\n\n### `syncEphemeral`: create\/update\/delete QuantumObjects via a FlatGraphDiff as the payload, do not write them to the database,\nand discard them at the end of the websocket session.\nex)\n```json\n{\n    \"type\": \"syncEphemeral\",\n    \"id\": \"F5B6BC51-B991-440C-8ACB-B55C65FD7C24\",\n    \"payload\": {\n        \"added\": [],\n        \"updated\": [\n            {\n                \"description\": null,\n                \"ID\": \"80187B0B-CEEB-488A-A9B7-06784CFB0464\",\n                \"longitude\": null,\n                \"locationPropertyID\": null,\n                \"elevation\": null,\n                \"latitude\": null,\n                \"address\": null,\n                \"timeZone\": null,\n                \"siteIDs\": [\n                    \"7E7E04B4-8F32-4585-839D-E0EFC7BB3544\"\n                ],\n                \"weatherSourceIDs\": [],\n                \"locked\": false,\n                \"authGroupID\": \"A1EBEC59-D887-473F-A5C5-7CBD4ADB2556\",\n                \"__typename\": \"Location\",\n                \"name\": \"foo\"\n            }\n        ],\n        \"removed\": []\n    }\n}\n```\n\n### `propertyHistory`: Get history data for a property & listen for updates.\nex)\n```json\n{\n    \"type\": \"propertyHistory\",\n    \"id\": \"propertyHistory1\",\n    \"payload\": {\n        \"propertyIDs\": [\"E585C3B8-F1E5-40D0-83A7-658B248DF103\"],\n        \"startAt\": \"2024-01-01T00:00:00Z\",\n        \"endAt\": \"2024-01-01T01:00:00Z\",\n        \"resample\": {\n            \"interval\": {\n                \"to\": \"minutely\",\n                \"reduceUsing\": \"avg\",\n                \"fillUsing\": \"interpolate\"\n        },\n        \"pollIntervalSec\": 60\n    }\n}\n\n### `propertyHistoryStop`: Stop listening for property history updates\nex)\n```json\n{\n    \"type\": \"propertyHistoryStop\",\n    \"id\": \"propertyHistory1\"\n}\n```\n\n### `writeHistory`: Write historical data to a property\nex)\n```json\n{\n    \"type\": \"writeHistory\",\n    \"id\": \"writeHistory\",\n    \"payload\": {\n        \"histories\": [\n            {\n                \"propertyID\": \"E585C3B8-F1E5-40D0-83A7-658B248DF103\",\n                \"time\": \"2024-01-01T00:00:00Z\",\n                \"value\": 5.0\n            }\n        ]\n    }\n}\n```","security":[{"Basic Auth - login":[]},{"XSRF header":[]},{"DEPRECATED - PL API Key":[]},{"PL API Key":[]}],"summary":"QuantumSync API over websockets","operationId":"getApiV0.19Quantumsync","tags":["Quantum Sync"]}},"\/api\/v0.20\/util\/externalauthconfig":{"get":{"summary":"Provides information about the external auth configuration","responses":{"200":{"description":"OK","content":{"text\/plain":{"examples":{"String":{"$ref":"#\/components\/examples\/String"}},"schema":{"type":"string"}}}}},"description":"Use to check whether or not external auth (i.e. Keycloak) is enabled, and if so what the public settings are.","tags":["Utility"],"operationId":"getApiV0.20UtilExternalauthconfig"}},"\/api\/v0.19\/auth\/api-key\/generate":{"get":{"security":[{"Basic Auth - login":[]},{"XSRF header":[]},{"DEPRECATED - PL API Key":[]},{"PL API Key":[]}],"responses":{"200":{"content":{"application\/json":{"examples":{"GenerateApiKeyResponse":{"$ref":"#\/components\/examples\/GenerateApiKeyResponse"}},"schema":{"$ref":"#\/components\/schemas\/GenerateApiKeyResponse"}}},"description":"OK"}},"description":"Generates, stores, and returns a new API key with the default expiration period for the user currently logged in.\n\nOnce created, you can then provide this API key in an\n`Authorization: PL-API-KEY <Key>` header in replacement of an `X-PL-AUTH` header.","operationId":"getApiV0.19AuthApi-keyGenerate","summary":"Generates an API key for the current user","tags":["Authentication"],"parameters":[{"in":"query","schema":{"format":"int64","type":"integer","nullable":true},"description":"Number of seconds until the key expires.","example":2678400,"name":"expireSeconds","required":false},{"in":"query","schema":{"nullable":true,"type":"string"},"description":"Role of the new key.","example":"ReadOnlyUser","name":"role","required":false}]}},"\/app\/login\/signIn":{"get":{"tags":["app"],"description":"","summary":"Redirects to external authentication provider (Keycloak).","operationId":"getAppLoginSignIn"}},"\/api\/device\/register":{"post":{"description":"POST \/device\/register","security":[{"Basic Auth - login":[]},{"XSRF header":[]},{"DEPRECATED - PL API Key":[]},{"PL API Key":[]}],"tags":["PassiveLogic Device"]}},"\/api\/v0.20\/graphql":{"get":{"security":[{"Basic Auth - login":[]},{"XSRF header":[]},{"DEPRECATED - PL API Key":[]},{"PL API Key":[]}],"responses":{"200":{"description":"OK","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/GraphQLResult"}}}}},"operationId":"getApiV0.20Graphql","description":"Serves the GraphQL API. For more details, see [graphql.org](https:\/\/graphql.org\/learn\/serving-over-http\/#get-request)","externalDocs":{"url":"https:\/\/graphql.org\/learn\/serving-over-http\/#get-request","description":"GraphQL documentation."},"summary":"GraphQL API","parameters":[{"schema":{"type":"string"},"in":"query","required":true,"name":"query"},{"schema":{"nullable":true,"type":"string"},"in":"query","required":false,"name":"operationName"},{"schema":{"type":"object","nullable":true,"additionalProperties":{"type":"boolean"}},"in":"query","required":false,"example":{},"name":"variables"}],"tags":["GraphQL"]},"post":{"security":[{"Basic Auth - login":[]},{"XSRF header":[]},{"DEPRECATED - PL API Key":[]},{"PL API Key":[]}],"responses":{"200":{"description":"OK","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/GraphQLResult"}}}}},"operationId":"postApiV0.20Graphql","description":"Serves the GraphQL API. For more details, see [graphql.org](https:\/\/graphql.org\/learn\/serving-over-http\/#post-request)","externalDocs":{"url":"https:\/\/graphql.org\/learn\/serving-over-http\/#post-request","description":"GraphQL documentation."},"summary":"GraphQL API","requestBody":{"required":true,"content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/GraphQLRequest"}}}},"tags":["GraphQL"]}},"\/app\/login\/**":{"get":{"tags":["app"],"description":"GET \/app\/login\/**"}},"\/api\/v0.19\/auth\/api-key":{"delete":{"security":[{"Basic Auth - login":[]},{"XSRF header":[]},{"DEPRECATED - PL API Key":[]},{"PL API Key":[]}],"responses":{"200":{"content":{"application\/json":{"examples":{"GenerateApiKeyResponse":{"$ref":"#\/components\/examples\/GenerateApiKeyResponse"}},"schema":{"$ref":"#\/components\/schemas\/GenerateApiKeyResponse"}}},"description":"OK"}},"description":"Validates that the given token is linked to the currently authenticated user and removes it if so.","operationId":"deleteApiV0.19AuthApi-key","summary":"Removes a given API key for the user","requestBody":{"required":true,"content":{"application\/json":{"examples":{"RemoveApiKeyRequest":{"$ref":"#\/components\/examples\/RemoveApiKeyRequest"}},"schema":{"$ref":"#\/components\/schemas\/RemoveApiKeyRequest"}}}},"tags":["Authentication"]}},"\/app\/qc\/**":{"get":{"tags":["app"],"description":"GET \/app\/qc\/**"}},"\/api\/device\/tailscale\/authToken":{"get":{"description":"AutToken generated allowing hive's to enroll in our tailnet.\n\nmTLS authentication required.","operationId":"getApiDeviceTailscaleAuthToken","summary":"Generates an OAuth token for Tailscale","responses":{"200":{"description":"OK","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/TailscalePostTailnetKeyResponse"}}}}},"tags":["PassiveLogic Device"],"security":[{"Basic Auth - login":[]},{"XSRF header":[]},{"DEPRECATED - PL API Key":[]},{"PL API Key":[]}]}},"\/api\/v0.20\/auth\/password\/reset\/change":{"post":{"security":[{"Basic Auth - login":[]},{"XSRF header":[]},{"DEPRECATED - PL API Key":[]},{"PL API Key":[]}],"responses":{"200":{"content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/GenericMessageResponse"},"examples":{"GenericMessageResponse":{"$ref":"#\/components\/examples\/GenericMessageResponse"}}}},"description":"OK"}},"description":"DEPRECATED: This endpoint is not available when Keycloak authentication is turned on and will be removed in the future.\n\nChanges a user's password to the specified value, reached from password reset flow.\n\nToken authentication required, only using the authentication JWT decoded from the password reset URL sent to a user\nfrom a reset initiation.","operationId":"postApiV0.20AuthPasswordResetChange","deprecated":true,"summary":"Changes a user's password from the password reset flow.","requestBody":{"content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ChangePasswordData"},"examples":{"ChangePasswordData":{"$ref":"#\/components\/examples\/ChangePasswordData"}}}},"required":true},"tags":["Authentication"]}},"\/api\/auth\/email\/change":{"post":{"security":[{"Basic Auth - login":[]},{"XSRF header":[]},{"DEPRECATED - PL API Key":[]},{"PL API Key":[]}],"responses":{"200":{"description":"OK","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/GenericMessageResponse"},"examples":{"GenericMessageResponse":{"$ref":"#\/components\/examples\/GenericMessageResponse"}}}}}},"description":"DEPRECATED: This endpoint is not available when Keycloak authentication is turned on and will be removed in the future.\n\nSends an update email request to the provided new email address.","operationId":"postApiAuthEmailChange","deprecated":true,"summary":"Initiates an email change for the current user.","requestBody":{"content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/UpdatedUserEmail"},"examples":{"UpdatedUserEmail":{"$ref":"#\/components\/examples\/UpdatedUserEmail"}}}},"required":true},"tags":["Authentication"]}},"\/api\/v0.19\/auth\/password\/reset":{"post":{"responses":{"200":{"description":"OK","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/GenericMessageResponse"},"examples":{"GenericMessageResponse":{"$ref":"#\/components\/examples\/GenericMessageResponse"}}}}}},"operationId":"postApiV0.19AuthPasswordReset","description":"DEPRECATED: This endpoint is not available when Keycloak authentication is turned on and will be removed in the future.\n\nInitiates a password reset for the given user, sending them an email with a password reset link authenticated to their\naccount only.","deprecated":true,"summary":"Initiates a password reset.","requestBody":{"content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/RequestResetPasswordData"},"examples":{"RequestResetPasswordData":{"$ref":"#\/components\/examples\/RequestResetPasswordData"}}}},"required":true},"tags":["Authentication"]}},"\/api\/v0.20\/auth\/api-key\/generate":{"get":{"security":[{"Basic Auth - login":[]},{"XSRF header":[]},{"DEPRECATED - PL API Key":[]},{"PL API Key":[]}],"responses":{"200":{"description":"OK","content":{"application\/json":{"examples":{"GenerateApiKeyResponse":{"$ref":"#\/components\/examples\/GenerateApiKeyResponse"}},"schema":{"$ref":"#\/components\/schemas\/GenerateApiKeyResponse"}}}}},"description":"Generates, stores, and returns a new API key with the default expiration period for the user currently logged in.\n\nOnce created, you can then provide this API key in an\n`Authorization: PL-API-KEY <Key>` header in replacement of an `X-PL-AUTH` header.","operationId":"getApiV0.20AuthApi-keyGenerate","summary":"Generates an API key for the current user","tags":["Authentication"],"parameters":[{"name":"expireSeconds","in":"query","required":false,"schema":{"format":"int64","type":"integer","nullable":true},"description":"Number of seconds until the key expires.","example":2678400},{"name":"role","in":"query","required":false,"schema":{"type":"string","nullable":true},"description":"Role of the new key.","example":"ReadOnlyUser"}]}},"\/api\/v0.20\/auth\/magic-link-generate":{"post":{"security":[{"Basic Auth - login":[]},{"XSRF header":[]},{"DEPRECATED - PL API Key":[]},{"PL API Key":[]}],"responses":{"200":{"description":"OK","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/MagicLinkResponse"}}}}},"description":"DEPRECATED: This endpoint is not available when Keycloak authentication is turned on and will be removed in the future.\n\nGenerates magic link containing `?token=<signed JWT with user email contained>` and sends it in an email to the user.\nThis is the secure mode and MUST be used in production.\nThis will not return a link to the client.\n\nIf User does not exist in Database, will throw 400 bad request. If user exists, will return 200 ok.\nThese links can then be used to login from GET magic-link-login.","operationId":"postApiV0.20AuthMagic-link-generate","deprecated":true,"summary":"Generates a Magic Link to be used to login.","requestBody":{"content":{"application\/json":{"examples":{"UserRegistrationInitiation":{"$ref":"#\/components\/examples\/UserRegistrationInitiation"}},"schema":{"$ref":"#\/components\/schemas\/UserRegistrationInitiation"}}},"required":true},"tags":["Authentication"]}},"\/api\/v0.19\/auth\/zendesk":{"get":{"summary":"Logs a user in to Zendesk using their PL Account","tags":["Authentication"],"description":"Redirects a user to the PassiveLogic Zendesk portal.\nIf they are already authenticated with their PL account when making this request,\nthey will be automatically logged in to Zendesk as well. Otherwise they will be redirected to the Zendesk login page.\nA `returnTo` query parameter can be used to support deep linking to, for example, specific support articles.","operationId":"getApiV0.19AuthZendesk"}},"\/api\/v0.19\/account\/eula\/accept":{"post":{"security":[{"Basic Auth - login":[]},{"XSRF header":[]},{"DEPRECATED - PL API Key":[]},{"PL API Key":[]}],"responses":{"200":{"description":"OK","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/GenericMessageResponse"},"examples":{"GenericMessageResponse":{"$ref":"#\/components\/examples\/GenericMessageResponse"}}}}}},"description":"DEPRECATED: This endpoint is not available when Keycloak authentication is turned on and will be removed in the future.\nDenotes that the current user has accepted the EULA.\nReturns updated access and refresh tokens.","deprecated":true,"operationId":"postApiV0.19AccountEulaAccept","summary":"Accepts EULA for the current user","tags":["Account"]}},"\/api\/v0.20\/auth\/api-key":{"delete":{"security":[{"Basic Auth - login":[]},{"XSRF header":[]},{"DEPRECATED - PL API Key":[]},{"PL API Key":[]}],"responses":{"200":{"content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/GenerateApiKeyResponse"},"examples":{"GenerateApiKeyResponse":{"$ref":"#\/components\/examples\/GenerateApiKeyResponse"}}}},"description":"OK"}},"description":"Validates that the given token is linked to the currently authenticated user and removes it if so.","operationId":"deleteApiV0.20AuthApi-key","summary":"Removes a given API key for the user","requestBody":{"content":{"application\/json":{"examples":{"RemoveApiKeyRequest":{"$ref":"#\/components\/examples\/RemoveApiKeyRequest"}},"schema":{"$ref":"#\/components\/schemas\/RemoveApiKeyRequest"}}},"required":true},"tags":["Authentication"]}},"\/api\/authgroup\/join":{"get":{"security":[{"Basic Auth - login":[]},{"XSRF header":[]},{"DEPRECATED - PL API Key":[]},{"PL API Key":[]}],"responses":{"200":{"content":{"application\/json":{"examples":{"GenericMessageResponse":{"$ref":"#\/components\/examples\/GenericMessageResponse"}},"schema":{"$ref":"#\/components\/schemas\/GenericMessageResponse"}}},"description":"OK"}},"description":"DEPRECATED: GET \/api\/authgroup\/join was used to accept a project (auth group) invitation by clicking directly in an email.\nAccepting invitations is now handled by the \/app\/login\/post-auth route provided by the front end, which calls POST\n\/api\/authgroup\/join. This can be removed when any invitations linked to in this way have expired.","operationId":"getApiAuthgroupJoin","summary":"Accepts an AuthGroup Invitation","requestBody":{"required":true,"content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/AcceptOrganizationInvite"},"examples":{"AcceptOrganizationInvite":{"$ref":"#\/components\/examples\/AcceptOrganizationInvite"}}}}},"tags":["Auth Groups"]},"post":{"security":[{"Basic Auth - login":[]},{"XSRF header":[]},{"DEPRECATED - PL API Key":[]},{"PL API Key":[]}],"responses":{"200":{"description":"OK","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/GenericMessageResponse"},"examples":{"GenericMessageResponse":{"$ref":"#\/components\/examples\/GenericMessageResponse"}}}}}},"description":"Used by the front end `\/app\/login\/post-auth` route to accept project (auth group) invitations. The role the user receives in the\nreferenced AuthGroup is determined through AuthGroup invite role; if no role is defined, we default to read-only user.","operationId":"postApiAuthgroupJoin","deprecated":true,"summary":"Accepts an AuthGroup Invitation","requestBody":{"required":true,"content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/AcceptOrganizationInvite"},"examples":{"AcceptOrganizationInvite":{"$ref":"#\/components\/examples\/AcceptOrganizationInvite"}}}}},"tags":["Auth Groups"]}},"\/api\/v0.19\/util\/ping":{"get":{"operationId":"getApiV0.19UtilPing","description":"Use to check webserver health or keep connection alive. Returns pong message.","tags":["Utility"],"summary":"Keep-alive ping\/pong route","responses":{"200":{"content":{"text\/plain":{"schema":{"type":"string"},"examples":{"String":{"$ref":"#\/components\/examples\/String"}}}},"description":"OK"}}}},"\/api\/auth\/api-key":{"delete":{"security":[{"Basic Auth - login":[]},{"XSRF header":[]},{"DEPRECATED - PL API Key":[]},{"PL API Key":[]}],"responses":{"200":{"description":"OK","content":{"application\/json":{"examples":{"GenerateApiKeyResponse":{"$ref":"#\/components\/examples\/GenerateApiKeyResponse"}},"schema":{"$ref":"#\/components\/schemas\/GenerateApiKeyResponse"}}}}},"description":"Validates that the given token is linked to the currently authenticated user and removes it if so.","operationId":"deleteApiAuthApi-key","summary":"Removes a given API key for the user","requestBody":{"required":true,"content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/RemoveApiKeyRequest"},"examples":{"RemoveApiKeyRequest":{"$ref":"#\/components\/examples\/RemoveApiKeyRequest"}}}}},"tags":["Authentication"]}},"\/api\/v0.20\/auth\/email\/change":{"post":{"security":[{"Basic Auth - login":[]},{"XSRF header":[]},{"DEPRECATED - PL API Key":[]},{"PL API Key":[]}],"responses":{"200":{"description":"OK","content":{"application\/json":{"examples":{"GenericMessageResponse":{"$ref":"#\/components\/examples\/GenericMessageResponse"}},"schema":{"$ref":"#\/components\/schemas\/GenericMessageResponse"}}}}},"description":"DEPRECATED: This endpoint is not available when Keycloak authentication is turned on and will be removed in the future.\n\nSends an update email request to the provided new email address.","operationId":"postApiV0.20AuthEmailChange","deprecated":true,"summary":"Initiates an email change for the current user.","requestBody":{"required":true,"content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/UpdatedUserEmail"},"examples":{"UpdatedUserEmail":{"$ref":"#\/components\/examples\/UpdatedUserEmail"}}}}},"tags":["Authentication"]}},"\/api\/util\/quantumversion":{"get":{"operationId":"getApiUtilQuantumversion","summary":"Returns the Quantum Schema version","description":"Returns the current version of the Quantum schema in use by this webserver as a semantic version.","tags":["Utility"],"responses":{"200":{"content":{"text\/plain":{"schema":{"type":"string"},"examples":{"String":{"$ref":"#\/components\/examples\/String"}}}},"description":"OK"}}}},"\/api\/site\/copy":{"post":{"security":[{"Basic Auth - login":[]},{"XSRF header":[]},{"DEPRECATED - PL API Key":[]},{"PL API Key":[]}],"responses":{"200":{"content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ObjectIdentifiers"}}},"description":"OK"}},"description":"Copies Project from one organization to a target organization given a project Identifier.\nAll UUID's are created new for the copied project.\nReturns a mapping of old identifiers and new identifiers of the given project.\nHistory data is NOT copied unless startDate and endDate are provided.\nHistory copy will take time to complete in the background and there will be no indication of success.","operationId":"postApiSiteCopy","summary":"Copy Project from one organization to another","tags":["Site"],"parameters":[{"in":"query","description":"Organization to copy the given site into.","required":true,"schema":{"format":"uuid","type":"string"},"name":"targetOrganizationID"},{"in":"query","description":"Site to copy.","required":true,"schema":{"format":"uuid","type":"string"},"name":"siteID"},{"in":"query","description":"Optionally change the copied site name.","required":false,"schema":{"type":"string","nullable":true},"name":"siteName"},{"in":"query","description":"Optionally change the copied site directory.","required":false,"schema":{"type":"string","nullable":true},"name":"siteDirectory"},{"in":"query","description":"Date to start copying history from. Required to export all history.","required":false,"schema":{"nullable":true,"type":"string"},"name":"startDate"},{"in":"query","description":"Date to end copying history at. Required to export all history.","required":false,"schema":{"type":"string","nullable":true},"name":"endDate"}]}},"\/api\/v0.20\/account\/credentials":{"get":{"summary":"Retrieves a list of the credentials the current user has enabled.","description":"Retrieves the list of credentials enabled for the current user as reported by Keycloak. Credential types include password,\nTOPT, and passkeys. Note that `createdDate` will be sent as an ISO 8601 formatted string (e.g. 2025-10-10T16:32:11Z). Also note\nthat this API must be called with a properly authenticated JWT.","responses":{"200":{"content":{"application\/json":{"schema":{"items":{"$ref":"#\/components\/schemas\/KeycloakCredentialInfo"},"type":"array"}}},"description":"OK"}},"tags":["Account"],"operationId":"getApiV0.20AccountCredentials","security":[{"Basic Auth - login":[]},{"XSRF header":[]},{"DEPRECATED - PL API Key":[]},{"PL API Key":[]}]}},"\/api\/v0.20\/util\/quantumversion":{"get":{"description":"Returns the current version of the Quantum schema in use by this webserver as a semantic version.","operationId":"getApiV0.20UtilQuantumversion","summary":"Returns the Quantum Schema version","tags":["Utility"],"responses":{"200":{"content":{"text\/plain":{"examples":{"String":{"$ref":"#\/components\/examples\/String"}},"schema":{"type":"string"}}},"description":"OK"}}}},"\/api\/auth\/api-key\/generate":{"get":{"security":[{"Basic Auth - login":[]},{"XSRF header":[]},{"DEPRECATED - PL API Key":[]},{"PL API Key":[]}],"responses":{"200":{"content":{"application\/json":{"examples":{"GenerateApiKeyResponse":{"$ref":"#\/components\/examples\/GenerateApiKeyResponse"}},"schema":{"$ref":"#\/components\/schemas\/GenerateApiKeyResponse"}}},"description":"OK"}},"description":"Generates, stores, and returns a new API key with the default expiration period for the user currently logged in.\n\nOnce created, you can then provide this API key in an\n`Authorization: PL-API-KEY <Key>` header in replacement of an `X-PL-AUTH` header.","operationId":"getApiAuthApi-keyGenerate","summary":"Generates an API key for the current user","parameters":[{"name":"expireSeconds","in":"query","required":false,"schema":{"format":"int64","nullable":true,"type":"integer"},"example":2678400,"description":"Number of seconds until the key expires."},{"name":"role","in":"query","required":false,"schema":{"nullable":true,"type":"string"},"example":"ReadOnlyUser","description":"Role of the new key."}],"tags":["Authentication"]}},"\/api\/auth\/register":{"post":{"responses":{"200":{"content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/RegisterUserResponse"},"examples":{"RegisterUserResponse":{"$ref":"#\/components\/examples\/RegisterUserResponse"}}}},"description":"OK"}},"operationId":"postApiAuthRegister","description":"DEPRECATED: This endpoint is not available when Keycloak authentication is turned on and will be removed in the future.\n\nCreates a new user based on the provided information. Requires jwt obtained via email from\n`\/api\/auth\/register\/initiate`. The user status is set to `Active` and immediately logged in.\n\n\n\nRegistration token is required when email verification is enforced, as indicated by a failed response to this endpoint","deprecated":true,"summary":"Registers a new user","requestBody":{"required":true,"content":{"application\/json":{"examples":{"RegisterUserData":{"$ref":"#\/components\/examples\/RegisterUserData"}},"schema":{"$ref":"#\/components\/schemas\/RegisterUserData"}}}},"tags":["Authentication"]}},"\/api\/v0.20\/account\/user\/delete":{"delete":{"tags":["Account"],"responses":{"200":{"description":"OK","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/GenericMessageResponse"},"examples":{"GenericMessageResponse":{"$ref":"#\/components\/examples\/GenericMessageResponse"}}}}}},"security":[{"Basic Auth - login":[]},{"XSRF header":[]},{"DEPRECATED - PL API Key":[]},{"PL API Key":[]}],"description":"Deletes the requesting user if they are not a SuperUser within any organizations.\nOtherwise prompts them to transfer ownership or delete the org before making this request.","summary":"Deletes the user making this request.","operationId":"deleteApiV0.20AccountUserDelete"}},"\/api\/v0.19\/auth\/password\/reset\/change":{"post":{"security":[{"Basic Auth - login":[]},{"XSRF header":[]},{"DEPRECATED - PL API Key":[]},{"PL API Key":[]}],"responses":{"200":{"content":{"application\/json":{"examples":{"GenericMessageResponse":{"$ref":"#\/components\/examples\/GenericMessageResponse"}},"schema":{"$ref":"#\/components\/schemas\/GenericMessageResponse"}}},"description":"OK"}},"operationId":"postApiV0.19AuthPasswordResetChange","description":"DEPRECATED: This endpoint is not available when Keycloak authentication is turned on and will be removed in the future.\n\nChanges a user's password to the specified value, reached from password reset flow.\n\nToken authentication required, only using the authentication JWT decoded from the password reset URL sent to a user\nfrom a reset initiation.","deprecated":true,"summary":"Changes a user's password from the password reset flow.","requestBody":{"required":true,"content":{"application\/json":{"examples":{"ChangePasswordData":{"$ref":"#\/components\/examples\/ChangePasswordData"}},"schema":{"$ref":"#\/components\/schemas\/ChangePasswordData"}}}},"tags":["Authentication"]}},"\/app\/login\/signUp":{"get":{"operationId":"getAppLoginSignUp","tags":["app"],"summary":"Redirects to external authentication provider (Keycloak).","description":""}},"\/api\/auth\/verify":{"get":{"parameters":[{"example":"darthvader@galactic-empire.com","required":true,"description":"User's email to confirm as verified","name":"email","in":"query","schema":{"type":"string"}}],"description":"Redirects user to `\/api\/auth\/login`, passing along the provided valid jwt and email.\n\nExists in this form for backward compatibility.","tags":["Authentication"],"operationId":"getApiAuthVerify","summary":"Redirects user to login"}},"\/api\/metrics":{"get":{"tags":["api"],"description":"GET \/api\/metrics"}},"\/api\/binding":{"post":{"security":[{"Basic Auth - login":[]},{"XSRF header":[]},{"DEPRECATED - PL API Key":[]},{"PL API Key":[]}],"responses":{"200":{"description":"OK","content":{"application\/json":{"examples":{"BindingUploadResponse":{"$ref":"#\/components\/examples\/BindingUploadResponse"}},"schema":{"$ref":"#\/components\/schemas\/BindingUploadResponse"}}}}},"description":"Uploads a file to the server and associates that file with a binding node, setting its new stored URL & checksum in the\ndatabase. The data may be sent in either multipart\/form-data or JSON format. If using JSON, the image file must be\nBase64-encoded. Using multipart\/form-data is recommended as it is a more efficient way to transmit binary data.","operationId":"postApiBinding","summary":"Uploads a file associated with a binding.","requestBody":{"required":true,"content":{"multipart\/form-data":{"examples":{"UploadFileData":{"$ref":"#\/components\/examples\/UploadFileData"}},"schema":{"$ref":"#\/components\/schemas\/UploadFileData"}},"application\/json":{"examples":{"UploadFileData":{"$ref":"#\/components\/examples\/UploadFileData"}},"schema":{"$ref":"#\/components\/schemas\/UploadFileData"}}}},"tags":["Bindings"]}},"\/api\/graphql":{"get":{"security":[{"Basic Auth - login":[]},{"XSRF header":[]},{"DEPRECATED - PL API Key":[]},{"PL API Key":[]}],"responses":{"200":{"description":"OK","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/GraphQLResult"}}}}},"description":"Serves the GraphQL API. For more details, see [graphql.org](https:\/\/graphql.org\/learn\/serving-over-http\/#get-request)","operationId":"getApiGraphql","externalDocs":{"description":"GraphQL documentation.","url":"https:\/\/graphql.org\/learn\/serving-over-http\/#get-request"},"summary":"GraphQL API","parameters":[{"in":"query","required":true,"name":"query","schema":{"type":"string"}},{"in":"query","required":false,"name":"operationName","schema":{"type":"string","nullable":true}},{"in":"query","example":{},"required":false,"name":"variables","schema":{"additionalProperties":{"type":"boolean"},"nullable":true,"type":"object"}}],"tags":["GraphQL"]},"post":{"security":[{"Basic Auth - login":[]},{"XSRF header":[]},{"DEPRECATED - PL API Key":[]},{"PL API Key":[]}],"responses":{"200":{"content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/GraphQLResult"}}},"description":"OK"}},"description":"Serves the GraphQL API. For more details, see [graphql.org](https:\/\/graphql.org\/learn\/serving-over-http\/#post-request)","operationId":"postApiGraphql","externalDocs":{"url":"https:\/\/graphql.org\/learn\/serving-over-http\/#post-request","description":"GraphQL documentation."},"summary":"GraphQL API","requestBody":{"content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/GraphQLRequest"}}},"required":true},"tags":["GraphQL"]}},"\/api\/v0.19\/auth\/api-key\/remove":{"delete":{"security":[{"Basic Auth - login":[]},{"XSRF header":[]},{"DEPRECATED - PL API Key":[]},{"PL API Key":[]}],"responses":{"200":{"description":"OK","content":{"application\/json":{"examples":{"GenerateApiKeyResponse":{"$ref":"#\/components\/examples\/GenerateApiKeyResponse"}},"schema":{"$ref":"#\/components\/schemas\/GenerateApiKeyResponse"}}}}},"description":"Validates that the given token is linked to the currently authenticated user and removes it if so.","operationId":"deleteApiV0.19AuthApi-keyRemove","deprecated":true,"summary":"Removes a given API key for the user. This route has been deprecated in favor of: DELETE \/api\/v0.19\/auth\/api-key.","requestBody":{"required":true,"content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/RemoveApiKeyRequest"},"examples":{"RemoveApiKeyRequest":{"$ref":"#\/components\/examples\/RemoveApiKeyRequest"}}}}},"tags":["Authentication"]},"post":{"security":[{"Basic Auth - login":[]},{"XSRF header":[]},{"DEPRECATED - PL API Key":[]},{"PL API Key":[]}],"responses":{"200":{"content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/GenerateApiKeyResponse"},"examples":{"GenerateApiKeyResponse":{"$ref":"#\/components\/examples\/GenerateApiKeyResponse"}}}},"description":"OK"}},"description":"Validates that the given token is linked to the currently authenticated user and removes it if so.","operationId":"postApiV0.19AuthApi-keyRemove","deprecated":true,"summary":"Removes a given API key for the user. This route has been deprecated in favor of: DELETE \/api\/v0.19\/auth\/api-key.","requestBody":{"content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/RemoveApiKeyRequest"},"examples":{"RemoveApiKeyRequest":{"$ref":"#\/components\/examples\/RemoveApiKeyRequest"}}}},"required":true},"tags":["Authentication"]}},"\/app\/lp\/**":{"get":{"tags":["app"],"description":"GET \/app\/lp\/**"}},"\/api\/v0.19\/auth\/register":{"post":{"responses":{"200":{"content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/RegisterUserResponse"},"examples":{"RegisterUserResponse":{"$ref":"#\/components\/examples\/RegisterUserResponse"}}}},"description":"OK"}},"description":"DEPRECATED: This endpoint is not available when Keycloak authentication is turned on and will be removed in the future.\n\nCreates a new user based on the provided information. Requires jwt obtained via email from\n`\/api\/v0.19\/auth\/register\/initiate`. The user status is set to `Active` and immediately logged in.\n\n\n\nRegistration token is required when email verification is enforced, as indicated by a failed response to this endpoint","operationId":"postApiV0.19AuthRegister","deprecated":true,"summary":"Registers a new user","requestBody":{"content":{"application\/json":{"examples":{"RegisterUserData":{"$ref":"#\/components\/examples\/RegisterUserData"}},"schema":{"$ref":"#\/components\/schemas\/RegisterUserData"}}},"required":true},"tags":["Authentication"]}},"\/api\/v0.19\/util\/quantumlens":{"post":{"responses":{"200":{"description":"OK","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/QuantumLensResponse"}}}}},"tags":["Utility"],"operationId":"postApiV0.19UtilQuantumlens","summary":"QuantumLens (iOS) update & compatibility check","security":[{"Basic Auth - login":[]},{"XSRF header":[]},{"DEPRECATED - PL API Key":[]},{"PL API Key":[]}],"description":"Returns the status of the QuantumLens application for the current user.\n\n- `appUpdate`: indicates if a new app version is required (true = forced, false = soft, nil = no update)\n- `osUpdate`: indicates if an iOS update is required (true = update required, nil = compatible)\n- `user`: information about the current user\n\nThis response helps the client determine whether the app or iOS requires an update before continuing."}},"\/api\/v0.20\/organization\/update-logo":{"post":{"security":[{"Basic Auth - login":[]},{"XSRF header":[]},{"DEPRECATED - PL API Key":[]},{"PL API Key":[]}],"responses":{"200":{"content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ImageUploadResponse"},"examples":{"ImageUploadResponse":{"$ref":"#\/components\/examples\/ImageUploadResponse"}}}},"description":"OK"}},"operationId":"postApiV0.20OrganizationUpdate-logo","description":"Verifies that the user making the request has sufficient permissions to change the logo for the organization.\nTakes in a new image as the organization's logo. Creates or replaces the previous stored logo.","summary":"Updates the organization's logo","requestBody":{"content":{"application\/json":{"examples":{"OrganizationImageData":{"$ref":"#\/components\/examples\/OrganizationImageData"}},"schema":{"$ref":"#\/components\/schemas\/OrganizationImageData"}}},"required":true},"tags":["Organization"]}},"\/api\/auth\/magic-link-login":{"get":{"security":[{"Basic Auth - login":[]},{"XSRF header":[]},{"DEPRECATED - PL API Key":[]},{"PL API Key":[]}],"responses":{"200":{"content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/GenericMessageResponse"},"examples":{"GenericMessageResponse":{"$ref":"#\/components\/examples\/GenericMessageResponse"}}}},"description":"OK"}},"description":"DEPRECATED: This endpoint is not available when Keycloak authentication is turned on and will be removed in the future.\n\nRequires a magic login link containing containing `?token=<signed JWT with user email contained>`.\nThis is the secure mode and MUST be used in production.","deprecated":true,"operationId":"getApiAuthMagic-link-login","summary":"Logs in a user using Magic Link generated by POST magic-link-generate","tags":["Authentication"]}},"\/app\/login\/userAuth":{"get":{"operationId":"getAppLoginUserAuth","description":"","tags":["app"],"summary":"Redirects to external authentication provider (Keycloak)."}},"\/api\/v0.19\/util\/externalauthconfig":{"get":{"summary":"Provides information about the external auth configuration","operationId":"getApiV0.19UtilExternalauthconfig","tags":["Utility"],"description":"Use to check whether or not external auth (i.e. Keycloak) is enabled, and if so what the public settings are.","responses":{"200":{"content":{"text\/plain":{"examples":{"String":{"$ref":"#\/components\/examples\/String"}},"schema":{"type":"string"}}},"description":"OK"}}}},"\/api\/organization\/update-logo":{"post":{"security":[{"Basic Auth - login":[]},{"XSRF header":[]},{"DEPRECATED - PL API Key":[]},{"PL API Key":[]}],"responses":{"200":{"content":{"application\/json":{"examples":{"ImageUploadResponse":{"$ref":"#\/components\/examples\/ImageUploadResponse"}},"schema":{"$ref":"#\/components\/schemas\/ImageUploadResponse"}}},"description":"OK"}},"description":"Verifies that the user making the request has sufficient permissions to change the logo for the organization.\nTakes in a new image as the organization's logo. Creates or replaces the previous stored logo.","operationId":"postApiOrganizationUpdate-logo","summary":"Updates the organization's logo","requestBody":{"required":true,"content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/OrganizationImageData"},"examples":{"OrganizationImageData":{"$ref":"#\/components\/examples\/OrganizationImageData"}}}}},"tags":["Organization"]}},"\/api\/auth\/profile\/change":{"get":{"operationId":"getApiAuthProfileChange","summary":"Redirects the user the change profile flow in the external auth provider (Keycloak).","description":"","tags":["Authentication"],"security":[{"Basic Auth - login":[]},{"XSRF header":[]},{"DEPRECATED - PL API Key":[]},{"PL API Key":[]}]}},"\/api\/export\/property\/history":{"get":{"summary":"Exports CSV formatted property history data","security":[{"Basic Auth - login":[]},{"XSRF header":[]},{"DEPRECATED - PL API Key":[]},{"PL API Key":[]}],"responses":{"200":{"content":{"text\/plain":{"examples":{"String":{"$ref":"#\/components\/examples\/String"}},"schema":{"type":"string"}}},"description":"OK"}},"tags":["Export"],"operationId":"getApiExportPropertyHistory","description":"Returns a string representation of property history values in CSV format from the given properties.\nreturns in the following headers:\nTime,Equipment name,Property name,Unit,Value\n\nTime returned in ISO8601 string format"}},"\/api\/image":{"post":{"security":[{"Basic Auth - login":[]},{"XSRF header":[]},{"DEPRECATED - PL API Key":[]},{"PL API Key":[]}],"responses":{"200":{"content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ImageUploadResponse"},"examples":{"ImageUploadResponse":{"$ref":"#\/components\/examples\/ImageUploadResponse"}}}},"description":"OK"}},"operationId":"postApiImage","description":"Uploads an image to the server, setting its new stored url & checksum in the database. If an existing ID is given, this will\nattempt an update of the image data. The data may be sent in either multipart\/form-data or JSON format. If using JSON, the\nimage file must be Base64-encoded. Using multipart\/form-data is recommended as it is a more efficient way to transmit binary\ndata.\n\nThis endpoint is intended for associating image file data with an existing `Image` node in the Quantum schema.","summary":"Uploads an image.","requestBody":{"required":true,"content":{"application\/json":{"examples":{"UploadImageData":{"$ref":"#\/components\/examples\/UploadImageData"}},"schema":{"$ref":"#\/components\/schemas\/UploadImageData"}},"multipart\/form-data":{"examples":{"UploadImageData":{"$ref":"#\/components\/examples\/UploadImageData"}},"schema":{"$ref":"#\/components\/schemas\/UploadImageData"}}}},"tags":["Images"]}},"\/api\/auth\/email\/change\/verify":{"get":{"security":[{"Basic Auth - login":[]},{"XSRF header":[]},{"DEPRECATED - PL API Key":[]},{"PL API Key":[]}],"responses":{"200":{"description":"OK","content":{"application\/json":{"examples":{"GenericMessageResponse":{"$ref":"#\/components\/examples\/GenericMessageResponse"}},"schema":{"$ref":"#\/components\/schemas\/GenericMessageResponse"}}}}},"operationId":"getApiAuthEmailChangeVerify","description":"DEPRECATED: This endpoint is not available when Keycloak authentication is turned on and will be removed in the future.\n\nVerifies the new email is valid. Updates the user email with the newly validated one.\n\nToken authentication required. Provided by \/api\/auth\/email\/change.","deprecated":true,"summary":"Verifies and updates new user email","requestBody":{"content":{"application\/json":{"examples":{"UpdatedUserEmail":{"$ref":"#\/components\/examples\/UpdatedUserEmail"}},"schema":{"$ref":"#\/components\/schemas\/UpdatedUserEmail"}}},"required":true},"tags":["Authentication"]}},"\/api\/health\/readiness":{"get":{"tags":["Health"],"operationId":"getApiHealthReadiness","security":[{"Basic Auth - login":[]},{"XSRF header":[]},{"DEPRECATED - PL API Key":[]},{"PL API Key":[]}],"summary":"Readiness check used to determine if webserver is ready to accept traffic","description":"See https:\/\/kubernetes.io\/docs\/concepts\/configuration\/liveness-readiness-startup-probes\/#readiness-probe"}},"\/app\/qe\/*":{"get":{"tags":["app"],"description":"GET \/app\/qe\/*"}},"\/api\/v0.19\/organization\/join":{"post":{"security":[{"Basic Auth - login":[]},{"XSRF header":[]},{"DEPRECATED - PL API Key":[]},{"PL API Key":[]}],"responses":{"200":{"description":"OK","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/GenericMessageResponse"},"examples":{"GenericMessageResponse":{"$ref":"#\/components\/examples\/GenericMessageResponse"}}}}}},"operationId":"postApiV0.19OrganizationJoin","description":"Adds user to organization based on Organization invite ID.\nRole in organization is determined through Organization invite role, if no role is defined, we default to read-only user.","summary":"Adds a user to an organization","requestBody":{"required":true,"content":{"application\/json":{"examples":{"AcceptOrganizationInvite":{"$ref":"#\/components\/examples\/AcceptOrganizationInvite"}},"schema":{"$ref":"#\/components\/schemas\/AcceptOrganizationInvite"}}}},"tags":["Organization"]}},"\/api\/v0.19\/auth\/magic-link-login":{"get":{"security":[{"Basic Auth - login":[]},{"XSRF header":[]},{"DEPRECATED - PL API Key":[]},{"PL API Key":[]}],"responses":{"200":{"description":"OK","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/GenericMessageResponse"},"examples":{"GenericMessageResponse":{"$ref":"#\/components\/examples\/GenericMessageResponse"}}}}}},"operationId":"getApiV0.19AuthMagic-link-login","deprecated":true,"description":"DEPRECATED: This endpoint is not available when Keycloak authentication is turned on and will be removed in the future.\n\nRequires a magic login link containing containing `?token=<signed JWT with user email contained>`.\nThis is the secure mode and MUST be used in production.","summary":"Logs in a user using Magic Link generated by POST magic-link-generate","tags":["Authentication"]}}},"openapi":"3.0.1","info":{"description":"This page documents the operations supported by the PassiveLogic HTTP API, covering authentication, user management, and\nGraphQL API access.","version":"0.0.0","title":"PassiveLogic REST API"}}