udServer API

The udServer API provides access for developers to integrate with or automate tasks in udServer.

All API endpoints are prefixed with /api/ (e.g. /api/_user/whoami).

All endpoints return a JSON object containing at minimum a success boolean. If success is false, a message field may provide additional detail.

Common message values:

  • serverfault — internal server error; check server logs
  • writefailure — a write operation failed
  • malformed — request was not in the expected format
  • badcredentials — username or password did not match
  • notfound — requested resource was not found
  • sessionexpired — the session is no longer valid

Authentication is provided via the apikey cookie (set at login) or an apikey field in the JSON body.

Note: There is an additional API at /api/sdk/xxx for udSDK communication that is not publicly documented.


Authentication (OAuth2)

/_oauth/login

Initiates the OAuth2 login flow, redirecting the browser to the configured OAuth provider.

  • Minimum Privilege: Public (no existing session)
  • Expected JSON: { provider: [string], email: [string], redirect: [string] }
    • provider required: The OAuth provider ID
    • email optional: Login hint for the provider
    • redirect optional: URL to redirect to after successful login
  • Response: HTTP redirect to OAuth provider

/_oauth/redirect

OAuth2 callback handler. Completes the login flow and sets the apikey cookie.

  • Minimum Privilege: Public
  • Query Params: code, state
  • Response: HTTP redirect to post-login page with apikey cookie set

/_oauth/logout

Ends the current session and clears the apikey cookie.

  • Minimum Privilege: User
  • Expected JSON: nothing additional
  • Response: HTTP redirect to home page

Current User

/_user/whoami

Returns information about the currently authenticated user.

  • Minimum Privilege: Public (returns limited info if unauthenticated)
  • Query Params: extended optional — if present, includes email and pending invites
  • JSON on Success: { id: [string], globalperms: [int], name: [string], language: [string], expires: [double], lastorgid: [string], needsAuthProvider: [bool], needsEULA: [bool], showWhatsNew: [bool] }
    • If extended: also includes email, emailoptin, invites

/_user/update

Updates the current user's profile, or another user's profile if the caller has the User Edit global permission.

  • Minimum Privilege: User
  • Expected JSON: { userid: [string], realname: [string], language: [string], globalPermissions: [int] }
    • userid optional: Defaults to the current user; requires User Edit global permission to update another user
    • globalPermissions optional: Requires admin-level global permission to set
  • JSON on Success: nothing additional

API Keys

/_user/apikeys/create

Creates a new API key for the current user.

  • Minimum Privilege: User
  • Expected JSON: { name: [string], expiryDays: [int] }
    • name: 1–30 characters
    • expiryDays: 0–720 (0 = no expiry)
  • JSON on Success: { newApiKey: { id: [string] } }

/_user/apikeys/delete

Deletes an API key belonging to the current user.

  • Minimum Privilege: User
  • Expected JSON: { apikey: [string] }
  • JSON on Success: nothing additional

/_user/apikeys/list

Lists all API keys for the current user.

  • Minimum Privilege: User
  • Expected JSON: nothing additional
  • JSON on Success: { apikeys: [array] }
    • Each item: { id: [string], name: [string], expires: [double], created: [double], lastaccess: [double], key: [string] }

Organisations

Organisations are the top-level grouping for users, projects, and assets.

/org/list

Lists all organisations the current user is a member of.

  • Minimum Privilege: User
  • Expected JSON: nothing additional
  • JSON on Success: { orgs: [array] }

/org/create

Creates a new organisation. Requires the "Only Admins Create Orgs" global permission if that setting is enabled.

  • Minimum Privilege: User (or Global Org Edit if restricted)
  • Expected JSON: { name: [string], orgid: [string] }
    • orgid optional: Custom organisation ID
  • JSON on Success: { orgid: [string] }

/_org/listall

Lists all organisations on the server (administrative), with member/project counts and owner details. Excludes organisations pending deletion. Supports pagination.

  • Minimum Privilege: Organisation List (global)
  • Expected JSON: { index: [int], count: [int] }
    • Both optional; index defaults to 0, count is 1–100 (default 25)
  • JSON on Success: { orgs: [array], total: [int] }
    • Each item: { orgid: [string], name: [string], membercount: [int], projectcount: [int], ownername: [string], owneremail: [string] }

