Agent-readable docs index: /llms.txt. Full docs in one file: /llms-full.txt. Download /docs.zip to grep all markdown files locally.

Make and save a random account detail

/v1/leases/{lease}/randomPOST
Makes a random name, last name, username, 18+ birthdate or password for a new account, and saves it in state.db with the lease's reason, label and iPhone. username is built from the newest name and last name made on this lease, else from random ones. Values are never deleted: GET /v1/random lists them after the lease ends.
Authorizationoptional
bearerAuth?Bearer <token>
Required on the tunnel. An API token of the account, from ghosthand tunnel url --new-token. The unix socket needs no token
Request Bodyapplication/jsonrequired
kind *"name" | "lastname" | "username" | "birthdate" | "password"
name, lastname: common US first or last name. username: lowercase letters and 4 digits, at most 15 chars, also an email username. birthdate: YYYY-MM-DD, age 19 to 45. password: 16 chars with uppercase, lowercase, digits and symbols !@#$%*, starts uppercase.
Response
201 ยท Value made and saved
id *integer
Row id in state.db, increasing
kind *"name" | "lastname" | "username" | "birthdate" | "password"
name, lastname: common US first or last name. username: lowercase letters and 4 digits, at most 15 chars, also an email username. birthdate: YYYY-MM-DD, age 19 to 45. password: 16 chars with uppercase, lowercase, digits and symbols !@#$%*, starts uppercase.
value *string
Example: "Kq7m#Xp2vR9t$bWn"
createdAt *string (date-time)
lease *string
Lease id: the slug of the Mac that holds it and a decimal number that only increases, e.g. studio:42 (42 when that Mac is signed out). Pass it back exactly as returned. Whoever has it can use the iPhone.
Example: "42"Pattern: ^([a-z0-9-]+:)?[1-9][0-9]*$
reason *string
The lease's task when the value was made
label?string
The lease's label when the value was made
device *string
Screen capture id of the lease's iPhone (the id in GET /v1/devices)
deviceName?string
The iPhone's name when the value was made, if it was on USB
Default ยท Error (RFC 9457 problem details). `code` is stable; switch on it, not on `title` or `detail`.
code *"invalid-request" | "unauthorized" | "not-found" | "device-not-found" | "no-device" | "multiple-devices" | "permission-denied" | "bluetooth-unavailable" | "bluetooth-disconnected" | "no-frame" | "device-locked" | "lock-failed" | "pairing-timeout" | "pointer-not-found" | "lock-state-unavailable" | "lockdown-unavailable" | "unlock-failed" | "mute-unconfirmed" | "text-not-found" | "wait-text-timeout" | "cancelled" | "lease-invalid" | "device-leased" | "recording-active" | "no-recording" | "recording-failed" | "daemon-busy" | "tunnel-offline" | "login-required" | "subscription-required" | "unsupported-in-mode" | "xctest-unavailable" | "task-failed" | "internal-error"
Stable error code. Switch on it; title and detail are for people.
title *string
Short summary of the code, the same for every error with this code
status *integer
HTTP status of the error. In stream mode the response status stays 200.
detail *string
What happened and what to do next. Agents should read it.
Request example
curl -X POST "https://ghosthand.dev/macs/studio/v1/leases/42/random" \ -H "Authorization: Bearer <token>" \ -H "Content-Type: application/json" \ -d '{ "kind": "name" }'
Response example
{ "code": "device-leased", "title": "iPhone leased by another client", "status": 409, "detail": "Tommy's iPhone is in use by another lease:\n ses_456 (book a table on OpenTable), acquired 2 min ago, last used 10 s ago (tap)\nDecide first: if that task is still active, give up or tell the user the iPhone is busy." }