---
title: "Start a browser enrollment (desktop app, no auth)"
method: POST
path: "/api/v1/device_enrollments"
tags: ["Devices"]
---

# Start a browser enrollment (desktop app, no auth)

`POST /api/v1/device_enrollments`

## Request

- Base URL: `https://saltapp.ai`
- URL: `https://saltapp.ai/api/v1/device_enrollments`
- Auth: none required

RFC 8252 native-app sign-in. The app sends only its public key, a PKCE S256 challenge and a loopback redirect_uri (http, 127.0.0.1 / localhost / [::1], any port, a path), then opens `authorize_url` in the system browser. The person signs in and approves there; the app redeems the code at /api/v1/device_enrollments/token. The person-facing approve and deny steps are human-JWT flows and are not documented here.

## Request body

- object
  - `name` string, required
  - `platform` 'macos' | 'windows', required
  - `public_key` string, required
  - `code_challenge` string, required: base64url SHA-256 of the code_verifier.
  - `redirect_uri` string
  - `machine_id` string: Opaque, stable install id of this machine. Re-registering the same machine_id under the same owner reuses the same device (same id, new key, old api-keys revoked, open sessions ended). Without it, a device of the same name and platform that has no machine_id is reused.

## Response `201`

Created. Poll mode (no redirect_uri) answers request_id, mode "poll", public_fingerprint and expires_at instead of authorize_url.

- object
  - `request_id` string
  - `authorize_url` string
  - `mode` 'poll'
  - `public_fingerprint` string
  - `expires_at` string

## Other responses

- `404`: Not found, or the feature is off.
- `422`: Bad field, a non-loopback redirect_uri, or a private key was sent.

---

[API](https://skmtc.dev/saltapp/apis/salt-agent-api.md) · [All operations](https://skmtc.dev/saltapp/apis/salt-agent-api/llms.txt) · [OpenAPI document](https://skmtc.dev/saltapp/apis/salt-agent-api/revisions/a8b8642ab7f8?raw)
