openapi: 3.0.3 info: title: Entrosity Axis Portal API version: 0.5.0 description: > Entrosity Axis portal REST API. This file is the source of truth for the backend server interfaces (oapi-codegen), request validation, and the frontend types (openapi-typescript). Run `make gen` after editing. Authentication: `Authorization: Bearer `: users sign in on Entrosity Hub, which issues five-minute product tokens for Axis (`POST /api/platform/v1/auth/product-token {"product":"rmm"}`, with the Hub's session cookie). Users, tenants (the Hub's organizations) and roles are managed on the Hub; Axis keeps a copy. Every route's access rule (public, authenticated, global admin, tenant permission) is declared in `backend/internal/http/portal/access.go` and enforced before the handler runs. servers: - url: /api/v1 tags: - name: system - name: screens - name: auth - name: admin - name: tenant - name: enrollment - name: devices - name: adsync - name: packages - name: deployments - name: scripts security: - bearerAuth: [] paths: /healthz: get: operationId: getHealthz summary: Liveness probe tags: - system security: [] responses: '200': description: The API process is up. content: application/json: schema: $ref: '#/components/schemas/Health' default: $ref: '#/components/responses/Problem' /auth/sse-token: post: operationId: createStreamToken summary: Short-lived token for a tenant event stream (EventSource) description: | Returns a token valid for 60 seconds that opens `GET /tenants/{tenantID}/events?sse_token=` for the given tenant and the caller's session. Access to the tenant is checked when the stream opens. Keeps the access token out of URLs (proxy logs, browser history). tags: - auth requestBody: required: true content: application/json: schema: type: object additionalProperties: false required: - tenant_id properties: tenant_id: type: string format: uuid responses: '200': description: Stream token. content: application/json: schema: type: object required: - token - expires_in properties: token: type: string expires_in: type: integer description: Seconds until the token expires. default: $ref: '#/components/responses/Problem' /me: get: operationId: getMe summary: The signed-in user with their tenants and roles tags: - auth responses: '200': description: Current user. content: application/json: schema: $ref: '#/components/schemas/Me' default: $ref: '#/components/responses/Problem' /admin/overview: get: operationId: getAdminOverview summary: Cross-tenant counters tags: - admin responses: '200': description: Overview. content: application/json: schema: $ref: '#/components/schemas/AdminOverview' default: $ref: '#/components/responses/Problem' /admin/tenants: get: operationId: listTenants summary: List tenants tags: - admin parameters: - $ref: '#/components/parameters/Page' - $ref: '#/components/parameters/PageSize' - $ref: '#/components/parameters/Query' - name: status in: query schema: $ref: '#/components/schemas/TenantStatus' responses: '200': description: Tenants. content: application/json: schema: $ref: '#/components/schemas/TenantList' default: $ref: '#/components/responses/Problem' /admin/tenants/{tenantID}: parameters: - $ref: '#/components/parameters/TenantID' get: operationId: getAdminTenant summary: Get any tenant (including suspended ones) tags: - admin responses: '200': description: Tenant. content: application/json: schema: $ref: '#/components/schemas/Tenant' default: $ref: '#/components/responses/Problem' patch: operationId: updateAdminTenant summary: Change the settings of a tenant (name and status are the Hub's) tags: - admin requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/UpdateAdminTenantRequest' responses: '200': description: Updated. content: application/json: schema: $ref: '#/components/schemas/Tenant' default: $ref: '#/components/responses/Problem' /admin/users: get: operationId: listGlobalAdmins summary: Global admins (the platform admins of Entrosity Hub) tags: - admin responses: '200': description: Users. content: application/json: schema: $ref: '#/components/schemas/UserDirectory' default: $ref: '#/components/responses/Problem' /admin/audit: get: operationId: listAdminAudit summary: Cross-tenant audit log tags: - admin parameters: - $ref: '#/components/parameters/Page' - $ref: '#/components/parameters/PageSize' - name: tenant_id in: query schema: type: string format: uuid - $ref: '#/components/parameters/AuditActor' - $ref: '#/components/parameters/AuditAction' - $ref: '#/components/parameters/AuditResourceType' - $ref: '#/components/parameters/AuditFrom' - $ref: '#/components/parameters/AuditTo' responses: '200': description: Audit entries, newest first. content: application/json: schema: $ref: '#/components/schemas/AuditList' default: $ref: '#/components/responses/Problem' /admin/packages: get: operationId: listGlobalPackages summary: Global packages (visible to every tenant) tags: - admin - packages parameters: - $ref: '#/components/parameters/Page' - $ref: '#/components/parameters/PageSize' - $ref: '#/components/parameters/Query' - $ref: '#/components/parameters/PackageKindFilter' - $ref: '#/components/parameters/ReadyOnly' responses: '200': description: One page of global packages. content: application/json: schema: $ref: '#/components/schemas/PackageList' default: $ref: '#/components/responses/Problem' post: operationId: createGlobalPackage summary: Create a global package tags: - admin - packages requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/CreatePackageRequest' responses: '201': description: Created. content: application/json: schema: $ref: '#/components/schemas/Package' default: $ref: '#/components/responses/Problem' /admin/packages/{packageID}: parameters: - $ref: '#/components/parameters/PackageID' get: operationId: getGlobalPackage summary: Global package detail tags: - admin - packages responses: '200': description: Package. content: application/json: schema: $ref: '#/components/schemas/Package' default: $ref: '#/components/responses/Problem' patch: operationId: updateGlobalPackage summary: Edit a global package tags: - admin - packages requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/UpdatePackageRequest' responses: '200': description: Updated. content: application/json: schema: $ref: '#/components/schemas/Package' default: $ref: '#/components/responses/Problem' delete: operationId: deleteGlobalPackage summary: Delete a global package (409 package_in_use) tags: - admin - packages responses: '204': description: Deleted. default: $ref: '#/components/responses/Problem' /admin/packages/{packageID}/upload-url: parameters: - $ref: '#/components/parameters/PackageID' post: operationId: createGlobalPackageUploadURL summary: Presigned PUT for a global package file tags: - admin - packages requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/PackageUploadRequest' responses: '200': description: Upload target. content: application/json: schema: $ref: '#/components/schemas/PackageUploadTarget' default: $ref: '#/components/responses/Problem' /admin/packages/{packageID}/finalize: parameters: - $ref: '#/components/parameters/PackageID' post: operationId: finalizeGlobalPackage summary: Verify a global package upload and mark it ready tags: - admin - packages requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/PackageFinalizeRequest' responses: '200': description: Ready. content: application/json: schema: $ref: '#/components/schemas/Package' default: $ref: '#/components/responses/Problem' /admin/winget/search: get: operationId: searchWingetGlobal summary: Search the cached winget index (global package library) tags: - admin - packages parameters: - $ref: '#/components/parameters/WingetQuery' responses: '200': description: Matches. content: application/json: schema: $ref: '#/components/schemas/WingetSearchResult' default: $ref: '#/components/responses/Problem' /tenants/{tenantID}: parameters: - $ref: '#/components/parameters/TenantID' get: operationId: getTenant summary: Tenant profile tags: - tenant responses: '200': description: Tenant. content: application/json: schema: $ref: '#/components/schemas/Tenant' default: $ref: '#/components/responses/Problem' patch: operationId: updateTenant summary: Change the tenant's settings (the name is the Hub's) tags: - tenant requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/UpdateTenantRequest' responses: '200': description: Updated. content: application/json: schema: $ref: '#/components/schemas/Tenant' default: $ref: '#/components/responses/Problem' /tenants/{tenantID}/me/notification-prefs: get: operationId: getTenantNotificationPrefs summary: My alert e-mail preferences for this tenant description: Defaults for global admins who are not members of the tenant. tags: - tenant - alerts parameters: - $ref: '#/components/parameters/TenantID' responses: '200': description: Preferences. content: application/json: schema: $ref: '#/components/schemas/NotificationPrefs' default: $ref: '#/components/responses/Problem' put: operationId: setTenantNotificationPrefs summary: >- Set my alert e-mail preferences for this tenant (members only; 409 not_a_member) tags: - tenant - alerts parameters: - $ref: '#/components/parameters/TenantID' requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/NotificationPrefs' responses: '200': description: Stored. content: application/json: schema: $ref: '#/components/schemas/NotificationPrefs' default: $ref: '#/components/responses/Problem' /tenants/{tenantID}/dashboard: parameters: - $ref: '#/components/parameters/TenantID' get: operationId: getTenantDashboard summary: Tenant counters and device overview tags: - tenant responses: '200': description: Dashboard. content: application/json: schema: $ref: '#/components/schemas/TenantDashboard' default: $ref: '#/components/responses/Problem' /tenants/{tenantID}/users: parameters: - $ref: '#/components/parameters/TenantID' get: operationId: listTenantUsers summary: Tenant members and their roles (managed on Entrosity Hub) tags: - tenant responses: '200': description: Users. content: application/json: schema: $ref: '#/components/schemas/UserDirectory' default: $ref: '#/components/responses/Problem' /tenants/{tenantID}/sites: parameters: - $ref: '#/components/parameters/TenantID' get: operationId: listSites summary: Sites of the tenant tags: - tenant responses: '200': description: Sites. content: application/json: schema: $ref: '#/components/schemas/SiteList' default: $ref: '#/components/responses/Problem' post: operationId: createSite summary: Create a site tags: - tenant requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/CreateSiteRequest' responses: '201': description: Created. content: application/json: schema: $ref: '#/components/schemas/Site' default: $ref: '#/components/responses/Problem' /tenants/{tenantID}/sites/{siteID}: parameters: - $ref: '#/components/parameters/TenantID' - $ref: '#/components/parameters/SiteID' get: operationId: getSite summary: Get a site tags: - tenant responses: '200': description: Site. content: application/json: schema: $ref: '#/components/schemas/Site' default: $ref: '#/components/responses/Problem' patch: operationId: updateSite summary: Update a site tags: - tenant requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/UpdateSiteRequest' responses: '200': description: Updated. content: application/json: schema: $ref: '#/components/schemas/Site' default: $ref: '#/components/responses/Problem' delete: operationId: deleteSite summary: Delete a site tags: - tenant responses: '204': description: Deleted. default: $ref: '#/components/responses/Problem' /tenants/{tenantID}/audit: parameters: - $ref: '#/components/parameters/TenantID' get: operationId: listTenantAudit summary: Audit log of the tenant tags: - tenant parameters: - $ref: '#/components/parameters/Page' - $ref: '#/components/parameters/PageSize' - $ref: '#/components/parameters/AuditActor' - $ref: '#/components/parameters/AuditAction' - $ref: '#/components/parameters/AuditResourceType' - $ref: '#/components/parameters/AuditFrom' - $ref: '#/components/parameters/AuditTo' responses: '200': description: Audit entries, newest first. content: application/json: schema: $ref: '#/components/schemas/AuditList' default: $ref: '#/components/responses/Problem' /tenants/{tenantID}/enrollment-tokens: parameters: - $ref: '#/components/parameters/TenantID' get: operationId: listEnrollmentTokens summary: Enrollment tokens of the tenant tags: - enrollment responses: '200': description: Tokens, newest first. content: application/json: schema: $ref: '#/components/schemas/EnrollmentTokenList' default: $ref: '#/components/responses/Problem' post: operationId: createEnrollmentToken summary: Create an enrollment token (the secret is returned once) tags: - enrollment requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/CreateEnrollmentTokenRequest' responses: '201': description: >- Created. `token`, `install_command` and `download_url` are shown only now. content: application/json: schema: $ref: '#/components/schemas/CreatedEnrollmentToken' default: $ref: '#/components/responses/Problem' /tenants/{tenantID}/enrollment-tokens/{tokenID}: parameters: - $ref: '#/components/parameters/TenantID' - $ref: '#/components/parameters/TokenID' delete: operationId: revokeEnrollmentToken summary: Revoke an enrollment token tags: - enrollment responses: '204': description: Revoked. default: $ref: '#/components/responses/Problem' /tenants/{tenantID}/enrollment-tokens/{tokenID}/delete: parameters: - $ref: '#/components/parameters/TenantID' - $ref: '#/components/parameters/TokenID' post: operationId: deleteEnrollmentToken summary: >- Delete an enrollment token permanently (global admins; requires the password) description: | Removes the token from the list for good. Unlike revoking, nothing of the token is kept except the audit entry. Agents and connectors that enrolled with it keep working (they have their own keys). Only global admins may delete tokens, and they must confirm with their own password: they send `step_up_token`, which Entrosity Hub issues for the password (`POST /api/platform/v1/auth/step-up`, product `rmm`); an invalid, expired or reused one is a 422 with a `step_up_token` field error. Deleting the token an Active Directory sync uses for agent pushes is allowed; a new one is made for the next push. tags: - enrollment requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/DeleteEnrollmentTokenRequest' responses: '204': description: Deleted. default: $ref: '#/components/responses/Problem' /tenants/{tenantID}/devices: parameters: - $ref: '#/components/parameters/TenantID' get: operationId: listDevices summary: Devices of the tenant (filtered, sorted, paginated) tags: - devices parameters: - $ref: '#/components/parameters/Page' - $ref: '#/components/parameters/PageSize' - $ref: '#/components/parameters/Query' - name: sort in: query description: >- Column, `-` prefix for descending: hostname, status, os_name, last_seen_at, agent_version, last_user, created_at. schema: type: string maxLength: 40 - name: status in: query style: form explode: true schema: type: array maxItems: 3 items: $ref: '#/components/schemas/DevicePresence' - name: os in: query style: form explode: true schema: type: array maxItems: 20 items: type: string maxLength: 200 - name: ou in: query schema: type: string maxLength: 500 - name: tag in: query style: form explode: true schema: type: array maxItems: 20 items: type: string maxLength: 64 - name: site_id in: query schema: type: string format: uuid - name: source in: query schema: type: string enum: - agent - ad - both - name: software in: query schema: type: string maxLength: 200 - name: agent_version in: query schema: type: string maxLength: 64 - name: last_seen_before in: query schema: type: string format: date-time - name: last_seen_after in: query schema: type: string format: date-time responses: '200': description: One page of devices. content: application/json: schema: $ref: '#/components/schemas/DeviceList' default: $ref: '#/components/responses/Problem' /tenants/{tenantID}/devices/bulk-actions: parameters: - $ref: '#/components/parameters/TenantID' post: operationId: bulkDeviceAction summary: Run an action on many devices (ids or filter, max 5000) tags: - devices requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/BulkActionRequest' responses: '200': description: Jobs created. content: application/json: schema: $ref: '#/components/schemas/BulkActionResult' default: $ref: '#/components/responses/Problem' /tenants/{tenantID}/devices/{deviceID}: parameters: - $ref: '#/components/parameters/TenantID' - $ref: '#/components/parameters/DeviceID' get: operationId: getDevice summary: Device detail tags: - devices responses: '200': description: Device. content: application/json: schema: $ref: '#/components/schemas/Device' default: $ref: '#/components/responses/Problem' patch: operationId: updateDevice summary: Edit display name, tags, custom fields or site tags: - devices requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/UpdateDeviceRequest' responses: '200': description: Updated. content: application/json: schema: $ref: '#/components/schemas/Device' default: $ref: '#/components/responses/Problem' delete: operationId: decommissionDevice summary: Decommission (soft delete, revoke the agent key, close its connection) tags: - devices responses: '204': description: Decommissioned. default: $ref: '#/components/responses/Problem' /tenants/{tenantID}/devices/{deviceID}/software: parameters: - $ref: '#/components/parameters/TenantID' - $ref: '#/components/parameters/DeviceID' get: operationId: listDeviceSoftware summary: Installed software tags: - devices parameters: - $ref: '#/components/parameters/Query' responses: '200': description: Software. content: application/json: schema: $ref: '#/components/schemas/DeviceSoftwareList' default: $ref: '#/components/responses/Problem' /tenants/{tenantID}/devices/{deviceID}/disks: parameters: - $ref: '#/components/parameters/TenantID' - $ref: '#/components/parameters/DeviceID' get: operationId: listDeviceDisks summary: Logical disks tags: - devices responses: '200': description: Disks. content: application/json: schema: $ref: '#/components/schemas/DeviceDiskList' default: $ref: '#/components/responses/Problem' /tenants/{tenantID}/devices/{deviceID}/network: parameters: - $ref: '#/components/parameters/TenantID' - $ref: '#/components/parameters/DeviceID' get: operationId: listDeviceNetwork summary: Network adapters tags: - devices responses: '200': description: Adapters. content: application/json: schema: $ref: '#/components/schemas/DeviceNetworkList' default: $ref: '#/components/responses/Problem' /tenants/{tenantID}/devices/{deviceID}/services: parameters: - $ref: '#/components/parameters/TenantID' - $ref: '#/components/parameters/DeviceID' get: operationId: listDeviceServices summary: Windows services tags: - devices responses: '200': description: Services. content: application/json: schema: $ref: '#/components/schemas/DeviceServiceList' default: $ref: '#/components/responses/Problem' /tenants/{tenantID}/devices/{deviceID}/updates: parameters: - $ref: '#/components/parameters/TenantID' - $ref: '#/components/parameters/DeviceID' get: operationId: listDeviceUpdates summary: Installed updates (hotfixes) tags: - devices responses: '200': description: Updates. content: application/json: schema: $ref: '#/components/schemas/DeviceUpdateList' default: $ref: '#/components/responses/Problem' /tenants/{tenantID}/devices/{deviceID}/local-users: parameters: - $ref: '#/components/parameters/TenantID' - $ref: '#/components/parameters/DeviceID' get: operationId: listDeviceLocalUsers summary: Local accounts tags: - devices responses: '200': description: Local users. content: application/json: schema: $ref: '#/components/schemas/DeviceLocalUserList' default: $ref: '#/components/responses/Problem' /tenants/{tenantID}/devices/{deviceID}/logons: parameters: - $ref: '#/components/parameters/TenantID' - $ref: '#/components/parameters/DeviceID' get: operationId: listDeviceLogons summary: Sign-ins on the device (newest first, last 7 days) description: > Windows sign-ins (console and Remote Desktop) reported by the agent. Entries are deleted 7 days after the sign-out; sign-ins that are still open are kept. tags: - devices parameters: - name: limit in: query schema: type: integer minimum: 1 maximum: 500 default: 200 responses: '200': description: Sign-ins. content: application/json: schema: $ref: '#/components/schemas/DeviceLogonList' default: $ref: '#/components/responses/Problem' /tenants/{tenantID}/devices/{deviceID}/metrics: parameters: - $ref: '#/components/parameters/TenantID' - $ref: '#/components/parameters/DeviceID' get: operationId: getDeviceMetrics summary: Downsampled CPU, memory, disk and CPU temperature series tags: - devices parameters: - name: range in: query schema: type: string enum: - 1h - 24h - 7d - 30d default: 24h responses: '200': description: Series. content: application/json: schema: $ref: '#/components/schemas/DeviceMetrics' default: $ref: '#/components/responses/Problem' /tenants/{tenantID}/devices/{deviceID}/jobs: parameters: - $ref: '#/components/parameters/TenantID' - $ref: '#/components/parameters/DeviceID' get: operationId: listDeviceJobs summary: Recent jobs of the device (newest first) tags: - devices parameters: - name: limit in: query schema: type: integer minimum: 1 maximum: 200 default: 50 responses: '200': description: Jobs. content: application/json: schema: $ref: '#/components/schemas/JobList' default: $ref: '#/components/responses/Problem' /tenants/{tenantID}/devices/{deviceID}/actions/inventory: parameters: - $ref: '#/components/parameters/TenantID' - $ref: '#/components/parameters/DeviceID' post: operationId: deviceActionInventory summary: Request an inventory refresh tags: - devices requestBody: required: false content: application/json: schema: $ref: '#/components/schemas/InventoryActionRequest' responses: '202': description: Job created. content: application/json: schema: $ref: '#/components/schemas/Job' default: $ref: '#/components/responses/Problem' /tenants/{tenantID}/devices/{deviceID}/actions/reboot: parameters: - $ref: '#/components/parameters/TenantID' - $ref: '#/components/parameters/DeviceID' post: operationId: deviceActionReboot summary: Reboot the device tags: - devices requestBody: required: false content: application/json: schema: $ref: '#/components/schemas/PowerActionRequest' responses: '202': description: Job created. content: application/json: schema: $ref: '#/components/schemas/Job' default: $ref: '#/components/responses/Problem' /tenants/{tenantID}/devices/{deviceID}/actions/shutdown: parameters: - $ref: '#/components/parameters/TenantID' - $ref: '#/components/parameters/DeviceID' post: operationId: deviceActionShutdown summary: Shut the device down tags: - devices requestBody: required: false content: application/json: schema: $ref: '#/components/schemas/PowerActionRequest' responses: '202': description: Job created. content: application/json: schema: $ref: '#/components/schemas/Job' default: $ref: '#/components/responses/Problem' /tenants/{tenantID}/devices/{deviceID}/actions/uninstall-software: parameters: - $ref: '#/components/parameters/TenantID' - $ref: '#/components/parameters/DeviceID' post: operationId: deviceActionUninstallSoftware summary: Uninstall a program from the device inventory description: | Uses the MSI product code (msiexec /x … /qn), the vendor's quiet uninstall string, winget, or the uninstall string with the given silent arguments. 409 codes: no_agent, software_not_found, needs_silent_args, no_uninstall_method. tags: - devices requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/UninstallSoftwareRequest' responses: '202': description: Job created. content: application/json: schema: $ref: '#/components/schemas/Job' default: $ref: '#/components/responses/Problem' /tenants/{tenantID}/devices/{deviceID}/actions/wake: parameters: - $ref: '#/components/parameters/TenantID' - $ref: '#/components/parameters/DeviceID' post: operationId: deviceActionWake summary: Wake the device (Wake-on-LAN through its site's connector) description: '409 codes: no_site, no_connector, no_mac_address.' tags: - devices responses: '202': description: Connector job created. content: application/json: schema: $ref: '#/components/schemas/Job' default: $ref: '#/components/responses/Problem' /tenants/{tenantID}/devices/{deviceID}/remote-sessions: parameters: - $ref: '#/components/parameters/TenantID' - $ref: '#/components/parameters/DeviceID' post: operationId: createRemoteSession summary: Start a remote desktop session on the device description: | Queues a `remote_desktop` job: the agent (after the signed-in user accepts, when `require_consent` is set) opens a stream to the server. Open the viewer WebSocket at `viewer_path?ticket=` within `ticket_expires_in` seconds; the ticket works once. A newer session on the same device ends the older one. 403 code remote_unattended_forbidden: `require_consent` false or `show_banner` false without `devices:remote_unattended` (only tenant and global admins may skip the prompt or hide the session bar). 409 codes: offline, no_agent, remote_unsupported (the agent is too old or not on Windows), decommissioned. tags: - devices requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/RemoteSessionCreate' responses: '201': description: Session created; the viewer may connect. content: application/json: schema: $ref: '#/components/schemas/RemoteSessionStart' default: $ref: '#/components/responses/Problem' /tenants/{tenantID}/remote-sessions/{sessionID}/end: parameters: - $ref: '#/components/parameters/TenantID' - $ref: '#/components/parameters/SessionID' post: operationId: endRemoteSession summary: End a remote desktop session description: Closes both sides of the stream. Ending a finished session is a no-op. tags: - devices responses: '200': description: The session. content: application/json: schema: $ref: '#/components/schemas/RemoteSession' default: $ref: '#/components/responses/Problem' /tenants/{tenantID}/screen-wall/rooms: parameters: - $ref: '#/components/parameters/TenantID' get: operationId: listScreenWallRooms summary: Rooms whose screens the caller may watch description: | The rooms of Entrosity Matrix with their computers: every room for technicians and administrators, the rooms granted on Matrix's Room rights page for teachers. `banner` says whether the computers show the session bar: `always` (technicians), `never` (teachers) or `optional` (administrators choose; on by default). 503 screen_wall_unavailable: Entrosity Matrix is not configured. tags: - screens responses: '200': description: Rooms. content: application/json: schema: $ref: '#/components/schemas/ScreenWallRoomList' default: $ref: '#/components/responses/Problem' /tenants/{tenantID}/screen-wall/open: parameters: - $ref: '#/components/parameters/TenantID' post: operationId: openScreenWall summary: Watch a room's screens (view only, up to 30) description: | Starts a small view-only remote desktop session (profile `wall`) on each online computer of the room, at most 30, without asking the users. Open each tile's viewer WebSocket at `viewer_path?ticket=` within `ticket_expires_in` seconds; closing it ends the session. A tile without a picture says why in `status`: `not_in_axis` (no device with that name), `offline`, `no_agent`, `busy` (someone is in a remote session with it; the wall never ends it), `agent_too_old` (the agent updates itself), `unsupported` or `unavailable`. `show_banner` is used for administrators only. 404: the room does not exist or is not granted to the teacher. tags: - screens requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/ScreenWallOpen' responses: '200': description: The wall's tiles. content: application/json: schema: $ref: '#/components/schemas/ScreenWall' default: $ref: '#/components/responses/Problem' /tenants/{tenantID}/devices/{deviceID}/merge: parameters: - $ref: '#/components/parameters/TenantID' - $ref: '#/components/parameters/DeviceID' post: operationId: mergeDevice summary: Merge another device record into this one description: | This device is kept; the other one's history (jobs, deployment targets, script runs, alerts), AD link and, if it has one, its agent with inventory and metrics move over, and the other record is removed. 409 both_have_agents when both have an agent. tags: - devices requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/MergeDeviceRequest' responses: '200': description: The kept device. content: application/json: schema: $ref: '#/components/schemas/Device' default: $ref: '#/components/responses/Problem' /tenants/{tenantID}/jobs/{jobID}: parameters: - $ref: '#/components/parameters/TenantID' - $ref: '#/components/parameters/JobID' get: operationId: getJob summary: Job status and result tags: - devices responses: '200': description: Job. content: application/json: schema: $ref: '#/components/schemas/Job' default: $ref: '#/components/responses/Problem' /tenants/{tenantID}/jobs/{jobID}/cancel: parameters: - $ref: '#/components/parameters/TenantID' - $ref: '#/components/parameters/JobID' post: operationId: cancelJob summary: Cancel an unfinished job (best effort on the agent) tags: - devices responses: '200': description: Cancelled. content: application/json: schema: $ref: '#/components/schemas/Job' default: $ref: '#/components/responses/Problem' /tenants/{tenantID}/events: parameters: - $ref: '#/components/parameters/TenantID' get: operationId: streamTenantEvents summary: Server-sent events for the tenant description: | `text/event-stream` of `event: ` / `data: ` frames (`device.status`, `device.inventory`, `device.updated`, `device.event`, `job.update`) plus a comment heartbeat every 25 s. Browsers cannot set headers on EventSource: instead of the Authorization header, pass a stream token from `POST /auth/sse-token` as `?sse_token=` (valid for a minute, for this tenant only; the stream stays open after it expires). tags: - tenant parameters: - name: sse_token in: query schema: type: string maxLength: 4096 responses: '200': description: Event stream. content: text/event-stream: schema: type: string default: $ref: '#/components/responses/Problem' /tenants/{tenantID}/connectors: parameters: - $ref: '#/components/parameters/TenantID' get: operationId: listConnectors summary: Site connectors of the tenant tags: - adsync responses: '200': description: Connectors. content: application/json: schema: $ref: '#/components/schemas/ConnectorList' default: $ref: '#/components/responses/Problem' /tenants/{tenantID}/connectors/{connectorID}: parameters: - $ref: '#/components/parameters/TenantID' - $ref: '#/components/parameters/ConnectorID' get: operationId: getConnector summary: One site connector tags: - adsync responses: '200': description: The connector. content: application/json: schema: $ref: '#/components/schemas/Connector' default: $ref: '#/components/responses/Problem' delete: operationId: deleteConnector summary: Revoke a connector (its AD sync configurations are removed) tags: - adsync responses: '204': description: Revoked. default: $ref: '#/components/responses/Problem' /tenants/{tenantID}/connectors/{connectorID}/test-ldap: parameters: - $ref: '#/components/parameters/TenantID' - $ref: '#/components/parameters/ConnectorID' post: operationId: testLDAP summary: Test LDAP settings through the connector (waits up to 20 s) tags: - adsync requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/LDAPProbeRequest' responses: '200': description: Test result. content: application/json: schema: $ref: '#/components/schemas/LDAPTestResult' default: $ref: '#/components/responses/Problem' /tenants/{tenantID}/connectors/{connectorID}/ldap-ous: parameters: - $ref: '#/components/parameters/TenantID' - $ref: '#/components/parameters/ConnectorID' post: operationId: probeLDAPOUs summary: List the directory's OUs with the given settings (waits up to 20 s) tags: - adsync requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/LDAPProbeRequest' responses: '200': description: Organizational units. content: application/json: schema: $ref: '#/components/schemas/OUList' default: $ref: '#/components/responses/Problem' /tenants/{tenantID}/ad-sync/configs: parameters: - $ref: '#/components/parameters/TenantID' get: operationId: listADSyncConfigs summary: AD sync configurations tags: - adsync responses: '200': description: Configurations. content: application/json: schema: $ref: '#/components/schemas/ADSyncConfigList' default: $ref: '#/components/responses/Problem' post: operationId: createADSyncConfig summary: Create an AD sync configuration tags: - adsync requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/ADSyncConfigRequest' responses: '201': description: Created. content: application/json: schema: $ref: '#/components/schemas/ADSyncConfig' default: $ref: '#/components/responses/Problem' /tenants/{tenantID}/ad-sync/configs/{configID}: parameters: - $ref: '#/components/parameters/TenantID' - $ref: '#/components/parameters/ConfigID' get: operationId: getADSyncConfig summary: One AD sync configuration tags: - adsync responses: '200': description: The configuration (secrets are never returned). content: application/json: schema: $ref: '#/components/schemas/ADSyncConfig' default: $ref: '#/components/responses/Problem' put: operationId: updateADSyncConfig summary: Replace an AD sync configuration (omitted passwords are kept) tags: - adsync requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/ADSyncConfigRequest' responses: '200': description: Updated. content: application/json: schema: $ref: '#/components/schemas/ADSyncConfig' default: $ref: '#/components/responses/Problem' delete: operationId: deleteADSyncConfig summary: Delete an AD sync configuration and its mirrored computers tags: - adsync responses: '204': description: Deleted. default: $ref: '#/components/responses/Problem' /tenants/{tenantID}/ad-sync/configs/{configID}/run: parameters: - $ref: '#/components/parameters/TenantID' - $ref: '#/components/parameters/ConfigID' post: operationId: runADSync summary: Start a sync now (409 when the connector is offline or a run is active) tags: - adsync responses: '202': description: Run started. content: application/json: schema: $ref: '#/components/schemas/ADSyncRun' default: $ref: '#/components/responses/Problem' /tenants/{tenantID}/ad-sync/configs/{configID}/runs: parameters: - $ref: '#/components/parameters/TenantID' - $ref: '#/components/parameters/ConfigID' get: operationId: listADSyncRuns summary: Recent runs of a configuration (newest first, max 100) tags: - adsync responses: '200': description: Runs. content: application/json: schema: $ref: '#/components/schemas/ADSyncRunList' default: $ref: '#/components/responses/Problem' /tenants/{tenantID}/ad-sync/configs/{configID}/ous: parameters: - $ref: '#/components/parameters/TenantID' - $ref: '#/components/parameters/ConfigID' get: operationId: listADSyncConfigOUs summary: The directory's OUs using the stored settings (waits up to 20 s) tags: - adsync responses: '200': description: Organizational units. content: application/json: schema: $ref: '#/components/schemas/OUList' default: $ref: '#/components/responses/Problem' /tenants/{tenantID}/ad-computers: parameters: - $ref: '#/components/parameters/TenantID' get: operationId: listADComputers summary: Computers mirrored from Active Directory tags: - adsync parameters: - $ref: '#/components/parameters/Page' - $ref: '#/components/parameters/PageSize' - $ref: '#/components/parameters/Query' - name: config_id in: query schema: type: string format: uuid - name: ou in: query schema: type: string maxLength: 2048 - name: enabled in: query schema: type: boolean - name: gone in: query schema: type: boolean - name: unmanaged in: query description: true for computers without an agent-managed device. schema: type: boolean - name: push in: query description: >- Agent push state: `none` (never pushed), `pending` (queued or in progress), `success`, `failed`. schema: type: string enum: - none - pending - success - failed - name: push_error_code in: query description: >- Only failed pushes with this error code (see the error codes reference). schema: type: string maxLength: 64 responses: '200': description: One page of computers. content: application/json: schema: $ref: '#/components/schemas/ADComputerList' default: $ref: '#/components/responses/Problem' /tenants/{tenantID}/ad-computers/summary: parameters: - $ref: '#/components/parameters/TenantID' get: operationId: getADComputerSummary summary: How many AD computers run the agent, and why the others do not description: | Counts for an OU (and every OU below it) and/or a domain configuration, or the whole tenant. The push counts and the failures by error code cover present computers that still have no agent: the ones that need attention. tags: - adsync parameters: - name: config_id in: query schema: type: string format: uuid - name: ou in: query schema: type: string maxLength: 2048 responses: '200': description: The counts. content: application/json: schema: $ref: '#/components/schemas/ADComputerSummary' default: $ref: '#/components/responses/Problem' /tenants/{tenantID}/ad-computers/ous: parameters: - $ref: '#/components/parameters/TenantID' get: operationId: listADComputerOUs summary: OUs that contain synced computers (for filters) tags: - adsync responses: '200': description: OUs with computer counts. content: application/json: schema: $ref: '#/components/schemas/ADOUCountList' default: $ref: '#/components/responses/Problem' /tenants/{tenantID}/ad-computers/push-agent: parameters: - $ref: '#/components/parameters/TenantID' post: operationId: pushAgent summary: Install the agent on AD computers through their connector tags: - adsync requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/PushAgentRequest' responses: '202': description: Push jobs queued; progress arrives as `adsync.push` events. content: application/json: schema: $ref: '#/components/schemas/PushAgentResult' default: $ref: '#/components/responses/Problem' /tenants/{tenantID}/packages: parameters: - $ref: '#/components/parameters/TenantID' get: operationId: listPackages summary: Packages of the tenant plus global packages (`scope` tells which) tags: - packages parameters: - $ref: '#/components/parameters/Page' - $ref: '#/components/parameters/PageSize' - $ref: '#/components/parameters/Query' - $ref: '#/components/parameters/PackageKindFilter' - $ref: '#/components/parameters/ReadyOnly' responses: '200': description: One page of packages. content: application/json: schema: $ref: '#/components/schemas/PackageList' default: $ref: '#/components/responses/Problem' post: operationId: createPackage summary: Create a package (file kinds start as draft until finalize) tags: - packages requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/CreatePackageRequest' responses: '201': description: Created. content: application/json: schema: $ref: '#/components/schemas/Package' default: $ref: '#/components/responses/Problem' /tenants/{tenantID}/packages/{packageID}: parameters: - $ref: '#/components/parameters/TenantID' - $ref: '#/components/parameters/PackageID' get: operationId: getPackage summary: Package detail (tenant or global) tags: - packages responses: '200': description: Package. content: application/json: schema: $ref: '#/components/schemas/Package' default: $ref: '#/components/responses/Problem' patch: operationId: updatePackage summary: >- Edit package metadata (omitted fields keep their value; global packages are read-only here) tags: - packages requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/UpdatePackageRequest' responses: '200': description: Updated. content: application/json: schema: $ref: '#/components/schemas/Package' default: $ref: '#/components/responses/Problem' delete: operationId: deletePackage summary: >- Delete a package (409 package_in_use while a deployment that has not finished uses it) tags: - packages responses: '204': description: Deleted. default: $ref: '#/components/responses/Problem' /tenants/{tenantID}/packages/{packageID}/upload-url: parameters: - $ref: '#/components/parameters/TenantID' - $ref: '#/components/parameters/PackageID' post: operationId: createPackageUploadURL summary: Presigned PUT for the package file (draft packages; max 4 GiB) tags: - packages requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/PackageUploadRequest' responses: '200': description: Upload target. content: application/json: schema: $ref: '#/components/schemas/PackageUploadTarget' default: $ref: '#/components/responses/Problem' /tenants/{tenantID}/packages/{packageID}/finalize: parameters: - $ref: '#/components/parameters/TenantID' - $ref: '#/components/parameters/PackageID' post: operationId: finalizePackage summary: >- Verify the uploaded file (size, SHA-256; MSI metadata) and mark the package ready description: >- `422 hash_mismatch`, `size_mismatch`, `upload_missing` or `object_key_mismatch` leave the package draft. tags: - packages requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/PackageFinalizeRequest' responses: '200': description: Ready. content: application/json: schema: $ref: '#/components/schemas/Package' default: $ref: '#/components/responses/Problem' /tenants/{tenantID}/winget/search: parameters: - $ref: '#/components/parameters/TenantID' get: operationId: searchWinget summary: >- Search the cached winget index (25 results; 503 winget_index_unavailable when never loaded) tags: - packages parameters: - $ref: '#/components/parameters/WingetQuery' responses: '200': description: Matches. content: application/json: schema: $ref: '#/components/schemas/WingetSearchResult' default: $ref: '#/components/responses/Problem' /tenants/{tenantID}/deployments/preview: parameters: - $ref: '#/components/parameters/TenantID' post: operationId: previewDeployment summary: >- Resolve targets without creating anything (count, first 50 hostnames, exclusions) tags: - deployments requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/DeploymentPreviewRequest' responses: '200': description: Preview. content: application/json: schema: $ref: '#/components/schemas/DeploymentPreview' default: $ref: '#/components/responses/Problem' /tenants/{tenantID}/deployments: parameters: - $ref: '#/components/parameters/TenantID' get: operationId: listDeployments summary: Deployments, newest first, with counters tags: - deployments parameters: - $ref: '#/components/parameters/Page' - $ref: '#/components/parameters/PageSize' - $ref: '#/components/parameters/Query' - name: status in: query style: form explode: true schema: type: array maxItems: 7 items: $ref: '#/components/schemas/DeploymentStatus' - name: package_id in: query schema: type: string format: uuid responses: '200': description: One page of deployments. content: application/json: schema: $ref: '#/components/schemas/DeploymentList' default: $ref: '#/components/responses/Problem' post: operationId: createDeployment summary: Create a deployment (starts at once for schedule_kind now) tags: - deployments requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/CreateDeploymentRequest' responses: '201': description: Created. content: application/json: schema: $ref: '#/components/schemas/Deployment' default: $ref: '#/components/responses/Problem' /tenants/{tenantID}/deployments/batch: parameters: - $ref: '#/components/parameters/TenantID' post: operationId: createDeployments summary: Deploy several packages at once (one deployment per package) description: | Creates one deployment per package, in the order given, all with the same targets, schedule and options, in one transaction (all or nothing). Each is named " · ". The agent installs the packages of a computer one after another in this order; a restart a reboot policy asks for waits for the last of them. tags: - deployments requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/CreateDeploymentsRequest' responses: '201': description: Created, in package order. content: application/json: schema: $ref: '#/components/schemas/DeploymentBatch' default: $ref: '#/components/responses/Problem' /tenants/{tenantID}/deployments/{deploymentID}: parameters: - $ref: '#/components/parameters/TenantID' - $ref: '#/components/parameters/DeploymentID' get: operationId: getDeployment summary: Deployment with counters tags: - deployments responses: '200': description: Deployment. content: application/json: schema: $ref: '#/components/schemas/Deployment' default: $ref: '#/components/responses/Problem' patch: operationId: actOnDeployment summary: Cancel, pause, resume or add devices that now match tags: - deployments requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/DeploymentActionRequest' responses: '200': description: Updated. content: application/json: schema: $ref: '#/components/schemas/Deployment' default: $ref: '#/components/responses/Problem' /tenants/{tenantID}/deployments/{deploymentID}/targets: parameters: - $ref: '#/components/parameters/TenantID' - $ref: '#/components/parameters/DeploymentID' get: operationId: listDeploymentTargets summary: Per-device status, attempt, exit code, error and output tail tags: - deployments parameters: - $ref: '#/components/parameters/Page' - $ref: '#/components/parameters/PageSize' - $ref: '#/components/parameters/Query' - name: status in: query style: form explode: true schema: type: array maxItems: 9 items: $ref: '#/components/schemas/DeploymentTargetStatus' responses: '200': description: One page of targets. content: application/json: schema: $ref: '#/components/schemas/DeploymentTargetList' default: $ref: '#/components/responses/Problem' /tenants/{tenantID}/deployments/{deploymentID}/targets/{deviceID}/retry: parameters: - $ref: '#/components/parameters/TenantID' - $ref: '#/components/parameters/DeploymentID' - $ref: '#/components/parameters/DeviceID' post: operationId: retryDeploymentTarget summary: >- Retry a failed, timed-out or cancelled target (reopens a finished deployment) tags: - deployments responses: '200': description: Target back to pending. content: application/json: schema: $ref: '#/components/schemas/DeploymentTarget' default: $ref: '#/components/responses/Problem' /tenants/{tenantID}/devices/{deviceID}/deployments: parameters: - $ref: '#/components/parameters/TenantID' - $ref: '#/components/parameters/DeviceID' get: operationId: listDeviceDeployments summary: Deployments that targeted the device (newest first) tags: - deployments parameters: - name: limit in: query schema: type: integer minimum: 1 maximum: 200 default: 50 responses: '200': description: Deployment history. content: application/json: schema: $ref: '#/components/schemas/DeviceDeploymentList' default: $ref: '#/components/responses/Problem' /tenants/{tenantID}/alerts: parameters: - $ref: '#/components/parameters/TenantID' get: operationId: listAlerts summary: Alerts, newest first, with counts per status tags: - alerts parameters: - $ref: '#/components/parameters/Page' - $ref: '#/components/parameters/PageSize' - name: status in: query schema: type: string enum: - open - acknowledged - resolved - name: severity in: query schema: $ref: '#/components/schemas/AlertSeverity' - name: device_id in: query schema: type: string format: uuid responses: '200': description: One page of alerts. content: application/json: schema: $ref: '#/components/schemas/AlertList' default: $ref: '#/components/responses/Problem' /tenants/{tenantID}/alerts/acknowledge: parameters: - $ref: '#/components/parameters/TenantID' post: operationId: acknowledgeAlerts summary: Acknowledge open alerts (they still resolve by themselves) tags: - alerts requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/AlertIDs' responses: '200': description: The alerts that changed. content: application/json: schema: $ref: '#/components/schemas/AlertChangeResult' default: $ref: '#/components/responses/Problem' /tenants/{tenantID}/alerts/resolve: parameters: - $ref: '#/components/parameters/TenantID' post: operationId: resolveAlerts summary: Resolve alerts by hand (a condition that still holds opens a new alert) tags: - alerts requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/AlertIDs' responses: '200': description: The alerts that changed. content: application/json: schema: $ref: '#/components/schemas/AlertChangeResult' default: $ref: '#/components/responses/Problem' /tenants/{tenantID}/alert-rules: parameters: - $ref: '#/components/parameters/TenantID' get: operationId: listAlertRules summary: The tenant's rules and the global ones (with the tenant's on/off state) tags: - alerts responses: '200': description: Rules. content: application/json: schema: $ref: '#/components/schemas/AlertRuleList' default: $ref: '#/components/responses/Problem' post: operationId: createAlertRule summary: Create a tenant rule tags: - alerts requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/AlertRuleCreate' responses: '201': description: Created. content: application/json: schema: $ref: '#/components/schemas/AlertRule' default: $ref: '#/components/responses/Problem' /tenants/{tenantID}/alert-rules/{ruleID}: parameters: - $ref: '#/components/parameters/TenantID' - $ref: '#/components/parameters/RuleID' patch: operationId: updateAlertRule summary: >- Edit a tenant rule, or turn a global rule off/on for the tenant (only `enabled`) tags: - alerts requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/AlertRuleUpdate' responses: '200': description: Updated. content: application/json: schema: $ref: '#/components/schemas/AlertRule' default: $ref: '#/components/responses/Problem' delete: operationId: deleteAlertRule summary: Delete a tenant rule (and its alerts) tags: - alerts responses: '204': description: Deleted. default: $ref: '#/components/responses/Problem' /tenants/{tenantID}/scripts: parameters: - $ref: '#/components/parameters/TenantID' get: operationId: listScripts summary: Scripts of the tenant and the global library tags: - scripts parameters: - $ref: '#/components/parameters/Page' - $ref: '#/components/parameters/PageSize' - $ref: '#/components/parameters/Query' - $ref: '#/components/parameters/ScriptLanguageFilter' responses: '200': description: One page of scripts. content: application/json: schema: $ref: '#/components/schemas/ScriptList' default: $ref: '#/components/responses/Problem' post: operationId: createScript summary: Add a script (version 1) tags: - scripts requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/CreateScriptRequest' responses: '201': description: Created. content: application/json: schema: $ref: '#/components/schemas/Script' default: $ref: '#/components/responses/Problem' /tenants/{tenantID}/scripts/{scriptID}: parameters: - $ref: '#/components/parameters/TenantID' - $ref: '#/components/parameters/ScriptID' get: operationId: getScript summary: Script detail (tenant or global) tags: - scripts responses: '200': description: Script. content: application/json: schema: $ref: '#/components/schemas/Script' default: $ref: '#/components/responses/Problem' patch: operationId: updateScript summary: Change a tenant script (new content or parameters save a new version) tags: - scripts requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/UpdateScriptRequest' responses: '200': description: Updated. content: application/json: schema: $ref: '#/components/schemas/Script' default: $ref: '#/components/responses/Problem' delete: operationId: deleteScript summary: Delete a tenant script (runs keep their history) tags: - scripts responses: '204': description: Deleted. default: $ref: '#/components/responses/Problem' /tenants/{tenantID}/scripts/{scriptID}/versions: parameters: - $ref: '#/components/parameters/TenantID' - $ref: '#/components/parameters/ScriptID' get: operationId: listScriptVersions summary: Version history, newest first tags: - scripts responses: '200': description: Versions. content: application/json: schema: $ref: '#/components/schemas/ScriptVersionList' default: $ref: '#/components/responses/Problem' /tenants/{tenantID}/scripts/{scriptID}/run: parameters: - $ref: '#/components/parameters/TenantID' - $ref: '#/components/parameters/ScriptID' post: operationId: runScript summary: >- Run the current version on devices (explicit ids, a filter or all devices) tags: - scripts requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/RunScriptRequest' responses: '201': description: Runs created (one per device with an agent). content: application/json: schema: $ref: '#/components/schemas/ScriptRunBatch' default: $ref: '#/components/responses/Problem' /tenants/{tenantID}/script-runs: parameters: - $ref: '#/components/parameters/TenantID' get: operationId: listScriptRuns summary: Script runs, newest first tags: - scripts parameters: - $ref: '#/components/parameters/Page' - $ref: '#/components/parameters/PageSize' - name: script_id in: query schema: type: string format: uuid - name: device_id in: query schema: type: string format: uuid - name: status in: query schema: $ref: '#/components/schemas/ScriptRunStatus' - name: from in: query schema: type: string format: date-time - name: to in: query schema: type: string format: date-time responses: '200': description: One page of runs. content: application/json: schema: $ref: '#/components/schemas/ScriptRunList' default: $ref: '#/components/responses/Problem' /tenants/{tenantID}/script-runs/{runID}: parameters: - $ref: '#/components/parameters/TenantID' - $ref: '#/components/parameters/RunID' get: operationId: getScriptRun summary: Run detail with its output (live output while running) tags: - scripts responses: '200': description: Run. content: application/json: schema: $ref: '#/components/schemas/ScriptRunDetail' default: $ref: '#/components/responses/Problem' /tenants/{tenantID}/script-runs/{runID}/cancel: parameters: - $ref: '#/components/parameters/TenantID' - $ref: '#/components/parameters/RunID' post: operationId: cancelScriptRun summary: Cancel a queued or running run (a running script is stopped) tags: - scripts responses: '200': description: Cancelled. content: application/json: schema: $ref: '#/components/schemas/ScriptRun' default: $ref: '#/components/responses/Problem' /admin/agent-releases: get: operationId: listAgentReleases summary: >- Agent and connector releases, version adoption and the release public key tags: - admin - releases responses: '200': description: Releases. content: application/json: schema: $ref: '#/components/schemas/AgentReleaseList' default: $ref: '#/components/responses/Problem' post: operationId: createAgentRelease summary: Declare a release and get a presigned upload for its MSI description: > Global admins, or release automation with `Authorization: Bearer `. PUT the MSI to `upload.url` with `upload.headers`, then POST .../publish. tags: - admin - releases requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/AgentReleaseCreate' responses: '201': description: Draft release. content: application/json: schema: $ref: '#/components/schemas/AgentReleaseCreated' default: $ref: '#/components/responses/Problem' /admin/agent-releases/{releaseID}: parameters: - $ref: '#/components/parameters/ReleaseID' patch: operationId: updateAgentRelease summary: Change rollout percentage, channel or notes tags: - admin - releases requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/AgentReleaseUpdate' responses: '200': description: Updated. content: application/json: schema: $ref: '#/components/schemas/AgentRelease' default: $ref: '#/components/responses/Problem' delete: operationId: deleteAgentRelease summary: Delete a release and its MSI tags: - admin - releases responses: '204': description: Deleted. default: $ref: '#/components/responses/Problem' /admin/agent-releases/{releaseID}/publish: parameters: - $ref: '#/components/parameters/ReleaseID' post: operationId: publishAgentRelease summary: Verify the uploaded MSI, sign the manifest and publish description: >- 409 codes: upload_missing, upload_mismatch, signing_key_missing, not_draft. tags: - admin - releases responses: '200': description: Published. content: application/json: schema: $ref: '#/components/schemas/AgentRelease' default: $ref: '#/components/responses/Problem' /admin/agent-releases/{releaseID}/download: parameters: - $ref: '#/components/parameters/ReleaseID' get: operationId: downloadAgentRelease summary: A one-hour download link for a release MSI description: > Global admins only (not the release automation token). The link is presigned for one hour and the browser saves the file as `file_name` (`rmm--.msi`). Drafts can be downloaded once their MSI is uploaded. Each link is audited as `release.download`. 409 codes: upload_missing, storage_unavailable. tags: - admin - releases responses: '200': description: Download link. content: application/json: schema: $ref: '#/components/schemas/AgentReleaseDownload' default: $ref: '#/components/responses/Problem' /admin/alert-rules: get: operationId: listGlobalAlertRules summary: Global alert rules (evaluated for every tenant) tags: - admin - alerts responses: '200': description: Rules. content: application/json: schema: $ref: '#/components/schemas/AlertRuleList' default: $ref: '#/components/responses/Problem' post: operationId: createGlobalAlertRule summary: Create a global rule tags: - admin - alerts requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/AlertRuleCreate' responses: '201': description: Created. content: application/json: schema: $ref: '#/components/schemas/AlertRule' default: $ref: '#/components/responses/Problem' /admin/alert-rules/{ruleID}: parameters: - $ref: '#/components/parameters/RuleID' patch: operationId: updateGlobalAlertRule summary: Edit a global rule tags: - admin - alerts requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/AlertRuleUpdate' responses: '200': description: Updated. content: application/json: schema: $ref: '#/components/schemas/AlertRule' default: $ref: '#/components/responses/Problem' delete: operationId: deleteGlobalAlertRule summary: Delete a global rule (and its alerts in every tenant) tags: - admin - alerts responses: '204': description: Deleted. default: $ref: '#/components/responses/Problem' /admin/scripts: get: operationId: listGlobalScripts summary: Global script library tags: - admin - scripts parameters: - $ref: '#/components/parameters/Page' - $ref: '#/components/parameters/PageSize' - $ref: '#/components/parameters/Query' - $ref: '#/components/parameters/ScriptLanguageFilter' responses: '200': description: One page of global scripts. content: application/json: schema: $ref: '#/components/schemas/ScriptList' default: $ref: '#/components/responses/Problem' post: operationId: createGlobalScript summary: Add a global script (every tenant can run it) tags: - admin - scripts requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/CreateScriptRequest' responses: '201': description: Created. content: application/json: schema: $ref: '#/components/schemas/Script' default: $ref: '#/components/responses/Problem' /admin/scripts/{scriptID}: parameters: - $ref: '#/components/parameters/ScriptID' get: operationId: getGlobalScript summary: Global script detail tags: - admin - scripts responses: '200': description: Script. content: application/json: schema: $ref: '#/components/schemas/Script' default: $ref: '#/components/responses/Problem' patch: operationId: updateGlobalScript summary: Change a global script tags: - admin - scripts requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/UpdateScriptRequest' responses: '200': description: Updated. content: application/json: schema: $ref: '#/components/schemas/Script' default: $ref: '#/components/responses/Problem' delete: operationId: deleteGlobalScript summary: Delete a global script tags: - admin - scripts responses: '204': description: Deleted. default: $ref: '#/components/responses/Problem' /admin/scripts/{scriptID}/versions: parameters: - $ref: '#/components/parameters/ScriptID' get: operationId: listGlobalScriptVersions summary: Version history of a global script tags: - admin - scripts responses: '200': description: Versions. content: application/json: schema: $ref: '#/components/schemas/ScriptVersionList' default: $ref: '#/components/responses/Problem' components: securitySchemes: bearerAuth: type: http scheme: bearer bearerFormat: JWT parameters: TenantID: name: tenantID in: path required: true schema: type: string format: uuid SiteID: name: siteID in: path required: true schema: type: string format: uuid DeviceID: name: deviceID in: path required: true schema: type: string format: uuid TokenID: name: tokenID in: path required: true schema: type: string format: uuid SessionID: name: sessionID in: path required: true schema: type: string format: uuid JobID: name: jobID in: path required: true schema: type: string format: uuid ConnectorID: name: connectorID in: path required: true schema: type: string format: uuid ConfigID: name: configID in: path required: true schema: type: string format: uuid Page: name: page in: query schema: type: integer minimum: 1 maximum: 100000 default: 1 PageSize: name: page_size in: query schema: type: integer minimum: 1 maximum: 200 default: 50 Query: name: q in: query schema: type: string maxLength: 200 AuditActor: name: actor_user_id in: query schema: type: string format: uuid AuditAction: name: action in: query schema: type: string maxLength: 100 AuditResourceType: name: resource_type in: query schema: type: string maxLength: 100 AuditFrom: name: from in: query schema: type: string format: date-time AuditTo: name: to in: query schema: type: string format: date-time PackageID: name: packageID in: path required: true schema: type: string format: uuid DeploymentID: name: deploymentID in: path required: true schema: type: string format: uuid PackageKindFilter: name: kind in: query schema: $ref: '#/components/schemas/PackageKind' ReadyOnly: name: ready_only in: query description: Only packages that can be deployed. schema: type: boolean WingetQuery: name: q in: query description: >- 2-100 characters (optional in the schema so access checks run first; 422 when missing). schema: type: string maxLength: 100 ReleaseID: name: releaseID in: path required: true schema: type: string format: uuid RuleID: name: ruleID in: path required: true schema: type: string format: uuid ScriptID: name: scriptID in: path required: true schema: type: string format: uuid RunID: name: runID in: path required: true schema: type: string format: uuid ScriptLanguageFilter: name: language in: query schema: $ref: '#/components/schemas/ScriptLanguage' responses: Problem: description: Error (RFC 7807). content: application/problem+json: schema: $ref: '#/components/schemas/Problem' schemas: Health: type: object required: - status properties: status: type: string enum: - ok Problem: type: object description: RFC 7807 problem details. required: - type - title - status properties: type: type: string description: URI reference identifying the problem type. example: about:blank title: type: string status: type: integer detail: type: string code: type: string description: Stable machine-readable error code, e.g. totp_required. instance: type: string request_id: type: string fields: type: object description: Per-field validation errors. additionalProperties: type: string Role: type: string enum: - global_admin - tenant_admin - technician - viewer - teacher TenantRole: type: string enum: - tenant_admin - technician - viewer - teacher UserStatus: type: string enum: - active - disabled - invited - deleted TenantStatus: type: string enum: - active - suspended User: type: object required: - id - email - display_name - role - tenant_id - status - created_at properties: id: type: string format: uuid email: type: string display_name: type: string role: $ref: '#/components/schemas/Role' tenant_id: type: string format: uuid nullable: true status: $ref: '#/components/schemas/UserStatus' created_at: type: string format: date-time Me: type: object description: >- The signed-in user. A user can belong to several tenants, with one role in each; global admins have every permission in every tenant. required: - id - email - display_name - status - is_global_admin - memberships - created_at properties: id: type: string format: uuid email: type: string display_name: type: string status: $ref: '#/components/schemas/UserStatus' is_global_admin: type: boolean memberships: type: array description: >- The user's tenants (suspended ones included, flagged by tenant_status). items: $ref: '#/components/schemas/TenantMembership' created_at: type: string format: date-time TenantMembership: type: object required: - tenant_id - tenant_name - tenant_status - role properties: tenant_id: type: string format: uuid tenant_name: type: string tenant_status: $ref: '#/components/schemas/TenantStatus' role: $ref: '#/components/schemas/TenantRole' DeleteEnrollmentTokenRequest: type: object required: - step_up_token additionalProperties: false description: A step-up token from Entrosity Hub, which confirms the password. properties: step_up_token: type: string minLength: 1 maxLength: 4096 UserDirectory: type: object required: - users properties: users: type: array items: $ref: '#/components/schemas/User' Tenant: type: object required: - id - name - slug - status - settings - created_at - updated_at properties: id: type: string format: uuid name: type: string slug: type: string status: $ref: '#/components/schemas/TenantStatus' settings: $ref: '#/components/schemas/TenantSettings' created_at: type: string format: date-time updated_at: type: string format: date-time TenantRetention: type: object additionalProperties: false description: | Overrides of the server's retention windows for this tenant (sent as a whole; omitted fields use the server default). properties: job_days: type: integer minimum: 7 maximum: 730 description: Finished jobs and script runs (with their output). audit_days: type: integer minimum: 30 maximum: 3650 description: Audit log entries. TenantSettings: type: object description: Tenant-level toggles. Unknown keys are rejected. additionalProperties: false properties: default_timezone: type: string maxLength: 64 description: >- IANA time zone for deployment maintenance windows of devices without a site (default UTC). update_channel: type: string enum: - stable - beta description: >- Which agent/connector releases the tenant's installations update to (default stable). retention: $ref: '#/components/schemas/TenantRetention' TenantList: type: object required: - items - page - page_size - total properties: items: type: array items: $ref: '#/components/schemas/Tenant' page: type: integer page_size: type: integer total: type: integer UpdateAdminTenantRequest: type: object additionalProperties: false description: Names and status come from Entrosity Hub; the settings are Axis's. properties: settings: $ref: '#/components/schemas/TenantSettings' UpdateTenantRequest: type: object additionalProperties: false properties: settings: $ref: '#/components/schemas/TenantSettings' Site: type: object required: - id - tenant_id - name - description - timezone - created_at - updated_at properties: id: type: string format: uuid tenant_id: type: string format: uuid name: type: string description: type: string timezone: type: string description: IANA time zone e.g. Europe/Sofia.: null created_at: type: string format: date-time updated_at: type: string format: date-time SiteList: type: object required: - items properties: items: type: array items: $ref: '#/components/schemas/Site' CreateSiteRequest: type: object required: - name additionalProperties: false properties: name: type: string minLength: 1 maxLength: 200 description: type: string maxLength: 2000 timezone: type: string minLength: 1 maxLength: 64 UpdateSiteRequest: type: object additionalProperties: false properties: name: type: string minLength: 1 maxLength: 200 description: type: string maxLength: 2000 timezone: type: string minLength: 1 maxLength: 64 AuditEntry: type: object required: - id - ts - tenant_id - actor_user_id - actor_email - action - resource_type - resource_id - before - after - ip - request_id properties: id: type: string format: uuid ts: type: string format: date-time tenant_id: type: string format: uuid nullable: true actor_user_id: type: string format: uuid nullable: true actor_email: type: string action: type: string resource_type: type: string resource_id: type: string before: type: object nullable: true additionalProperties: true after: type: object nullable: true additionalProperties: true ip: type: string request_id: type: string AuditList: type: object required: - items - page - page_size - total properties: items: type: array items: $ref: '#/components/schemas/AuditEntry' page: type: integer page_size: type: integer total: type: integer AdminOverview: type: object required: - tenants_total - tenants_active - global_admins - tenant_users - devices_online - devices_offline - devices_never_connected - deployments_running - alerts_open - tenants properties: devices_never_connected: type: integer tenants: type: array description: Device counts per tenant. items: $ref: '#/components/schemas/TenantDeviceCounts' tenants_total: type: integer tenants_active: type: integer global_admins: type: integer tenant_users: type: integer devices_online: type: integer devices_offline: type: integer deployments_running: type: integer alerts_open: type: integer TenantDashboard: type: object required: - users_total - sites_total - devices_total - devices_online - devices_offline - devices_never_connected - jobs_open - os_breakdown - recently_seen - long_offline - deployments_running - deployments_active - deployments_recent - alerts_open - alerts_critical properties: deployments_active: type: array description: Scheduled, running and paused deployments (newest 10) with progress. items: $ref: '#/components/schemas/Deployment' deployments_recent: type: array description: The last 5 finished deployments. items: $ref: '#/components/schemas/Deployment' devices_never_connected: type: integer jobs_open: type: integer description: Agent jobs not yet finished. os_breakdown: type: array items: $ref: '#/components/schemas/OSCount' recently_seen: type: array items: $ref: '#/components/schemas/Device' long_offline: type: array description: Devices offline for more than 24 h. items: $ref: '#/components/schemas/Device' users_total: type: integer sites_total: type: integer devices_total: type: integer devices_online: type: integer devices_offline: type: integer deployments_running: type: integer alerts_open: type: integer alerts_critical: type: integer description: Open alerts of critical severity. OSCount: type: object required: - os_name - count properties: os_name: type: string count: type: integer TenantDeviceCounts: type: object required: - tenant_id - tenant_name - tenant_status - online - offline - never_connected - total properties: tenant_id: type: string format: uuid tenant_name: type: string tenant_status: $ref: '#/components/schemas/TenantStatus' online: type: integer offline: type: integer never_connected: type: integer total: type: integer EnrollmentTokenStatus: type: string enum: - active - revoked - expired - exhausted EnrollmentToken: type: object required: - id - tenant_id - site_id - kind - label - max_uses - uses - expires_at - revoked_at - created_by - created_by_email - created_at - status properties: id: type: string format: uuid tenant_id: type: string format: uuid site_id: type: string format: uuid nullable: true kind: type: string enum: - agent - connector label: type: string max_uses: type: integer nullable: true uses: type: integer expires_at: type: string format: date-time nullable: true revoked_at: type: string format: date-time nullable: true created_by: type: string format: uuid nullable: true created_by_email: type: string created_at: type: string format: date-time status: $ref: '#/components/schemas/EnrollmentTokenStatus' EnrollmentTokenList: type: object required: - items properties: items: type: array items: $ref: '#/components/schemas/EnrollmentToken' CreateEnrollmentTokenRequest: type: object additionalProperties: false properties: kind: type: string enum: - agent - connector default: agent label: type: string maxLength: 200 site_id: type: string format: uuid expires_at: type: string format: date-time max_uses: type: integer minimum: 1 maximum: 100000 CreatedEnrollmentToken: type: object required: - token - secret - install_command - download_url properties: token: $ref: '#/components/schemas/EnrollmentToken' secret: type: string description: The raw token. Shown only once. install_command: type: string description: msiexec one-liner for silent installation. download_url: type: string description: >- Presigned MSI URL (1 h); empty when object storage is not configured. DevicePresence: type: string enum: - online - offline - never_connected Device: type: object required: - id - tenant_id - site_id - display_name - hostname - fqdn - domain - machine_sid - machine_guid - agent_id - os_name - os_version - os_build - os_arch - manufacturer - model - serial_number - cpu_model - cpu_cores - ram_bytes - last_boot_at - last_user - ip_addresses - mac_addresses - status - source - agent_version - pending_reboot - last_seen_at - last_inventory_at - ad_dn - ad_ou - ad_enabled - ad_last_logon_at - tags - custom_fields - created_at - updated_at properties: id: type: string format: uuid tenant_id: type: string format: uuid site_id: type: string format: uuid nullable: true display_name: type: string hostname: type: string fqdn: type: string domain: type: string machine_sid: type: string nullable: true machine_guid: type: string nullable: true agent_id: type: string format: uuid nullable: true os_name: type: string os_version: type: string os_build: type: string os_arch: type: string manufacturer: type: string model: type: string serial_number: type: string cpu_model: type: string cpu_cores: type: integer ram_bytes: type: integer format: int64 last_boot_at: type: string format: date-time nullable: true last_user: type: string ip_addresses: type: array items: type: string mac_addresses: type: array items: type: string status: type: string enum: - online - offline - never_connected - decommissioned source: type: string enum: - agent - ad - both agent_version: type: string pending_reboot: type: boolean last_seen_at: type: string format: date-time nullable: true last_inventory_at: type: string format: date-time nullable: true ad_dn: type: string ad_ou: type: string ad_enabled: type: boolean nullable: true ad_last_logon_at: type: string format: date-time nullable: true tags: type: array items: type: string custom_fields: type: object additionalProperties: type: string created_at: type: string format: date-time updated_at: type: string format: date-time DeviceList: type: object required: - items - page - page_size - total properties: items: type: array items: $ref: '#/components/schemas/Device' page: type: integer page_size: type: integer total: type: integer UpdateDeviceRequest: type: object additionalProperties: false properties: display_name: type: string maxLength: 200 tags: type: array maxItems: 50 items: type: string minLength: 1 maxLength: 64 custom_fields: type: object maxProperties: 50 additionalProperties: type: string maxLength: 1024 site_id: type: string format: uuid clear_site: type: boolean description: Remove the device from its site. DeviceSoftware: type: object required: - id - name - version - publisher - install_date - source - arch - scope - product_code - winget_id properties: id: type: integer format: int64 name: type: string version: type: string publisher: type: string install_date: type: string format: date nullable: true source: type: string arch: type: string scope: type: string product_code: type: string winget_id: type: string DeviceSoftwareList: type: object required: - items properties: items: type: array items: $ref: '#/components/schemas/DeviceSoftware' DeviceDisk: type: object required: - drive - label - file_system - kind - size_bytes - free_bytes properties: drive: type: string label: type: string file_system: type: string kind: type: string size_bytes: type: integer format: int64 free_bytes: type: integer format: int64 DeviceDiskList: type: object required: - items properties: items: type: array items: $ref: '#/components/schemas/DeviceDisk' DeviceNetworkAdapter: type: object required: - name - description - mac_address - ipv4 - ipv6 - gateways - dns_servers - dhcp_enabled - speed_mbps properties: name: type: string description: type: string mac_address: type: string ipv4: type: array items: type: string ipv6: type: array items: type: string gateways: type: array items: type: string dns_servers: type: array items: type: string dhcp_enabled: type: boolean speed_mbps: type: integer format: int64 DeviceNetworkList: type: object required: - items properties: items: type: array items: $ref: '#/components/schemas/DeviceNetworkAdapter' DeviceService: type: object required: - name - display_name - state - start_mode - account - path properties: name: type: string display_name: type: string state: type: string start_mode: type: string account: type: string path: type: string DeviceServiceList: type: object required: - items properties: items: type: array items: $ref: '#/components/schemas/DeviceService' DeviceUpdate: type: object required: - kb - title - installed_on - installed_by properties: kb: type: string title: type: string installed_on: type: string format: date nullable: true installed_by: type: string DeviceUpdateList: type: object required: - items properties: items: type: array items: $ref: '#/components/schemas/DeviceUpdate' DeviceLocalUser: type: object required: - name - full_name - sid - enabled - is_admin - last_logon_at properties: name: type: string full_name: type: string sid: type: string enabled: type: boolean is_admin: type: boolean last_logon_at: type: string format: date-time nullable: true DeviceLocalUserList: type: object required: - items properties: items: type: array items: $ref: '#/components/schemas/DeviceLocalUser' MetricPoint: type: object required: - ts - cpu_pct - mem_pct - disks description: Averages over one bucket. properties: ts: type: string format: date-time description: Bucket start. cpu_pct: type: number mem_pct: type: number cpu_temp_c: type: number nullable: true description: >- Highest thermal zone temperature in °C (null when the device reports none). disks: type: object additionalProperties: type: number format: double description: Used percentage per drive (e.g. {"C:" 71.5}). DeviceLogon: type: object required: - id - user - session_type - logon_at - logoff_estimated properties: id: type: string format: uuid user: type: string description: DOMAIN\name, or the name of a local account. session_type: type: string enum: - console - remote client: type: string description: Remote Desktop client name or address (empty at the console). logon_at: type: string format: date-time logoff_at: type: string format: date-time nullable: true description: null while still signed in. logoff_estimated: type: boolean description: >- The agent did not see the sign-out (it was stopped or offline); logoff_at is when it noticed. DeviceLogonList: type: object required: - items - retention_days properties: items: type: array items: $ref: '#/components/schemas/DeviceLogon' retention_days: type: integer description: How long ended sign-ins are kept (7). DeviceMetrics: type: object required: - range - bucket_seconds - points properties: range: type: string bucket_seconds: type: integer points: type: array items: $ref: '#/components/schemas/MetricPoint' JobStatus: type: string enum: - created - sent - acked - running - succeeded - failed - timeout - cancelled RemoteSessionCreate: type: object additionalProperties: false required: - mode properties: mode: type: string enum: - control - view description: '`view` streams the screen only; the server drops input.' require_consent: type: boolean default: false description: | Ask the signed-in user to accept first (skipped at the sign-in screen). `false` needs `devices:remote_unattended` (administrators). show_banner: type: boolean default: true description: | Show the on-screen session bar on the device (who is connected; the user can end the session). `false` needs `devices:remote_unattended` (administrators). RemoteSession: type: object required: - id - device_id - mode - require_consent - show_banner - status - created_at properties: id: type: string format: uuid device_id: type: string format: uuid job_id: type: string format: uuid nullable: true mode: type: string enum: - control - view require_consent: type: boolean show_banner: type: boolean description: The device shows the on-screen session bar. status: type: string enum: - pending - active - ended - failed description: '`pending` until both sides are connected.' created_by: type: string format: uuid nullable: true created_at: type: string format: date-time started_at: type: string format: date-time nullable: true ended_at: type: string format: date-time nullable: true end_reason: type: string description: Why the session ended or failed (empty while running). ScreenWallRoom: type: object required: - firewall_id - firewall_name - room - building - building_name - computers properties: firewall_id: type: string format: uuid firewall_name: type: string room: type: string description: Room code e.g. SB2-215.: null building: type: string building_name: type: string description: The firewall's name for the building ("" when none). computers: type: integer description: Number of computers in the room. ScreenWallRoomList: type: object required: - items - banner - max_screens properties: items: type: array items: $ref: '#/components/schemas/ScreenWallRoom' banner: type: string enum: - always - never - optional max_screens: type: integer ScreenWallOpen: type: object additionalProperties: false required: - firewall_id - room properties: firewall_id: type: string format: uuid room: type: string minLength: 1 maxLength: 64 show_banner: type: boolean description: >- Administrators: show the session bar on the computers (default true). ScreenWallTile: type: object required: - computer - device_id - hostname - last_user - status - session_id - viewer_path - viewer_ticket - ticket_expires_in properties: computer: type: string description: The computer's name in Matrix. device_id: type: string format: uuid nullable: true hostname: type: string last_user: type: string status: type: string enum: - connecting - not_in_axis - offline - no_agent - busy - agent_too_old - unsupported - unavailable session_id: type: string format: uuid nullable: true viewer_path: type: string nullable: true viewer_ticket: type: string nullable: true ticket_expires_in: type: integer nullable: true ScreenWall: type: object required: - room - show_banner - omitted - tiles properties: room: $ref: '#/components/schemas/ScreenWallRoom' show_banner: type: boolean omitted: type: integer description: Computers of the room beyond the 30 shown. tiles: type: array items: $ref: '#/components/schemas/ScreenWallTile' RemoteSessionStart: type: object required: - session - viewer_path - viewer_ticket - ticket_expires_in properties: session: $ref: '#/components/schemas/RemoteSession' viewer_path: type: string description: >- Path of the viewer WebSocket on this server (`/api/remote/v1/sessions/{id}/viewer`). viewer_ticket: type: string description: One-time ticket for the viewer WebSocket (`?ticket=`). ticket_expires_in: type: integer description: Seconds until the ticket expires. Job: type: object required: - id - tenant_id - device_id - type - payload - status - priority - timeout_seconds - expires_at - attempts - created_by - sent_at - acked_at - started_at - finished_at - progress_pct - progress_message - exit_code - error_code - error - output_tail - created_at - updated_at properties: id: type: string format: uuid tenant_id: type: string format: uuid device_id: type: string format: uuid nullable: true type: type: string payload: type: object additionalProperties: true status: $ref: '#/components/schemas/JobStatus' priority: type: integer timeout_seconds: type: integer expires_at: type: string format: date-time attempts: type: integer created_by: type: string format: uuid nullable: true sent_at: type: string format: date-time nullable: true acked_at: type: string format: date-time nullable: true started_at: type: string format: date-time nullable: true finished_at: type: string format: date-time nullable: true progress_pct: type: integer nullable: true progress_message: type: string exit_code: type: integer nullable: true error_code: type: string error: type: string output_tail: type: string created_at: type: string format: date-time updated_at: type: string format: date-time JobList: type: object required: - items properties: items: type: array items: $ref: '#/components/schemas/Job' InventoryActionRequest: type: object additionalProperties: false properties: kind: type: string enum: - full - delta default: full PowerActionRequest: type: object additionalProperties: false properties: delay_seconds: type: integer minimum: 0 maximum: 86400 default: 0 message: type: string maxLength: 512 force: type: boolean default: false DeviceFilter: type: object additionalProperties: false properties: q: type: string maxLength: 200 status: type: array maxItems: 3 items: $ref: '#/components/schemas/DevicePresence' os: type: array maxItems: 20 items: type: string maxLength: 200 ou: type: string maxLength: 500 tags: type: array maxItems: 20 items: type: string maxLength: 64 site_id: type: string format: uuid source: type: string enum: - agent - ad - both software: type: string maxLength: 200 agent_version: type: string maxLength: 64 last_seen_before: type: string format: date-time last_seen_after: type: string format: date-time BulkActionRequest: type: object required: - action additionalProperties: false description: Exactly one of `device_ids` and `filter`. properties: action: type: string enum: - inventory - reboot - shutdown - add_tag - uninstall_software - wake device_ids: type: array minItems: 1 maxItems: 5000 items: type: string format: uuid filter: $ref: '#/components/schemas/DeviceFilter' payload: type: object additionalProperties: false description: >- inventory: {kind}; reboot/shutdown: {delay_seconds, message, force}; add_tag: {tag}; uninstall_software: {software_name, silent_args}; wake: none. properties: kind: type: string enum: - full - delta delay_seconds: type: integer minimum: 0 maximum: 86400 message: type: string maxLength: 512 force: type: boolean tag: type: string minLength: 1 maxLength: 64 software_name: type: string minLength: 1 maxLength: 256 description: Exact program name (case-insensitive). silent_args: type: string maxLength: 512 BulkActionResult: type: object required: - job_ids - affected - skipped properties: job_ids: type: array items: type: string format: uuid affected: type: integer description: Devices acted on. skipped: type: integer description: Devices the action did not apply to. skip_reasons: type: object additionalProperties: type: integer description: >- Skipped devices by reason (no_agent, software_not_found, needs_silent_args, no_uninstall_method, no_site, no_connector, no_mac_address, decommissioned). UninstallSoftwareRequest: type: object required: - software_id additionalProperties: false properties: software_id: type: integer format: int64 minimum: 1 description: DeviceSoftware id. silent_args: type: string maxLength: 512 description: >- Arguments that make the uninstall string silent (e.g. /S, /quiet, /VERYSILENT); required when the program has neither a product code nor a quiet uninstall string. MergeDeviceRequest: type: object required: - other_device_id additionalProperties: false properties: other_device_id: type: string format: uuid description: The device merged into this one and removed. Connector: type: object required: - id - site_id - name - hostname - domain - version - capabilities - status - last_seen_at - created_at properties: id: type: string format: uuid site_id: type: string format: uuid nullable: true name: type: string hostname: type: string domain: type: string version: type: string capabilities: type: array items: type: string status: type: string enum: - online - offline last_seen_at: type: string format: date-time nullable: true created_at: type: string format: date-time ConnectorList: type: object required: - items properties: items: type: array items: $ref: '#/components/schemas/Connector' TLSMode: type: string enum: - ldaps - starttls - none LDAPProbeRequest: type: object additionalProperties: false required: - ldap_host - tls_mode - base_dn - bind_dn description: >- LDAP settings to try. `bind_password` or `config_id` (borrow the stored password) is required. properties: ldap_host: type: string minLength: 1 maxLength: 255 ldap_port: type: integer minimum: 1 maximum: 65535 tls_mode: $ref: '#/components/schemas/TLSMode' skip_tls_verify: type: boolean ca_pem: type: string maxLength: 65536 base_dn: type: string minLength: 1 maxLength: 1024 bind_dn: type: string minLength: 1 maxLength: 1024 bind_password: type: string maxLength: 1024 writeOnly: true config_id: type: string format: uuid computer_filter: type: string maxLength: 1024 LDAPTestResult: type: object required: - ok - computers_found properties: ok: type: boolean error: type: string error_code: type: string computers_found: type: integer server_info: type: string default_naming_context: type: string OU: type: object required: - dn - name - parent_dn properties: dn: type: string name: type: string parent_dn: type: string OUList: type: object required: - items properties: items: type: array items: $ref: '#/components/schemas/OU' ADSyncConfigRequest: type: object additionalProperties: false required: - name - connector_id - ldap_host - tls_mode - base_dn - bind_dn properties: name: type: string minLength: 1 maxLength: 200 connector_id: type: string format: uuid site_id: type: string format: uuid nullable: true enabled: type: boolean default: true ldap_host: type: string minLength: 1 maxLength: 255 ldap_port: type: integer minimum: 1 maximum: 65535 tls_mode: $ref: '#/components/schemas/TLSMode' skip_tls_verify: type: boolean ca_pem: type: string maxLength: 65536 base_dn: type: string minLength: 1 maxLength: 1024 bind_dn: type: string minLength: 1 maxLength: 1024 bind_password: type: string maxLength: 1024 writeOnly: true description: Required on create; omit on update to keep the stored password. computer_filter: type: string maxLength: 1024 ou_include: type: array maxItems: 500 items: type: string maxLength: 2048 ou_exclude: type: array maxItems: 500 items: type: string maxLength: 2048 interval_minutes: type: integer minimum: 5 maximum: 10080 default: 60 auto_push_agent: type: boolean push_username: type: string maxLength: 256 push_password: type: string maxLength: 1024 writeOnly: true description: Omit on update to keep the stored password. ADSyncConfig: type: object required: - id - name - connector_id - connector_hostname - connector_status - site_id - enabled - ldap_host - ldap_port - tls_mode - skip_tls_verify - ca_pem - base_dn - bind_dn - bind_password_set - computer_filter - ou_include - ou_exclude - interval_minutes - auto_push_agent - push_username - push_password_set - last_sync_at - last_sync_status - consecutive_failures - next_sync_at - created_at - updated_at properties: id: type: string format: uuid name: type: string connector_id: type: string format: uuid connector_hostname: type: string connector_status: type: string site_id: type: string format: uuid nullable: true enabled: type: boolean ldap_host: type: string ldap_port: type: integer tls_mode: $ref: '#/components/schemas/TLSMode' skip_tls_verify: type: boolean ca_pem: type: string base_dn: type: string bind_dn: type: string bind_password_set: type: boolean computer_filter: type: string ou_include: type: array items: type: string ou_exclude: type: array items: type: string interval_minutes: type: integer auto_push_agent: type: boolean push_username: type: string push_password_set: type: boolean last_sync_at: type: string format: date-time nullable: true last_sync_status: type: string consecutive_failures: type: integer next_sync_at: type: string format: date-time nullable: true created_at: type: string format: date-time updated_at: type: string format: date-time ADSyncConfigList: type: object required: - items properties: items: type: array items: $ref: '#/components/schemas/ADSyncConfig' ADSyncRun: type: object required: - id - config_id - trigger - status - seen - created_count - updated_count - gone_count - matched_count - error_code - error_text - started_at - finished_at properties: id: type: string format: uuid config_id: type: string format: uuid trigger: type: string enum: - manual - schedule status: type: string enum: - pending - running - succeeded - failed seen: type: integer created_count: type: integer updated_count: type: integer gone_count: type: integer matched_count: type: integer error_code: type: string error_text: type: string started_at: type: string format: date-time finished_at: type: string format: date-time nullable: true ADSyncRunList: type: object required: - items properties: items: type: array items: $ref: '#/components/schemas/ADSyncRun' PushStatus: type: string enum: - '' - queued - connecting - copying - installing - success - failed ADComputerSummary: type: object additionalProperties: false required: - present - managed - unmanaged - disabled - gone - never_pushed - pushing - push_failed - failures properties: present: type: integer description: Computers currently in AD. managed: type: integer description: Present computers that run the agent. unmanaged: type: integer description: Present computers without the agent. disabled: type: integer description: Present computers whose AD account is disabled. gone: type: integer description: Computers no longer in AD. never_pushed: type: integer description: Without the agent and never pushed. pushing: type: integer description: Without the agent push queued or in progress.: null push_failed: type: integer description: Without the agent last push failed.: null failures: type: array description: >- Failed pushes (of computers without the agent) by error code, most frequent first. items: type: object additionalProperties: false required: - code - computers properties: code: type: string computers: type: integer ADComputer: type: object required: - id - config_id - object_guid - object_sid - dn - ou - name - dns_hostname - domain - os - os_version - description - enabled - last_logon_at - when_created - first_seen_at - last_seen_at - gone_since - device_id - device_hostname - device_status - device_source - push_status - push_error_code - push_error - push_at properties: id: type: string format: uuid config_id: type: string format: uuid object_guid: type: string object_sid: type: string dn: type: string ou: type: string name: type: string dns_hostname: type: string domain: type: string os: type: string os_version: type: string description: type: string enabled: type: boolean last_logon_at: type: string format: date-time nullable: true when_created: type: string format: date-time nullable: true first_seen_at: type: string format: date-time last_seen_at: type: string format: date-time gone_since: type: string format: date-time nullable: true device_id: type: string format: uuid nullable: true device_hostname: type: string nullable: true device_status: type: string nullable: true device_source: type: string nullable: true push_status: $ref: '#/components/schemas/PushStatus' push_error_code: type: string push_error: type: string push_at: type: string format: date-time nullable: true ADComputerList: type: object required: - items - page - page_size - total properties: items: type: array items: $ref: '#/components/schemas/ADComputer' page: type: integer page_size: type: integer total: type: integer ADOUCount: type: object required: - ou - computers properties: ou: type: string computers: type: integer ADOUCountList: type: object required: - items properties: items: type: array items: $ref: '#/components/schemas/ADOUCount' PushAgentRequest: type: object additionalProperties: false description: >- AD computers and/or AD-only devices to push the agent to (at most 500 in total). properties: ad_computer_ids: type: array maxItems: 500 items: type: string format: uuid device_ids: type: array maxItems: 500 items: type: string format: uuid PushAgentResult: type: object required: - job_ids - queued - skipped properties: job_ids: type: array items: type: string format: uuid queued: type: integer skipped: type: array items: $ref: '#/components/schemas/PushSkip' PushSkip: type: object required: - ad_computer_id - reason properties: ad_computer_id: type: string format: uuid reason: type: string enum: - gone - managed - no_hostname - not_in_ad PackageKind: type: string enum: - msi - exe - powershell - winget PackageStatus: type: string description: >- `draft` until the uploaded file is verified; winget and inline PowerShell packages are `ready` at once. enum: - draft - ready Detection: type: object additionalProperties: false description: > Decides whether the package is installed (skip before install, verify after). `msi_product_code` {product_code}; `registry` {key, value?, op?, expected?} (op exists, ==, !=, >=, >, <=, <; versions compare numerically); `file` {path, min_version?}; `winget` {id}. required: - type properties: type: type: string enum: - msi_product_code - registry - file - winget product_code: type: string maxLength: 38 key: type: string maxLength: 1024 value: type: string maxLength: 255 op: type: string enum: - exists - '==' - '!=' - '>=' - '>' - <= - < expected: type: string maxLength: 255 path: type: string maxLength: 1024 min_version: type: string maxLength: 64 id: type: string maxLength: 128 Package: type: object required: - id - tenant_id - scope - name - version - publisher - description - kind - status - file_name - size_bytes - sha256 - script_content - winget_id - winget_version - winget_source - msi_product_code - install_args - uninstall_args - success_exit_codes - detection - requires_reboot - timeout_seconds - run_as - arch - min_os_build - used_by - created_by - created_at - updated_at properties: id: type: string format: uuid tenant_id: type: string format: uuid nullable: true scope: type: string enum: - tenant - global name: type: string version: type: string publisher: type: string description: type: string kind: $ref: '#/components/schemas/PackageKind' status: $ref: '#/components/schemas/PackageStatus' file_name: type: string size_bytes: type: integer format: int64 sha256: type: string script_content: type: string winget_id: type: string winget_version: type: string winget_source: type: string msi_product_code: type: string description: Extracted from the MSI at finalize (best effort). install_args: type: string uninstall_args: type: string success_exit_codes: type: array items: type: integer detection: allOf: - $ref: '#/components/schemas/Detection' nullable: true requires_reboot: type: boolean timeout_seconds: type: integer run_as: type: string enum: - system - logged_on_user arch: type: string enum: - any - x64 - x86 - arm64 min_os_build: type: integer used_by: type: integer description: Deployments (in this tenant) using the package. created_by: type: string format: uuid nullable: true created_at: type: string format: date-time updated_at: type: string format: date-time PackageList: type: object required: - items - page - page_size - total properties: items: type: array items: $ref: '#/components/schemas/Package' page: type: integer page_size: type: integer total: type: integer CreatePackageRequest: type: object additionalProperties: false required: - name - kind properties: name: type: string minLength: 1 maxLength: 200 version: type: string maxLength: 100 publisher: type: string maxLength: 200 description: type: string maxLength: 2000 kind: $ref: '#/components/schemas/PackageKind' script_content: type: string maxLength: 262144 description: PowerShell packages without a file. winget_id: type: string maxLength: 128 winget_version: type: string maxLength: 64 winget_source: type: string enum: - winget - msstore install_args: type: string maxLength: 2000 uninstall_args: type: string maxLength: 2000 success_exit_codes: type: array maxItems: 20 items: type: integer detection: $ref: '#/components/schemas/Detection' requires_reboot: type: boolean timeout_seconds: type: integer minimum: 60 maximum: 86400 run_as: type: string enum: - system - logged_on_user arch: type: string enum: - any - x64 - x86 - arm64 min_os_build: type: integer minimum: 0 maximum: 1000000 UpdatePackageRequest: type: object additionalProperties: false description: Omitted fields keep their value; `clear_detection` removes the rule. properties: name: type: string minLength: 1 maxLength: 200 version: type: string maxLength: 100 publisher: type: string maxLength: 200 description: type: string maxLength: 2000 script_content: type: string maxLength: 262144 winget_id: type: string maxLength: 128 winget_version: type: string maxLength: 64 winget_source: type: string enum: - winget - msstore install_args: type: string maxLength: 2000 uninstall_args: type: string maxLength: 2000 success_exit_codes: type: array maxItems: 20 items: type: integer detection: $ref: '#/components/schemas/Detection' clear_detection: type: boolean requires_reboot: type: boolean timeout_seconds: type: integer minimum: 60 maximum: 86400 run_as: type: string enum: - system - logged_on_user arch: type: string enum: - any - x64 - x86 - arm64 min_os_build: type: integer minimum: 0 maximum: 1000000 PackageUploadRequest: type: object additionalProperties: false required: - file_name - size_bytes properties: file_name: type: string minLength: 1 maxLength: 255 size_bytes: type: integer format: int64 minimum: 1 maximum: 4294967296 content_type: type: string maxLength: 100 PackageUploadTarget: type: object required: - url - headers - object_key - expires_at description: >- PUT the file body to `url` with exactly these `headers`, then call finalize. properties: url: type: string headers: type: object additionalProperties: type: string object_key: type: string expires_at: type: string format: date-time PackageFinalizeRequest: type: object additionalProperties: false required: - object_key - sha256 properties: object_key: type: string maxLength: 512 sha256: type: string pattern: ^[0-9a-fA-F]{64}$ WingetPackage: type: object required: - id - name - publisher - versions properties: id: type: string name: type: string publisher: type: string versions: type: array items: type: string description: Newest first (at most 50). WingetSearchResult: type: object required: - items properties: items: type: array items: $ref: '#/components/schemas/WingetPackage' DeploymentStatus: type: string enum: - draft - scheduled - running - paused - completed - cancelled - failed DeploymentTargetStatus: type: string enum: - pending - queued - downloading - installing - success - failed - skipped - cancelled - timeout SoftwareCondition: type: object additionalProperties: false required: - name description: >- Installed software whose name contains `name` (case-insensitive), optionally with a version comparison. properties: name: type: string minLength: 1 maxLength: 200 version_op: type: string enum: - < - <= - '=' - '!=' - '>=' - '>' version: type: string maxLength: 100 DeploymentTargetFilter: type: object additionalProperties: false description: The device list filters plus software present/absent. properties: q: type: string maxLength: 200 status: type: array maxItems: 3 items: $ref: '#/components/schemas/DevicePresence' os: type: array maxItems: 20 items: type: string maxLength: 200 ou: type: string maxLength: 500 tags: type: array maxItems: 20 items: type: string maxLength: 64 site_id: type: string format: uuid source: type: string enum: - agent - ad - both software: type: string maxLength: 200 agent_version: type: string maxLength: 64 last_seen_before: type: string format: date-time last_seen_after: type: string format: date-time software_present: $ref: '#/components/schemas/SoftwareCondition' software_absent: $ref: '#/components/schemas/SoftwareCondition' DeploymentPreviewRequest: type: object additionalProperties: false required: - target_kind properties: target_kind: type: string enum: - all - devices - filter device_ids: type: array minItems: 1 maxItems: 20000 items: type: string format: uuid target_filter: $ref: '#/components/schemas/DeploymentTargetFilter' DeploymentExclusions: type: object required: - no_agent - decommissioned - not_found description: Devices left out, by reason. properties: no_agent: type: integer description: Never connected / AD-only devices. decommissioned: type: integer not_found: type: integer DeploymentPreview: type: object required: - count - sample - excluded properties: count: type: integer sample: type: array items: type: string description: Up to 50 hostnames. excluded: $ref: '#/components/schemas/DeploymentExclusions' CreateDeploymentRequest: type: object additionalProperties: false required: - name - package_id - target_kind properties: name: type: string minLength: 1 maxLength: 200 package_id: type: string format: uuid action: type: string enum: - install - uninstall default: install target_kind: type: string enum: - all - devices - filter device_ids: type: array minItems: 1 maxItems: 20000 items: type: string format: uuid target_filter: $ref: '#/components/schemas/DeploymentTargetFilter' schedule_kind: type: string enum: - now - at - window default: now scheduled_at: type: string format: date-time window_start: type: string pattern: ^([01][0-9]|2[0-3]):[0-5][0-9]$ description: HH:MM in each device's site timezone. window_end: type: string pattern: ^([01][0-9]|2[0-3]):[0-5][0-9]$ reboot_policy: type: string enum: - never - if_required - always default: never max_concurrency: type: integer minimum: 1 maximum: 1000 default: 50 retry_count: type: integer minimum: 0 maximum: 10 default: 0 retry_backoff_seconds: type: integer minimum: 0 maximum: 86400 default: 300 expires_after_hours: type: integer minimum: 1 maximum: 720 default: 72 CreateDeploymentsRequest: type: object additionalProperties: false required: - name - package_ids - target_kind properties: name: type: string minLength: 1 maxLength: 200 package_ids: type: array minItems: 1 maxItems: 20 uniqueItems: true items: type: string format: uuid description: The packages, in install order. action: type: string enum: - install - uninstall default: install target_kind: type: string enum: - all - devices - filter device_ids: type: array minItems: 1 maxItems: 20000 items: type: string format: uuid target_filter: $ref: '#/components/schemas/DeploymentTargetFilter' schedule_kind: type: string enum: - now - at - window default: now scheduled_at: type: string format: date-time window_start: type: string pattern: ^([01][0-9]|2[0-3]):[0-5][0-9]$ description: HH:MM in each device's site timezone. window_end: type: string pattern: ^([01][0-9]|2[0-3]):[0-5][0-9]$ reboot_policy: type: string enum: - never - if_required - always default: never max_concurrency: type: integer minimum: 1 maximum: 1000 default: 50 retry_count: type: integer minimum: 0 maximum: 10 default: 0 retry_backoff_seconds: type: integer minimum: 0 maximum: 86400 default: 300 expires_after_hours: type: integer minimum: 1 maximum: 720 default: 72 DeploymentBatch: type: object required: - items properties: items: type: array items: $ref: '#/components/schemas/Deployment' DeploymentCounts: type: object required: - pending - queued - running - success - failed - skipped - cancelled - timeout properties: pending: type: integer queued: type: integer running: type: integer description: Downloading or installing. success: type: integer failed: type: integer skipped: type: integer cancelled: type: integer timeout: type: integer Deployment: type: object required: - id - tenant_id - name - package_id - package_name - package_version - package_kind - action - target_kind - target_filter - schedule_kind - scheduled_at - window_start - window_end - reboot_policy - max_concurrency - retry_count - retry_backoff_seconds - expires_at - status - excluded_count - total - counts - created_by - created_by_email - created_at - updated_at - started_at - finished_at properties: id: type: string format: uuid tenant_id: type: string format: uuid name: type: string package_id: type: string format: uuid package_name: type: string package_version: type: string package_kind: $ref: '#/components/schemas/PackageKind' action: type: string enum: - install - uninstall target_kind: type: string enum: - all - devices - filter target_filter: allOf: - $ref: '#/components/schemas/DeploymentTargetFilter' nullable: true schedule_kind: type: string enum: - now - at - window scheduled_at: type: string format: date-time nullable: true window_start: type: string nullable: true window_end: type: string nullable: true reboot_policy: type: string enum: - never - if_required - always max_concurrency: type: integer retry_count: type: integer retry_backoff_seconds: type: integer expires_at: type: string format: date-time status: $ref: '#/components/schemas/DeploymentStatus' excluded_count: type: integer total: type: integer description: Targets. counts: $ref: '#/components/schemas/DeploymentCounts' created_by: type: string format: uuid nullable: true created_by_email: type: string created_at: type: string format: date-time updated_at: type: string format: date-time started_at: type: string format: date-time nullable: true finished_at: type: string format: date-time nullable: true DeploymentList: type: object required: - items - page - page_size - total properties: items: type: array items: $ref: '#/components/schemas/Deployment' page: type: integer page_size: type: integer total: type: integer DeploymentActionRequest: type: object additionalProperties: false required: - action properties: action: type: string enum: - cancel - pause - resume - add_new_devices DeploymentTarget: type: object required: - id - deployment_id - device_id - hostname - device_status - status - attempt - next_attempt_at - job_id - exit_code - error_code - error - output_tail - started_at - finished_at - updated_at properties: id: type: string format: uuid deployment_id: type: string format: uuid device_id: type: string format: uuid hostname: type: string device_status: type: string status: $ref: '#/components/schemas/DeploymentTargetStatus' attempt: type: integer next_attempt_at: type: string format: date-time nullable: true description: Retry backoff of a failed attempt. job_id: type: string format: uuid nullable: true exit_code: type: integer nullable: true error_code: type: string error: type: string output_tail: type: string started_at: type: string format: date-time nullable: true finished_at: type: string format: date-time nullable: true updated_at: type: string format: date-time DeploymentTargetList: type: object required: - items - page - page_size - total properties: items: type: array items: $ref: '#/components/schemas/DeploymentTarget' page: type: integer page_size: type: integer total: type: integer DeviceDeployment: type: object required: - deployment_id - deployment_name - deployment_status - action - package_id - package_name - package_version - status - attempt - exit_code - error_code - error - started_at - finished_at - created_at properties: deployment_id: type: string format: uuid deployment_name: type: string deployment_status: $ref: '#/components/schemas/DeploymentStatus' action: type: string enum: - install - uninstall package_id: type: string format: uuid package_name: type: string package_version: type: string status: $ref: '#/components/schemas/DeploymentTargetStatus' attempt: type: integer exit_code: type: integer nullable: true error_code: type: string error: type: string started_at: type: string format: date-time nullable: true finished_at: type: string format: date-time nullable: true created_at: type: string format: date-time DeviceDeploymentList: type: object required: - items properties: items: type: array items: $ref: '#/components/schemas/DeviceDeployment' ScriptLanguage: type: string description: '`pwsh` runs PowerShell 7 when installed, otherwise Windows PowerShell.' enum: - powershell - pwsh - cmd ScriptParamsSchema: type: object additionalProperties: true description: > JSON Schema (draft-07 subset): `{"type":"object","properties":{name: spec},"required":[...],"x-order":[...]}` where each spec has `type` string|number|integer|boolean and optional `title`, `description`, `default`, `enum` (strings and numbers), `maxLength` (strings), `minimum`/`maximum` (numbers). Names are PowerShell identifiers; values reach the script as `-Name` parameters (PowerShell) and `RMM_PARAM_` variables. Script: type: object required: - id - tenant_id - scope - name - description - language - content - params_schema - run_as - timeout_seconds - current_version - last_run_at - created_by - created_at - updated_at properties: id: type: string format: uuid tenant_id: type: string format: uuid nullable: true scope: type: string enum: - tenant - global name: type: string description: type: string language: $ref: '#/components/schemas/ScriptLanguage' content: type: string params_schema: $ref: '#/components/schemas/ScriptParamsSchema' run_as: type: string enum: - system - logged_on_user timeout_seconds: type: integer current_version: type: integer last_run_at: type: string format: date-time nullable: true created_by: type: string format: uuid nullable: true created_at: type: string format: date-time updated_at: type: string format: date-time AgentRelease: type: object required: - id - component - version - channel - status - size_bytes - sha256 - signature - notes - rollout_pct - created_at - published_at properties: id: type: string format: uuid component: type: string enum: - agent - connector version: type: string channel: type: string enum: - stable - beta status: type: string enum: - draft - published size_bytes: type: integer format: int64 sha256: type: string signature: type: string description: >- Base64 Ed25519 signature of the release manifest (empty while draft). notes: type: string rollout_pct: type: integer description: Installations with bucket(id) < rollout_pct are offered the release. created_at: type: string format: date-time published_at: type: string format: date-time nullable: true AgentReleaseDownload: type: object required: - download_url - expires_at - file_name properties: download_url: type: string description: >- Presigned GET URL of the MSI (served as an attachment named file_name). expires_at: type: string format: date-time file_name: type: string description: rmm--.msi AgentReleaseList: type: object required: - items - adoption - public_key properties: items: type: array items: $ref: '#/components/schemas/AgentRelease' adoption: type: array items: $ref: '#/components/schemas/AgentReleaseAdoption' public_key: type: string description: >- Base64 public key agents must be built with (empty without RMM_RELEASE_SIGNING_KEY). AgentReleaseAdoption: type: object required: - component - version - count description: How many live installations run a version. properties: component: type: string enum: - agent - connector version: type: string count: type: integer format: int64 AgentReleaseCreate: type: object required: - component - version - sha256 - size_bytes additionalProperties: false properties: component: type: string enum: - agent - connector version: type: string maxLength: 64 channel: type: string enum: - stable - beta notes: type: string maxLength: 4000 sha256: type: string pattern: ^[0-9a-fA-F]{64}$ size_bytes: type: integer format: int64 minimum: 1 maximum: 524288000 rollout_pct: type: integer minimum: 0 maximum: 100 AgentReleaseCreated: type: object required: - release - upload properties: release: $ref: '#/components/schemas/AgentRelease' upload: $ref: '#/components/schemas/PackageUploadTarget' AgentReleaseUpdate: type: object additionalProperties: false properties: channel: type: string enum: - stable - beta notes: type: string maxLength: 4000 rollout_pct: type: integer minimum: 0 maximum: 100 AlertSeverity: type: string enum: - info - warning - critical AlertRuleType: type: string enum: - device_offline - disk_free_pct - agent_outdated - cpu_pct - mem_pct - cpu_temp - deployment_failed - adsync_failed - connector_offline AlertCondition: type: object additionalProperties: false description: > Parameters by rule type — device_offline {minutes (default 60)}; disk_free_pct {below, drive?}; agent_outdated {min_version? (default: latest stable agent release)}; cpu_pct / mem_pct {above, minutes (default 15)}; cpu_temp {above_c (default 90), minutes (default 10)}; deployment_failed {threshold_pct (default 20)}; adsync_failed {}; connector_offline {minutes (default 15)}. properties: minutes: type: integer minimum: 5 maximum: 10080 below: type: number format: double exclusiveMinimum: true minimum: 0 exclusiveMaximum: true maximum: 100 drive: type: string pattern: ^[A-Za-z]:$ min_version: type: string maxLength: 64 above: type: number format: double exclusiveMinimum: true minimum: 0 exclusiveMaximum: true maximum: 100 threshold_pct: type: integer minimum: 1 maximum: 100 above_c: type: number format: double minimum: 30 maximum: 120 description: Degrees Celsius (cpu_temp). AlertRule: type: object required: - id - tenant_id - scope - name - type - condition - severity - enabled - enabled_for_tenant - created_at - updated_at properties: id: type: string format: uuid tenant_id: type: string format: uuid nullable: true scope: type: string enum: - tenant - global name: type: string type: $ref: '#/components/schemas/AlertRuleType' condition: $ref: '#/components/schemas/AlertCondition' severity: $ref: '#/components/schemas/AlertSeverity' enabled: type: boolean description: The rule's own switch. enabled_for_tenant: type: boolean description: >- Effective for the calling tenant (a tenant can turn a global rule off). created_at: type: string format: date-time updated_at: type: string format: date-time AlertRuleList: type: object required: - items properties: items: type: array items: $ref: '#/components/schemas/AlertRule' AlertRuleCreate: type: object required: - name - type additionalProperties: false properties: name: type: string minLength: 1 maxLength: 200 type: $ref: '#/components/schemas/AlertRuleType' condition: $ref: '#/components/schemas/AlertCondition' severity: $ref: '#/components/schemas/AlertSeverity' enabled: type: boolean AlertRuleUpdate: type: object additionalProperties: false properties: name: type: string minLength: 1 maxLength: 200 condition: $ref: '#/components/schemas/AlertCondition' severity: $ref: '#/components/schemas/AlertSeverity' enabled: type: boolean Alert: type: object required: - id - rule_id - rule_name - subject_type - subject_id - device_id - device_hostname - severity - title - message - status - opened_at - acknowledged_at - resolved_at properties: id: type: string format: uuid rule_id: type: string format: uuid rule_name: type: string subject_type: type: string enum: - device - connector - deployment - adsync_config subject_id: type: string format: uuid device_id: type: string format: uuid nullable: true device_hostname: type: string severity: $ref: '#/components/schemas/AlertSeverity' title: type: string message: type: string status: type: string enum: - open - acknowledged - resolved opened_at: type: string format: date-time acknowledged_at: type: string format: date-time nullable: true acknowledged_by: type: string format: uuid nullable: true resolved_at: type: string format: date-time nullable: true resolved_by: type: string format: uuid nullable: true description: null when it resolved by itself. AlertList: type: object required: - items - total - page - page_size - counts properties: items: type: array items: $ref: '#/components/schemas/Alert' total: type: integer format: int64 page: type: integer page_size: type: integer counts: type: object required: - open - acknowledged - resolved properties: open: type: integer format: int64 acknowledged: type: integer format: int64 resolved: type: integer format: int64 AlertIDs: type: object required: - ids additionalProperties: false properties: ids: type: array minItems: 1 maxItems: 500 items: type: string format: uuid AlertChangeResult: type: object required: - changed properties: changed: type: integer description: Alerts whose status changed (others were already there). NotificationPrefs: type: object required: - alert_email - min_severity additionalProperties: false description: > Responses always carry every field. In a PUT, omitted optional fields keep their stored value (or the default named in their description); the schema declares no defaults so that the request validator does not fill them in. properties: alert_email: type: string enum: - 'off' - immediate - digest description: > immediate mails new alerts as they open (a storm becomes one summary); digest collects them and mails them every digest_interval. Offline devices are never mailed one by one (see offline_batch_minutes). min_severity: $ref: '#/components/schemas/AlertSeverity' digest_interval: type: string enum: - 15m - hourly - daily description: How often digest delivery mails (daily at digest_hour). Default 15m. digest_hour: type: integer minimum: 0 maximum: 23 description: Hour of the daily digest, in timezone. Default 8. timezone: type: string maxLength: 64 description: >- IANA time zone for digest_hour and quiet_hours ("" = the tenant's default time zone). offline_batch_minutes: type: integer enum: - 5 - 15 - 30 - 60 description: > Default 15. Devices going offline are collected for this long and mailed together: one e-mail lists the devices that went offline and every device that is currently offline. muted_types: type: array uniqueItems: true maxItems: 32 items: $ref: '#/components/schemas/AlertRuleType' description: Alert types that are never e-mailed. Default none. notify_resolved: type: boolean description: >- Also mail when alerts resolve (devices back online are listed in the offline e-mail). Default false. quiet_hours: $ref: '#/components/schemas/QuietHours' QuietHours: type: object required: - enabled - start - end additionalProperties: false description: > No e-mail is sent between start and end (in timezone; end before start spans midnight). What would have been sent goes out as one summary when the quiet hours end. Critical alerts are held too unless critical_bypass. properties: enabled: type: boolean start: type: string pattern: ^([01][0-9]|2[0-3]):[0-5][0-9]$ example: '22:00' end: type: string pattern: ^([01][0-9]|2[0-3]):[0-5][0-9]$ example: '07:00' critical_bypass: type: boolean description: Critical alerts are mailed even during quiet hours. Default true. ScriptList: type: object required: - items - page - page_size - total properties: items: type: array items: $ref: '#/components/schemas/Script' page: type: integer page_size: type: integer total: type: integer CreateScriptRequest: type: object additionalProperties: false required: - name - language - content properties: name: type: string minLength: 1 maxLength: 200 description: type: string maxLength: 2000 language: $ref: '#/components/schemas/ScriptLanguage' content: type: string minLength: 1 maxLength: 262144 params_schema: $ref: '#/components/schemas/ScriptParamsSchema' run_as: type: string enum: - system - logged_on_user default: system timeout_seconds: type: integer minimum: 10 maximum: 86400 default: 600 UpdateScriptRequest: type: object additionalProperties: false properties: name: type: string minLength: 1 maxLength: 200 description: type: string maxLength: 2000 language: $ref: '#/components/schemas/ScriptLanguage' content: type: string minLength: 1 maxLength: 262144 params_schema: $ref: '#/components/schemas/ScriptParamsSchema' run_as: type: string enum: - system - logged_on_user timeout_seconds: type: integer minimum: 10 maximum: 86400 ScriptVersion: type: object required: - version - content - params_schema - created_by - created_at properties: version: type: integer content: type: string params_schema: $ref: '#/components/schemas/ScriptParamsSchema' created_by: type: string format: uuid nullable: true created_at: type: string format: date-time ScriptVersionList: type: object required: - items properties: items: type: array items: $ref: '#/components/schemas/ScriptVersion' RunScriptRequest: type: object additionalProperties: false required: - target_kind properties: target_kind: type: string enum: - all - devices - filter device_ids: type: array minItems: 1 maxItems: 5000 items: type: string format: uuid target_filter: $ref: '#/components/schemas/DeploymentTargetFilter' params: type: object additionalProperties: true description: >- Parameter values by name (validated against the script's params_schema; 422 with `params.` fields). ScriptRunStatus: type: string enum: - queued - running - succeeded - failed - timeout - cancelled ScriptRun: type: object required: - id - script_id - script_version - script_name - device_id - device_hostname - job_id - requested_by - requested_by_email - params - run_as - status - exit_code - output_bytes - error_code - error - created_at - started_at - finished_at properties: id: type: string format: uuid script_id: type: string format: uuid nullable: true script_version: type: integer script_name: type: string device_id: type: string format: uuid device_hostname: type: string job_id: type: string format: uuid nullable: true requested_by: type: string format: uuid nullable: true requested_by_email: type: string params: type: object additionalProperties: true run_as: type: string status: $ref: '#/components/schemas/ScriptRunStatus' exit_code: type: integer nullable: true output_bytes: type: integer format: int64 error_code: type: string error: type: string created_at: type: string format: date-time started_at: type: string format: date-time nullable: true finished_at: type: string format: date-time nullable: true ScriptRunDetail: allOf: - $ref: '#/components/schemas/ScriptRun' - type: object required: - output - output_end - output_truncated properties: output: type: string description: >- Combined stdout/stderr. While running, the live output seen so far (possibly only its end). output_end: type: integer format: int64 description: >- Byte offset just past `output`; `script_run.output` events from this offset continue it. output_truncated: type: boolean description: The output exceeded 10 MiB and was cut. ScriptRunList: type: object required: - items - page - page_size - total properties: items: type: array items: $ref: '#/components/schemas/ScriptRun' page: type: integer page_size: type: integer total: type: integer ScriptRunBatch: type: object required: - runs - excluded properties: runs: type: array items: $ref: '#/components/schemas/ScriptRun' excluded: $ref: '#/components/schemas/DeploymentExclusions'