> ## Documentation Index
> Fetch the complete documentation index at: https://docs.getunbound.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Workspace ONE

> Deploy Unbound to Windows devices with Workspace ONE UEM

Workspace ONE UEM runs one PowerShell script on a schedule, so devices stay onboarded and re-apply if their setup drifts. There is no detection script — the schedule does that job.

## Before you begin

* Push Python 3 as an app first, with `InstallAllUsers=1 PrependPath=1 Include_launcher=1`. The script runs as SYSTEM, and a per-user install is not on SYSTEM's PATH.
* Allow HTTPS to `getunbound.ai`, `backend.getunbound.ai`, `api.getunbound.ai`, `raw.githubusercontent.com` and `github.com`.

***

## 1. Get your API key

Sign in to Unbound as an admin and open [Configure](https://gateway.getunbound.ai/configure). Under **Choose scope** select **My org (MDM)**, then under **Run the install command** select the **Windows** tab and copy the command. Your key is the value after `-ApiKey`. It is masked on screen and copied in full.

***

## 2. Add the script

In the Workspace ONE UEM console go to **Resources → Scripts → Add → Windows**.

<Steps>
  <Step title="General">
    **Name**: `Unbound daily onboard`. Select **Next**.
  </Step>

  <Step title="Details">
    **Language**: PowerShell. **Execution Context**: **System**. **Execution Architecture**: **64-bit**. **Timeout**: `18000` — five hours, in seconds. The first run includes a discovery scan that can take hours on a large machine; a shorter timeout kills it partway through. Paste this as the script, replacing `YOUR_ADMIN_API_KEY` with the key from step 1:

    ```powershell theme={null}
    [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
    $base = 'C:\Program Files\Unbound'
    New-Item -ItemType Directory -Force -Path $base | Out-Null
    icacls $base /setowner '*S-1-5-32-544' /T /C | Out-Null
    icacls $base /reset /T /C | Out-Null
    icacls $base /inheritance:r /grant:r '*S-1-5-18:(OI)(CI)F' '*S-1-5-32-544:(OI)(CI)F' | Out-Null
    $acl = Get-Acl $base
    $allowed = @('S-1-5-18', 'S-1-5-32-544')
    if ($acl.GetOwner([Security.Principal.SecurityIdentifier]).Value -notin $allowed -or
        ($acl.Access | Where-Object {
            $_.IdentityReference.Translate([Security.Principal.SecurityIdentifier]).Value -notin $allowed })) {
        throw "Could not secure $base. Refusing to continue."
    }
    Remove-Item (Join-Path $base '*') -Force -Recurse -ErrorAction SilentlyContinue

    $installer = Join-Path $base 'onboard.ps1'
    Invoke-WebRequest -Uri 'https://getunbound.ai/setup/mdm/windows/onboard' -OutFile $installer -UseBasicParsing -ErrorAction Stop

    & $installer -ApiKey 'YOUR_ADMIN_API_KEY' -Backfill
    $code = $LASTEXITCODE

    if ($code -eq 0) {
        try { Set-Content -Path (Join-Path $base 'last-success.txt') -Value (Get-Date -Format 'o') -ErrorAction Stop }
        catch { Write-Output "Installed, but could not write the marker. $_"; $code = 1 }
    }
    Remove-Item $installer -Force -ErrorAction SilentlyContinue
    exit $code
    ```
  </Step>

  <Step title="Variables">
    None. Select **Save**.
  </Step>
</Steps>

The `icacls` lines lock `C:\Program Files\Unbound` to SYSTEM and administrators before the key is written, and the script stops if it cannot.

***

## 3. Assign it

Open the script and select **Assign → New Assignment**.

<Steps>
  <Step title="Definition">
    **Assignment Name**: `Unbound daily onboard`. Under **Select Smart Group**, choose your developer device group.
  </Step>

  <Step title="Deployment">
    Under **Triggers** select **Schedule** and set the interval to **24 hours**. Also select the **Run Immediately** event, so devices already enrolled run it at their next check-in instead of waiting a day. Select **Save**.
  </Step>
</Steps>

***

## 4. Verify

<CardGroup cols={3}>
  <Card title="Workspace ONE" icon="list-check">
    Open the device under **Devices → List View**, then the **Scripts** tab. The **Status** column shows **Executed** for `Unbound daily onboard`. **Failed** means the exit code was not 0 — open the row to read the output.
  </Card>

  <Card title="Device" icon="desktop">
    `C:\Program Files\Unbound\last-success.txt` updates daily.
  </Card>

  <Card title="Unbound" icon="chart-line" href="https://gateway.getunbound.ai/settings?tab=devices">
    Devices appear with a recent last-seen time.
  </Card>
</CardGroup>

***

## Troubleshooting

| Symptom                                                              | Fix                                                                                                                                 |
| -------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------- |
| `Python 3 is required but not found in PATH`                         | Re-deploy Python with `InstallAllUsers=1 PrependPath=1 Include_launcher=1`, then reboot.                                            |
| `Could not download` or a `404`/`403` on `raw.githubusercontent.com` | The installer fetches its Python stage from GitHub. Allow `raw.githubusercontent.com` through your proxy, including TLS inspection. |
| Status shows **Failed**                                              | Open the device's **Scripts** tab and read the output. The installer prints which step failed.                                      |
| Status shows **Failed** with output that stops during **Discovery**  | The script hit its **Timeout**. Confirm it is `18000` (five hours).                                                                 |
| Copilot rows show `auto`                                             | Allow one daily cycle. Sessions VS Code has already rotated cannot be read.                                                         |

***

## Command switches

| Switch                 | Purpose                                                                                                                                                                               | Default                         |
| ---------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------- |
| `-ApiKey <key>`        | Your admin API key. Required unless `-Clear`                                                                                                                                          | —                               |
| `-BackendUrl <url>`    | Where setup results and scans are reported                                                                                                                                            | `https://backend.getunbound.ai` |
| `-GatewayUrl <url>`    | The AI gateway the installed tools point at                                                                                                                                           | `https://api.getunbound.ai`     |
| `-FrontendUrl <url>`   | Your dashboard host, written into each user's config                                                                                                                                  | `https://gateway.getunbound.ai` |
| `-Backfill`            | Import past Claude Code, Codex and GitHub Copilot sessions                                                                                                                            | off                             |
| `-SkipManagedSettings` | Claude Code only: install the hook, leave its managed settings to you. See [Tamper Resistance](/mdm-integrations/tamper-resistance#when-your-claude-code-policy-is-managed-elsewhere) | off                             |
| `-Clear`               | Remove the configuration for every tool                                                                                                                                               | off                             |

***

## Remove Unbound

Remove the script's assignment first, or the next scheduled run reinstalls. Then, in an elevated PowerShell on the device:

```powershell theme={null}
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
$f = Join-Path $env:ProgramFiles 'Unbound\onboard.ps1'
New-Item -ItemType Directory -Force -Path (Split-Path $f) | Out-Null
Invoke-WebRequest -Uri 'https://getunbound.ai/setup/mdm/windows/onboard' -OutFile $f -UseBasicParsing
& $f -Clear
Remove-Item (Split-Path $f) -Recurse -Force
```

<Card title="Tamper Resistance" icon="lock" href="/mdm-integrations/tamper-resistance">
  Keeping Unbound active on every device with managed settings.
</Card>
