Devices API
Lists the routes that register a machine, remove it, list its workspaces, and ask it to take, restore and delete snapshots.
Last updated
On this page
- POST /v1/devices
- GET /v1/devices
- PATCH /v1/devices/{id}
- GET /v1/devices/{id}/config
- DELETE /v1/devices/{id}
- GET /v1/devices/{id}/workspaces
- Snapshots
- POST /v1/workspaces/{id}/snapshots on a device
- GET /v1/devices/{id}/snapshots
- DELETE /v1/devices/{id}/snapshots/{sid}
- POST /v1/workspaces/{id}/device-restore
- GET /v1/devices/{id}/requests
- POST /v1/devices/{id}/requests/{rid}
POST /v1/devices
Registers the machine. The body is {"hardware", "name", "os", "arch", "nono_version"}. hardware is the machine's UUID; Kode stores only a keyed digest. The other fields are 1 to 64 printable characters. Answers 201 {"id", "token"}, or 200 when the owner registers the machine again. The token is in this answer only; Kode keeps only its digest.
GET /v1/devices
Lists the caller's devices as {id, name, os, arch, nono_version, enabled, account, online, last_seen_at, workspaces}.
PATCH /v1/devices/{id}
The body is {"enabled"?: bool, "account"?: string} with at least one field; any other field is 422. account is your handle or a team where you are an active member. Answers 200 with the device as the list shows it. The account the device leaves sees it offline. 409 if another write changed the device at the same time.
GET /v1/devices/{id}/config
Takes the device token and no other credential. Answers 200 {"enabled", "account", "refused"} with Cache-Control: no-store. refused is null, or the sentence that says why the account is refused, for example that your access to the team is paused. A removed device answers 401, and a device from before one-device-per-machine answers 410.
DELETE /v1/devices/{id}
Removes the device and answers 204. The workspaces stay, and a re-register of the machine picks them up. Removing the device ends its token.
GET /v1/devices/{id}/workspaces
Takes the device token and no other credential. Answers 200 with the workspaces this device holds as [{id, name, region, desiredState, deviceWanted, deleting, request, cloneFrom, restartAt, reach}]; deviceWanted already folds in the desk's idle. restartAt is the token of the last restart request, and a new value restarts the workspace. reach lists {service, host, ports, desk, environment} for each service of the desk's environment. The machine deletes from this answer, which is why it is never answered to a login.
Snapshots
A device snapshot is a copy-on-write clone of the workspace folder, kept on the machine itself. Kode cannot reach the bytes, so every snapshot operation is a request the machine performs and answers. A workspace or a snapshot holds at most one pending request: a second is 409 a snapshot operation is already pending. The machine must be online (409 device {name} is offline). Every route below takes a login; an API token (klt_) is the generic 401. Another owner's workspace, device or snapshot is 404.
POST /v1/workspaces/{id}/snapshots on a device
Body {"message"}, optional, at most 200 printable characters. Answers 202 {"request", "snapshot"}: the snapshot id is made now (dsnap- and hex) and exists once the machine says it took it. The workspace document shows device_request until the machine answers, then last_request_error if it failed. A device snapshot is not counted in any quota.
GET /v1/devices/{id}/snapshots
Every snapshot the device holds, newest first, as [{id, workspace, workspace_name, device, message, created_at, pending, last_request_error}]. A snapshot stays listed after its workspace is deleted, until it is deleted by id. GET /v1/workspaces/{id}/snapshots lists those of one workspace's name.
DELETE /v1/devices/{id}/snapshots/{sid}
Asks the machine to move the snapshot into its trash (kept 7 days, like a deleted workspace's folder). Answers 202 {"request", "snapshot"}; the record goes when the machine answers.
POST /v1/workspaces/{id}/device-restore
Body {"snapshot": "dsnap-..."}. The machine stops the workspace, moves its folder to the trash, clones the snapshot into its place and starts it again. The snapshot stays. Answers 202 {"request", "snapshot"}. 422 for a snapshot taken from a workspace of another name (clone it instead) and for a workspace that is not on a device. A restore that fails leaves the folder as it was.
GET /v1/devices/{id}/requests
Takes the device token and no other credential. Answers the requests this device has not answered, as [{id, kind, workspace, snapshotId}]; kind is snapshot, restore or delete-snapshot and workspace is the folder name.
POST /v1/devices/{id}/requests/{rid}
Takes the device token and no other credential. Body {"ok": true, "snapshot": {"id", "createdAt", "bytes": null}} for a take; the id must be the one asked for, or the answer is 422. Use {"ok": true} for any other success, and {"ok": false, "error"} for a failure; error is cut to 300 printable characters. Answers 204 and clears the request. A success creates the snapshot record, or for a delete removes it. A request that is unknown or already answered is 404.