Skip to main content

ArborXR MDM API v2 to v3 Upgrade Guide

This guide covers the changes between the ArborXR MDM API v2 and v3, helping you update your integrations.

Base URL Change

VersionBase URL
v2https://api.xrdm.app/api/v2
v3https://api.xrdm.app/api/v3

Authentication Change

Important: API tokens have changed from organization-scoped to user-scoped in v3.

Aspectv2v3
Token scopeOrganization-wideUser-specific
Token permissionsBased on organizationBased on user's roles and permissions within an organization
v2 tokens in v3N/ANot supported

Action required: You must generate new API tokens for your v3 integrations. Existing v2 tokens will not work with v3 endpoints.

To generate a new token:

  1. Navigate to your organization's settings
  2. Go to the Access Tokens section
  3. Create a new token for v3 API access

Removed Endpoints

The following deprecated v2 endpoints have been removed in v3:

Device Groups (use /groups instead)

Removed EndpointReplacement
GET /device-groupsGET /groups
GET /device-groups/{groupId}GET /groups/{groupId}
POST /device-groupsPOST /groups
PUT /device-groups/{groupId}PUT /groups/{groupId}
DELETE /device-groups/{groupId}DELETE /groups/{groupId}
GET /device-groups/{groupId}/release-channelsGET /groups/{groupId}/release-channels
POST /device-groups/{groupId}/release-channelsPOST /groups/{groupId}/release-channels
DELETE /device-groups/{groupId}/release-channelsDELETE /groups/{groupId}/release-channels/{releaseChannelId}

User Invites

Removed EndpointReplacement
POST /invite-userPOST /user-invites

Roles

Removed EndpointReplacement
GET /organization-rolesGET /roles
GET /organization-roles/{roleId}GET /roles/{roleId}
GET /group-rolesGET /roles
GET /group-roles/{roleId}GET /roles/{roleId}

Changed Endpoints

Unshare Release Channel

The method for unsharing a release channel has changed from DELETE to POST with a dedicated unshare endpoint.

v2:

DELETE /apps/{appId}/release-channels/{releaseChannelId}/share

v3:

POST /apps/{appId}/release-channels/{releaseChannelId}/unshare

Remove Release Channel from Group/Device

Release channel removal now uses path-based identification instead of body-based.

v2:

DELETE /groups/{groupId}/release-channels
Body: { "releaseChannelId": "..." }

DELETE /devices/{deviceId}/release-channels
Body: { "releaseChannelId": "..." }

v3:

DELETE /groups/{groupId}/release-channels/{releaseChannelId}

DELETE /devices/{deviceId}/release-channels/{releaseChannelId}

Remove File from Group/Device

File removal now uses path-based identification instead of body-based.

v2:

DELETE /groups/{groupId}/files
Body: { "fileId": "..." }

DELETE /devices/{deviceId}/files
Body: { "fileId": "..." }

v3:

DELETE /groups/{groupId}/files/{fileId}

DELETE /devices/{deviceId}/files/{fileId}

Remove Video from Group/Device

Video removal now uses path-based identification instead of body-based.

v2:

DELETE /groups/{groupId}/videos
Body: { "videoId": "..." }

DELETE /devices/{deviceId}/videos
Body: { "videoId": "..." }

v3:

DELETE /groups/{groupId}/videos/{videoId}

DELETE /devices/{deviceId}/videos/{videoId}

Migrate Device to Organization

The authentication mechanism for migrating devices between organizations has changed significantly.

v2:

POST /devices/{deviceId}/migrate/{organizationSlug}
Body: { "targetOrganizationToken": "43|gC1ajKELCmETw...", "groupId": "..." }

Required a targetOrganizationToken - an API token for the target organization with MDM API ability.

v3:

POST /devices/{deviceId}/migrate/{organizationSlug}
Body: { "groupId": "..." }

The targetOrganizationToken field has been removed. Instead, the authenticated user must:

  1. Belong to both the source and target organizations
  2. Have DEVICE__MIGRATE permission in the source organization
  3. Have ENROLLMENT__ENROLL_DEVICE permission in the target organization
  4. Have GROUP__ADD_REMOVE_DEVICES permission on the target group (if groupId is specified)

Device Models

The GET /device-models endpoint behavior has changed:

v2: Required full=true query parameter to get all supported models plus enrolled unsupported models.

v3: Returns all supported models plus enrolled unsupported models by default (no query parameter needed).

New Endpoints

Current User

Get information about the currently authenticated user:

GET /current-user

Users Management

Full CRUD operations for managing users:

GET /users                    # List users
POST /users # Create user
GET /users/{userId} # Get user
PUT /users/{userId} # Update user
DELETE /users/{userId} # Delete user

Unified Roles

Roles are now unified under a single endpoint:

