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

Read battery, storage and iOS version

/v1/leases/{lease}/infoGET
Model, iOS build, serial number, battery, storage, language and time zone over USB lockdown. Works while locked.
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
Response
200 ยท Device info
udid *string
name *string
model?string
ProductType, e.g. iPhone12,8
modelName?string
iosVersion?string
build?string
serialNumber?string
batteryPercent?integer
charging?boolean
externalPower?boolean
storageTotalBytes?integer
Capacity of the data partition
storageFreeBytes?integer
language?string
e.g. en-IT
locale?string
e.g. en_IT
timeZone?string
e.g. Europe/Rome
wifiAddress?string
sim?object
SIM state from USB lockdown. A field is absent when the iPhone does not report it (unknown), so never read a missing field as "no SIM". A missing phone number does not mean no SIM either.
Show properties
telephony?boolean
The iPhone has a cellular modem (TelephonyCapability).
tray?"sim" | "empty" | "absent" | "unknown"
Physical SIM tray (SIMTrayStatus): sim a SIM card is in the tray, empty the tray is in without a card, absent no tray, unknown iOS does not know. An eSIM does not use the tray: check lines.
lines?object[]
Carrier settings of each SIM iOS reads, physical or eSIM (CarrierBundleInfoArray). Empty: no SIM is read. A line here does not prove cellular service works (PIN, activation, plan): check Settings > Cellular.
Show item properties
slot?integer
SIM slot
embedded?boolean
true: eSIM, false: physical SIM card
carrier?string
iOS carrier bundle, e.g. Vodafone_Ho_it
mcc?string
Mobile country code
mnc?string
Mobile network code
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 GET "https://ghosthand.dev/macs/studio/v1/leases/42/info" \ -H "Authorization: Bearer <token>"
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." }