/:orgid/_get

Returns details of an organisation.

  • Minimum Privilege: Organisation Member
  • Expected JSON: nothing additional
  • JSON on Success: { org: { orgid: [string], name: [string], defaultpermissions: [int64], created: [int64], ispublic: [bool], pendingdelete: [bool], userpermissions: [int64] } }

/:orgid/_update

Updates organisation name or default member permissions.

  • Minimum Privilege: Organisation Owner
  • Expected JSON: { name: [string], defaultpermissions: [int64] }
    • Both fields are optional
  • JSON on Success: nothing additional

/:orgid/_transfer

Transfers ownership of the organisation to another user.

  • Minimum Privilege: Organisation Owner
  • Expected JSON: { userid: [string] }
  • JSON on Success: nothing additional

/:orgid/_icon

Sets the organisation icon.

  • Minimum Privilege: Organisation Owner
  • Expected JSON: multipart/form-data with icon file
  • JSON on Success: nothing additional

/:orgid/_delete

Marks the organisation for deletion.

  • Minimum Privilege: Organisation Owner
  • Expected JSON: nothing additional
  • JSON on Success: nothing additional

/:orgid/_recover

Cancels a pending organisation deletion.

  • Minimum Privilege: Organisation Owner
  • Expected JSON: nothing additional
  • JSON on Success: nothing additional

Organisation Roles

Roles define named sets of permissions that can be assigned to organisation members.

/:orgid/_roles/list

Lists all roles defined in the organisation.

  • Minimum Privilege: Organisation UserList
  • Expected JSON: nothing additional
  • JSON on Success: { roles: [array] }

/:orgid/_roles/update

Creates a new role or updates an existing one.

  • Minimum Privilege: Organisation UserEditRoles
  • Expected JSON: { create: [bool], roleid: [string], name: [string], permissions: [int64], projects: [array] }
    • roleid required if not creating: 4-character role identifier
    • projects optional: Array of project IDs this role applies to
  • JSON on Success: { roleid: [string] } (on create only)

/:orgid/_roles/delete

Deletes a role from the organisation.

  • Minimum Privilege: Organisation UserEditRoles
  • Expected JSON: { roleid: [string] }
    • roleid: 4-character role identifier
  • JSON on Success: nothing additional

Organisation Users

/:orgid/_users/list

Lists users, roles, and pending invites in the organisation.

  • Minimum Privilege: Organisation UserList or UserInvite
  • Expected JSON: nothing additional
  • JSON on Success: { users: [array], roles: [array], invites: [array] }
    • users and roles: Returned if caller has UserList permission
    • invites: Returned if caller has UserInvite permission

/:orgid/_users/remove

Removes a user from the organisation. Users may remove themselves; removing others requires the UserKick permission.

  • Minimum Privilege: User (self) or Organisation UserKick (others)
  • Expected JSON: { userid: [string] }
  • JSON on Success: nothing additional

/:orgid/_users/roles/update

Adds or removes roles for a user in the organisation.

  • Minimum Privilege: Organisation UserAssignRoles
  • Expected JSON: { userid: [string], add: [array], remove: [array] }
    • add optional: Array of role IDs to assign
    • remove optional: Array of role IDs to remove
  • JSON on Success: { roles: [array] } — the user's current roles after the update

/:orgid/_users/invite/create

Invites a user (by email) to the organisation.

  • Minimum Privilege: Organisation UserInvite
  • Expected JSON: { email: [string], roles: [array] }
    • roles optional: Role IDs to assign on acceptance
  • JSON on Success: nothing additional

/:orgid/_users/invite/accept

Accepts a pending invite to an organisation (current user must not already be a member).

  • Minimum Privilege: User
  • Expected JSON: nothing additional
  • JSON on Success: nothing additional

/:orgid/_users/invite/cancel

Cancels a pending invite. Callers with UserInvite permission may cancel any invite; others may only cancel their own.

  • Minimum Privilege: User (own invite) or Organisation UserInvite (any invite)
  • Expected JSON: { email: [string] }
    • email required when cancelling another user's invite
  • JSON on Success: nothing additional

Projects

Projects are containers within an organisation for scenes and files.

/:orgid/_projects/list