GET /roles                    # List all roles
GET /roles/{roleId} # Get role details

File Deletion

Delete files directly:

DELETE /files/{fileId}

Video Deletion

Delete videos directly:

DELETE /videos/{videoId}

Response Body Changes (Schema Updates)

Renamed Fields

The following fields have been renamed across multiple resources for consistency:

Resourcev2 Fieldv3 Field
Devicetitlename
Grouptitlename
Apptitlename
Roletitlename

Device Schema Changes

Changev2v3
Name fieldtitlename
Group referencedeviceGroup (string, deprecated)Removed (use group object)
Model referencemodel (string)deviceModel (expanded object with id, name, manufacturer, isSupported)
Storage freestorageSpaceFreeGb (float, GB)storageSpaceFreeBytes (int64, bytes)
Storage totalstorageSpaceTotalGb (float, GB)storageSpaceTotalBytes (int64, bytes)
Custom fieldsInline object$ref to CustomField schema
TimestampsNot always presentcreatedAt, updatedAt always included
OrganizationNot includedorganization object included

Group Schema Changes

Changev2v3
Name fieldtitlename
Parent referenceparentId (UUID) + parent (expanded Group, if set)parent only (expanded Group object, nullable) - parentId removed
TimestampsNot includedcreatedAt, updatedAt always included

User Schema Changes

Changev2v3
Organization roleorganizationRole objectRemoved
Group rolesgroupRoles array of {group, role}Removed
Access controlsNot includedaccessControls array (unified structure with role + protectable)

The accessControls array in v3 contains objects with:

  • id: Access control ID
  • userId: User ID
  • role: Role object
  • protectable: Object with id and type (organization, group, or device)
  • createdAt, updatedAt: Timestamps

Role Schema Changes

Changev2v3
Name fieldtitlename
Type enum values"Organization", "Group" (capitalized)"organization", "group" (lowercase)
TimestampsNot includedcreatedAt, updatedAt always included

File Schema Changes

Changev2v3
Human-readable sizesize (e.g., "101 MB")Removed (use sizeBytes)
Filenamenamefilename
Checksumsha512 (string)checksum object with algorithm and value
Device StatusNot includeddeviceStatuses array of objects with deviceId, status, statusTimestamp
Device IDsdeviceIds arrayRemoved (use deviceStatuses)
TimestampaddedcreatedAt, updatedAt

Video Schema Changes

Changev2v3
Human-readable sizesize (e.g., "250 MB")Removed (use sizeBytes)
Content nameNot includedname
Filenamenamefilename
ChecksumNot includedchecksum object with algorithm and value
Device StatusNot includeddeviceStatuses array of objects with deviceId, status, statusTimestamp
Device IDsdeviceIds arrayRemoved (use deviceStatuses)
TimestampaddedcreatedAt, updatedAt

App Schema Changes

Changev2v3
Name fieldtitlename
TimestampsNot includedcreatedAt, updatedAt always included

ReleaseChannel Schema Changes

Changev2v3
ID formatString (no format specified)UUID format
App referenceNot includedapp object with full App schema
VersionConditionally loadedversion always included with full AppVersion schema
Device StatusNot includeddeviceStatuses array (see below)
Device IDsdeviceIds arrayRemoved (use deviceStatuses)
TimestampsNot includedcreatedAt, updatedAt always included

The deviceStatuses array contains objects with:

  • deviceId: Device UUID
  • targetVersion: Target version name from the release channel
  • installedVersion: Currently installed version name on the device
  • status: Status enum value
  • statusTimestamp: ISO8601 timestamp with millisecond precision

DeviceModel Schema Changes

Changev2v3
Support statusNot includedisSupported boolean
TimestampsNot includedcreatedAt, updatedAt always included

Organization Schema Changes

Changev2v3
TimestampsNot includedcreatedAt, updatedAt always included

AuditLog Schema Changes

Changev2v3
User infouser object with id, email, firstName, lastNameFlattened to userId and userEmail (no name fields)
Resource fieldsresourceSplit into resourceId, resourceType, and resourceName
IP AddressipAddressuserIpAddress
Type fieldStringEnum (string): created, read, updated, deleted, remote_action, exported
TimestampscreatedAt onlycreatedAt, updatedAt always included

New Checksum Object Structure

v3 introduces a structured checksum object instead of plain hash strings:

{
"checksum": {
"algorithm": "SHA-512",
"value": "3a7bd3e2360a3d29eea4a5c13c6b1b9b..."
}
}

Files and Videos use SHA-512 (or MD5 for legacy content). AppBuilds use SHA-256.

Timestamp Precision

All datetime fields in v3 now include millisecond precision in ISO8601 format:

  • v2: 2024-01-15T14:30:00Z
  • v3: 2024-01-15T14:30:00.123Z

