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 logswritefailure — a write operation failedmalformed — request was not in the expected formatbadcredentials — username or password did not matchnotfound — requested resource was not foundsessionexpired — the session is no longer validAuthentication 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/xxxforudSDKcommunication that is not publicly documented.
/_oauth/login
Initiates the OAuth2 login flow, redirecting the browser to the configured OAuth provider.
{ provider: [string], email: [string], redirect: [string] }provider required: The OAuth provider IDemail optional: Login hint for the providerredirect optional: URL to redirect to after successful login/_oauth/redirect
OAuth2 callback handler. Completes the login flow and sets the
apikeycookie.
code, stateapikey cookie set/_oauth/logout
Ends the current session and clears the
apikeycookie.
/_user/whoami
Returns information about the currently authenticated user.
extended optional — if present, includes email and pending invites{ id: [string], globalperms: [int], name: [string], language: [string], expires: [double], lastorgid: [string], needsAuthProvider: [bool], needsEULA: [bool], showWhatsNew: [bool] }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.
{ userid: [string], realname: [string], language: [string], globalPermissions: [int] }userid optional: Defaults to the current user; requires User Edit global permission to update another userglobalPermissions optional: Requires admin-level global permission to set/_user/apikeys/create
Creates a new API key for the current user.
{ name: [string], expiryDays: [int] }name: 1–30 charactersexpiryDays: 0–720 (0 = no expiry){ newApiKey: { id: [string] } }/_user/apikeys/delete
Deletes an API key belonging to the current user.
{ apikey: [string] }/_user/apikeys/list
Lists all API keys for the current user.
{ apikeys: [array] }{ id: [string], name: [string], expires: [double], created: [double], lastaccess: [double], key: [string] }Organisations are the top-level grouping for users, projects, and assets.
/org/list
Lists all organisations the current user is a member of.
{ orgs: [array] }/org/create
Creates a new organisation. Requires the "Only Admins Create Orgs" global permission if that setting is enabled.
{ name: [string], orgid: [string] }orgid optional: Custom organisation ID{ orgid: [string] }/_org/listall
Lists all organisations on the server (administrative), with member/project counts and owner details. Excludes organisations pending deletion. Supports pagination.
{ index: [int], count: [int] }index defaults to 0, count is 1–100 (default 25){ orgs: [array], total: [int] }{ orgid: [string], name: [string], membercount: [int], projectcount: [int], ownername: [string], owneremail: [string] }/:orgid/_get
Returns details of an organisation.
{ org: { orgid: [string], name: [string], defaultpermissions: [int64], created: [int64], ispublic: [bool], pendingdelete: [bool], userpermissions: [int64] } }/:orgid/_update
Updates organisation name or default member permissions.
{ name: [string], defaultpermissions: [int64] }/:orgid/_transfer
Transfers ownership of the organisation to another user.
{ userid: [string] }/:orgid/_icon
Sets the organisation icon.
/:orgid/_delete
Marks the organisation for deletion.
/:orgid/_recover
Cancels a pending organisation deletion.
Roles define named sets of permissions that can be assigned to organisation members.
/:orgid/_roles/list
Lists all roles defined in the organisation.
{ roles: [array] }/:orgid/_roles/update
Creates a new role or updates an existing one.
{ create: [bool], roleid: [string], name: [string], permissions: [int64], projects: [array] }roleid required if not creating: 4-character role identifierprojects optional: Array of project IDs this role applies to{ roleid: [string] } (on create only)/:orgid/_roles/delete
Deletes a role from the organisation.
{ roleid: [string] }roleid: 4-character role identifier/:orgid/_users/list
Lists users, roles, and pending invites in the organisation.
{ users: [array], roles: [array], invites: [array] }users and roles: Returned if caller has UserList permissioninvites: 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.
{ userid: [string] }/:orgid/_users/roles/update
Adds or removes roles for a user in the organisation.
{ userid: [string], add: [array], remove: [array] }add optional: Array of role IDs to assignremove optional: Array of role IDs to remove{ roles: [array] } — the user's current roles after the update/:orgid/_users/invite/create
Invites a user (by email) to the organisation.
{ email: [string], roles: [array] }roles optional: Role IDs to assign on acceptance/:orgid/_users/invite/accept
Accepts a pending invite to an organisation (current user must not already be a member).
/:orgid/_users/invite/cancel
Cancels a pending invite. Callers with UserInvite permission may cancel any invite; others may only cancel their own.
{ email: [string] }email required when cancelling another user's inviteProjects are containers within an organisation for scenes and files.
/:orgid/_projects/list
Lists all projects in the organisation visible to the current user.
{ projects: [array] }{ projid: [string], name: [string], created: [int64], permissions: [int64] }/:orgid/_projects/create
Creates a new project in the organisation.
{ name: [string], projid: [string] }name required: Minimum 2 charactersprojid optional: Custom project ID{ projid: [string] }/:orgid/:projid/_get
Returns details of a project.
{ project: { projid: [string], name: [string], created: [int64], permissions: [int64] } }/:orgid/:projid/_projects/rename
Renames a project.
{ name: [string] }name required: Minimum 2 characters/:orgid/:projid/_projects/delete
Deletes a project and all its contents.
/:orgid/:projid/_permission/audit
Audits effective permissions for the project.
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.
{ tags: [array] }{ 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.
{ tag: [string], color: [string] }tag required: Tag namecolor optional: Display colour for the tag/:orgid/:projid/_projects/tags/update
Renames a tag and/or changes its colour. The rename propagates to every scene using the tag.
{ oldTag: [string], newTag: [string], color: [string] }oldTag required: Existing tag namenewTag required: New tag namecolor optional: New colour/:orgid/:projid/_projects/tags/remove
Removes a tag from the project catalogue and from all scenes using it.
{ tag: [string] }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.
starttime optional — unix timestamp; returns only scenes updated after this time{ count: [int], scenes: [array] }{ 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.
{ body: [string], path: [string] }body: Full scene document as a JSON stringpath optional: Virtual folder to create the scene in (defaults to "", the project root){ sceneid: [string], sceneSessionID: [string] }/:orgid/:projid/:sceneid/_scene/get
Returns the scene document and opens a collaborative session.
{ scene: [object], sceneSessionID: [string] }/:orgid/:projid/:sceneid/_scene/replace
Replaces the entire scene document.
{ body: [string] }body: New scene document as a JSON string/:orgid/:projid/:sceneid/_scene/update
Updates scene metadata: shared visibility, tags, and/or virtual folder. At least one field must be supplied.
shared) / SceneEdit (for tags or path){ shared: [bool], tags: [array of string], path: [string] }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)/:orgid/:projid/:sceneid/_scene/delete
Deletes a scene.
/:orgid/:projid/:sceneid/_scene/sync
Synchronises collaborative editing state. Called periodically by connected clients.
{
"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{
"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.
{ image: [string] }image: Base64-encoded PNG image data/:orgid/:projid/:sceneid/_scene/thumbnail/get
Returns the thumbnail image for a scene as a raw PNG.
Content-Type: image/png)Each project can be connected to a file storage backend. The source field identifies the backend:
source | Backend |
|---|---|
none | No storage configured (file operations are locked) |
local | Local network storage |
aws_s3 | Amazon S3 bucket (bring-your-own) |
azure_blob | Azure 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.
{ source: [string], address: [string], region: [string], prefix: [string], accessid: [string], accesssecret: [string], redirect: [bool] }aws_s3: address = bucket name, region = AWS region, accessid = access key IDazure_blob: address = storage account name, region = endpoint suffix (blank ⇒ core.windows.net), accessid = container nameaccesssecret is masked as *** when set, or '' when no secret is storedredirect: 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.
{ source: [string], address: [string], region: [string], prefix: [string], accessid: [string], accesssecret: [string] }source: One of none, local, aws_s3, azure_blobaws_s3: address = S3 bucket name (3–63 chars, lowercase alphanumeric, - and . allowed), region = AWS region, accessid = access key ID, accesssecret = secret access keyazure_blob: address = storage account name, region = endpoint suffix (leave blank for core.windows.net), accessid = container name, accesssecret = storage account keyaccesssecret: Pass *** to keep the existing secret unchangedredirect 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./:orgid/:projid/_files/list
Lists files in the project storage.
folder optional{ files: [array] }/:orgid/:projid/_file/*
Streams or downloads a file from project storage. Supports HTTP range requests.
cell optional (0–7, image tile index), maxres optional (max resolution)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.
{ path: [string] }path: File path relative to project storage root{ 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.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
supportsarray; 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.
{ 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.{ 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 serverprovider: 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/createreturnedmethod: "presigned".
{ filename: [string], uploadId: [string], partNumber: [int] }{ 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/createreturnedmethod: "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.
X-Filename: Destination path (must match the value returned by upload/create)X-Upload-Id: Upload session ID returned by upload/createX-Part-Number: 1-based part index (1–10000)Content-Type: application/octet-stream){ 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.
{ filename: [string], uploadId: [string], parts: [array] }parts: Ordered array of { partNumber: [int], etag: [string] } objects, one per uploaded chunk.
etag is the value from the storage ETag response header (strip surrounding quotes)etag is the token (block ID) returned by upload/chunk-url for that partetag is the value returned by upload/chunk/:orgid/:projid/_files/delete
Deletes a single file from project storage. Supported on the AWS S3 and Azure Blob backends.
{ filename: [string] }/: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.
{ folder: [string] }folder: The folder prefix to delete. Must end with a trailing / (e.g. models/old-scans/){ 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.
{ folder: [string] }folder: The folder path to create. Must end with a trailing / (e.g. models/new-scans/)/config
Returns basic public server configuration.
/_config/full
Returns the full server configuration including general settings, SMTP, and license info.
{ 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] }/_config/modify
Modifies server configuration settings and saves to disk.
{ 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] } }smtp.username to "" clears both username and password/_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.
{ license: [string] }license: The license document (JSON string){ serverExpiry: [double], sessionExpiry: [double] }/_auth/providers/list
Lists configured OAuth providers. Returns full details (including client IDs and endpoints) to callers with Server Config Edit permission; returns only
idandnameto public callers.
{ providers: [array] }{ id: [string], name: [string] }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.
{ id: [string], name: [string], authendpoint: [string], tokenendpoint: [string], client_id: [string], client_secret: [string] }/_auth/providers/remove
Removes an OAuth provider.
{ id: [string] }/v1/user
Returns information about a user.
{ userid: [string] } or { email: [string] }{ 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.
{ userid: [string] }/v1/user/reactivate
Reactivates a previously deactivated user account.
{ userid: [string] } or { username: [string] }/_user/sessions
Lists active sessions for a user.
{ userid: [string], index: [int], count: [int] }userid optional: Defaults to current userindex optional: Offset for pagination (default 0)count optional: Results per page (10–50, default 25){ sessions: [array], total: [int] }{ applicationname: [string], created: [double], lastaccess: [double], remoteaddress: [string] }/_user/list
Lists all users on the server (administrative). Supports pagination and sorting.
{ index: [int], count: [int], sort: [string], sortDir: [string] }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){ users: [array], total: [int] }{ userid: [string], realname: [string], email: [string], language: [string], createdtime: [double], lastlogin: [double], globalpermissions: [int] }/_packages/create
Creates a new package record and attaches deliverable download links.
{ packagename: [string], versionstring: [string], versionnumber: [int], visibility: [int], releasenotes: [string], deliverables: [array] }versionnumber: Must be > 0visibility: 0 = Public, 1 = Betareleasenotes optional, markdown supporteddeliverables optional: Array of { variant: [string], fileurl: [string] }{ packageid: [string] }/_packages/list
Lists available packages.
{ packagename: [string], index: [int], count: [int] }{ packages: [array], total: [int] }{ 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.
{ packagename: [string], packagevariant: [string] }{ 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/latestis 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.
{ packageid: [string], visibility: [int] }visibility optional: 0 = Public, 1 = BetaAll analytics endpoints require the Analytics global permission.
/_analytics/overview
Returns high-level server usage statistics.
{ 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.
{ 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.
numdays (1–999, default 7), application, page (default 1){ 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.
start, end (YYYY-MM-DD), application, page (default 1){ dataset: [array] } — each item: [userid, email, realname, session_seconds]/_analytics/apps/usage/between/:start/:end
Returns application usage time per day between two dates.
start, end (YYYY-MM-DD){ dataset: [array] } — each item: { name: [string], dates: { [date]: [seconds] } }/_analytics/platform/usage/between/:start/:end
Returns platform usage time per day between two dates.
start, end (YYYY-MM-DD){ dataset: [array] } — each item: { name: [string], dates: { [date]: [seconds] } }/_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.
{ index: [int], count: [int], severity: [string], event: [string] }index: Offset for pagination (default 0)count: Results per page (1–200, default 50)severity optional: Filter by severityevent optional: Filter by event name{ entries: [array], total: [int] }{ 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/_webhook/list
Returns all configured webhook endpoints.
{ hooks: [array] }{ 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
hooksarray removes all entries for that URL.
{ url: [string], hooks: [array of string] }url: Webhook endpoint URLhooks: Array of event names to subscribe to. Pass [] to delete the webhook."user-create", "user-update", "user-login"