Lists all projects in the organisation visible to the current user.

  • Minimum Privilege: Organisation Member
  • Expected JSON: nothing additional
  • JSON on Success: { projects: [array] }
    • Each item: { projid: [string], name: [string], created: [int64], permissions: [int64] }

/:orgid/_projects/create

Creates a new project in the organisation.

  • Minimum Privilege: Organisation ProjectManage
  • Expected JSON: { name: [string], projid: [string] }
    • name required: Minimum 2 characters
    • projid optional: Custom project ID
  • JSON on Success: { projid: [string] }

/:orgid/:projid/_get

Returns details of a project.

  • Minimum Privilege: Organisation ProjectView
  • Expected JSON: nothing additional
  • JSON on Success: { project: { projid: [string], name: [string], created: [int64], permissions: [int64] } }

/:orgid/:projid/_projects/rename

Renames a project.

  • Minimum Privilege: Organisation ProjectManage
  • Expected JSON: { name: [string] }
    • name required: Minimum 2 characters
  • JSON on Success: nothing additional

/:orgid/:projid/_projects/delete

Deletes a project and all its contents.

  • Minimum Privilege: Organisation ProjectManage
  • Expected JSON: nothing additional
  • JSON on Success: nothing additional

/:orgid/:projid/_permission/audit

Audits effective permissions for the project.

  • Minimum Privilege: Organisation UserAssignRoles
  • Expected JSON: nothing additional
  • JSON on Success: nothing additional

Project Tags

Each project maintains a catalogue of tags that can be applied to its scenes. A tag has a name and an optional colour. Listing the catalogue requires only scene-list access; managing it requires ProjectManage.

/:orgid/:projid/_projects/tags

Lists the project's tag catalogue.

  • Minimum Privilege: Organisation SceneList
  • Expected JSON: nothing additional
  • JSON on Success: { tags: [array] }
    • Each item: { tag: [string], color: [string|null] }
    • color: null when the tag has no assigned colour

/:orgid/:projid/_projects/tags/add

Adds a tag to the project catalogue.

  • Minimum Privilege: Organisation ProjectManage
  • Expected JSON: { tag: [string], color: [string] }
    • tag required: Tag name
    • color optional: Display colour for the tag
  • JSON on Success: nothing additional

/:orgid/:projid/_projects/tags/update

Renames a tag and/or changes its colour. The rename propagates to every scene using the tag.

  • Minimum Privilege: Organisation ProjectManage
  • Expected JSON: { oldTag: [string], newTag: [string], color: [string] }
    • oldTag required: Existing tag name
    • newTag required: New tag name
    • color optional: New colour
  • JSON on Success: nothing additional

/:orgid/:projid/_projects/tags/remove

Removes a tag from the project catalogue and from all scenes using it.

  • Minimum Privilege: Organisation ProjectManage
  • Expected JSON: { tag: [string] }
  • JSON on Success: nothing additional

Scenes

Scenes are JSON documents stored within a project, used by udStream for 3D visualisation.

Scenes can be organised into virtual folders via a path field ("" = project root, e.g. "Buildings/Level 1"). There is no separate folder table — folders are derived from the distinct paths of the scenes in a project. Scenes can also carry tags drawn from the project tag catalogue (see Project Tags).

/:orgid/:projid/_scene/list

Lists all scenes in a project.

  • Minimum Privilege: Organisation SceneList
  • Query Params: starttime optional — unix timestamp; returns only scenes updated after this time
  • JSON on Success: { count: [int], scenes: [array] }
    • Each item: { sceneid: [string], name: [string], created: [double], lastupdated: [double], isshared: [bool], isfeatured: [bool], path: [string], tags: [array of string] }
    • path: The scene's containing virtual folder ("" = root)
    • tags: Tag names applied to the scene

/:orgid/:projid/_scene/create

Creates a new scene in a project.

  • Minimum Privilege: Organisation SceneManage
  • Expected JSON: { body: [string], path: [string] }
    • body: Full scene document as a JSON string
    • path optional: Virtual folder to create the scene in (defaults to "", the project root)
  • JSON on Success: { sceneid: [string], sceneSessionID: [string] }

/:orgid/:projid/:sceneid/_scene/get

Returns the scene document and opens a collaborative session.

  • Minimum Privilege: Organisation SceneAccess
  • Expected JSON: nothing additional
  • JSON on Success: { scene: [object], sceneSessionID: [string] }