Request Body Changes

Update Device Request

Changev2v3
Name fieldtitlename
Group ID fielddeviceGroupIdgroupId

Create/Update Group Request

Changev2v3
parentId requiredOptional (omit for root-level)Required (pass null for root-level)

Create User Request

The user creation request has been significantly restructured:

v2:

{
"firstName": "John",
"lastName": "Doe",
"email": "john.doe@example.com",
"organizationRoleId": "...", // OR groupRoleId + groupIds
"groupRoleId": "...",
"groupIds": ["..."]
}

v3:

{
"firstName": "John",
"lastName": "Doe",
"email": "john.doe@example.com",
"defaultRoleId": "...", // Required - works for both org and group roles
"groupRoles": [
// Optional - for additional group roles
{
"roleId": "...",
"groupId": "..."
}
]
}

Key changes:

  • organizationRoleIddefaultRoleId (required for ALL users, unified for both organization and group role types)
  • groupRoleId + groupIdsgroupRoles array with explicit role-group pairs (optional)

Update User Request

v2:

{
"firstName": "John",
"lastName": "Doe",
"organizationRoleId": "...",
"groupRoleId": "...",
"groupIds": ["..."]
}

v3:

{
"firstName": "John",
"lastName": "Doe",
"defaultRoleId": "...",
"groupRoles": [
{
"roleId": "...",
"groupId": "...",
"action": "attach" // or "detach"
}
]
}

Key changes:

  • organizationRoleIddefaultRoleId
  • groupRoleId + groupIdsgroupRoles array with explicit attach/detach actions

The groupRoles array requires each entry to have:

  • roleId: UUID of the role (required)
  • groupId: UUID of the group (required)
  • action: Must be either "attach" or "detach" (required, no default)

Update App Request

Changev2v3
Name fieldtitlename

Migrate Device to Organization Request

Changev2v3
targetOrganizationTokenRequired (API token for target org)Removed (user must belong to target org)
groupIdOptionalOptional (requires group permission if specified)

Error Response Improvements

V3 API endpoints now consistently return standardized error responses:

  • 400 Bad Request - Invalid request parameters
  • 401 Unauthorized - Missing or invalid authentication
  • 403 Forbidden - Insufficient permissions
  • 404 Not Found - Resource not found
  • 422 Unprocessable Entity - Validation errors
  • 500 Internal Server Error - Server-side errors

Upgrade Checklist

Endpoint Changes

  • Generate new user-scoped API tokens (v2 organization tokens are not compatible with v3)
  • Update base URL from /api/v2 to /api/v3
  • Replace /device-groups routes with /groups
  • Replace /invite-user with /user-invites
  • Replace /organization-roles and /group-roles with /roles
  • Update release channel unshare from DELETE .../share to POST .../unshare
  • Update group/device release channel removal to use path-based DELETE
  • Update group/device file removal to use path-based DELETE
  • Update group/device video removal to use path-based DELETE
  • Remove full=true parameter from /device-models calls (if used)
  • Update device migration to remove targetOrganizationToken and ensure user belongs to target organization with required permissions

Response Body Changes

  • Update code parsing title field to use name (Device, Group, App, Role)
  • Update Device parsing for storageSpaceFreeBytes/storageSpaceTotalBytes (was GB, now bytes)
  • Update Device parsing for deviceModel object (was model string)
  • Update Group parsing for parent object (parentId removed, only parent remains)
  • Update User parsing for accessControls array (replaces organizationRole and groupRoles)
  • Update Role parsing for lowercase type values (organization/group)
  • Update File/Video parsing for checksum object (replaces sha512)
  • Update File/Video parsing for createdAt/updatedAt (replaces added)
  • Handle new name field in Video responses (content display name, separate from filename)
  • Update AuditLog parsing: user object flattened to userId/userEmail, resource split into resourceId/resourceType/resourceName, ipAddress renamed to userIpAddress
  • Handle new ReleaseChannel fields (app object, version always included, deviceStatuses with extended fields)
  • Update timestamp parsing for millisecond precision (e.g., 2024-01-15T14:30:00.123Z)
  • Handle new createdAt/updatedAt timestamps on all resources

Request Body Changes

  • Update Device update requests to use name instead of title
  • Update Device update requests to use groupId instead of deviceGroupId
  • Update App update requests to use name instead of title
  • Update Group create/update requests to always include parentId (use null for root-level)
  • Ensure defaultRoleId is always provided in user creation requests (now required for ALL users)
  • Update User create requests to use defaultRoleId and groupRoles array
  • Update User update requests to use defaultRoleId and groupRoles with required action field ("attach" or "detach")
  • Update device migration requests to remove targetOrganizationToken (authentication now based on user membership)

Error Handling

  • Update error handling to account for consistent 400/500 responses