/:orgid/:projid/:sceneid/_scene/replace

Replaces the entire scene document.

  • Minimum Privilege: Organisation SceneEdit
  • Expected JSON: { body: [string] }
    • body: New scene document as a JSON string
  • JSON on Success: nothing additional

/:orgid/:projid/:sceneid/_scene/update

Updates scene metadata: shared visibility, tags, and/or virtual folder. At least one field must be supplied.

  • Minimum Privilege: Organisation SceneShare (for shared) / SceneEdit (for tags or path)
  • Expected JSON: { shared: [bool], tags: [array of string], path: [string] }
    • All fields optional, but at least one is required
    • shared: Toggles shared visibility (requires SceneShare)
    • tags: Replaces the full set of tags applied to the scene (requires SceneEdit)
    • path: Moves the scene into the given virtual folder; "" moves it to the project root (requires SceneEdit)
  • JSON on Success: nothing additional

/:orgid/:projid/:sceneid/_scene/delete

Deletes a scene.

  • Minimum Privilege: Organisation SceneManage
  • Expected JSON: nothing additional
  • JSON on Success: nothing additional

/:orgid/:projid/:sceneid/_scene/sync

Synchronises collaborative editing state. Called periodically by connected clients.

  • Minimum Privilege: Organisation SceneAccess
  • Expected JSON:
    {
      "lastupdate": [double],
      "sceneSessionID": [string],
      "flags": [int],
      "head": { "x": [double], "y": [double], "z": [double], "h": [double], "p": [double], "r": [double] },
      "handLeft": { ... },
      "handRight": { ... },
      "anchor": { "x": [double], "y": [double], "z": [double], "w": [double] },
      "messages": [array],
      "selectedNodes": [array],
      "changes": [object]
    }
    
    • changes optional: Requires SceneEdit permission
  • JSON on Success:
    {
      "viewers": [array],
      "changes": [array],
      "delay": [float],
      "nextupdate": [double]
    }
    

/:orgid/:projid/:sceneid/_scene/thumbnail/save

Saves a thumbnail image for a scene. The image must be a PNG no larger than 320×180 pixels.

  • Minimum Privilege: Organisation SceneEdit
  • Expected JSON: { image: [string] }
    • image: Base64-encoded PNG image data
  • JSON on Success: nothing additional

/:orgid/:projid/:sceneid/_scene/thumbnail/get

Returns the thumbnail image for a scene as a raw PNG.

  • Minimum Privilege: Organisation SceneList
  • Expected JSON: nothing additional
  • Response: Raw PNG binary data (Content-Type: image/png)

Files

Each project can be connected to a file storage backend. The source field identifies the backend:

sourceBackend
noneNo storage configured (file operations are locked)
localLocal network storage
aws_s3Amazon S3 bucket (bring-your-own)
azure_blobAzure Blob Storage container (bring-your-own)

The meaning of address, region, and accessid depends on the backend (see below). File operations such as listing, uploading, deleting, and creating folders are supported on the aws_s3 and azure_blob backends.

/:orgid/:projid/_files/settings

Returns the file storage configuration for a project.

  • Minimum Privilege: Organisation FileSetup
  • Expected JSON: nothing additional
  • JSON on Success: { source: [string], address: [string], region: [string], prefix: [string], accessid: [string], accesssecret: [string], redirect: [bool] }
    • For aws_s3: address = bucket name, region = AWS region, accessid = access key ID
    • For azure_blob: address = storage account name, region = endpoint suffix (blank ⇒ core.windows.net), accessid = container name
    • accesssecret is masked as *** when set, or '' when no secret is stored
    • redirect: When true, direct-from-storage access is enabled for file reads (see _file/* and _files/url below)

/:orgid/:projid/_files/update

Updates the file storage configuration for a project.

  • Minimum Privilege: Organisation FileSetup
  • Expected JSON: { source: [string], address: [string], region: [string], prefix: [string], accessid: [string], accesssecret: [string] }
    • source: One of none, local, aws_s3, azure_blob
    • For aws_s3: address = S3 bucket name (3–63 chars, lowercase alphanumeric, - and . allowed), region = AWS region, accessid = access key ID, accesssecret = secret access key
    • For azure_blob: address = storage account name, region = endpoint suffix (leave blank for core.windows.net), accessid = container name, accesssecret = storage account key
    • accesssecret: Pass *** to keep the existing secret unchanged
    • redirect optional: Enable direct-from-storage access for file reads (aws_s3/azure_blob only). Defaults to false; omit to leave the current value unchanged. See _file/* and _files/url.
  • JSON on Success: nothing additional

/:orgid/:projid/_files/list

Lists files in the project storage.

  • Minimum Privilege: Organisation FileList
  • Query Params: folder optional
  • JSON on Success: { files: [array] }

/:orgid/:projid/_file/*

Streams or downloads a file from project storage. Supports HTTP range requests.

  • Minimum Privilege: Organisation FileStream (SDK sessions only) or Organisation FileDownload
    • Streaming is permitted when the request is from an SDK session and the caller has FileStream.
    • Downloading is permitted for any session when the caller has FileDownload.
    • The request is rejected unless at least one of these conditions is met.
  • Path: File path relative to project storage root
  • Query Params: cell optional (0–7, image tile index), maxres optional (max resolution)
  • Response: Binary file data
    • When the project has direct access (redirect) enabled, the server instead responds with an HTTP 302 redirect to a short-lived presigned/SAS URL, so clients that follow redirects stream the bytes directly from storage. Image post-processing requests (cell/maxres) are always proxied.

/:orgid/:projid/_files/url

Vends a short-lived presigned (S3) / SAS (Azure) URL for streaming a file directly from storage, taking the server out of the data path. Requires the project's direct-access (redirect) setting to be enabled. Used by the SDK to stream model data without a per-request server round-trip.

  • Minimum Privilege: Organisation FileStream (SDK sessions only) or Organisation FileDownload
  • Expected JSON: { path: [string] }
    • path: File path relative to project storage root
  • JSON on Success: { url: [string], expiresIn: [int], size: [int] }
    • url: A presigned GET URL (AWS S3) or read SAS URL (Azure Blob). The client may issue HTTP range requests against it and should treat it as opaque.
    • expiresIn: Seconds the URL remains valid; the client should request a fresh URL before this elapses (the value is a duration so refresh is driven by the client's own clock).
    • size: File size in bytes, so the client can open the stream without a separate HEAD request.
  • Returns notallowed when direct access is not enabled for the project.

/:orgid/:projid/_files/upload/create

Initiates a multipart upload session. The client declares which storage backends it can speak to directly via the supports array; the server responds with the upload method to use and the chunk size to apply. Supported when project storage is configured as AWS S3 or Azure Blob.

  • Minimum Privilege: Organisation FileManage
  • Expected JSON: { filename: [string], supports: [array] }
    • filename: Destination path within the project storage (e.g. models/scan.las)
    • supports: Backends the client supports uploading to directly, e.g. ["aws"] or ["azure"]. The value must match the project's configured backend ("aws" for aws_s3, "azure" for azure_blob) to enable presigned mode. Omit or pass [] to force proxied mode.
  • JSON on Success: { uploadId: [string], filename: [string], method: [string], provider: [string], chunkSize: [int] }
    • method: "presigned" — client uploads chunks directly to storage; or "proxied" — client sends chunks through the server
    • provider: Storage provider name when method is "presigned""aws" or "azure"
    • uploadId: For AWS S3 this is the S3 multipart upload ID; for Azure Blob it is the literal "azure-blockblob" (block blobs require no separate initiation)
    • chunkSize: Bytes per chunk the client should use (100 MB presigned, 32 MB proxied)

/:orgid/:projid/_files/upload/chunk-url

Returns a short-lived presigned URL the client uses to PUT a single chunk directly to storage, bypassing the server entirely. Only call this when upload/create returned method: "presigned".

  • Minimum Privilege: Organisation FileManage
  • Expected JSON: { filename: [string], uploadId: [string], partNumber: [int] }
  • JSON on Success: { url: [string], token: [string] }
    • url: Presigned PUT URL valid for 1 hour. The client PUTs the raw chunk body to this URL with no additional auth headers. For Azure this is a blob SAS URL with comp=block&blockid=....
    • token: The server-issued identifier the client must echo back in the upload/complete parts list. Empty string for AWS S3 — the ETag is instead returned by storage in the PUT response ETag header and must be collected by the client. For Azure Blob this is the block ID for the part.

/:orgid/:projid/_files/upload/chunk

Uploads a single chunk of a multipart upload through the server (proxied mode). Only call this when upload/create returned method: "proxied". Chunks must be at least 5 MB except for the final part. Metadata is passed via HTTP headers; the raw binary chunk data is the request body.

  • Minimum Privilege: Organisation FileManage
  • Request Headers:
    • X-Filename: Destination path (must match the value returned by upload/create)
    • X-Upload-Id: Upload session ID returned by upload/create
    • X-Part-Number: 1-based part index (1–10000)
  • Request Body: Raw binary chunk data (Content-Type: application/octet-stream)
  • JSON on Success: { partNumber: [int], etag: [string] }
    • etag: MD5 hex digest of the chunk; required when calling upload/complete

/:orgid/:projid/_files/upload/complete

Completes a multipart upload. All parts must be provided in order. The file becomes accessible in project storage once this call succeeds. Works for both presigned and proxied uploads, on AWS S3 and Azure Blob.

  • Minimum Privilege: Organisation FileManage
  • Expected JSON: { filename: [string], uploadId: [string], parts: [array] }
    • parts: Ordered array of { partNumber: [int], etag: [string] } objects, one per uploaded chunk.
      • AWS S3 presigned: etag is the value from the storage ETag response header (strip surrounding quotes)
      • Azure Blob presigned: etag is the token (block ID) returned by upload/chunk-url for that part
      • Proxied: etag is the value returned by upload/chunk
  • JSON on Success: nothing additional

/:orgid/:projid/_files/delete

Deletes a single file from project storage. Supported on the AWS S3 and Azure Blob backends.

  • Minimum Privilege: Organisation FileManage
  • Expected JSON: { filename: [string] }
  • JSON on Success: nothing additional

/:orgid/:projid/_files/delete-folder

Deletes all objects under a folder prefix from project storage. Object stores have no native folder delete — this lists all objects with the prefix and batch-deletes them. Supported on the AWS S3 and Azure Blob backends.

  • Minimum Privilege: Organisation FileManage
  • Expected JSON: { folder: [string] }
    • folder: The folder prefix to delete. Must end with a trailing / (e.g. models/old-scans/)
  • JSON on Success: { deleted: [int] }
    • deleted: Total number of objects removed

/:orgid/:projid/_files/create-folder

Creates an empty folder in project storage by writing a zero-byte marker object at the folder key. Supported on the AWS S3 and Azure Blob backends.

  • Minimum Privilege: Organisation FileManage
  • Expected JSON: { folder: [string] }
    • folder: The folder path to create. Must end with a trailing / (e.g. models/new-scans/)
  • JSON on Success: nothing additional

Server Configuration

/config

Returns basic public server configuration.

  • Minimum Privilege: Public
  • Expected JSON: nothing additional
  • Response: Server configuration (plain text)

/_config/full

Returns the full server configuration including general settings, SMTP, and license info.

  • Minimum Privilege: Server Config Edit
  • Expected JSON: nothing additional
  • JSON on Success: { serverurl: [string], supportemail: [string], sessiontimeouthours: [int], userscreatedisabled: [bool], onlyadmincreateorgs: [bool], smtpenabled: [bool], smtpserver: [string], smtpsourceaddress: [string], smtpusername: [string], smtpusetls: [bool], userlimit: [int], userCount: [int], shardCount: [int], shardlimit: [int], serverid: [string], serverExpiry: [double], sessionExpiry: [double], domains: [array] }
    • serverExpiry, sessionExpiry: Unix epoch seconds (double)
    • domains: Array of { domain: [string], sessionlimit: [int], ispremium: [bool] }
    • SMTP password is never returned

/_config/modify

Modifies server configuration settings and saves to disk.

  • Minimum Privilege: Server Config Edit
  • Expected JSON: { sessionTimeoutHours: [int], permissionCacheExpirySeconds: [double], serverurl: [string], supportemail: [string], userscreatebanned: [bool], onlyadmincreateorgs: [bool], smtp: { enabled: [bool], server: [string], sourceaddress: [string], usetls: [bool], username: [string], password: [string] } }
    • All fields optional; omitted fields retain their current value
    • Setting smtp.username to "" clears both username and password
  • JSON on Success: nothing additional

/_config/license

Applies a server license. This lets an administrator update the server's license through the API without filesystem access to the host. The license is validated against the running config (contacting the licensing server for online licenses), applied, and persisted so it survives a restart.

  • Minimum Privilege: Server Config Edit
  • Expected JSON: { license: [string] }
    • license: The license document (JSON string)
  • JSON on Success: { serverExpiry: [double], sessionExpiry: [double] }
    • Both are Unix epoch seconds reflecting the newly applied license

Auth Providers

/_auth/providers/list

Lists configured OAuth providers. Returns full details (including client IDs and endpoints) to callers with Server Config Edit permission; returns only id and name to public callers.

  • Minimum Privilege: Public
  • Expected JSON: nothing additional
  • JSON on Success: { providers: [array] }
    • Public: { id: [string], name: [string] }
    • Admin: also includes clientid, authendpoint, tokenendpoint

/_auth/providers/add

Adds an OAuth provider. If no providers are configured yet, this endpoint is public (to allow initial setup); otherwise requires Server Config Edit.

  • Minimum Privilege: Public (first provider), Server Config Edit (subsequent providers)
  • Expected JSON: { id: [string], name: [string], authendpoint: [string], tokenendpoint: [string], client_id: [string], client_secret: [string] }
    • All fields required, minimum 3 characters each
  • JSON on Success: nothing additional

/_auth/providers/remove

Removes an OAuth provider.

  • Minimum Privilege: Server Config Edit
  • Expected JSON: { id: [string] }
  • JSON on Success: nothing additional

Users (v1)

/v1/user

Returns information about a user.

  • Minimum Privilege: User
  • Expected JSON: { userid: [string] } or { email: [string] }
  • JSON on Success: { user: { userid: [string], realname: [string], email: [string], createdtime: [double], lastlogin: [double], language: [string], globalPermissions: [int] } }
    • email, createdtime, lastlogin, language, globalPermissions: Only returned to the user themselves or callers with User Edit permission

/v1/user/deactivate

Deactivates (blocks) a user account.

  • Minimum Privilege: User Edit
  • Expected JSON: { userid: [string] }
  • JSON on Success: nothing additional

/v1/user/reactivate

Reactivates a previously deactivated user account.

  • Minimum Privilege: User Edit
  • Expected JSON: { userid: [string] } or { username: [string] }
  • JSON on Success: nothing additional

/_user/sessions

Lists active sessions for a user.

  • Minimum Privilege: User (own sessions) or User Edit (any user)
  • Expected JSON: { userid: [string], index: [int], count: [int] }
    • userid optional: Defaults to current user
    • index optional: Offset for pagination (default 0)
    • count optional: Results per page (10–50, default 25)
  • JSON on Success: { sessions: [array], total: [int] }
    • Each item: { applicationname: [string], created: [double], lastaccess: [double], remoteaddress: [string] }

/_user/list

Lists all users on the server (administrative). Supports pagination and sorting.

  • Minimum Privilege: User List
  • Expected JSON: { index: [int], count: [int], sort: [string], sortDir: [string] }
    • All fields optional
    • index: Offset for pagination (default 0)
    • count: Results per page (1–100, default 25)
    • sort: One of name, email, lastlogin, created (default created)
    • sortDir: asc or desc (default desc)
  • JSON on Success: { users: [array], total: [int] }
    • Each item: { userid: [string], realname: [string], email: [string], language: [string], createdtime: [double], lastlogin: [double], globalpermissions: [int] }

Packages

/_packages/create

Creates a new package record and attaches deliverable download links.

  • Minimum Privilege: Server Config Edit
  • Expected JSON: { packagename: [string], versionstring: [string], versionnumber: [int], visibility: [int], releasenotes: [string], deliverables: [array] }
    • versionnumber: Must be > 0
    • visibility: 0 = Public, 1 = Beta
    • releasenotes optional, markdown supported
    • deliverables optional: Array of { variant: [string], fileurl: [string] }
  • JSON on Success: { packageid: [string] }

/_packages/list

Lists available packages.

  • Minimum Privilege: User
  • Expected JSON: { packagename: [string], index: [int], count: [int] }
    • All fields optional
  • JSON on Success: { packages: [array], total: [int] }
    • Each item: { packageid: [string], name: [string], versionstring: [string], versionnumber: [int], created: [int], isavailable: [bool], visibility: [int], releasenotes: [string], deliverables: [array] }
    • isavailable deprecated: no longer used for availability — a package is available when it has a matching deliverable.

/_packages/latest

Returns the latest version of a named package for a given variant. A package resolves only if it has a deliverable matching the requested variant.

  • Minimum Privilege: User
  • Expected JSON: { packagename: [string], packagevariant: [string] }
  • JSON on Success: { package: { packageid: [string], name: [string], versionstring: [string], versionnumber: [int], created: [int], isavailable: [bool], visibility: [int], releasenotes: [string], deliverables: [array] } }
    • isavailable deprecated: always reported, but no longer gates resolution.

Compatibility: /package/latest is a legacy alias of /_packages/latest, retained for older clients that predate the _packages/ namespace. New integrations should use /_packages/latest.


/_packages/update

Updates package metadata.

  • Minimum Privilege: Server Config Edit
  • Expected JSON: { packageid: [string], visibility: [int] }
    • visibility optional: 0 = Public, 1 = Beta
  • JSON on Success: nothing additional

Analytics

All analytics endpoints require the Analytics global permission.

/_analytics/overview

Returns high-level server usage statistics.

  • JSON on Success: { users: { total: [int], loggedin: [int], created: [int] }, sessions: [int], scenes: { total: [int], active: [int], deleted: [int] }, workspaces: [int] }

/_analytics/dau

Returns daily active user counts for the last 30 days.

  • JSON on Success: { dataset: [array] } — each item: [date, user_count]

/_analytics/users/top/since/:application/_analytics/users/top/since/:numdays/:application/_analytics/users/top/since/:numdays/:application/:page

Returns top users by session time for an application over the last N days.

  • Path Params: numdays (1–999, default 7), application, page (default 1)
  • JSON on Success: { since: [string], dataset: [array] } — each item: [userid, email, realname, session_seconds]

/_analytics/users/top/between/:start/:end/:application/_analytics/users/top/between/:start/:end/:application/:page

Returns top users by session time for an application between two dates.

  • Path Params: start, end (YYYY-MM-DD), application, page (default 1)
  • JSON on Success: { dataset: [array] } — each item: [userid, email, realname, session_seconds]

/_analytics/apps/usage/between/:start/:end

Returns application usage time per day between two dates.

  • Path Params: start, end (YYYY-MM-DD)
  • JSON on Success: { dataset: [array] } — each item: { name: [string], dates: { [date]: [seconds] } }

/_analytics/platform/usage/between/:start/:end

Returns platform usage time per day between two dates.

  • Path Params: start, end (YYYY-MM-DD)
  • JSON on Success: { dataset: [array] } — each item: { name: [string], dates: { [date]: [seconds] } }

System Log

/_admin/syslog/list

Returns server-initiated system log events (startup/shutdown, crashes, license changes, and similar). Supports pagination and optional filtering by severity and event type.

  • Minimum Privilege: Analytics
  • Expected JSON: { index: [int], count: [int], severity: [string], event: [string] }
    • All fields optional
    • index: Offset for pagination (default 0)
    • count: Results per page (1–200, default 50)
    • severity optional: Filter by severity
    • event optional: Filter by event name
  • JSON on Success: { entries: [array], total: [int] }
    • Each item: { id: [string], created: [double], event: [string], severity: [string], userid: [string], metadata: [string] }
    • userid and metadata are present only when recorded for the event; metadata is a JSON string

Webhooks

/_webhook/list

Returns all configured webhook endpoints.

  • Minimum Privilege: Server Config Edit
  • Expected JSON: nothing additional
  • JSON on Success: { hooks: [array] }
    • Each item: { url: [string], hooks: [array of string] }
    • hooks: Array of event name strings — "user-create", "user-update", "user-login"

/_webhook/update

Creates, updates, or deletes a webhook endpoint. Passing an empty hooks array removes all entries for that URL.

  • Minimum Privilege: Server Config Edit
  • Expected JSON: { url: [string], hooks: [array of string] }
    • url: Webhook endpoint URL
    • hooks: Array of event names to subscribe to. Pass [] to delete the webhook.
    • Valid event names: "user-create", "user-update", "user-login"
  • JSON on Success: nothing additional