{"openapi":"3.1.0","info":{"title":"Distilled API","version":"v1","description":"Cloud Android phones for your code: list them, look at their screens and act on them, and run workflows on them with the hosted agent. Every request takes an API key from the console's Developers page as `Authorization: Bearer dk_live_…`, and each key holds only the scopes it was given. Bodies and answers are JSON. An error answers `{ error, detail }` with a 4xx or 5xx status, and a 429 says when to try again in Retry-After."},"servers":[{"url":"https://api.distilled.cx"}],"tags":[{"name":"Account"},{"name":"Phones"},{"name":"Apps"},{"name":"Proxies"},{"name":"Control"},{"name":"Assistant"},{"name":"Runs"},{"name":"Workflows"},{"name":"Secrets"},{"name":"Usage"},{"name":"Billing"},{"name":"Developers"}],"paths":{"/v1/me":{"get":{"operationId":"getMe","summary":"The calling key","description":"The workspace the key belongs to, and the key's name and scopes. Any live key may call it.","tags":["Account"],"security":[{"apiKey":[]}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Me"}}}},"default":{"description":"An error: `{ error, detail }`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/phones":{"get":{"operationId":"listPhones","summary":"List phones","description":"Every phone in the workspace, with its device profile, Android version and state. Needs the `phones:read` scope.","tags":["Phones"],"security":[{"apiKey":["phones:read"]}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/Phone"}}}}},"default":{"description":"An error: `{ error, detail }`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"post":{"operationId":"allocatePhones","summary":"Allocate phones","description":"Makes `count` new phones of a device the catalog offers, all or none. The balance must cover a day of the workspace's running phones and these. A retry with the same Idempotency-Key answers with the same phones. Needs the `phones:write` scope.","tags":["Phones"],"security":[{"apiKey":["phones:write"]}],"parameters":[{"in":"header","name":"Idempotency-Key","schema":{"type":"string","minLength":1,"maxLength":200,"description":"Names this request, so retrying it with the same key does it once."}}],"requestBody":{"required":true,"content":{"application/json":{"example":{"profileId":"google/lynx/android-14/AP2A.240905.003","count":2},"schema":{"type":"object","properties":{"profileId":{"type":"string","pattern":"^[a-z0-9][a-z0-9._-]*\\/[a-z0-9][a-z0-9._-]*\\/android-(?:13|14|15|16)\\/[A-Za-z0-9._-]+$"},"count":{"type":"integer","minimum":1,"maximum":50},"region":{"type":"string","minLength":1,"maxLength":64},"plan":{"default":"payg","type":"string","enum":["monthly","payg"]}},"required":["profileId","count"],"additionalProperties":false}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"type":"object","properties":{"phones":{"type":"array","items":{"$ref":"#/components/schemas/Phone"}}},"required":["phones"],"additionalProperties":false}}}},"402":{"description":"The balance doesn't cover these phones: a month of each on `monthly`, a day of each on `payg`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"There aren't that many free slots right now, so none were allocated.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"default":{"description":"An error: `{ error, detail }`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/phones/{id}":{"get":{"operationId":"getPhone","summary":"Get a phone","description":"Needs the `phones:read` scope.","tags":["Phones"],"security":[{"apiKey":["phones:read"]}],"parameters":[{"in":"path","name":"id","schema":{"type":"string","minLength":1,"maxLength":128,"description":"The phone's id."},"required":true,"description":"The phone's id."}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Phone"}}}},"404":{"description":"No such phone in this workspace.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"default":{"description":"An error: `{ error, detail }`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"delete":{"operationId":"releasePhone","summary":"Release a phone","description":"Removes the phone and wipes its data at once. It stops being charged. Needs the `phones:write` scope.","tags":["Phones"],"security":[{"apiKey":["phones:write"]}],"parameters":[{"in":"path","name":"id","schema":{"type":"string","minLength":1,"maxLength":128,"description":"The phone's id."},"required":true,"description":"The phone's id."}],"responses":{"204":{"description":"No content"},"404":{"description":"No such phone in this workspace.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"default":{"description":"An error: `{ error, detail }`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/phones/{id}/respoof":{"post":{"operationId":"respoofPhone","summary":"Give a phone a new identity","description":"A new device identity. Send `{ \"wipe\": true }` to delete its apps and data as well. Needs the `phones:write` scope.","tags":["Phones"],"security":[{"apiKey":["phones:write"]}],"parameters":[{"in":"path","name":"id","schema":{"type":"string","minLength":1,"maxLength":128,"description":"The phone's id."},"required":true,"description":"The phone's id."}],"requestBody":{"required":true,"content":{"application/json":{"example":{"wipe":false},"schema":{"default":{"wipe":false},"type":"object","properties":{"wipe":{"default":false,"type":"boolean"}},"additionalProperties":false}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Phone"}}}},"default":{"description":"An error: `{ error, detail }`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/phones/{id}/lease":{"post":{"operationId":"leasePhone","summary":"Take or renew a lease","description":"Holds the phone for this key, so nobody else drives it meanwhile. Observe and act take one on their own. Needs the `control:write` scope.","tags":["Control"],"security":[{"apiKey":["control:write"]}],"parameters":[{"in":"path","name":"id","schema":{"type":"string","minLength":1,"maxLength":128,"description":"The phone's id."},"required":true,"description":"The phone's id."}],"requestBody":{"required":true,"content":{"application/json":{"example":{"ttlSeconds":300},"schema":{"type":"object","properties":{"ttlSeconds":{"default":300,"type":"integer","minimum":30,"maximum":900}},"additionalProperties":false}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Lease"}}}},"409":{"description":"Someone else holds the phone.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"default":{"description":"An error: `{ error, detail }`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"delete":{"operationId":"releaseLease","summary":"Let a phone go","description":"Ends this key's lease, for a person or another driver. Needs the `control:write` scope.","tags":["Control"],"security":[{"apiKey":["control:write"]}],"parameters":[{"in":"path","name":"id","schema":{"type":"string","minLength":1,"maxLength":128,"description":"The phone's id."},"required":true,"description":"The phone's id."}],"responses":{"204":{"description":"No content"},"default":{"description":"An error: `{ error, detail }`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/phones/{id}/observe":{"post":{"operationId":"observePhone","summary":"Look at a phone","description":"A screenshot, the app in front and, if asked, the screen's elements. Holds the phone for five minutes, as a lease does. Needs the `control:write` scope.","tags":["Control"],"security":[{"apiKey":["control:write"]}],"parameters":[{"in":"path","name":"id","schema":{"type":"string","minLength":1,"maxLength":128,"description":"The phone's id."},"required":true,"description":"The phone's id."}],"requestBody":{"required":true,"content":{"application/json":{"example":{"screenshot":{"maxEdge":960},"uiTree":false},"schema":{"$ref":"#/components/schemas/ObserveRequest"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ObservationOutput"}}}},"409":{"description":"The phone is held by someone else, or isn't running.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"The phone's node is offline.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"default":{"description":"An error: `{ error, detail }`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/phones/{id}/act":{"post":{"operationId":"actOnPhone","summary":"Act on a phone","description":"Tap, long-press, swipe, type, press a key, open an app or a link, or wait. Holds the phone like observe. Needs the `control:write` scope.","tags":["Control"],"security":[{"apiKey":["control:write"]}],"parameters":[{"in":"path","name":"id","schema":{"type":"string","minLength":1,"maxLength":128,"description":"The phone's id."},"required":true,"description":"The phone's id."},{"in":"header","name":"Idempotency-Key","schema":{"type":"string","pattern":"^[A-Za-z0-9_.:-]{1,100}$","description":"Names this action, so retrying it with the same key never plays it twice."}}],"requestBody":{"required":true,"content":{"application/json":{"example":{"action":{"type":"tap","x":540,"y":1200},"frame":{"width":1080,"height":2400}},"schema":{"$ref":"#/components/schemas/ActRequest"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ActResult"}}}},"409":{"description":"The phone is held by someone else, or isn't running.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"The action can't be played.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"default":{"description":"An error: `{ error, detail }`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/phones/{id}/file-uploads":{"post":{"operationId":"startPhoneFileUpload","summary":"Put a file on a phone: start","description":"For a file up to 104857600 bytes, of any size down to one byte. Name the file and its size. A picture or a video goes to the phone's camera roll, so its gallery and every app's media picker show it, and any other file goes to Downloads. A file with the same name on the phone is replaced. A name is letters, digits, dots, dashes and underscores with a type the phone takes: jpg, jpeg, png, webp, gif, heic, heif, mp4, m4v, mov, webm, mkv, 3gp, mp3, m4a, wav, ogg, pdf, txt, csv, json, zip. The answer says where to send it: PUT each part, `partBytes` long except the last, to `{uploadUrl}/parts/{n}` for n from 1, with `Authorization: Bearer {token}` and the part as the body. Each part answers its `part` and `etag`. A part past the file's last, or of another length, is refused with 400 before anything is stored. A part that failed can be sent again with the same token, in any order, and the last copy is kept. Then call `finishPhoneFileUpload` with every part's number and etag. The parts go straight to storage, not through this api. An upload stays open until `expiresAt`, an hour plus two minutes for each part, and its token is never renewed. A workspace may have 5 open, and start 20 GiB of uploads a day (UTC). The token lets in parts of this one upload only, so a browser page on any site may send them without the API key. Needs the `control:write` scope.","tags":["Control"],"security":[{"apiKey":["control:write"]}],"parameters":[{"in":"path","name":"id","schema":{"type":"string","minLength":1,"maxLength":128,"description":"The phone's id."},"required":true,"description":"The phone's id."}],"requestBody":{"required":true,"content":{"application/json":{"example":{"name":"clip.mp4","size":80000000},"schema":{"type":"object","properties":{"name":{"type":"string","pattern":"^[A-Za-z0-9][A-Za-z0-9._-]{0,100}\\.[A-Za-z0-9]{2,4}$"},"size":{"type":"integer","exclusiveMinimum":0,"maximum":104857600},"sha256":{"type":"string","pattern":"^[0-9a-f]{64}$"}},"required":["name","size"],"additionalProperties":false}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","pattern":"^pfu_[a-f0-9]{16}$"},"name":{"type":"string"},"size":{"type":"integer","exclusiveMinimum":0,"maximum":9007199254740991},"partBytes":{"type":"integer","exclusiveMinimum":0,"maximum":9007199254740991},"uploadUrl":{"type":"string","format":"uri"},"token":{"type":"string"},"expiresAt":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"}},"required":["id","name","size","partBytes","uploadUrl","token","expiresAt"],"additionalProperties":false}}}},"409":{"description":"The phone isn't running.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"The name or type isn't one the phone takes, or the size is past the cap.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"`busy`: 5 uploads are already open in the workspace; finish or drop one. `quota-exceeded`: the workspace has started 20 GiB of uploads today (UTC).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"File uploads aren't available on this server.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"default":{"description":"An error: `{ error, detail }`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/phones/{id}/file-uploads/{uploadId}":{"delete":{"operationId":"cancelPhoneFileUpload","summary":"Drop an upload in parts","description":"Throws away what was sent so far. Needs the `control:write` scope.","tags":["Control"],"security":[{"apiKey":["control:write"]}],"parameters":[{"in":"path","name":"id","schema":{"type":"string","minLength":1,"maxLength":128,"description":"The phone's id."},"required":true,"description":"The phone's id."},{"in":"path","name":"uploadId","schema":{"type":"string","pattern":"^pfu_[a-f0-9]{16}$","description":"The upload's id."},"required":true,"description":"The upload's id."}],"responses":{"204":{"description":"No content"},"default":{"description":"An error: `{ error, detail }`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/phones/{id}/file-uploads/{uploadId}/finish":{"post":{"operationId":"finishPhoneFileUpload","summary":"Put a file on a phone: finish","description":"Send every part's number and the etag its request answered. The file is checked against the size, and the `sha256` if one was named, and then put on the phone. Unlike observe and act, this doesn't hold the phone, so it works while someone else drives. The answer comes once the phone has the file. The upload is closed by this call whatever it answers. When the file doesn't reach the phone nothing of it is left there, and the error carries a `reason`: `push-timeout` (the phone didn't take it within a minute), `checksum-mismatch` (storage held other bytes) or `upload-gone` (the upload was deleted first). Needs the `control:write` scope.","tags":["Control"],"security":[{"apiKey":["control:write"]}],"parameters":[{"in":"path","name":"id","schema":{"type":"string","minLength":1,"maxLength":128,"description":"The phone's id."},"required":true,"description":"The phone's id."},{"in":"path","name":"uploadId","schema":{"type":"string","pattern":"^pfu_[a-f0-9]{16}$","description":"The upload's id."},"required":true,"description":"The upload's id."}],"requestBody":{"required":true,"content":{"application/json":{"example":{"parts":[{"part":1,"etag":"a1b2c3"}]},"schema":{"type":"object","properties":{"parts":{"minItems":1,"maxItems":7,"type":"array","items":{"type":"object","properties":{"part":{"type":"integer","minimum":1,"maximum":7},"etag":{"type":"string","minLength":1}},"required":["part","etag"]}}},"required":["parts"],"additionalProperties":false}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string"},"path":{"type":"string"},"size":{"type":"integer","minimum":0,"maximum":9007199254740991},"sha256":{"type":"string","pattern":"^[0-9a-f]{64}$"},"gallery":{"type":"boolean"}},"required":["name","path","size","sha256","gallery"],"additionalProperties":false}}}},"409":{"description":"The phone isn't running.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"The parts don't make a file of the size named, or the file's bytes don't match the named `sha256`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"The phone's server can't take files yet, or didn't answer in time.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"default":{"description":"An error: `{ error, detail }`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/phones/{id}/stream-tickets":{"post":{"operationId":"createStreamTicket","summary":"Get a live stream ticket","description":"A one-use ticket, good for 30 seconds, to open the phone's live stream. `view` only watches. `preview` also only watches, but gets key frames, at most two a second, and the pictures since the last once the screen goes still, for a grid of small screens. `control` also drives the phone by touch and keys, needs `control:write` as well, and holds the phone while the stream is open, as a lease does. Get a new ticket for each connection. Needs the `phones:read` scope.","tags":["Control"],"security":[{"apiKey":["phones:read"]}],"parameters":[{"in":"path","name":"id","schema":{"type":"string","minLength":1,"maxLength":128,"description":"The phone's id."},"required":true,"description":"The phone's id."}],"requestBody":{"required":true,"content":{"application/json":{"example":{"mode":"view"},"schema":{"type":"object","properties":{"mode":{"type":"string","enum":["view","preview","control"]}},"required":["mode"],"additionalProperties":false}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StreamTicket"}}}},"409":{"description":"The phone isn't running, or, for control, someone else holds it (`leased`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many tickets, or too many streams open in the workspace.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"Live view isn't available for this phone's server.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"default":{"description":"An error: `{ error, detail }`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/phones/{id}/stream":{"get":{"operationId":"openPhoneStream","summary":"Open a live stream","description":"A WebSocket upgrade, authorized by a ticket from `createStreamTicket` rather than a key. Offer the subprotocols `distilled.stream.v1` and `distilled.ticket.<ticket>`, and the api names `distilled.stream.v1` back. The `ticket` query still works but puts the ticket in access logs. Binary messages are H.264 access units behind a 24-byte header, text messages are the stream's status once a second and `{\"type\":\"clipboard\",\"text\"}` whenever something on the phone copies text. In control mode text messages sent up are touches, keys, and `{\"type\":\"clipboard\",\"text\",\"paste\"}` to put text on the phone's clipboard and optionally paste it. Any viewer may send `{\"type\":\"keyframe\"}` to ask for a key frame. The socket closes after an hour at most. 4409 means someone else took the phone, 4410 that the phone stopped or moved since the ticket was given, so ask for a new one, and 4503 that the phone's server couldn't be reached. Needs no key.","tags":["Control"],"security":[],"parameters":[{"in":"path","name":"id","schema":{"type":"string","minLength":1,"maxLength":128,"description":"The phone's id."},"required":true,"description":"The phone's id."},{"in":"query","name":"ticket","schema":{"type":"string","pattern":"^st_[A-Za-z0-9_-]{43}$","description":"The ticket, when it isn't offered as a subprotocol. It works once."}}],"responses":{"101":{"description":"Switching protocols"},"401":{"description":"The ticket is spent, has run out, or is for another phone.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"The phone stopped or moved since the ticket was given.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"default":{"description":"An error: `{ error, detail }`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/apps/updates":{"get":{"operationId":"listAppUpdates","summary":"Apps with updates available on this workspace's phones","description":"Needs the `phones:read` scope.","tags":["Apps"],"security":[{"apiKey":["phones:read"]}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"updates":{"type":"array","items":{"type":"object","properties":{"phoneId":{"type":"string","minLength":1,"maxLength":128},"pkg":{"type":"string","maxLength":255,"pattern":"^[a-zA-Z][a-zA-Z0-9_]*(\\.[a-zA-Z][a-zA-Z0-9_]*)+$"},"label":{"type":"string"},"installedVersionCode":{"type":"integer","exclusiveMinimum":0,"maximum":9007199254740991},"availableVersionCode":{"type":"integer","exclusiveMinimum":0,"maximum":9007199254740991}},"required":["phoneId","pkg","label","installedVersionCode","availableVersionCode"],"additionalProperties":false}}},"required":["updates"],"additionalProperties":false}}}},"default":{"description":"An error: `{ error, detail }`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/apps/installs":{"get":{"operationId":"listWorkspaceAppInstalls","summary":"Installs across the workspace","description":"Every phone's installs and uninstalls that are queued or running, or ended in the last hour, newest first. At most 1000. Needs the `phones:read` scope.","tags":["Apps"],"security":[{"apiKey":["phones:read"]}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"installs":{"type":"array","items":{"$ref":"#/components/schemas/PhoneAppInstall"}}},"required":["installs"],"additionalProperties":false}}}},"default":{"description":"An error: `{ error, detail }`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/skills":{"get":{"operationId":"listSkills","summary":"List workflows","description":"Needs the `skills:read` scope.","tags":["Workflows"],"security":[{"apiKey":["skills:read"]}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/Skill"}}}}},"default":{"description":"An error: `{ error, detail }`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"post":{"operationId":"createSkill","summary":"Save a workflow","description":"Needs the `skills:write` scope.","tags":["Workflows"],"security":[{"apiKey":["skills:write"]}],"requestBody":{"required":true,"content":{"application/json":{"example":{"name":"Dark theme","app":"com.android.settings","workflow":[{"kind":"step","text":"Open Display and turn on dark theme"}]},"schema":{"$ref":"#/components/schemas/SkillDefinition"}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Skill"}}}},"default":{"description":"An error: `{ error, detail }`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/skills/{id}":{"get":{"operationId":"getSkill","summary":"Get a workflow","description":"Needs the `skills:read` scope.","tags":["Workflows"],"security":[{"apiKey":["skills:read"]}],"parameters":[{"in":"path","name":"id","schema":{"type":"string","pattern":"^sk_[a-z0-9]{12,32}$","description":"The workflow's id."},"required":true,"description":"The workflow's id."}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Skill"}}}},"default":{"description":"An error: `{ error, detail }`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"put":{"operationId":"updateSkill","summary":"Change a workflow","description":"Replaces its definition and keeps its id. Runs already started keep their own copy. Needs the `skills:write` scope.","tags":["Workflows"],"security":[{"apiKey":["skills:write"]}],"parameters":[{"in":"path","name":"id","schema":{"type":"string","pattern":"^sk_[a-z0-9]{12,32}$","description":"The workflow's id."},"required":true,"description":"The workflow's id."}],"requestBody":{"required":true,"content":{"application/json":{"example":{"name":"Dark theme","app":"com.android.settings","workflow":[{"kind":"step","text":"Open Display and turn on dark theme"}]},"schema":{"$ref":"#/components/schemas/SkillDefinition"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Skill"}}}},"default":{"description":"An error: `{ error, detail }`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"delete":{"operationId":"deleteSkill","summary":"Delete a workflow","description":"Runs already started keep their own copy. Needs the `skills:write` scope.","tags":["Workflows"],"security":[{"apiKey":["skills:write"]}],"parameters":[{"in":"path","name":"id","schema":{"type":"string","pattern":"^sk_[a-z0-9]{12,32}$","description":"The workflow's id."},"required":true,"description":"The workflow's id."}],"responses":{"204":{"description":"No content"},"default":{"description":"An error: `{ error, detail }`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/skills/{id}/enabled":{"post":{"operationId":"postSkillEnabled","summary":"Turn a workflow on or off (POST)","description":"The same as PUT, for clients that only POST. Needs the `skills:write` scope.","tags":["Workflows"],"security":[{"apiKey":["skills:write"]}],"parameters":[{"in":"path","name":"id","schema":{"type":"string","pattern":"^sk_[a-z0-9]{12,32}$","description":"The workflow's id."},"required":true,"description":"The workflow's id."}],"requestBody":{"required":true,"content":{"application/json":{"example":{"enabled":false},"schema":{"type":"object","properties":{"enabled":{"type":"boolean"}},"required":["enabled"],"additionalProperties":false}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Skill"}}}},"default":{"description":"An error: `{ error, detail }`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"put":{"operationId":"setSkillEnabled","summary":"Turn a workflow on or off","description":"Needs the `skills:write` scope.","tags":["Workflows"],"security":[{"apiKey":["skills:write"]}],"parameters":[{"in":"path","name":"id","schema":{"type":"string","pattern":"^sk_[a-z0-9]{12,32}$","description":"The workflow's id."},"required":true,"description":"The workflow's id."}],"requestBody":{"required":true,"content":{"application/json":{"example":{"enabled":false},"schema":{"type":"object","properties":{"enabled":{"type":"boolean"}},"required":["enabled"],"additionalProperties":false}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Skill"}}}},"default":{"description":"An error: `{ error, detail }`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/runs":{"get":{"operationId":"listRuns","summary":"List runs","description":"Recent runs, newest first. Needs the `runs:read` scope.","tags":["Runs"],"security":[{"apiKey":["runs:read"]}],"parameters":[{"in":"query","name":"limit","schema":{"type":"integer","minimum":1,"maximum":200,"description":"How many, up to 200."}},{"in":"query","name":"state","schema":{"type":"string","enum":["queued","running","needs_human","done","failed","stopped"],"description":"Only runs in this state."}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/Run"}}}}},"default":{"description":"An error: `{ error, detail }`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"post":{"operationId":"startRun","summary":"Start a run","description":"Starts a saved workflow, or one given inline, on one or more phones. The same Idempotency-Key answers the run it first made. Needs the `runs:write` scope.","tags":["Runs"],"security":[{"apiKey":["runs:write"]}],"parameters":[{"in":"header","name":"Idempotency-Key","schema":{"type":"string","minLength":1,"maxLength":200,"description":"Names this request, so retrying it with the same key does it once."}}],"requestBody":{"required":true,"content":{"application/json":{"example":{"skill":{"name":"Dark theme","app":"com.android.settings","workflow":[{"kind":"step","text":"Open Display and turn on dark theme"}]},"phones":["ph-1"]},"schema":{"$ref":"#/components/schemas/CreateRunRequest"}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Run"}}}},"429":{"description":"The workspace has used its model tokens for the day.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"Hosted runs are switched off.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"default":{"description":"An error: `{ error, detail }`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/runs/{id}":{"get":{"operationId":"getRun","summary":"Get a run","description":"One run, and how each phone is getting on. Needs the `runs:read` scope.","tags":["Runs"],"security":[{"apiKey":["runs:read"]}],"parameters":[{"in":"path","name":"id","schema":{"type":"string","pattern":"^run_[a-z0-9]{12,32}$","description":"The run's id."},"required":true,"description":"The run's id."}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Run"}}}},"default":{"description":"An error: `{ error, detail }`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/runs/{id}/stop":{"post":{"operationId":"stopRun","summary":"Stop a run","description":"Stopping a run that has ended changes nothing. Needs the `runs:write` scope.","tags":["Runs"],"security":[{"apiKey":["runs:write"]}],"parameters":[{"in":"path","name":"id","schema":{"type":"string","pattern":"^run_[a-z0-9]{12,32}$","description":"The run's id."},"required":true,"description":"The run's id."}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Run"}}}},"default":{"description":"An error: `{ error, detail }`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/runs/{id}/steps":{"get":{"operationId":"listRunSteps","summary":"List a run's steps","description":"Steps in order of phone, then step. A page shorter than the limit is the last. Needs the `runs:read` scope.","tags":["Runs"],"security":[{"apiKey":["runs:read"]}],"parameters":[{"in":"path","name":"id","schema":{"type":"string","pattern":"^run_[a-z0-9]{12,32}$","description":"The run's id."},"required":true,"description":"The run's id."},{"in":"query","name":"phoneId","schema":{"type":"string","description":"Only this phone's steps."}},{"in":"query","name":"afterN","schema":{"type":"integer","minimum":0,"maximum":9007199254740991,"description":"With phoneId: the last step of the page before."}},{"in":"query","name":"after","schema":{"type":"string","description":"`<phoneId>:<n>`, the last step of the page before."}},{"in":"query","name":"limit","schema":{"type":"integer","minimum":1,"maximum":500,"description":"How many, up to 500."}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/RunStep"}}}}},"default":{"description":"An error: `{ error, detail }`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/runs/{id}/steps/{phoneId}/{n}/screenshot":{"get":{"operationId":"getRunStepScreenshot","summary":"A step's screenshot","description":"The screen the model saw at a step. Needs the `runs:read` scope.","tags":["Runs"],"security":[{"apiKey":["runs:read"]}],"parameters":[{"in":"path","name":"id","schema":{"type":"string","pattern":"^run_[a-z0-9]{12,32}$","description":"The run's id."},"required":true,"description":"The run's id."},{"in":"path","name":"phoneId","schema":{"type":"string","minLength":1,"maxLength":128,"description":"The phone's id."},"required":true,"description":"The phone's id."},{"in":"path","name":"n","schema":{"type":"integer","minimum":1,"maximum":9007199254740991,"description":"The step's number."},"required":true,"description":"The step's number."}],"responses":{"200":{"description":"OK","content":{"image/jpeg":{"schema":{"type":"string","description":"The image."}},"image/png":{"schema":{"type":"string","description":"The image."}}}},"404":{"description":"No screenshot was kept for that step.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"default":{"description":"An error: `{ error, detail }`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/runs/{id}/events":{"get":{"operationId":"streamRunEvents","summary":"Follow a run","description":"Server-sent events until the run ends, each a run event as JSON. Resumes after Last-Event-ID. Needs the `runs:read` scope.","tags":["Runs"],"security":[{"apiKey":["runs:read"]}],"parameters":[{"in":"path","name":"id","schema":{"type":"string","pattern":"^run_[a-z0-9]{12,32}$","description":"The run's id."},"required":true,"description":"The run's id."},{"in":"header","name":"Last-Event-ID","schema":{"type":"string","description":"The seq of the last event seen."}}],"responses":{"200":{"description":"OK","content":{"text/event-stream":{"schema":{"$ref":"#/components/schemas/RunEvent"}}}},"204":{"description":"The run has ended and nothing came after Last-Event-ID."},"default":{"description":"An error: `{ error, detail }`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/runs/{id}/phones/{phoneId}/resume":{"post":{"operationId":"resumeRunPhone","summary":"Resume a phone","description":"Carries on a phone that stopped to wait for a person, with a fresh time budget. Needs the `runs:write` scope.","tags":["Runs"],"security":[{"apiKey":["runs:write"]}],"parameters":[{"in":"path","name":"id","schema":{"type":"string","pattern":"^run_[a-z0-9]{12,32}$","description":"The run's id."},"required":true,"description":"The run's id."},{"in":"path","name":"phoneId","schema":{"type":"string","minLength":1,"maxLength":128,"description":"The phone's id."},"required":true,"description":"The phone's id."}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Run"}}}},"default":{"description":"An error: `{ error, detail }`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/secrets":{"get":{"operationId":"listSecrets","summary":"List secrets","description":"Their names. Values never come back. Needs the `runs:write` scope.","tags":["Secrets"],"security":[{"apiKey":["runs:write"]}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/Secret"}}}}},"default":{"description":"An error: `{ error, detail }`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/secrets/{name}":{"put":{"operationId":"putSecret","summary":"Set a secret","description":"A value a workflow types as `{{secret:name}}`. The model only sees the placeholder. Needs the `runs:write` scope.","tags":["Secrets"],"security":[{"apiKey":["runs:write"]}],"parameters":[{"in":"path","name":"name","schema":{"type":"string","pattern":"^[a-z][a-z0-9_]{0,39}$","description":"The secret's name."},"required":true,"description":"The secret's name."}],"requestBody":{"required":true,"content":{"application/json":{"example":{"value":"correct horse battery staple"},"schema":{"type":"object","properties":{"value":{"type":"string","minLength":1,"maxLength":500}},"required":["value"],"additionalProperties":false}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Secret"}}}},"default":{"description":"An error: `{ error, detail }`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"delete":{"operationId":"deleteSecret","summary":"Delete a secret","description":"Needs the `runs:write` scope.","tags":["Secrets"],"security":[{"apiKey":["runs:write"]}],"parameters":[{"in":"path","name":"name","schema":{"type":"string","pattern":"^[a-z][a-z0-9_]{0,39}$","description":"The secret's name."},"required":true,"description":"The secret's name."}],"responses":{"204":{"description":"No content"},"default":{"description":"An error: `{ error, detail }`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/usage":{"get":{"operationId":"getUsage","summary":"Agent usage","description":"Steps the workspace's runs took, and model tokens its runs and assistant used, in [from, to). The last 30 days unless said. Needs the `runs:read` scope.","tags":["Usage"],"security":[{"apiKey":["runs:read"]}],"parameters":[{"in":"query","name":"from","schema":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$","description":"The start."}},{"in":"query","name":"to","schema":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$","description":"The end."}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Usage"}}}},"default":{"description":"An error: `{ error, detail }`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/usage/agent":{"get":{"operationId":"getAgentUsage","summary":"Agent use","description":"What the workspace's runs and assistant used in a month, in US cents and in model tokens, what its phone time includes, and what is charged past that. Needs the `runs:read` scope.","tags":["Usage"],"security":[{"apiKey":["runs:read"]}],"parameters":[{"in":"query","name":"period","schema":{"type":"string","pattern":"^\\d{4}-(0[1-9]|1[0-2])$","description":"`YYYY-MM` in UTC. This month unless said."}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentUsage"}}}},"default":{"description":"An error: `{ error, detail }`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/egress":{"get":{"operationId":"getEgress","summary":"Phone traffic","description":"Each phone's internet traffic through our network in a month, and what it costs. Needs the `phones:read` scope.","tags":["Usage"],"security":[{"apiKey":["phones:read"]}],"parameters":[{"in":"query","name":"period","schema":{"type":"string","pattern":"^\\d{4}-(0[1-9]|1[0-2])$","description":"`YYYY-MM` in UTC. This month unless said."}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EgressUsage"}}}},"default":{"description":"An error: `{ error, detail }`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/egress/series":{"get":{"operationId":"getEgressSeries","summary":"Phone traffic over time","description":"Each phone's traffic in buckets of 1, 6 or 24 hours, for charts. Counted as `/v1/egress` counts it, with traffic through the workspace's own proxies, and never priced. At most 200 buckets. Needs the `phones:read` scope.","tags":["Usage"],"security":[{"apiKey":["phones:read"]}],"parameters":[{"in":"query","name":"from","schema":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$","description":"The start, taken back to a whole step in UTC: the hour, or midnight for 24. 7 days before `to` unless said."}},{"in":"query","name":"to","schema":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$","description":"The end. Now unless said."}},{"in":"query","name":"step","schema":{"anyOf":[{"type":"number","const":1},{"type":"number","const":6},{"type":"number","const":24}],"description":"Hours in each bucket, 1 unless said."}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EgressSeries"}}}},"400":{"description":"The span is empty, or too long for the step.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"default":{"description":"An error: `{ error, detail }`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/catalog":{"get":{"operationId":"getCatalog","summary":"What can be allocated","description":"The devices phones can be allocated as, the regions with free slots, and a phone's monthly price in US cents. Needs the `phones:read` scope.","tags":["Phones"],"security":[{"apiKey":["phones:read"]}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Catalog"}}}},"default":{"description":"An error: `{ error, detail }`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/billing":{"get":{"operationId":"getBilling","summary":"Balance","description":"The prepaid balance in US cents, how many phones are running on it, and its latest entries, newest first. Pass `nextBefore` back as `before` for older entries. Needs the `billing:read` scope.","tags":["Billing"],"security":[{"apiKey":["billing:read"]}],"parameters":[{"in":"query","name":"before","schema":{"type":"string","minLength":1,"maxLength":200,"description":"A `nextBefore` from an earlier answer: the entries before it."}},{"in":"query","name":"limit","schema":{"type":"integer","minimum":1,"maximum":200,"description":"How many entries."}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Billing"}}}},"default":{"description":"An error: `{ error, detail }`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/billing/top-ups":{"post":{"operationId":"startTopUp","summary":"Top up on a payment page","description":"Answers with a payment page to send the payer to: Stripe Checkout for `card`, the default, or the processor's own page for `crypto`. The balance goes up once the payment goes through. Needs the `billing:write` scope.","tags":["Billing"],"security":[{"apiKey":["billing:write"]}],"requestBody":{"required":true,"content":{"application/json":{"example":{"cents":5000},"schema":{"type":"object","properties":{"cents":{"type":"integer","minimum":1000,"maximum":100000},"method":{"default":"card","type":"string","enum":["card","crypto"]}},"required":["cents"],"additionalProperties":false}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"type":"object","properties":{"url":{"type":"string","format":"uri"}},"required":["url"],"additionalProperties":false}}}},"503":{"description":"The payment processor refused or couldn't be reached, or Top-ups aren't set up.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"default":{"description":"An error: `{ error, detail }`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/billing/promo-codes":{"post":{"operationId":"redeemPromoCode","summary":"Redeem a promotion code","description":"Takes the code's share off what the workspace's phones are charged, by the month or by the minute, until the discount ends. Each workspace redeems one code, once. Needs the `billing:write` scope.","tags":["Billing"],"security":[{"apiKey":["billing:write"]}],"requestBody":{"required":true,"content":{"application/json":{"example":{"code":"DISTILLED20"},"schema":{"type":"object","properties":{"code":{"type":"string","minLength":1,"maxLength":40}},"required":["code"],"additionalProperties":false}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"type":"object","properties":{"code":{"type":"string"},"percentOff":{"type":"integer","minimum":1,"maximum":100},"phoneMonthlyCents":{"type":"integer","minimum":0,"maximum":9007199254740991},"redeemedAt":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},"endsAt":{"anyOf":[{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},{"type":"null"}]}},"required":["code","percentOff","phoneMonthlyCents","redeemedAt","endsAt"],"additionalProperties":false}}}},"404":{"description":"No such code.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"The code has expired, the workspace already redeemed one, or the code is for new workspaces and this one has topped up before.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"default":{"description":"An error: `{ error, detail }`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/billing/card/payments":{"post":{"operationId":"startCardPayment","summary":"Top up by card in your own page","description":"Answers with a payment for Stripe's card form to collect in a page of your own: load Stripe's script with `publishableKey` and set its form up with `clientSecret`. The balance goes up once the payment succeeds. Ask the payment for where it stands. Needs the `billing:write` scope.","tags":["Billing"],"security":[{"apiKey":["billing:write"]}],"requestBody":{"required":true,"content":{"application/json":{"example":{"cents":5000},"schema":{"type":"object","properties":{"cents":{"type":"integer","minimum":1000,"maximum":100000}},"required":["cents"],"additionalProperties":false}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"cents":{"type":"integer","exclusiveMinimum":0,"maximum":9007199254740991},"clientSecret":{"type":"string"},"publishableKey":{"type":"string"}},"required":["id","cents","clientSecret","publishableKey"],"additionalProperties":false}}}},"503":{"description":"The payment processor refused or couldn't be reached, or Card payments in your own page aren't set up.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"default":{"description":"An error: `{ error, detail }`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/billing/card/payments/{id}":{"get":{"operationId":"getCardPayment","summary":"A card top-up's state","description":"Whether the payment is still to be paid, is with the bank, was paid or was cancelled, with Stripe's receipt page once it is paid. A paid one is on the balance by the time this answers. Needs the `billing:read` scope.","tags":["Billing"],"security":[{"apiKey":["billing:read"]}],"parameters":[{"in":"path","name":"id","schema":{"type":"string","description":"The payment's `id`."},"required":true,"description":"The payment's `id`."}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"status":{"type":"string","enum":["waiting","processing","paid","failed"]},"cents":{"type":"integer","exclusiveMinimum":0,"maximum":9007199254740991},"receiptUrl":{"anyOf":[{"type":"string","format":"uri"},{"type":"null"}]}},"required":["id","status","cents","receiptUrl"],"additionalProperties":false}}}},"503":{"description":"The payment processor refused or couldn't be reached, or Card payments in your own page aren't set up.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"default":{"description":"An error: `{ error, detail }`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/billing/trial/checks":{"post":{"operationId":"checkTrialCard","summary":"Start the free trial","description":"Checks a card and starts the free trial when it passes. Nothing is charged. Collect the card with Stripe's Payment Element in `setup` mode, loaded with the trial's `publishableKey` from the balance, and send the confirmation token it makes. A card in a wallet, a prepaid card, or one that already started a trial is refused. When `status` is `action`, pass `clientSecret` to Stripe's `handleNextAction`, then ask the check for where it stands. Needs the `billing:write` scope.","tags":["Billing"],"security":[{"apiKey":["billing:write"]}],"requestBody":{"required":true,"content":{"application/json":{"example":{"confirmationToken":"ctoken_1PgaQ2"},"schema":{"type":"object","properties":{"confirmationToken":{"type":"string","pattern":"^ctoken_[0-9A-Za-z_]{1,200}$"}},"required":["confirmationToken"],"additionalProperties":false}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"anyOf":[{"type":"string"},{"type":"null"}]},"status":{"type":"string","enum":["started","action","processing","declined","refused"]},"clientSecret":{"anyOf":[{"type":"string"},{"type":"null"}]},"reason":{"anyOf":[{"type":"string"},{"type":"null"}]}},"required":["id","status","clientSecret","reason"],"additionalProperties":false}}}},"404":{"description":"Stripe has no such confirmation token.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"The workspace already had its trial, has topped up before, or is billed by invoice.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many card checks for the workspace. Retry after the seconds `Retry-After` gives.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"The payment processor refused or couldn't be reached, or Card payments in your own page aren't set up.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"default":{"description":"An error: `{ error, detail }`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/billing/trial/checks/{id}":{"get":{"operationId":"getTrialCheck","summary":"A free trial card check's state","description":"Where a card check stands once the bank had the cardholder approve it. A started trial is on the balance by the time this answers, and a declined check is cancelled. Needs the `billing:read` scope.","tags":["Billing"],"security":[{"apiKey":["billing:read"]}],"parameters":[{"in":"path","name":"id","schema":{"type":"string","description":"The card check's `id`."},"required":true,"description":"The card check's `id`."}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"anyOf":[{"type":"string"},{"type":"null"}]},"status":{"type":"string","enum":["started","action","processing","declined","refused"]},"clientSecret":{"anyOf":[{"type":"string"},{"type":"null"}]},"reason":{"anyOf":[{"type":"string"},{"type":"null"}]}},"required":["id","status","clientSecret","reason"],"additionalProperties":false}}}},"404":{"description":"No such card check in this workspace.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"The payment processor refused or couldn't be reached, or Card payments in your own page aren't set up.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"default":{"description":"An error: `{ error, detail }`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/billing/auto-top-up":{"put":{"operationId":"setAutoTopUp","summary":"Turn automatic top-up on or off","description":"The card saved when the free trial started tops the balance up by `cents` whenever it covers less than what the phones drawing on it need in the next `hours`, from `startsAt`, the day the trial ends. Nothing is charged automatically before then. Turning it on again clears the last failure, so the card is tried at the next hourly check. Needs the `billing:write` scope.","tags":["Billing"],"security":[{"apiKey":["billing:write"]}],"requestBody":{"required":true,"content":{"application/json":{"example":{"enabled":false},"schema":{"type":"object","properties":{"enabled":{"type":"boolean"}},"required":["enabled"],"additionalProperties":false}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"enabled":{"type":"boolean"},"startsAt":{"anyOf":[{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},{"type":"null"}]},"cents":{"type":"integer","exclusiveMinimum":0,"maximum":9007199254740991},"hours":{"type":"integer","exclusiveMinimum":0,"maximum":9007199254740991},"card":{"type":"string"},"failure":{"anyOf":[{"type":"string"},{"type":"null"}]},"failedAt":{"anyOf":[{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},{"type":"null"}]}},"required":["enabled","startsAt","cents","hours","card","failure","failedAt"],"additionalProperties":false}}}},"404":{"description":"The workspace has no saved card.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"default":{"description":"An error: `{ error, detail }`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/billing/crypto/currencies":{"get":{"operationId":"listCryptoCurrencies","summary":"Coins for a crypto top-up","description":"The coins a crypto top-up can be paid in, each with the networks it can be sent over. Needs the `billing:read` scope.","tags":["Billing"],"security":[{"apiKey":["billing:read"]}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"currencies":{"type":"array","items":{"type":"object","properties":{"symbol":{"type":"string"},"name":{"type":"string"},"networks":{"minItems":1,"type":"array","items":{"type":"object","properties":{"network":{"type":"string"},"name":{"type":"string"}},"required":["network","name"],"additionalProperties":false}}},"required":["symbol","name","networks"],"additionalProperties":false}}},"required":["currencies"],"additionalProperties":false}}}},"503":{"description":"The payment processor refused or couldn't be reached, or Crypto top-ups aren't set up.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"default":{"description":"An error: `{ error, detail }`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/billing/crypto/payments":{"post":{"operationId":"startCryptoPayment","summary":"Top up by crypto","description":"Answers with an address and the amount of the coin to send to it, to show in a page of your own. The balance goes up once the payment is confirmed. Ask the payment for where it stands. Needs the `billing:write` scope.","tags":["Billing"],"security":[{"apiKey":["billing:write"]}],"requestBody":{"required":true,"content":{"application/json":{"example":{"cents":5000,"currency":"USDT","network":"Tron"},"schema":{"type":"object","properties":{"cents":{"type":"integer","minimum":1000,"maximum":100000},"currency":{"type":"string","pattern":"^[A-Z0-9]{2,12}$"},"network":{"type":"string","minLength":1,"maxLength":40}},"required":["cents","currency","network"],"additionalProperties":false}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"cents":{"type":"integer","exclusiveMinimum":0,"maximum":9007199254740991},"payAmount":{"type":"number","exclusiveMinimum":0},"payCurrency":{"type":"string"},"networkName":{"type":"string"},"address":{"type":"string"},"memo":{"anyOf":[{"type":"string"},{"type":"null"}]},"paymentUri":{"anyOf":[{"type":"string"},{"type":"null"}]},"expiresAt":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"}},"required":["id","cents","payAmount","payCurrency","networkName","address","memo","paymentUri","expiresAt"],"additionalProperties":false}}}},"503":{"description":"The payment processor refused or couldn't be reached, or Crypto top-ups aren't set up.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"default":{"description":"An error: `{ error, detail }`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/billing/crypto/payments/{id}":{"get":{"operationId":"getCryptoPayment","summary":"A crypto top-up's state","description":"Whether the payment was seen, is confirming, came up short, was paid or ran out of time, with the transaction that paid it once one was seen. A paid one is on the balance by the time this answers. Needs the `billing:read` scope.","tags":["Billing"],"security":[{"apiKey":["billing:read"]}],"parameters":[{"in":"path","name":"id","schema":{"type":"string","description":"The payment's `id`."},"required":true,"description":"The payment's `id`."}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"status":{"type":"string","enum":["waiting","confirming","underpaid","paid","expired"]},"cents":{"type":"integer","exclusiveMinimum":0,"maximum":9007199254740991},"transaction":{"default":null,"anyOf":[{"type":"object","properties":{"hash":{"type":"string"},"network":{"type":"string"}},"required":["hash","network"],"additionalProperties":false},{"type":"null"}]}},"required":["id","status","cents","transaction"],"additionalProperties":false}}}},"503":{"description":"The payment processor refused or couldn't be reached, or Crypto top-ups aren't set up.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"default":{"description":"An error: `{ error, detail }`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/status":{"get":{"operationId":"getStatus","summary":"Platform status","description":"Whether each part of the platform is working, its last 90 days and past incidents, which regions take new phones, and how many of yours run in each. Any key may ask. Any live key may call it.","tags":["Account"],"security":[{"apiKey":[]}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"checkedAt":{"anyOf":[{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},{"type":"null"}]},"components":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"detail":{"type":"string"},"health":{"anyOf":[{"type":"string","enum":["ok","degraded","down"]},{"type":"null"}]},"uptime":{"anyOf":[{"type":"number","minimum":0,"maximum":1},{"type":"null"}]},"days":{"minItems":90,"maxItems":90,"type":"array","items":{"type":"object","properties":{"day":{"type":"string","format":"date","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"},"health":{"anyOf":[{"type":"string","enum":["ok","degraded","down"]},{"type":"null"}]},"troubleMinutes":{"type":"integer","minimum":0,"maximum":9007199254740991}},"required":["day","health","troubleMinutes"],"additionalProperties":false}}},"required":["id","name","detail","health","uptime","days"],"additionalProperties":false}},"regions":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"health":{"anyOf":[{"type":"string","enum":["ok","degraded","down"]},{"type":"null"}]},"takingPhones":{"type":"boolean"},"yourPhones":{"type":"integer","minimum":0,"maximum":9007199254740991}},"required":["id","name","health","takingPhones","yourPhones"],"additionalProperties":false}},"incidents":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"title":{"type":"string"},"note":{"type":"string"},"component":{"type":"string"},"health":{"type":"string","enum":["degraded","down"]},"startedAt":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},"resolvedAt":{"anyOf":[{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},{"type":"null"}]}},"required":["id","title","note","component","health","startedAt","resolvedAt"],"additionalProperties":false}}},"required":["checkedAt","components","regions","incidents"],"additionalProperties":false}}}},"default":{"description":"An error: `{ error, detail }`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/notices":{"get":{"operationId":"getNotices","summary":"Workspace notices","description":"What the workspace should know about now. `rollout` is set while a node holding any of your phones is being updated, so those phones may briefly restart or disconnect, and is null otherwise. Any key may ask. Any live key may call it.","tags":["Account"],"security":[{"apiKey":[]}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"rollout":{"anyOf":[{"type":"object","properties":{"startedAt":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},"phones":{"type":"integer","exclusiveMinimum":0,"maximum":9007199254740991}},"required":["startedAt","phones"],"additionalProperties":false},{"type":"null"}]}},"required":["rollout"],"additionalProperties":false}}}},"default":{"description":"An error: `{ error, detail }`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/requests":{"get":{"operationId":"listRequests","summary":"Request log","description":"The workspace's latest calls to /v1, newest first, kept for 30 days, and each hour's count for the last seven days. Needs the `runs:read` scope.","tags":["Developers"],"security":[{"apiKey":["runs:read"]}],"parameters":[{"in":"query","name":"since","schema":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"}},{"in":"query","name":"until","schema":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"}},{"in":"query","name":"status","schema":{"anyOf":[{"type":"string","enum":["ok","error","2xx","3xx","4xx","5xx"]},{"type":"string","pattern":"^[1-5][0-9]{2}$"}]}},{"in":"query","name":"method","schema":{"type":"string","enum":["GET","POST","PUT","DELETE"]}},{"in":"query","name":"path","schema":{"type":"string","minLength":1,"maxLength":200}},{"in":"query","name":"limit","schema":{"default":100,"type":"integer","minimum":1,"maximum":1000}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RequestLog"}}}},"default":{"description":"An error: `{ error, detail }`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/openapi.json":{"get":{"operationId":"getOpenApi","summary":"This document","description":"The API as OpenAPI 3.1. Needs no key. Needs no key.","tags":["Developers"],"security":[],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}}}}},"default":{"description":"An error: `{ error, detail }`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/proxies":{"get":{"operationId":"listProxies","summary":"List proxies","description":"The workspace's own proxies, with each one's last check and the phones that use it. Logins are never shown. Needs the `phones:read` scope.","tags":["Proxies"],"security":[{"apiKey":["phones:read"]}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"proxies":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":128},"label":{"type":"string"},"endpoint":{"type":"string"},"scheme":{"type":"string","enum":["http","https"]},"host":{"type":"string"},"port":{"type":"integer","exclusiveMinimum":0,"maximum":9007199254740991},"hasLogin":{"type":"boolean"},"country":{"anyOf":[{"type":"string","pattern":"^[A-Z]{2}$"},{"type":"null"}]},"phones":{"type":"integer","minimum":0,"maximum":9007199254740991},"lastCheck":{"anyOf":[{"type":"object","properties":{"at":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},"reachable":{"type":"boolean"},"latencyMs":{"anyOf":[{"type":"integer","minimum":0,"maximum":9007199254740991},{"type":"null"}]},"exitIp":{"anyOf":[{"type":"string"},{"type":"null"}]},"exitCountry":{"anyOf":[{"type":"string","pattern":"^[A-Z]{2}$"},{"type":"null"}]},"residential":{"anyOf":[{"type":"boolean"},{"type":"null"}]},"connectionType":{"anyOf":[{"type":"string"},{"type":"null"}]},"error":{"anyOf":[{"type":"string"},{"type":"null"}]}},"required":["at","reachable","latencyMs","exitIp","exitCountry","error"],"additionalProperties":false},{"type":"null"}]},"createdAt":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"}},"required":["id","label","endpoint","scheme","host","port","hasLogin","country","phones","lastCheck","createdAt"],"additionalProperties":false}},"limit":{"type":"integer","exclusiveMinimum":0,"maximum":9007199254740991},"rotation":{"type":"boolean"}},"required":["proxies","limit","rotation"],"additionalProperties":false}}}},"default":{"description":"An error: `{ error, detail }`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"post":{"operationId":"saveProxy","summary":"Save a proxy","description":"An http:// or https:// proxy with its login. The login is sealed and never shown again. At most 50 per workspace. Needs the `phones:write` scope.","tags":["Proxies"],"security":[{"apiKey":["phones:write"]}],"requestBody":{"required":true,"content":{"application/json":{"example":{"label":"Residential US","url":"http://user:pass@proxy.example.com:8080"},"schema":{"type":"object","properties":{"label":{"type":"string","minLength":1,"maxLength":80},"url":{"type":"string","minLength":1,"maxLength":2048},"country":{"type":"string","pattern":"^[A-Z]{2}$"}},"required":["label","url"],"additionalProperties":false}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":128},"label":{"type":"string"},"endpoint":{"type":"string"},"scheme":{"type":"string","enum":["http","https"]},"host":{"type":"string"},"port":{"type":"integer","exclusiveMinimum":0,"maximum":9007199254740991},"hasLogin":{"type":"boolean"},"country":{"anyOf":[{"type":"string","pattern":"^[A-Z]{2}$"},{"type":"null"}]},"phones":{"type":"integer","minimum":0,"maximum":9007199254740991},"lastCheck":{"anyOf":[{"type":"object","properties":{"at":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},"reachable":{"type":"boolean"},"latencyMs":{"anyOf":[{"type":"integer","minimum":0,"maximum":9007199254740991},{"type":"null"}]},"exitIp":{"anyOf":[{"type":"string"},{"type":"null"}]},"exitCountry":{"anyOf":[{"type":"string","pattern":"^[A-Z]{2}$"},{"type":"null"}]},"residential":{"anyOf":[{"type":"boolean"},{"type":"null"}]},"connectionType":{"anyOf":[{"type":"string"},{"type":"null"}]},"error":{"anyOf":[{"type":"string"},{"type":"null"}]}},"required":["at","reachable","latencyMs","exitIp","exitCountry","error"],"additionalProperties":false},{"type":"null"}]},"createdAt":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"}},"required":["id","label","endpoint","scheme","host","port","hasLogin","country","phones","lastCheck","createdAt"],"additionalProperties":false}}}},"default":{"description":"An error: `{ error, detail }`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/proxies/{id}":{"delete":{"operationId":"deleteProxy","summary":"Remove a proxy","description":"Needs the `phones:write` scope.","tags":["Proxies"],"security":[{"apiKey":["phones:write"]}],"parameters":[{"in":"path","name":"id","schema":{"type":"string","description":"The proxy's id."},"required":true,"description":"The proxy's id."}],"responses":{"204":{"description":"No content"},"409":{"description":"A phone still uses it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"default":{"description":"An error: `{ error, detail }`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/proxies/{id}/check":{"post":{"operationId":"checkProxy","summary":"Check a proxy","description":"Connects through the proxy the way a phone would and keeps whether it answered, how fast, and the address and country it exits from. Needs the `phones:write` scope.","tags":["Proxies"],"security":[{"apiKey":["phones:write"]}],"parameters":[{"in":"path","name":"id","schema":{"type":"string","description":"The proxy's id."},"required":true,"description":"The proxy's id."}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":128},"label":{"type":"string"},"endpoint":{"type":"string"},"scheme":{"type":"string","enum":["http","https"]},"host":{"type":"string"},"port":{"type":"integer","exclusiveMinimum":0,"maximum":9007199254740991},"hasLogin":{"type":"boolean"},"country":{"anyOf":[{"type":"string","pattern":"^[A-Z]{2}$"},{"type":"null"}]},"phones":{"type":"integer","minimum":0,"maximum":9007199254740991},"lastCheck":{"anyOf":[{"type":"object","properties":{"at":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},"reachable":{"type":"boolean"},"latencyMs":{"anyOf":[{"type":"integer","minimum":0,"maximum":9007199254740991},{"type":"null"}]},"exitIp":{"anyOf":[{"type":"string"},{"type":"null"}]},"exitCountry":{"anyOf":[{"type":"string","pattern":"^[A-Z]{2}$"},{"type":"null"}]},"residential":{"anyOf":[{"type":"boolean"},{"type":"null"}]},"connectionType":{"anyOf":[{"type":"string"},{"type":"null"}]},"error":{"anyOf":[{"type":"string"},{"type":"null"}]}},"required":["at","reachable","latencyMs","exitIp","exitCountry","error"],"additionalProperties":false},{"type":"null"}]},"createdAt":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"}},"required":["id","label","endpoint","scheme","host","port","hasLogin","country","phones","lastCheck","createdAt"],"additionalProperties":false}}}},"default":{"description":"An error: `{ error, detail }`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/phones/{id}/egress":{"post":{"operationId":"setPhoneExit","summary":"Route a phone through a proxy","description":"Send a saved proxy's id, or null for Distilled's network. Whatever the phone has open closes. `restarting` in the answer says whether it also restarts, which it does when it goes on or off a proxy. Needs the `phones:write` scope.","tags":["Proxies"],"security":[{"apiKey":["phones:write"]}],"parameters":[{"in":"path","name":"id","schema":{"type":"string","minLength":1,"maxLength":128,"description":"The phone's id."},"required":true,"description":"The phone's id."}],"requestBody":{"required":true,"content":{"application/json":{"example":{"proxyId":null},"schema":{"type":"object","properties":{"proxyId":{"anyOf":[{"type":"string","minLength":1,"maxLength":128},{"type":"null"}]}},"required":["proxyId"],"additionalProperties":false}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"phoneId":{"type":"string","minLength":1,"maxLength":128},"exit":{"type":"object","properties":{"kind":{"type":"string","enum":["distilled","proxy"]},"proxyId":{"type":"string","minLength":1,"maxLength":128},"label":{"type":"string"},"exitIp":{"type":"string"},"country":{"type":"string","pattern":"^[A-Z]{2}$"},"threatScore":{"type":"integer","minimum":0,"maximum":100},"scamScore":{"type":"integer","minimum":0,"maximum":100},"vettedAt":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},"city":{"type":"string"},"observedIp":{"type":"string"},"observedAt":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},"drifted":{"type":"boolean","const":true}},"required":["kind"],"additionalProperties":false},"restarting":{"type":"boolean"}},"required":["phoneId","exit","restarting"],"additionalProperties":false}}}},"409":{"description":"The phone's server can't route phones through proxies yet.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"default":{"description":"An error: `{ error, detail }`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/phones/{id}/egress/rotate":{"post":{"operationId":"rotatePhoneExit","summary":"Rotate a phone's IP","description":"Moves the phone to a fresh Distilled exit, in a country if you name one. Every exit was vetted before it was offered (a threat score of 25 or lower, no proxy, VPN or Tor flags) and is checked again before the phone moves. Whatever the phone has open closes. `restarting` in the answer says whether it also restarts, which it does when it wasn't on a proxy before. Needs the `phones:write` scope.","tags":["Proxies"],"security":[{"apiKey":["phones:write"]}],"parameters":[{"in":"path","name":"id","schema":{"type":"string","minLength":1,"maxLength":128,"description":"The phone's id."},"required":true,"description":"The phone's id."}],"requestBody":{"required":true,"content":{"application/json":{"example":{},"schema":{"type":"object","properties":{"country":{"type":"string","pattern":"^[A-Z]{2}$"},"city":{"type":"string","enum":["Phoenix","Los_Angeles","Charlotte","Atlanta","Chicago","Philadelphia"]}},"additionalProperties":false}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"phoneId":{"type":"string","minLength":1,"maxLength":128},"exit":{"type":"object","properties":{"kind":{"type":"string","enum":["distilled","proxy"]},"proxyId":{"type":"string","minLength":1,"maxLength":128},"label":{"type":"string"},"exitIp":{"type":"string"},"country":{"type":"string","pattern":"^[A-Z]{2}$"},"threatScore":{"type":"integer","minimum":0,"maximum":100},"scamScore":{"type":"integer","minimum":0,"maximum":100},"vettedAt":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},"city":{"type":"string"},"observedIp":{"type":"string"},"observedAt":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},"drifted":{"type":"boolean","const":true}},"required":["kind"],"additionalProperties":false},"restarting":{"type":"boolean"}},"required":["phoneId","exit","restarting"],"additionalProperties":false}}}},"503":{"description":"No vetted exit is ready (`exits-exhausted`, try again later), or rotation isn't available here.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"default":{"description":"An error: `{ error, detail }`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/phones/defaults":{"get":{"operationId":"getPhoneDefaults","summary":"New phone defaults","description":"The device and region offered first for new phones. Needs the `phones:read` scope.","tags":["Phones"],"security":[{"apiKey":["phones:read"]}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"profileId":{"anyOf":[{"type":"string","pattern":"^[a-z0-9][a-z0-9._-]*\\/[a-z0-9][a-z0-9._-]*\\/android-(?:13|14|15|16)\\/[A-Za-z0-9._-]+$"},{"type":"null"}]},"region":{"anyOf":[{"type":"string"},{"type":"null"}]}},"required":["profileId","region"],"additionalProperties":false}}}},"default":{"description":"An error: `{ error, detail }`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"put":{"operationId":"setPhoneDefaults","summary":"Set new phone defaults","description":"null leaves the choice open. Needs the `phones:write` scope.","tags":["Phones"],"security":[{"apiKey":["phones:write"]}],"requestBody":{"required":true,"content":{"application/json":{"example":{"profileId":null,"region":null},"schema":{"type":"object","properties":{"profileId":{"anyOf":[{"type":"string","pattern":"^[a-z0-9][a-z0-9._-]*\\/[a-z0-9][a-z0-9._-]*\\/android-(?:13|14|15|16)\\/[A-Za-z0-9._-]+$"},{"type":"null"}]},"region":{"anyOf":[{"type":"string","minLength":1,"maxLength":64},{"type":"null"}]}},"required":["profileId","region"],"additionalProperties":false}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"profileId":{"anyOf":[{"type":"string","pattern":"^[a-z0-9][a-z0-9._-]*\\/[a-z0-9][a-z0-9._-]*\\/android-(?:13|14|15|16)\\/[A-Za-z0-9._-]+$"},{"type":"null"}]},"region":{"anyOf":[{"type":"string"},{"type":"null"}]}},"required":["profileId","region"],"additionalProperties":false}}}},"default":{"description":"An error: `{ error, detail }`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/phones/{id}/stop":{"post":{"operationId":"stopPhone","summary":"Stop a phone","description":"Switches it off. Apps and data are kept. Needs the `phones:write` scope.","tags":["Phones"],"security":[{"apiKey":["phones:write"]}],"parameters":[{"in":"path","name":"id","schema":{"type":"string","minLength":1,"maxLength":128,"description":"The phone's id."},"required":true,"description":"The phone's id."}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Phone"}}}},"409":{"description":"A run or a lease holds the phone.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"default":{"description":"An error: `{ error, detail }`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/phones/{id}/start":{"post":{"operationId":"startPhone","summary":"Start a phone","description":"Needs the `phones:write` scope.","tags":["Phones"],"security":[{"apiKey":["phones:write"]}],"parameters":[{"in":"path","name":"id","schema":{"type":"string","minLength":1,"maxLength":128,"description":"The phone's id."},"required":true,"description":"The phone's id."}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Phone"}}}},"402":{"description":"The balance is used up, or doesn't cover the month a monthly phone needs. Phones start again once it is topped up.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"A run or a lease holds the phone.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"default":{"description":"An error: `{ error, detail }`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/phones/{id}/renew":{"post":{"operationId":"renewPhone","summary":"Renew a monthly phone","description":"Takes the phone's next 30 days from the balance. They follow the ones already paid for, so renewing early loses nothing, and only the next 30 can be paid ahead. A monthly phone is never renewed by itself: when its 30 days end it is stopped, with its apps and data kept, and renewing it then starts it again. Needs the `phones:write` scope.","tags":["Phones"],"security":[{"apiKey":["phones:write"]}],"parameters":[{"in":"path","name":"id","schema":{"type":"string","minLength":1,"maxLength":128,"description":"The phone's id."},"required":true,"description":"The phone's id."}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Phone"}}}},"402":{"description":"The balance doesn't cover 30 days of the phone.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"The phone is charged by the minute, or its next 30 days are already paid for.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"default":{"description":"An error: `{ error, detail }`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/phones/{id}/plan":{"put":{"operationId":"setPhonePlan","summary":"Change how a phone is paid for","description":"`monthly` takes a month of the phone from the balance at once when it is running, and nothing more is charged for it. At `paidThrough` it is stopped, unless it was renewed. `payg` charges each minute it runs. A month already paid for is kept either way, and minutes are charged only once it ends. Needs the `phones:write` scope.","tags":["Phones"],"security":[{"apiKey":["phones:write"]}],"parameters":[{"in":"path","name":"id","schema":{"type":"string","minLength":1,"maxLength":128,"description":"The phone's id."},"required":true,"description":"The phone's id."}],"requestBody":{"required":true,"content":{"application/json":{"example":{"plan":"monthly"},"schema":{"type":"object","properties":{"plan":{"type":"string","enum":["monthly","payg"]}},"required":["plan"],"additionalProperties":false}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Phone"}}}},"402":{"description":"The balance doesn't cover a month of the phone.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"A run or a lease holds the phone.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"default":{"description":"An error: `{ error, detail }`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/phones/{id}/name":{"put":{"operationId":"setPhoneName","summary":"Set a phone's nickname","description":"Gives the phone a human-friendly nickname the workspace knows it by, up to 64 characters. Its permanent `ph-…` id does not change. An empty name or `null` clears the nickname. A run or a lease on the phone doesn't stop it. Needs the `phones:write` scope.","tags":["Phones"],"security":[{"apiKey":["phones:write"]}],"parameters":[{"in":"path","name":"id","schema":{"type":"string","minLength":1,"maxLength":128,"description":"The phone's id."},"required":true,"description":"The phone's id."}],"requestBody":{"required":true,"content":{"application/json":{"example":{"name":"Checkout tester"},"schema":{"type":"object","properties":{"name":{"anyOf":[{"type":"string","maxLength":64},{"type":"null"}]}},"required":["name"],"additionalProperties":false}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Phone"}}}},"404":{"description":"No such phone in this workspace.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"default":{"description":"An error: `{ error, detail }`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/phones/{id}/notes":{"put":{"operationId":"setPhoneNotes","summary":"Keep notes on a phone","description":"Sets the workspace's own notes on the phone, up to 4000 characters, such as what it is for and which accounts are on it. Notes aren't sealed, so keep passwords out of them. An empty value or `null` clears them. A run or a lease on the phone doesn't stop it. Needs the `phones:write` scope.","tags":["Phones"],"security":[{"apiKey":["phones:write"]}],"parameters":[{"in":"path","name":"id","schema":{"type":"string","minLength":1,"maxLength":128,"description":"The phone's id."},"required":true,"description":"The phone's id."}],"requestBody":{"required":true,"content":{"application/json":{"example":{"notes":"UK storefront. Instagram @shop_uk, TikTok @shop_uk."},"schema":{"type":"object","properties":{"notes":{"anyOf":[{"type":"string","maxLength":4000},{"type":"null"}]}},"required":["notes"],"additionalProperties":false}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Phone"}}}},"404":{"description":"No such phone in this workspace.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"default":{"description":"An error: `{ error, detail }`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/phones/{id}/accounts":{"get":{"operationId":"listPhoneAccounts","summary":"List a phone's accounts","description":"The app accounts signed in on the phone, by app then username. Needs the `phones:read` scope.","tags":["Phones"],"security":[{"apiKey":["phones:read"]}],"parameters":[{"in":"path","name":"id","schema":{"type":"string","minLength":1,"maxLength":128,"description":"The phone's id."},"required":true,"description":"The phone's id."}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","pattern":"^acc_[a-z0-9]{24}$"},"phoneId":{"type":"string","minLength":1,"maxLength":128},"app":{"type":"string"},"appLabel":{"anyOf":[{"type":"string"},{"type":"null"}]},"username":{"type":"string"},"notes":{"anyOf":[{"type":"string"},{"type":"null"}]},"createdAt":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},"updatedAt":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"}},"required":["id","phoneId","app","appLabel","username","notes","createdAt","updatedAt"],"additionalProperties":false}}}}},"404":{"description":"No such phone in this workspace.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"default":{"description":"An error: `{ error, detail }`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"post":{"operationId":"createPhoneAccount","summary":"Record an account on a phone","description":"Records which app account is signed in on the phone. `app` is the package name when known. A phone keeps up to 50, and each login once. No password is taken. Needs the `phones:write` scope.","tags":["Phones"],"security":[{"apiKey":["phones:write"]}],"parameters":[{"in":"path","name":"id","schema":{"type":"string","minLength":1,"maxLength":128,"description":"The phone's id."},"required":true,"description":"The phone's id."}],"requestBody":{"required":true,"content":{"application/json":{"example":{"app":"com.instagram.android","username":"@shop_uk","notes":"Main UK storefront"},"schema":{"type":"object","properties":{"app":{"type":"string","minLength":1,"maxLength":200},"username":{"type":"string","minLength":1,"maxLength":320},"notes":{"anyOf":[{"type":"string","maxLength":1000},{"type":"null"}]}},"required":["app","username"],"additionalProperties":false}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","pattern":"^acc_[a-z0-9]{24}$"},"phoneId":{"type":"string","minLength":1,"maxLength":128},"app":{"type":"string"},"appLabel":{"anyOf":[{"type":"string"},{"type":"null"}]},"username":{"type":"string"},"notes":{"anyOf":[{"type":"string"},{"type":"null"}]},"createdAt":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},"updatedAt":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"}},"required":["id","phoneId","app","appLabel","username","notes","createdAt","updatedAt"],"additionalProperties":false}}}},"404":{"description":"No such phone in this workspace.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"That login is already on this phone.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"The phone already has as many accounts as it keeps.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"default":{"description":"An error: `{ error, detail }`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/phones/{id}/accounts/{accountId}":{"patch":{"operationId":"updatePhoneAccount","summary":"Change an account","description":"Changes the fields given and leaves the rest. `null` or an empty value clears the notes. Needs the `phones:write` scope.","tags":["Phones"],"security":[{"apiKey":["phones:write"]}],"parameters":[{"in":"path","name":"id","schema":{"type":"string","minLength":1,"maxLength":128,"description":"The phone's id."},"required":true,"description":"The phone's id."},{"in":"path","name":"accountId","schema":{"type":"string","pattern":"^acc_[a-z0-9]{24}$","description":"The account's id."},"required":true,"description":"The account's id."}],"requestBody":{"required":true,"content":{"application/json":{"example":{"notes":"Moved to the EU storefront"},"schema":{"type":"object","properties":{"app":{"type":"string","minLength":1,"maxLength":200},"username":{"type":"string","minLength":1,"maxLength":320},"notes":{"anyOf":[{"type":"string","maxLength":1000},{"type":"null"}]}},"additionalProperties":false}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","pattern":"^acc_[a-z0-9]{24}$"},"phoneId":{"type":"string","minLength":1,"maxLength":128},"app":{"type":"string"},"appLabel":{"anyOf":[{"type":"string"},{"type":"null"}]},"username":{"type":"string"},"notes":{"anyOf":[{"type":"string"},{"type":"null"}]},"createdAt":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},"updatedAt":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"}},"required":["id","phoneId","app","appLabel","username","notes","createdAt","updatedAt"],"additionalProperties":false}}}},"404":{"description":"No such account on that phone.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"That login is already on this phone.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"default":{"description":"An error: `{ error, detail }`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"delete":{"operationId":"deletePhoneAccount","summary":"Forget an account","description":"Deletes the record. The app on the phone is untouched. Needs the `phones:write` scope.","tags":["Phones"],"security":[{"apiKey":["phones:write"]}],"parameters":[{"in":"path","name":"id","schema":{"type":"string","minLength":1,"maxLength":128,"description":"The phone's id."},"required":true,"description":"The phone's id."},{"in":"path","name":"accountId","schema":{"type":"string","pattern":"^acc_[a-z0-9]{24}$","description":"The account's id."},"required":true,"description":"The account's id."}],"responses":{"204":{"description":"No content"},"404":{"description":"No such account on that phone.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"default":{"description":"An error: `{ error, detail }`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/accounts":{"get":{"operationId":"searchPhoneAccounts","summary":"Find accounts","description":"The app accounts across the workspace's phones, each with its `phoneId`, to answer which phone a login is on. Needs the `phones:read` scope.","tags":["Phones"],"security":[{"apiKey":["phones:read"]}],"parameters":[{"in":"query","name":"app","schema":{"type":"string","description":"Only this app, as its package name or the name it was kept under."}},{"in":"query","name":"q","schema":{"type":"string","description":"Only accounts whose username, app or notes hold this text, in any case."}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","pattern":"^acc_[a-z0-9]{24}$"},"phoneId":{"type":"string","minLength":1,"maxLength":128},"app":{"type":"string"},"appLabel":{"anyOf":[{"type":"string"},{"type":"null"}]},"username":{"type":"string"},"notes":{"anyOf":[{"type":"string"},{"type":"null"}]},"createdAt":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},"updatedAt":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"}},"required":["id","phoneId","app","appLabel","username","notes","createdAt","updatedAt"],"additionalProperties":false}}}}},"default":{"description":"An error: `{ error, detail }`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/phones/{id}/restart":{"post":{"operationId":"restartPhone","summary":"Restart a phone","description":"Recreates its container. Apps, data and identity stay. Needs the `phones:write` scope.","tags":["Phones"],"security":[{"apiKey":["phones:write"]}],"parameters":[{"in":"path","name":"id","schema":{"type":"string","minLength":1,"maxLength":128,"description":"The phone's id."},"required":true,"description":"The phone's id."}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Phone"}}}},"409":{"description":"The phone is stopped, a run or a lease holds it, or its server can't restart phones yet.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"default":{"description":"An error: `{ error, detail }`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/phones/{id}/debug":{"get":{"operationId":"getPhoneDebug","summary":"A phone's debugging tools","description":"Whether the phone runs an undetected frida-server and intercepts its own HTTPS traffic, and which Frida version is inside it. Needs the `phones:read` scope.","tags":["Phones"],"security":[{"apiKey":["phones:read"]}],"parameters":[{"in":"path","name":"id","schema":{"type":"string","minLength":1,"maxLength":128,"description":"The phone's id."},"required":true,"description":"The phone's id."}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"phoneId":{"type":"string","minLength":1,"maxLength":128},"debug":{"anyOf":[{"type":"object","properties":{"frida":{"type":"object","properties":{"version":{"type":"string","pattern":"^\\d+\\.\\d+\\.\\d+$"},"variant":{"type":"string","enum":["default"]}},"additionalProperties":false},"mitm":{"default":false,"type":"boolean"}},"required":["mitm"],"additionalProperties":false},{"type":"null"}]},"fridaVersion":{"anyOf":[{"type":"string","pattern":"^\\d+\\.\\d+\\.\\d+$"},{"type":"null"}]}},"required":["phoneId","debug","fridaVersion"],"additionalProperties":false}}}},"default":{"description":"An error: `{ error, detail }`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"put":{"operationId":"setPhoneDebug","summary":"Turn a phone's debugging tools on or off","description":"Turning Frida on starts the phone's undetected frida-server, which needs no restart. Turning interception on may restart the phone once. Turning debug off stops the frida-server and wipes the phone's recorded flows. Needs the `debug:write` scope.","tags":["Phones"],"security":[{"apiKey":["debug:write"]}],"parameters":[{"in":"path","name":"id","schema":{"type":"string","minLength":1,"maxLength":128,"description":"The phone's id."},"required":true,"description":"The phone's id."}],"requestBody":{"required":true,"content":{"application/json":{"example":{"debug":{"mitm":true}},"schema":{"type":"object","properties":{"debug":{"anyOf":[{"type":"object","properties":{"frida":{"type":"object","properties":{"version":{"type":"string","pattern":"^\\d+\\.\\d+\\.\\d+$"},"variant":{"type":"string","enum":["default"]}},"additionalProperties":false},"mitm":{"default":false,"type":"boolean"}},"additionalProperties":false},{"type":"null"}]}},"required":["debug"],"additionalProperties":false}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"phoneId":{"type":"string","minLength":1,"maxLength":128},"debug":{"anyOf":[{"type":"object","properties":{"frida":{"type":"object","properties":{"version":{"type":"string","pattern":"^\\d+\\.\\d+\\.\\d+$"},"variant":{"type":"string","enum":["default"]}},"additionalProperties":false},"mitm":{"default":false,"type":"boolean"}},"required":["mitm"],"additionalProperties":false},{"type":"null"}]},"fridaVersion":{"anyOf":[{"type":"string","pattern":"^\\d+\\.\\d+\\.\\d+$"},{"type":"null"}]}},"required":["phoneId","debug","fridaVersion"],"additionalProperties":false}}}},"409":{"description":"The phone is stopped or removed, or its server can't run debugging tools yet.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"default":{"description":"An error: `{ error, detail }`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/phones/{id}/location":{"get":{"operationId":"getPhoneLocation","summary":"Where a phone is placed","description":"How the phone is placed, at wherever its traffic leaves from or exactly where its owner said, with the coordinates its Android last took. `pending` says the coordinates aren't settled yet: a fresh exit, or a geolocation that hasn't answered — never a guess. Needs the `phones:read` scope.","tags":["Phones"],"security":[{"apiKey":["phones:read"]}],"parameters":[{"in":"path","name":"id","schema":{"type":"string","minLength":1,"maxLength":128,"description":"The phone's id."},"required":true,"description":"The phone's id."}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"mode":{"type":"string","enum":["exit","manual"]},"location":{"anyOf":[{"type":"object","properties":{"latitude":{"type":"number","minimum":-90,"maximum":90},"longitude":{"type":"number","minimum":-180,"maximum":180},"altitudeM":{"type":"number"},"accuracyM":{"type":"number","exclusiveMinimum":0}},"required":["latitude","longitude"],"additionalProperties":false},{"type":"null"}]},"pending":{"type":"boolean"},"applied":{"anyOf":[{"type":"object","properties":{"latitude":{"type":"number","minimum":-90,"maximum":90},"longitude":{"type":"number","minimum":-180,"maximum":180},"altitudeM":{"type":"number"},"accuracyM":{"type":"number","exclusiveMinimum":0}},"required":["latitude","longitude"],"additionalProperties":false},{"type":"null"}]},"error":{"anyOf":[{"type":"string"},{"type":"null"}]}},"required":["mode","location","pending","applied","error"],"additionalProperties":false}}}},"default":{"description":"An error: `{ error, detail }`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"put":{"operationId":"setPhoneLocation","summary":"Place a phone","description":"`exit` follows the phone's traffic, so its coordinates change as its exit does. `manual` sits at exact coordinates however its exits move. The answer is the phone's state once its exit has been placed; a geolocation that can't be answered leaves it `pending` with `error` saying why. Needs the `phones:write` scope.","tags":["Phones"],"security":[{"apiKey":["phones:write"]}],"parameters":[{"in":"path","name":"id","schema":{"type":"string","minLength":1,"maxLength":128,"description":"The phone's id."},"required":true,"description":"The phone's id."}],"requestBody":{"required":true,"content":{"application/json":{"example":{"mode":"manual","latitude":35.6895,"longitude":139.6917},"schema":{"oneOf":[{"type":"object","properties":{"mode":{"type":"string","const":"exit"}},"required":["mode"],"additionalProperties":false},{"type":"object","properties":{"mode":{"type":"string","const":"manual"},"latitude":{"type":"number","minimum":-90,"maximum":90},"longitude":{"type":"number","minimum":-180,"maximum":180}},"required":["mode","latitude","longitude"],"additionalProperties":false}],"type":"object"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"mode":{"type":"string","enum":["exit","manual"]},"location":{"anyOf":[{"type":"object","properties":{"latitude":{"type":"number","minimum":-90,"maximum":90},"longitude":{"type":"number","minimum":-180,"maximum":180},"altitudeM":{"type":"number"},"accuracyM":{"type":"number","exclusiveMinimum":0}},"required":["latitude","longitude"],"additionalProperties":false},{"type":"null"}]},"pending":{"type":"boolean"},"applied":{"anyOf":[{"type":"object","properties":{"latitude":{"type":"number","minimum":-90,"maximum":90},"longitude":{"type":"number","minimum":-180,"maximum":180},"altitudeM":{"type":"number"},"accuracyM":{"type":"number","exclusiveMinimum":0}},"required":["latitude","longitude"],"additionalProperties":false},{"type":"null"}]},"error":{"anyOf":[{"type":"string"},{"type":"null"}]}},"required":["mode","location","pending","applied","error"],"additionalProperties":false}}}},"409":{"description":"A run or a lease holds the phone, or its server can't set a phone's location yet.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"default":{"description":"An error: `{ error, detail }`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/phones/{id}/debug/flows":{"get":{"operationId":"listPhoneDebugFlows","summary":"A phone's intercepted HTTPS exchanges","description":"The exchanges the phone made while interception was on, newest first, without bodies. At most 5000; older ones are dropped. Needs the `debug:write` scope.","tags":["Phones"],"security":[{"apiKey":["debug:write"]}],"parameters":[{"in":"path","name":"id","schema":{"type":"string","minLength":1,"maxLength":128,"description":"The phone's id."},"required":true,"description":"The phone's id."}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"flows":{"maxItems":5000,"type":"array","items":{"type":"object","properties":{"id":{"type":"integer","minimum":0,"maximum":9007199254740991},"startedAt":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},"method":{"type":"string","minLength":1,"maxLength":16},"url":{"type":"string","maxLength":2048},"status":{"type":"integer","minimum":0,"maximum":9007199254740991},"requestBytes":{"anyOf":[{"type":"integer","minimum":0,"maximum":9007199254740991},{"type":"null"}]},"responseBytes":{"anyOf":[{"type":"integer","minimum":0,"maximum":9007199254740991},{"type":"null"}]},"durationMs":{"anyOf":[{"type":"integer","minimum":0,"maximum":9007199254740991},{"type":"null"}]}},"required":["id","startedAt","method","url","status","requestBytes","responseBytes","durationMs"],"additionalProperties":false}},"truncated":{"type":"boolean"},"phoneId":{"type":"string","minLength":1,"maxLength":128}},"required":["flows","truncated","phoneId"],"additionalProperties":false}}}},"409":{"description":"The phone isn't running or isn't intercepting.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"default":{"description":"An error: `{ error, detail }`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/phones/{id}/debug/flows/stream":{"get":{"operationId":"streamPhoneDebugFlows","summary":"Follow a phone's intercepted HTTPS exchanges","description":"Server-sent events: the flows the phone has so far, then each new one as it makes them, oldest first. Each event is a batch of new exchanges and whether older ones were dropped for the cap or their age. Reconnect to pick up where it left off. Needs the `debug:write` scope.","tags":["Phones"],"security":[{"apiKey":["debug:write"]}],"parameters":[{"in":"path","name":"id","schema":{"type":"string","minLength":1,"maxLength":128,"description":"The phone's id."},"required":true,"description":"The phone's id."}],"responses":{"200":{"description":"OK","content":{"text/event-stream":{"schema":{"type":"object","properties":{"flows":{"maxItems":5000,"type":"array","items":{"type":"object","properties":{"id":{"type":"integer","minimum":0,"maximum":9007199254740991},"startedAt":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},"method":{"type":"string","minLength":1,"maxLength":16},"url":{"type":"string","maxLength":2048},"status":{"type":"integer","minimum":0,"maximum":9007199254740991},"requestBytes":{"anyOf":[{"type":"integer","minimum":0,"maximum":9007199254740991},{"type":"null"}]},"responseBytes":{"anyOf":[{"type":"integer","minimum":0,"maximum":9007199254740991},{"type":"null"}]},"durationMs":{"anyOf":[{"type":"integer","minimum":0,"maximum":9007199254740991},{"type":"null"}]}},"required":["id","startedAt","method","url","status","requestBytes","responseBytes","durationMs"],"additionalProperties":false}},"truncated":{"type":"boolean"}},"required":["flows","truncated"],"additionalProperties":false}}}},"default":{"description":"An error: `{ error, detail }`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/phones/{id}/debug/flow/{flowId}":{"get":{"operationId":"getPhoneDebugFlow","summary":"One intercepted exchange in full","description":"One flow by its id, with its request and response headers and the bodies the phone kept. Bodies over 262144 bytes are cut off, and binary ones are left out. A flow the phone no longer keeps is not found. Needs the `debug:write` scope.","tags":["Phones"],"security":[{"apiKey":["debug:write"]}],"parameters":[{"in":"path","name":"id","schema":{"type":"string","minLength":1,"maxLength":128,"description":"The phone's id."},"required":true,"description":"The phone's id."},{"in":"path","name":"flowId","schema":{"type":"string","description":"The flow's id, from the flows list."},"required":true,"description":"The flow's id, from the flows list."}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"integer","minimum":0,"maximum":9007199254740991},"startedAt":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},"method":{"type":"string","minLength":1,"maxLength":16},"url":{"type":"string","maxLength":2048},"status":{"type":"integer","minimum":0,"maximum":9007199254740991},"requestBytes":{"anyOf":[{"type":"integer","minimum":0,"maximum":9007199254740991},{"type":"null"}]},"responseBytes":{"anyOf":[{"type":"integer","minimum":0,"maximum":9007199254740991},{"type":"null"}]},"durationMs":{"anyOf":[{"type":"integer","minimum":0,"maximum":9007199254740991},{"type":"null"}]},"requestHeaders":{"maxItems":200,"type":"array","items":{"type":"object","properties":{"name":{"type":"string","maxLength":256},"value":{"type":"string","maxLength":8192}},"required":["name","value"],"additionalProperties":false}},"responseHeaders":{"maxItems":200,"type":"array","items":{"type":"object","properties":{"name":{"type":"string","maxLength":256},"value":{"type":"string","maxLength":8192}},"required":["name","value"],"additionalProperties":false}},"requestBody":{"type":"object","properties":{"size":{"type":"integer","minimum":0,"maximum":9007199254740991},"contentType":{"anyOf":[{"type":"string","maxLength":256},{"type":"null"}]},"text":{"anyOf":[{"type":"string"},{"type":"null"}]},"truncated":{"type":"boolean"},"binary":{"type":"boolean"}},"required":["size","contentType","text","truncated","binary"],"additionalProperties":false},"responseBody":{"type":"object","properties":{"size":{"type":"integer","minimum":0,"maximum":9007199254740991},"contentType":{"anyOf":[{"type":"string","maxLength":256},{"type":"null"}]},"text":{"anyOf":[{"type":"string"},{"type":"null"}]},"truncated":{"type":"boolean"},"binary":{"type":"boolean"}},"required":["size","contentType","text","truncated","binary"],"additionalProperties":false}},"required":["id","startedAt","method","url","status","requestBytes","responseBytes","durationMs","requestHeaders","responseHeaders","requestBody","responseBody"],"additionalProperties":false}}}},"404":{"description":"No such flow, or it is no longer kept.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"The phone isn't running or isn't intercepting.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"default":{"description":"An error: `{ error, detail }`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/phones/{id}/debug/har":{"get":{"operationId":"getPhoneDebugHar","summary":"A phone's flows as a HAR document","description":"The same exchanges as a HAR 1.2 document, without bodies, for tools that read one. Needs the `debug:write` scope.","tags":["Phones"],"security":[{"apiKey":["debug:write"]}],"parameters":[{"in":"path","name":"id","schema":{"type":"string","minLength":1,"maxLength":128,"description":"The phone's id."},"required":true,"description":"The phone's id."}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"log":{"type":"object","properties":{"version":{"type":"string","const":"1.2"},"creator":{"type":"object","properties":{"name":{"type":"string","const":"distilled"},"version":{"type":"string","minLength":1}},"required":["name","version"],"additionalProperties":false},"entries":{"maxItems":5000,"type":"array","items":{"type":"object","properties":{"startedDateTime":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},"time":{"type":"integer","minimum":0,"maximum":9007199254740991},"request":{"type":"object","properties":{"method":{"type":"string","minLength":1,"maxLength":16},"url":{"type":"string","maxLength":2048},"headers":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":128},"value":{"type":"string","maxLength":4096}},"required":["name","value"],"additionalProperties":false}},"bodySize":{"type":"integer","minimum":0,"maximum":9007199254740991}},"required":["method","url","headers","bodySize"],"additionalProperties":false},"response":{"type":"object","properties":{"status":{"type":"integer","minimum":0,"maximum":9007199254740991},"headers":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":128},"value":{"type":"string","maxLength":4096}},"required":["name","value"],"additionalProperties":false}},"bodySize":{"type":"integer","minimum":0,"maximum":9007199254740991}},"required":["status","headers","bodySize"],"additionalProperties":false}},"required":["startedDateTime","time","request","response"],"additionalProperties":false}}},"required":["version","creator","entries"],"additionalProperties":false}},"required":["log"],"additionalProperties":false}}}},"409":{"description":"The phone isn't running or isn't intercepting.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"default":{"description":"An error: `{ error, detail }`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/phones/{id}/debug-tickets":{"post":{"operationId":"createPhoneDebugTicket","summary":"Get a frida relay ticket","description":"A one-use ticket, good for 30 seconds, to open the phone's frida relay. Run the platform's local forward with it, then point `frida -H` at the forward's port. Needs the `debug:write` scope.","tags":["Phones"],"security":[{"apiKey":["debug:write"]}],"parameters":[{"in":"path","name":"id","schema":{"type":"string","minLength":1,"maxLength":128,"description":"The phone's id."},"required":true,"description":"The phone's id."}],"requestBody":{"required":true,"content":{"application/json":{"example":{},"schema":{"type":"object","properties":{},"additionalProperties":false}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"type":"object","properties":{"path":{"type":"string","pattern":"^\\/v1\\/phones\\/.*"},"ticket":{"type":"string","pattern":"^dt_[A-Za-z0-9_-]{43}$"},"expiresAt":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"}},"required":["path","ticket","expiresAt"],"additionalProperties":false}}}},"409":{"description":"The phone isn't running or doesn't have debug on.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"The relay can't be reached right now.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"default":{"description":"An error: `{ error, detail }`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/phones/{id}/debug/frida":{"get":{"operationId":"openPhoneDebugFrida","summary":"Open a phone's frida relay","description":"A WebSocket upgrade, authorized by a ticket from `createPhoneDebugTicket` rather than a key. Binary messages carry raw bytes to and from the phone's frida-server. The platform's local forward speaks it, so plain `frida -H` works against it. Needs the `debug:write` scope.","tags":["Phones"],"security":[{"apiKey":["debug:write"]}],"parameters":[{"in":"path","name":"id","schema":{"type":"string","minLength":1,"maxLength":128,"description":"The phone's id."},"required":true,"description":"The phone's id."},{"in":"query","name":"ticket","schema":{"type":"string","pattern":"^dt_[A-Za-z0-9_-]{43}$","description":"The ticket. It works once."},"required":true,"description":"The ticket. It works once."}],"responses":{"101":{"description":"Switching protocols"},"401":{"description":"The ticket is spent, has run out, or is for another phone.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"The phone stopped or moved since the ticket was given.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"default":{"description":"An error: `{ error, detail }`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/phones/{id}/events":{"get":{"operationId":"listPhoneEvents","summary":"A phone's activity","description":"What happened to the phone while it was the workspace's, newest first. Needs the `phones:read` scope.","tags":["Phones"],"security":[{"apiKey":["phones:read"]}],"parameters":[{"in":"path","name":"id","schema":{"type":"string","minLength":1,"maxLength":128,"description":"The phone's id."},"required":true,"description":"The phone's id."},{"in":"query","name":"limit","schema":{"type":"integer","minimum":1,"maximum":200,"description":"How many, 50 unless said."}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","properties":{"id":{"type":"integer","exclusiveMinimum":0,"maximum":9007199254740991},"phoneId":{"type":"string","minLength":1,"maxLength":128},"kind":{"type":"string","enum":["allocated","released","stopped","started","restarted","respoofed","wiped","archived","restored","ready","not_responding","quarantined","proxy_changed","ip_rotated","exit_changed"]},"detail":{"anyOf":[{"type":"string"},{"type":"null"}]},"at":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"}},"required":["id","phoneId","kind","detail","at"],"additionalProperties":false}}}}},"default":{"description":"An error: `{ error, detail }`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/events":{"get":{"operationId":"listEvents","summary":"Activity across phones","description":"What happened to any of the workspace's phones while it owned them, newest first. Needs the `phones:read` scope.","tags":["Phones"],"security":[{"apiKey":["phones:read"]}],"parameters":[{"in":"query","name":"since","schema":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$","description":"Only events at or after this time."}},{"in":"query","name":"kinds","schema":{"type":"string","description":"Only these kinds, separated by commas: allocated, released, stopped, started, restarted, respoofed, wiped, archived, restored, ready, not_responding, quarantined, proxy_changed, ip_rotated, exit_changed."}},{"in":"query","name":"before","schema":{"type":"integer","exclusiveMinimum":0,"maximum":9007199254740991,"description":"Only events older than this id, to page back through them."}},{"in":"query","name":"limit","schema":{"type":"integer","minimum":1,"maximum":500,"description":"How many, 100 unless said."}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","properties":{"id":{"type":"integer","exclusiveMinimum":0,"maximum":9007199254740991},"phoneId":{"type":"string","minLength":1,"maxLength":128},"kind":{"type":"string","enum":["allocated","released","stopped","started","restarted","respoofed","wiped","archived","restored","ready","not_responding","quarantined","proxy_changed","ip_rotated","exit_changed"]},"detail":{"anyOf":[{"type":"string"},{"type":"null"}]},"at":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"}},"required":["id","phoneId","kind","detail","at"],"additionalProperties":false}}}}},"default":{"description":"An error: `{ error, detail }`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/apps":{"get":{"operationId":"searchApps","summary":"Search the app catalogue","description":"Apps whose package name or label contains `q`, ignoring case, by label. Without `q`, every app. At most 50. Needs the `phones:read` scope.","tags":["Apps"],"security":[{"apiKey":["phones:read"]}],"parameters":[{"in":"query","name":"q","schema":{"type":"string","maxLength":100,"description":"What to look for in the package name or label."}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"apps":{"type":"array","items":{"$ref":"#/components/schemas/StoreApp"}}},"required":["apps"],"additionalProperties":false}}}},"default":{"description":"An error: `{ error, detail }`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/apps/{pkg}":{"get":{"operationId":"getApp","summary":"Get an app","description":"Needs the `phones:read` scope.","tags":["Apps"],"security":[{"apiKey":["phones:read"]}],"parameters":[{"in":"path","name":"pkg","schema":{"type":"string","maxLength":255,"pattern":"^[a-zA-Z][a-zA-Z0-9_]*(\\.[a-zA-Z][a-zA-Z0-9_]*)+$","description":"The app's package name, such as `com.whatsapp`."},"required":true,"description":"The app's package name, such as `com.whatsapp`."}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StoreApp"}}}},"default":{"description":"An error: `{ error, detail }`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/phones/{id}/apps":{"get":{"operationId":"listPhoneApps","summary":"A phone's installs","description":"The installs asked of the phone, newest first, with how far each got. At most 100. Needs the `phones:read` scope.","tags":["Apps"],"security":[{"apiKey":["phones:read"]}],"parameters":[{"in":"path","name":"id","schema":{"type":"string","minLength":1,"maxLength":128,"description":"The phone's id."},"required":true,"description":"The phone's id."}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"phoneId":{"type":"string","minLength":1,"maxLength":128},"installs":{"type":"array","items":{"$ref":"#/components/schemas/PhoneAppInstall"}}},"required":["phoneId","installs"],"additionalProperties":false}}}},"default":{"description":"An error: `{ error, detail }`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"post":{"operationId":"installApp","summary":"Install an app","description":"Queues an install of the app's newest available build on the phone, which must be running. The phone's server downloads it and installs it. Follow the phone's installs for its progress and result. A retry with the same Idempotency-Key answers with the same install. Needs the `phones:write` scope.","tags":["Apps"],"security":[{"apiKey":["phones:write"]}],"parameters":[{"in":"path","name":"id","schema":{"type":"string","minLength":1,"maxLength":128,"description":"The phone's id."},"required":true,"description":"The phone's id."},{"in":"header","name":"Idempotency-Key","schema":{"type":"string","minLength":1,"maxLength":200,"description":"Names this request, so retrying it with the same key does it once."}}],"requestBody":{"required":true,"content":{"application/json":{"example":{"pkg":"com.whatsapp"},"schema":{"type":"object","properties":{"pkg":{"type":"string","maxLength":255,"pattern":"^[a-zA-Z][a-zA-Z0-9_]*(\\.[a-zA-Z][a-zA-Z0-9_]*)+$"}},"required":["pkg"],"additionalProperties":false}}}},"responses":{"202":{"description":"Accepted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PhoneAppInstall"}}}},"409":{"description":"The app can't be installed, the phone isn't running, or its server can't install apps yet.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"default":{"description":"An error: `{ error, detail }`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/phones/{id}/apps/{pkg}":{"delete":{"operationId":"uninstallApp","summary":"Uninstall an app","description":"Queues taking an app the catalogue installed off the phone, with its data. The phone must be running. It shows in the phone's installs with `action` `uninstall`. A retry with the same Idempotency-Key, or asking again while it is on its way, answers with the same uninstall. Needs the `phones:write` scope.","tags":["Apps"],"security":[{"apiKey":["phones:write"]}],"parameters":[{"in":"path","name":"id","schema":{"type":"string","minLength":1,"maxLength":128,"description":"The phone's id."},"required":true,"description":"The phone's id."},{"in":"path","name":"pkg","schema":{"type":"string","maxLength":255,"pattern":"^[a-zA-Z][a-zA-Z0-9_]*(\\.[a-zA-Z][a-zA-Z0-9_]*)+$","description":"The app's package name, such as `com.whatsapp`."},"required":true,"description":"The app's package name, such as `com.whatsapp`."},{"in":"header","name":"Idempotency-Key","schema":{"type":"string","minLength":1,"maxLength":200,"description":"Names this request, so retrying it with the same key does it once."}}],"responses":{"202":{"description":"Accepted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PhoneAppInstall"}}}},"404":{"description":"No such phone, or the catalogue didn't install that app on it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"The phone isn't running, an install of the app is on its way, or the phone's server can't uninstall apps yet.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"default":{"description":"An error: `{ error, detail }`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/phones/{id}/apps/events":{"get":{"operationId":"streamPhoneApps","summary":"Follow a phone's installs","description":"Server-sent events, each the phone's installs as `listPhoneApps` answers them. The first is sent at once, and another whenever an install is queued, moves along or ends. A running install's `progress` says how many bytes are downloaded, then that it is installing. Needs the `phones:read` scope.","tags":["Apps"],"security":[{"apiKey":["phones:read"]}],"parameters":[{"in":"path","name":"id","schema":{"type":"string","minLength":1,"maxLength":128,"description":"The phone's id."},"required":true,"description":"The phone's id."}],"responses":{"200":{"description":"OK","content":{"text/event-stream":{"schema":{"type":"object","properties":{"phoneId":{"type":"string","minLength":1,"maxLength":128},"installs":{"type":"array","items":{"$ref":"#/components/schemas/PhoneAppInstall"}}},"required":["phoneId","installs"],"additionalProperties":false}}}},"default":{"description":"An error: `{ error, detail }`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/apks":{"post":{"operationId":"uploadApk","summary":"Upload an APK","description":"The APK as the request's body, with its package, build and label in the query. At most 209715200 bytes, and the bytes must hash to the `sha256` named. The upload becomes the workspace's own app in the catalogue, which `installApp` installs like any other. Needs the `phones:write` scope.","tags":["Apps"],"security":[{"apiKey":["phones:write"]}],"parameters":[{"in":"query","name":"pkg","schema":{"type":"string","maxLength":255,"pattern":"^[a-zA-Z][a-zA-Z0-9_]*(\\.[a-zA-Z][a-zA-Z0-9_]*)+$","description":"The APK's package name, such as `com.example.app`."},"required":true,"description":"The APK's package name, such as `com.example.app`."},{"in":"query","name":"versionCode","schema":{"type":"integer","exclusiveMinimum":0,"maximum":9007199254740991,"description":"The APK's version code."},"required":true,"description":"The APK's version code."},{"in":"query","name":"label","schema":{"type":"string","minLength":1,"maxLength":100,"description":"The app's label, as the catalogue shows it."},"required":true,"description":"The app's label, as the catalogue shows it."},{"in":"query","name":"sha256","schema":{"type":"string","pattern":"^[0-9a-f]{64}$","description":"What the APK's bytes must hash to."},"required":true,"description":"What the APK's bytes must hash to."}],"requestBody":{"required":true,"content":{"application/vnd.android.package-archive":{"schema":{}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","pattern":"^apk_[a-f0-9]{16}$"},"pkg":{"type":"string","maxLength":255,"pattern":"^[a-zA-Z][a-zA-Z0-9_]*(\\.[a-zA-Z][a-zA-Z0-9_]*)+$"},"versionCode":{"type":"integer","exclusiveMinimum":0,"maximum":9007199254740991},"sha256":{"type":"string","pattern":"^[0-9a-f]{64}$"},"size":{"type":"integer","exclusiveMinimum":0,"maximum":9007199254740991},"url":{"type":"string","maxLength":2048,"format":"uri"},"createdAt":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"}},"required":["id","pkg","versionCode","sha256","size","url","createdAt"],"additionalProperties":false}}}},"409":{"description":"The same bytes were uploaded as another app.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"The APK is empty or past the cap, or its bytes don't match the named `sha256`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"default":{"description":"An error: `{ error, detail }`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/apks/{id}":{"get":{"operationId":"downloadApk","summary":"An uploaded APK's bytes","description":"The APK's bytes, as an install's server downloads them. Whoever holds the id may read them, so treat it as a secret. Needs no key.","tags":["Apps"],"security":[],"parameters":[{"in":"path","name":"id","schema":{"type":"string","pattern":"^apk_[a-f0-9]{16}$","description":"The upload's id."},"required":true,"description":"The upload's id."}],"responses":{"200":{"description":"OK"},"default":{"description":"An error: `{ error, detail }`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/assistant/threads":{"get":{"operationId":"listAssistantThreads","summary":"List assistant threads","description":"The caller's own conversations with the assistant in this workspace, newest first. Needs the `runs:read` scope.","tags":["Assistant"],"security":[{"apiKey":["runs:read"]}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/AssistantThread"}}}}},"default":{"description":"An error: `{ error, detail }`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"post":{"operationId":"createAssistantThread","summary":"Start an assistant thread","description":"A new, empty conversation. Its title comes from the first message unless one is given. Needs the `runs:write` scope.","tags":["Assistant"],"security":[{"apiKey":["runs:write"]}],"requestBody":{"required":true,"content":{"application/json":{"example":{"title":"Gmail sign-ins"},"schema":{"type":"object","properties":{"title":{"type":"string","minLength":1,"maxLength":120},"phoneId":{"type":"string","minLength":1,"maxLength":128}},"additionalProperties":false}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AssistantThread"}}}},"default":{"description":"An error: `{ error, detail }`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/assistant/threads/{id}":{"get":{"operationId":"getAssistantThread","summary":"Get an assistant thread","description":"The thread and every message in it: the person's, the assistant's with the tools it called, and each tool's result. Needs the `runs:read` scope.","tags":["Assistant"],"security":[{"apiKey":["runs:read"]}],"parameters":[{"in":"path","name":"id","schema":{"type":"string","pattern":"^at_[a-z0-9]{12,32}$","description":"The thread's id."},"required":true,"description":"The thread's id."}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","pattern":"^at_[a-z0-9]{12,32}$"},"title":{"type":"string"},"phoneId":{"default":null,"anyOf":[{"type":"string","minLength":1,"maxLength":128},{"type":"null"}]},"createdAt":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},"updatedAt":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},"messages":{"type":"array","items":{"$ref":"#/components/schemas/AssistantMessageOutput"}},"runsEnabled":{"type":"boolean"}},"required":["id","title","phoneId","createdAt","updatedAt","messages","runsEnabled"],"additionalProperties":false}}}},"404":{"description":"No such thread of yours in this workspace.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"default":{"description":"An error: `{ error, detail }`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"put":{"operationId":"renameAssistantThread","summary":"Rename an assistant thread","description":"Needs the `runs:write` scope.","tags":["Assistant"],"security":[{"apiKey":["runs:write"]}],"parameters":[{"in":"path","name":"id","schema":{"type":"string","pattern":"^at_[a-z0-9]{12,32}$","description":"The thread's id."},"required":true,"description":"The thread's id."}],"requestBody":{"required":true,"content":{"application/json":{"example":{"title":"TikTok accounts"},"schema":{"type":"object","properties":{"title":{"type":"string","minLength":1,"maxLength":120}},"required":["title"],"additionalProperties":false}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AssistantThread"}}}},"404":{"description":"No such thread of yours in this workspace.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"default":{"description":"An error: `{ error, detail }`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"delete":{"operationId":"deleteAssistantThread","summary":"Delete an assistant thread","description":"Takes the thread out of the list. The model tokens it used still count in usage. Needs the `runs:write` scope.","tags":["Assistant"],"security":[{"apiKey":["runs:write"]}],"parameters":[{"in":"path","name":"id","schema":{"type":"string","pattern":"^at_[a-z0-9]{12,32}$","description":"The thread's id."},"required":true,"description":"The thread's id."}],"responses":{"204":{"description":"No content"},"404":{"description":"No such thread of yours in this workspace.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"default":{"description":"An error: `{ error, detail }`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/assistant/threads/{id}/screens/{screenId}":{"get":{"operationId":"getAssistantScreen","summary":"A screenshot the assistant took","description":"A phone's screen as the assistant saw it, named by a tool result's `screen.id`. Needs the `runs:read` scope.","tags":["Assistant"],"security":[{"apiKey":["runs:read"]}],"parameters":[{"in":"path","name":"id","schema":{"type":"string","pattern":"^at_[a-z0-9]{12,32}$","description":"The thread's id."},"required":true,"description":"The thread's id."},{"in":"path","name":"screenId","schema":{"type":"string","pattern":"^as_[a-z0-9]{12,32}$","description":"The screenshot's id."},"required":true,"description":"The screenshot's id."}],"responses":{"200":{"description":"OK","content":{"image/jpeg":{"schema":{"type":"string","description":"The image."}},"image/png":{"schema":{"type":"string","description":"The image."}}}},"404":{"description":"No screenshot was kept under that id.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"default":{"description":"An error: `{ error, detail }`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/assistant/threads/{id}/messages":{"post":{"operationId":"sendAssistantMessage","summary":"Send the assistant a message","description":"The assistant reads the thread, calls tools on the workspace until it can answer, and answers in text. The response is server-sent events, each JSON: `text` with a piece of the answer as it is written, `message` with each message once it is kept, then `done` with why the turn ended. Workflows are saved, runs started and phones looked at and driven on their own; allocating, releasing, restarting or moving phones comes back as a pending action to confirm. `context` says which phone the person has open, so the assistant knows what \"this phone\" is. Needs the `runs:write` scope.","tags":["Assistant"],"security":[{"apiKey":["runs:write"]}],"parameters":[{"in":"path","name":"id","schema":{"type":"string","pattern":"^at_[a-z0-9]{12,32}$","description":"The thread's id."},"required":true,"description":"The thread's id."}],"requestBody":{"required":true,"content":{"application/json":{"example":{"content":"Close the app on this phone","context":{"phoneId":"ph-12d0131aa826c5b8"}},"schema":{"type":"object","properties":{"content":{"type":"string","minLength":1,"maxLength":4000},"context":{"type":"object","properties":{"phoneId":{"type":"string","minLength":1,"maxLength":128},"phoneIds":{"minItems":1,"maxItems":500,"type":"array","items":{"type":"string","minLength":1,"maxLength":128}},"view":{"type":"string","enum":["overview","egress","traffic","rollouts"]}},"additionalProperties":false}},"required":["content"],"additionalProperties":false}}}},"responses":{"200":{"description":"OK","content":{"text/event-stream":{"schema":{"$ref":"#/components/schemas/AssistantStreamEvent"}}}},"429":{"description":"The workspace has used its model tokens for the day.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"The assistant isn't set up on this server.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"default":{"description":"An error: `{ error, detail }`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/assistant/threads/{id}/actions/{actionId}":{"post":{"operationId":"decideAssistantAction","summary":"Confirm or cancel a proposed action","description":"Carries out, or drops, something the assistant proposed that costs money or restarts phones, such as allocating phones or rotating their exits. Confirming phone changes also needs phones:write. Needs the `runs:write` scope.","tags":["Assistant"],"security":[{"apiKey":["runs:write"]}],"parameters":[{"in":"path","name":"id","schema":{"type":"string","pattern":"^at_[a-z0-9]{12,32}$","description":"The thread's id."},"required":true,"description":"The thread's id."},{"in":"path","name":"actionId","schema":{"type":"string","pattern":"^aa_[a-z0-9]{12,32}$","description":"The action's id."},"required":true,"description":"The action's id."}],"requestBody":{"required":true,"content":{"application/json":{"example":{"decision":"confirm"},"schema":{"type":"object","properties":{"decision":{"type":"string","enum":["confirm","cancel"]}},"required":["decision"],"additionalProperties":false}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AssistantMessageOutput"}}}},"409":{"description":"The action was already decided.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"default":{"description":"An error: `{ error, detail }`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/assistant/threads/{id}/actions/{actionId}/continue":{"post":{"operationId":"continueAssistantTurn","summary":"Carry on after a decided action","description":"Once an action is confirmed or cancelled, the assistant carries on with what it was asked, knowing how the action came out. Nothing new is kept from the person. The response is server-sent events, as for a message. Needs the `runs:write` scope.","tags":["Assistant"],"security":[{"apiKey":["runs:write"]}],"parameters":[{"in":"path","name":"id","schema":{"type":"string","pattern":"^at_[a-z0-9]{12,32}$","description":"The thread's id."},"required":true,"description":"The thread's id."},{"in":"path","name":"actionId","schema":{"type":"string","pattern":"^aa_[a-z0-9]{12,32}$","description":"The decided action's id."},"required":true,"description":"The decided action's id."}],"requestBody":{"required":true,"content":{"application/json":{"example":{"context":{"phoneId":"ph-12d0131aa826c5b8"}},"schema":{"type":"object","properties":{"context":{"type":"object","properties":{"phoneId":{"type":"string","minLength":1,"maxLength":128},"phoneIds":{"minItems":1,"maxItems":500,"type":"array","items":{"type":"string","minLength":1,"maxLength":128}},"view":{"type":"string","enum":["overview","egress","traffic","rollouts"]}},"additionalProperties":false}},"additionalProperties":false}}}},"responses":{"200":{"description":"OK","content":{"text/event-stream":{"schema":{"$ref":"#/components/schemas/AssistantStreamEvent"}}}},"409":{"description":"The action still waits for a decision, or the person has written since.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"The workspace has used its model tokens for the day.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"The assistant isn't set up on this server.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"default":{"description":"An error: `{ error, detail }`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/assistant/threads/{id}/runs/{runId}/report":{"post":{"operationId":"reportAssistantRun","summary":"Report on a run that ended","description":"Once a run the thread started has ended, the assistant reports how it went, phone by phone, and deals with what failed. Nothing new is kept from the person. It is made once: a thread that has answered since the run ended is refused. The response is server-sent events, as for a message. Needs the `runs:write` scope.","tags":["Assistant"],"security":[{"apiKey":["runs:write"]}],"parameters":[{"in":"path","name":"id","schema":{"type":"string","pattern":"^at_[a-z0-9]{12,32}$","description":"The thread's id."},"required":true,"description":"The thread's id."},{"in":"path","name":"runId","schema":{"type":"string","pattern":"^run_[a-z0-9]{12,32}$","description":"The run's id."},"required":true,"description":"The run's id."}],"requestBody":{"required":true,"content":{"application/json":{"example":{},"schema":{"type":"object","properties":{"context":{"type":"object","properties":{"phoneId":{"type":"string","minLength":1,"maxLength":128},"phoneIds":{"minItems":1,"maxItems":500,"type":"array","items":{"type":"string","minLength":1,"maxLength":128}},"view":{"type":"string","enum":["overview","egress","traffic","rollouts"]}},"additionalProperties":false}},"additionalProperties":false}}}},"responses":{"200":{"description":"OK","content":{"text/event-stream":{"schema":{"$ref":"#/components/schemas/AssistantStreamEvent"}}}},"404":{"description":"The thread didn't start that run.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"The run hasn't ended, or the thread has answered since it did.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"The workspace has used its model tokens for the day.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"The assistant isn't set up on this server.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"default":{"description":"An error: `{ error, detail }`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}}},"components":{"schemas":{"ObserveRequest":{"type":"object","properties":{"screenshot":{"type":"object","properties":{"maxEdge":{"default":960,"type":"integer","minimum":240,"maximum":2000},"format":{"default":"jpeg","type":"string","enum":["jpeg","png"]},"quality":{"default":70,"type":"integer","minimum":30,"maximum":95}},"additionalProperties":false},"uiTree":{"default":false,"type":"boolean"},"foreground":{"default":true,"type":"boolean"},"settle":{"type":"object","properties":{"maxMs":{"default":3000,"type":"integer","minimum":0,"maximum":10000},"quietMs":{"default":500,"type":"integer","minimum":100,"maximum":3000}},"additionalProperties":false}},"additionalProperties":false},"Observation":{"type":"object","properties":{"screenshot":{"type":"object","properties":{"mediaType":{"type":"string","enum":["image/jpeg","image/png"]},"width":{"type":"integer","exclusiveMinimum":0,"maximum":9007199254740991},"height":{"type":"integer","exclusiveMinimum":0,"maximum":9007199254740991},"base64":{"type":"string","maxLength":12582912}},"required":["mediaType","width","height","base64"]},"uiTree":{"type":"object","properties":{"elements":{"maxItems":400,"type":"array","items":{"type":"object","properties":{"index":{"type":"integer","minimum":0,"maximum":9007199254740991},"class":{"type":"string","maxLength":200},"text":{"type":"string","maxLength":500},"desc":{"type":"string","maxLength":500},"resourceId":{"type":"string","maxLength":200},"bounds":{"type":"array","prefixItems":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}]},"clickable":{"type":"boolean"},"scrollable":{"type":"boolean"},"focused":{"type":"boolean"},"enabled":{"type":"boolean"},"checked":{"type":"boolean"},"selected":{"type":"boolean"}},"required":["index","class","text","desc","resourceId","bounds","clickable","scrollable","focused","enabled"]}},"truncated":{"type":"boolean"}},"required":["elements","truncated"]},"foreground":{"type":"object","properties":{"package":{"anyOf":[{"type":"string"},{"type":"null"}]},"activity":{"anyOf":[{"type":"string"},{"type":"null"}]},"keyboardShown":{"type":"boolean"}},"required":["package","activity","keyboardShown"]},"settle":{"type":"object","properties":{"stable":{"type":"boolean"},"waitedMs":{"type":"integer","minimum":0,"maximum":9007199254740991}},"required":["stable","waitedMs"]},"screen":{"type":"object","properties":{"width":{"type":"integer","exclusiveMinimum":0,"maximum":9007199254740991},"height":{"type":"integer","exclusiveMinimum":0,"maximum":9007199254740991}},"required":["width","height"]},"at":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"}},"required":["screen","at"]},"ActRequest":{"type":"object","properties":{"action":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","const":"tap"},"x":{"type":"integer","minimum":0,"maximum":8191},"y":{"type":"integer","minimum":0,"maximum":8191}},"required":["type","x","y"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","const":"longPress"},"x":{"type":"integer","minimum":0,"maximum":8191},"y":{"type":"integer","minimum":0,"maximum":8191},"durationMs":{"default":800,"type":"integer","minimum":300,"maximum":5000}},"required":["type","x","y"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","const":"swipe"},"x1":{"type":"integer","minimum":0,"maximum":8191},"y1":{"type":"integer","minimum":0,"maximum":8191},"x2":{"type":"integer","minimum":0,"maximum":8191},"y2":{"type":"integer","minimum":0,"maximum":8191},"durationMs":{"default":300,"type":"integer","minimum":80,"maximum":5000}},"required":["type","x1","y1","x2","y2"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","const":"key"},"key":{"type":"string","enum":["back","home","recents","enter","backspace","tab","escape","space","dpadUp","dpadDown","dpadLeft","dpadRight","volumeUp","volumeDown"]}},"required":["type","key"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","const":"type"},"text":{"type":"string","pattern":"^[\\x20-\\x7e\\n]{1,500}$"}},"required":["type","text"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","const":"launchApp"},"package":{"type":"string","maxLength":255,"pattern":"^[a-zA-Z][a-zA-Z0-9_]*(\\.[a-zA-Z][a-zA-Z0-9_]*)+$"}},"required":["type","package"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","const":"openUrl"},"url":{"type":"string","maxLength":2000,"format":"uri"}},"required":["type","url"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","const":"wait"},"ms":{"type":"integer","minimum":1,"maximum":10000}},"required":["type","ms"],"additionalProperties":false}],"type":"object"},"frame":{"type":"object","properties":{"width":{"type":"integer","minimum":1,"maximum":8192},"height":{"type":"integer","minimum":1,"maximum":8192}},"required":["width","height"],"additionalProperties":false},"then":{"$ref":"#/components/schemas/ObserveRequest"}},"required":["action"],"additionalProperties":false},"SkillBlock":{"oneOf":[{"type":"object","properties":{"kind":{"type":"string","const":"step"},"text":{"type":"string","minLength":1,"maxLength":500}},"required":["kind","text"],"additionalProperties":false},{"type":"object","properties":{"kind":{"type":"string","const":"wait"},"seconds":{"type":"integer","minimum":1,"maximum":600}},"required":["kind","seconds"],"additionalProperties":false},{"type":"object","properties":{"kind":{"type":"string","const":"repeat"},"times":{"type":"integer","minimum":1,"maximum":50},"body":{"minItems":1,"maxItems":32,"type":"array","items":{"$ref":"#/components/schemas/SkillBlock"}}},"required":["kind","times","body"],"additionalProperties":false},{"type":"object","properties":{"kind":{"type":"string","const":"if"},"condition":{"type":"string","minLength":1,"maxLength":300},"then":{"minItems":1,"maxItems":32,"type":"array","items":{"$ref":"#/components/schemas/SkillBlock"}},"else":{"maxItems":32,"type":"array","items":{"$ref":"#/components/schemas/SkillBlock"}}},"required":["kind","condition","then"],"additionalProperties":false}],"type":"object"},"SkillDefinition":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":80},"app":{"type":"string","maxLength":255,"pattern":"^[a-zA-Z][a-zA-Z0-9_]*(\\.[a-zA-Z][a-zA-Z0-9_]*)+$"},"intent":{"default":"","type":"string","maxLength":500},"workflow":{"minItems":1,"maxItems":32,"type":"array","items":{"$ref":"#/components/schemas/SkillBlock"}},"guardrails":{"default":{"maxMinutes":15,"maxSteps":60,"stopOn":["login wall","captcha"],"maxPhones":0,"uiTree":false,"allowedApps":[],"allowedHosts":[]},"type":"object","properties":{"maxMinutes":{"default":15,"type":"integer","minimum":1,"maximum":60},"maxSteps":{"default":60,"type":"integer","minimum":1,"maximum":200},"stopOn":{"default":["login wall","captcha"],"maxItems":10,"type":"array","items":{"type":"string","minLength":1,"maxLength":80}},"maxPhones":{"default":0,"type":"integer","minimum":0,"maximum":50},"uiTree":{"default":false,"type":"boolean"},"allowedApps":{"default":[],"maxItems":20,"type":"array","items":{"type":"string","maxLength":255,"pattern":"^[a-zA-Z][a-zA-Z0-9_]*(\\.[a-zA-Z][a-zA-Z0-9_]*)+$"}},"allowedHosts":{"default":[],"maxItems":20,"type":"array","items":{"type":"string","maxLength":253,"pattern":"^(?:[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?\\.)+[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?$"}}},"additionalProperties":false},"check":{"type":"object","properties":{"app":{"type":"string","maxLength":255,"pattern":"^[a-zA-Z][a-zA-Z0-9_]*(\\.[a-zA-Z][a-zA-Z0-9_]*)+$"},"text":{"minItems":1,"maxItems":5,"type":"array","items":{"type":"string","minLength":1,"maxLength":200}}},"additionalProperties":false}},"required":["name","app","workflow"],"additionalProperties":false},"CreateRunRequest":{"type":"object","properties":{"skill":{"anyOf":[{"type":"string","pattern":"^sk_[a-z0-9]{12,32}$"},{"$ref":"#/components/schemas/SkillDefinition"}]},"phones":{"minItems":1,"maxItems":50,"type":"array","items":{"type":"string","minLength":1,"maxLength":128}},"canary":{"type":"integer","minimum":0,"maximum":5}},"required":["skill"],"additionalProperties":false},"AssistantMessage":{"type":"object","properties":{"seq":{"type":"integer","exclusiveMinimum":0,"maximum":9007199254740991},"role":{"type":"string","enum":["user","assistant","tool"]},"content":{"type":"string"},"toolCalls":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":128},"name":{"type":"string","minLength":1,"maxLength":64},"arguments":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}}},"required":["id","name","arguments"]}},"result":{"anyOf":[{"type":"object","properties":{"callId":{"type":"string"},"name":{"type":"string"},"ok":{"type":"boolean"},"summary":{"type":"string","maxLength":500},"runId":{"anyOf":[{"type":"string","pattern":"^run_[a-z0-9]{12,32}$"},{"type":"null"}]},"phoneIds":{"type":"array","items":{"type":"string"}},"action":{"anyOf":[{"type":"object","properties":{"id":{"type":"string","pattern":"^aa_[a-z0-9]{12,32}$"},"input":{"oneOf":[{"type":"object","properties":{"kind":{"type":"string","const":"allocate_phones"},"profileId":{"type":"string","pattern":"^[a-z0-9][a-z0-9._-]*\\/[a-z0-9][a-z0-9._-]*\\/android-(?:13|14|15|16)\\/[A-Za-z0-9._-]+$"},"count":{"type":"integer","minimum":1,"maximum":50},"region":{"type":"string","minLength":1,"maxLength":64},"plan":{"default":"payg","type":"string","enum":["monthly","payg"]}},"required":["kind","profileId","count"],"additionalProperties":false},{"type":"object","properties":{"kind":{"type":"string","const":"release_phones"},"phoneIds":{"minItems":1,"maxItems":50,"type":"array","items":{"type":"string","minLength":1,"maxLength":128}}},"required":["kind","phoneIds"],"additionalProperties":false},{"type":"object","properties":{"kind":{"type":"string","const":"rotate_exits"},"phoneIds":{"minItems":1,"maxItems":50,"type":"array","items":{"type":"string","minLength":1,"maxLength":128}},"country":{"type":"string","pattern":"^[A-Z]{2}$"},"city":{"type":"string","enum":["Phoenix","Los_Angeles","Charlotte","Atlanta","Chicago","Philadelphia"]}},"required":["kind","phoneIds"],"additionalProperties":false},{"type":"object","properties":{"kind":{"type":"string","const":"set_phone_exit"},"phoneIds":{"minItems":1,"maxItems":50,"type":"array","items":{"type":"string","minLength":1,"maxLength":128}},"proxyId":{"anyOf":[{"type":"string","minLength":1,"maxLength":128},{"type":"null"}]}},"required":["kind","phoneIds","proxyId"],"additionalProperties":false},{"type":"object","properties":{"kind":{"type":"string","const":"phone_power"},"op":{"type":"string","enum":["restart","stop","start"]},"phoneIds":{"minItems":1,"maxItems":50,"type":"array","items":{"type":"string","minLength":1,"maxLength":128}}},"required":["kind","op","phoneIds"],"additionalProperties":false},{"type":"object","properties":{"kind":{"type":"string","const":"respoof_phones"},"phoneIds":{"minItems":1,"maxItems":50,"type":"array","items":{"type":"string","minLength":1,"maxLength":128}},"wipe":{"type":"boolean"}},"required":["kind","phoneIds","wipe"],"additionalProperties":false},{"type":"object","properties":{"kind":{"type":"string","const":"use_secrets"},"tool":{"type":"string","enum":["type_text","send_order","create_skill","update_skill"]},"arguments":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}},"secrets":{"minItems":1,"maxItems":32,"type":"array","items":{"type":"string","pattern":"^[a-z][a-z0-9_]{0,39}$"}},"phoneIds":{"maxItems":50,"type":"array","items":{"type":"string","minLength":1,"maxLength":128}},"app":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}]}},"required":["kind","tool","arguments","secrets","phoneIds","app"],"additionalProperties":false}],"type":"object"},"summary":{"type":"string","maxLength":500},"state":{"type":"string","enum":["pending","confirmed","cancelled","failed"]},"outcome":{"anyOf":[{"type":"string","maxLength":1000},{"type":"null"}]}},"required":["id","input","summary","state","outcome"]},{"type":"null"}]},"question":{"default":null,"anyOf":[{"type":"object","properties":{"prompt":{"type":"string","maxLength":500},"options":{"maxItems":6,"type":"array","items":{"type":"string","maxLength":120}},"multiple":{"type":"boolean"}},"required":["prompt","options","multiple"]},{"type":"null"}]},"plan":{"default":null,"anyOf":[{"maxItems":12,"type":"array","items":{"type":"object","properties":{"text":{"type":"string","maxLength":200},"status":{"type":"string","enum":["pending","doing","done","skipped"]}},"required":["text","status"]}},{"type":"null"}]},"screen":{"default":null,"anyOf":[{"type":"object","properties":{"id":{"anyOf":[{"type":"string","pattern":"^as_[a-z0-9]{12,32}$"},{"type":"null"}]},"phoneId":{"type":"string","minLength":1,"maxLength":128},"width":{"type":"integer","exclusiveMinimum":0,"maximum":9007199254740991},"height":{"type":"integer","exclusiveMinimum":0,"maximum":9007199254740991},"app":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}]}},"required":["id","phoneId","width","height","app"]},{"type":"null"}]},"queuedAt":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},"startedAt":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},"finishedAt":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},"durationMs":{"type":"integer","minimum":0,"maximum":9007199254740991}},"required":["callId","name","ok","summary","runId","phoneIds","action"]},{"type":"null"}]},"context":{"default":null,"anyOf":[{"type":"object","properties":{"phoneId":{"type":"string","minLength":1,"maxLength":128},"phoneIds":{"minItems":1,"maxItems":500,"type":"array","items":{"type":"string","minLength":1,"maxLength":128}},"view":{"type":"string","enum":["overview","egress","traffic","rollouts"]}},"additionalProperties":false},{"type":"null"}]},"at":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"}},"required":["seq","role","content","toolCalls","result","at"]},"Error":{"type":"object","properties":{"error":{"type":"string","minLength":1},"detail":{"anyOf":[{"type":"string"},{"type":"null"}]},"reason":{"type":"string","minLength":1}},"required":["error"],"additionalProperties":false},"Me":{"type":"object","properties":{"workspace":{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":128,"pattern":"^[a-z0-9][a-z0-9-]{0,62}$"},"name":{"type":"string"}},"required":["id","name"],"additionalProperties":false},"key":{"type":"object","properties":{"id":{"type":"string","pattern":"^[a-z2-7]{16}$"},"name":{"type":"string"},"scopes":{"type":"array","items":{"type":"string","enum":["phones:read","phones:write","control:write","runs:read","runs:write","skills:read","skills:write","billing:read","billing:write","debug:write"]}}},"required":["id","name","scopes"],"additionalProperties":false}},"required":["workspace","key"],"additionalProperties":false},"Phone":{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":128},"name":{"default":null,"anyOf":[{"type":"string"},{"type":"null"}]},"notes":{"default":null,"anyOf":[{"type":"string"},{"type":"null"}]},"accountCount":{"default":0,"type":"integer","minimum":0,"maximum":9007199254740991},"status":{"type":"string","enum":["assigned","stopped"]},"plan":{"default":"payg","type":"string","enum":["monthly","payg"]},"paidThrough":{"default":null,"anyOf":[{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},{"type":"null"}]},"profileId":{"type":"string","pattern":"^[a-z0-9][a-z0-9._-]*\\/[a-z0-9][a-z0-9._-]*\\/android-(?:13|14|15|16)\\/[A-Za-z0-9._-]+$"},"androidVersion":{"anyOf":[{"type":"number","const":13},{"type":"number","const":14},{"type":"number","const":15},{"type":"number","const":16}]},"phase":{"anyOf":[{"type":"string","enum":["ABSENT","WAIT_READY","ARMED","IDENTIFIED","MASKED","READY","DEAD","QUARANTINED"]},{"type":"null"}]},"storage":{"type":"object","properties":{"phase":{"type":"string","enum":["local","stopping","saving","cleaning","archived","restoring","starting"]},"bytes":{"anyOf":[{"type":"integer","minimum":0,"maximum":9007199254740991},{"type":"null"}]},"error":{"anyOf":[{"type":"string"},{"type":"null"}]}},"required":["phase","bytes","error"],"additionalProperties":false},"running":{"type":"boolean"},"respoofs":{"default":0,"type":"integer","minimum":0,"maximum":9007199254740991},"lastRespoofAt":{"default":null,"anyOf":[{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},{"type":"null"}]},"stoppedForBalance":{"default":false,"type":"boolean"},"createdAt":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},"exit":{"type":"object","properties":{"kind":{"type":"string","enum":["distilled","proxy"]},"proxyId":{"type":"string","minLength":1,"maxLength":128},"label":{"type":"string"},"exitIp":{"type":"string"},"country":{"type":"string","pattern":"^[A-Z]{2}$"},"threatScore":{"type":"integer","minimum":0,"maximum":100},"scamScore":{"type":"integer","minimum":0,"maximum":100},"vettedAt":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},"city":{"type":"string"},"observedIp":{"type":"string"},"observedAt":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},"drifted":{"type":"boolean","const":true}},"required":["kind"],"additionalProperties":false},"region":{"default":null,"anyOf":[{"type":"string"},{"type":"null"}]},"reportedAt":{"default":null,"anyOf":[{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},{"type":"null"}]},"auditPassed":{"default":null,"anyOf":[{"type":"boolean"},{"type":"null"}]},"auditCheckedAt":{"default":null,"anyOf":[{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},{"type":"null"}]},"auditProblems":{"default":[],"type":"array","items":{"type":"string"}},"heldBackReason":{"default":null,"anyOf":[{"type":"string"},{"type":"null"}]},"restarts":{"default":0,"type":"integer","minimum":0,"maximum":9007199254740991},"driver":{"default":null,"anyOf":[{"type":"object","properties":{"holder":{"oneOf":[{"type":"object","properties":{"kind":{"type":"string","const":"key"},"id":{"type":"string","minLength":1,"maxLength":64}},"required":["kind","id"],"additionalProperties":false},{"type":"object","properties":{"kind":{"type":"string","const":"user"},"id":{"type":"string","minLength":1,"maxLength":64}},"required":["kind","id"],"additionalProperties":false},{"type":"object","properties":{"kind":{"type":"string","const":"run"},"id":{"type":"string","minLength":1,"maxLength":64}},"required":["kind","id"],"additionalProperties":false}],"type":"object"},"expiresAt":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},"renewedAt":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"}},"required":["holder","expiresAt"],"additionalProperties":false},{"type":"null"}]}},"required":["id","name","notes","accountCount","status","plan","paidThrough","profileId","androidVersion","phase","running","respoofs","lastRespoofAt","stoppedForBalance","createdAt","region","reportedAt","auditPassed","auditCheckedAt","auditProblems","heldBackReason","restarts","driver"],"additionalProperties":false},"StoreApp":{"type":"object","properties":{"pkg":{"type":"string","maxLength":255,"pattern":"^[a-zA-Z][a-zA-Z0-9_]*(\\.[a-zA-Z][a-zA-Z0-9_]*)+$"},"label":{"type":"string"},"installable":{"type":"boolean"},"versionCode":{"anyOf":[{"type":"integer","exclusiveMinimum":0,"maximum":9007199254740991},{"type":"null"}]},"icon":{"default":null,"anyOf":[{"type":"string"},{"type":"null"}]}},"required":["pkg","label","installable","versionCode","icon"],"additionalProperties":false},"PhoneAppInstall":{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":128},"phoneId":{"type":"string","minLength":1,"maxLength":128},"action":{"default":"install","type":"string","enum":["install","uninstall"]},"pkg":{"type":"string","maxLength":255,"pattern":"^[a-zA-Z][a-zA-Z0-9_]*(\\.[a-zA-Z][a-zA-Z0-9_]*)+$"},"label":{"type":"string"},"versionCode":{"type":"integer","exclusiveMinimum":0,"maximum":9007199254740991},"status":{"type":"string","enum":["queued","running","succeeded","failed","cancelled"]},"detail":{"anyOf":[{"type":"string"},{"type":"null"}]},"progress":{"anyOf":[{"type":"object","properties":{"phase":{"type":"string","enum":["downloading","installing"]},"doneBytes":{"type":"integer","minimum":0,"maximum":9007199254740991},"totalBytes":{"type":"integer","minimum":0,"maximum":9007199254740991}},"required":["phase","doneBytes","totalBytes"],"additionalProperties":false},{"type":"null"}]},"requestedAt":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},"finishedAt":{"anyOf":[{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},{"type":"null"}]}},"required":["id","phoneId","action","pkg","label","versionCode","status","detail","progress","requestedAt","finishedAt"],"additionalProperties":false},"Lease":{"type":"object","properties":{"phoneId":{"type":"string"},"holder":{"oneOf":[{"type":"object","properties":{"kind":{"type":"string","const":"key"},"id":{"type":"string","minLength":1,"maxLength":64}},"required":["kind","id"],"additionalProperties":false},{"type":"object","properties":{"kind":{"type":"string","const":"user"},"id":{"type":"string","minLength":1,"maxLength":64}},"required":["kind","id"],"additionalProperties":false},{"type":"object","properties":{"kind":{"type":"string","const":"run"},"id":{"type":"string","minLength":1,"maxLength":64}},"required":["kind","id"],"additionalProperties":false}],"type":"object"},"expiresAt":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},"renewedAt":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"}},"required":["phoneId","holder","expiresAt"],"additionalProperties":false},"ActResult":{"type":"object","properties":{"playedMs":{"type":"integer","minimum":0,"maximum":9007199254740991},"observation":{"$ref":"#/components/schemas/ObservationOutput"}},"required":["playedMs"],"additionalProperties":false},"StreamTicket":{"type":"object","properties":{"path":{"type":"string","pattern":"^\\/v1\\/phones\\/.*"},"ticket":{"type":"string","pattern":"^st_[A-Za-z0-9_-]{43}$"},"expiresAt":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"}},"required":["path","ticket","expiresAt"],"additionalProperties":false},"Skill":{"type":"object","properties":{"id":{"type":"string","pattern":"^sk_[a-z0-9]{12,32}$"},"name":{"type":"string"},"app":{"type":"string"},"intent":{"type":"string"},"workflow":{"type":"array","items":{"$ref":"#/components/schemas/SkillBlock"}},"guardrails":{"type":"object","properties":{"maxMinutes":{"default":15,"type":"integer","minimum":1,"maximum":60},"maxSteps":{"default":60,"type":"integer","minimum":1,"maximum":200},"stopOn":{"default":["login wall","captcha"],"maxItems":10,"type":"array","items":{"type":"string","minLength":1,"maxLength":80}},"maxPhones":{"default":0,"type":"integer","minimum":0,"maximum":50},"uiTree":{"default":false,"type":"boolean"},"allowedApps":{"default":[],"maxItems":20,"type":"array","items":{"type":"string","maxLength":255,"pattern":"^[a-zA-Z][a-zA-Z0-9_]*(\\.[a-zA-Z][a-zA-Z0-9_]*)+$"}},"allowedHosts":{"default":[],"maxItems":20,"type":"array","items":{"type":"string","maxLength":253,"pattern":"^(?:[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?\\.)+[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?$"}}},"required":["maxMinutes","maxSteps","stopOn","maxPhones","uiTree","allowedApps","allowedHosts"],"additionalProperties":false},"check":{"type":"object","properties":{"app":{"type":"string","maxLength":255,"pattern":"^[a-zA-Z][a-zA-Z0-9_]*(\\.[a-zA-Z][a-zA-Z0-9_]*)+$"},"text":{"minItems":1,"maxItems":5,"type":"array","items":{"type":"string","minLength":1,"maxLength":200}}},"additionalProperties":false},"enabled":{"type":"boolean"},"version":{"default":1,"type":"integer","exclusiveMinimum":0,"maximum":9007199254740991},"proven":{"default":null,"anyOf":[{"type":"object","properties":{"runId":{"type":"string"},"at":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"}},"required":["runId","at"],"additionalProperties":false},{"type":"null"}]},"createdAt":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"}},"required":["id","name","app","intent","workflow","guardrails","enabled","version","proven","createdAt"],"additionalProperties":false},"Run":{"type":"object","properties":{"id":{"type":"string","pattern":"^run_[a-z0-9]{12,32}$"},"skillId":{"anyOf":[{"type":"string","pattern":"^sk_[a-z0-9]{12,32}$"},{"type":"null"}]},"name":{"type":"string"},"state":{"type":"string","enum":["queued","running","needs_human","done","failed","stopped"]},"phones":{"type":"array","items":{"type":"object","properties":{"phoneId":{"type":"string","minLength":1,"maxLength":128},"state":{"type":"string","enum":["queued","running","needs_human","done","failed","stopped"]},"steps":{"type":"integer","minimum":0,"maximum":9007199254740991},"note":{"anyOf":[{"type":"string"},{"type":"null"}]},"verified":{"default":null,"anyOf":[{"type":"boolean"},{"type":"null"}]},"canary":{"default":false,"type":"boolean"},"startedAt":{"anyOf":[{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},{"type":"null"}]},"finishedAt":{"anyOf":[{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},{"type":"null"}]}},"required":["phoneId","state","steps","note","verified","canary","startedAt","finishedAt"],"additionalProperties":false}},"createdAt":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},"finishedAt":{"anyOf":[{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},{"type":"null"}]}},"required":["id","skillId","name","state","phones","createdAt","finishedAt"],"additionalProperties":false},"RunStep":{"type":"object","properties":{"phoneId":{"type":"string","minLength":1,"maxLength":128},"n":{"type":"integer","exclusiveMinimum":0,"maximum":9007199254740991},"action":{"anyOf":[{"oneOf":[{"type":"object","properties":{"type":{"type":"string","const":"tap"},"x":{"type":"integer","minimum":0,"maximum":8191},"y":{"type":"integer","minimum":0,"maximum":8191}},"required":["type","x","y"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","const":"longPress"},"x":{"type":"integer","minimum":0,"maximum":8191},"y":{"type":"integer","minimum":0,"maximum":8191},"durationMs":{"default":800,"type":"integer","minimum":300,"maximum":5000}},"required":["type","x","y","durationMs"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","const":"swipe"},"x1":{"type":"integer","minimum":0,"maximum":8191},"y1":{"type":"integer","minimum":0,"maximum":8191},"x2":{"type":"integer","minimum":0,"maximum":8191},"y2":{"type":"integer","minimum":0,"maximum":8191},"durationMs":{"default":300,"type":"integer","minimum":80,"maximum":5000}},"required":["type","x1","y1","x2","y2","durationMs"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","const":"key"},"key":{"type":"string","enum":["back","home","recents","enter","backspace","tab","escape","space","dpadUp","dpadDown","dpadLeft","dpadRight","volumeUp","volumeDown"]}},"required":["type","key"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","const":"type"},"text":{"type":"string","pattern":"^[\\x20-\\x7e\\n]{1,500}$"}},"required":["type","text"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","const":"launchApp"},"package":{"type":"string","maxLength":255,"pattern":"^[a-zA-Z][a-zA-Z0-9_]*(\\.[a-zA-Z][a-zA-Z0-9_]*)+$"}},"required":["type","package"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","const":"openUrl"},"url":{"type":"string","maxLength":2000,"format":"uri"}},"required":["type","url"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","const":"wait"},"ms":{"type":"integer","minimum":1,"maximum":10000}},"required":["type","ms"],"additionalProperties":false}],"type":"object"},{"type":"object","properties":{"type":{"type":"string","const":"done"},"summary":{"default":"","type":"string","maxLength":300}},"required":["type","summary"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","const":"stop"},"category":{"type":"string","enum":["captcha","login","two_factor","stop_condition","blocked","error"]},"reason":{"type":"string","maxLength":200}},"required":["type","category","reason"],"additionalProperties":false}]},"progress":{"type":"string"},"changed":{"anyOf":[{"type":"boolean"},{"type":"null"}]},"screenshotUrl":{"anyOf":[{"type":"string"},{"type":"null"}]},"latencyMs":{"type":"integer","minimum":0,"maximum":9007199254740991},"inputTokens":{"type":"integer","minimum":0,"maximum":9007199254740991},"outputTokens":{"type":"integer","minimum":0,"maximum":9007199254740991},"at":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"}},"required":["phoneId","n","action","progress","changed","screenshotUrl","latencyMs","inputTokens","outputTokens","at"],"additionalProperties":false},"RunEvent":{"type":"object","properties":{"seq":{"type":"integer","exclusiveMinimum":0,"maximum":9007199254740991},"type":{"type":"string","enum":["state","step","message"]},"phoneId":{"anyOf":[{"type":"string","minLength":1,"maxLength":128},{"type":"null"}]},"state":{"anyOf":[{"type":"string","enum":["queued","running","needs_human","done","failed","stopped"]},{"type":"null"}]},"text":{"type":"string","maxLength":500},"at":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"}},"required":["seq","type","phoneId","state","text","at"],"additionalProperties":false},"Secret":{"type":"object","properties":{"name":{"type":"string","pattern":"^[a-z][a-z0-9_]{0,39}$"},"updatedAt":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"}},"required":["name","updatedAt"],"additionalProperties":false},"Usage":{"type":"object","properties":{"from":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},"to":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},"steps":{"type":"integer","minimum":0,"maximum":9007199254740991},"inputTokens":{"type":"integer","minimum":0,"maximum":9007199254740991},"outputTokens":{"type":"integer","minimum":0,"maximum":9007199254740991}},"required":["from","to","steps","inputTokens","outputTokens"],"additionalProperties":false},"AgentUsage":{"type":"object","properties":{"period":{"type":"string","pattern":"^\\d{4}-(0[1-9]|1[0-2])$"},"includedCentsPerPhone":{"type":"integer","exclusiveMinimum":0,"maximum":9007199254740991},"centsPerMillionInputTokens":{"type":"integer","exclusiveMinimum":0,"maximum":9007199254740991},"centsPerMillionOutputTokens":{"type":"integer","exclusiveMinimum":0,"maximum":9007199254740991},"inputTokens":{"type":"integer","minimum":0,"maximum":9007199254740991},"outputTokens":{"type":"integer","minimum":0,"maximum":9007199254740991},"usedCents":{"type":"integer","minimum":0,"maximum":9007199254740991},"includedCents":{"type":"integer","minimum":0,"maximum":9007199254740991},"cents":{"type":"integer","minimum":0,"maximum":9007199254740991}},"required":["period","includedCentsPerPhone","centsPerMillionInputTokens","centsPerMillionOutputTokens","inputTokens","outputTokens","usedCents","includedCents","cents"],"additionalProperties":false},"EgressUsage":{"type":"object","properties":{"period":{"type":"string","pattern":"^\\d{4}-(0[1-9]|1[0-2])$"},"freeBytesPerPhone":{"type":"integer","exclusiveMinimum":0,"maximum":9007199254740991},"centsPerGb":{"type":"integer","exclusiveMinimum":0,"maximum":9007199254740991},"phones":{"type":"array","items":{"type":"object","properties":{"phoneId":{"type":"string"},"bytes":{"type":"integer","minimum":0,"maximum":9007199254740991},"freeBytes":{"type":"integer","minimum":0,"maximum":9007199254740991},"billableBytes":{"type":"integer","minimum":0,"maximum":9007199254740991},"cents":{"type":"integer","minimum":0,"maximum":9007199254740991},"customerProxyBytes":{"type":"integer","minimum":0,"maximum":9007199254740991}},"required":["phoneId","bytes","freeBytes","billableBytes","cents","customerProxyBytes"],"additionalProperties":false}},"totals":{"type":"object","properties":{"bytes":{"type":"integer","minimum":0,"maximum":9007199254740991},"billableBytes":{"type":"integer","minimum":0,"maximum":9007199254740991},"cents":{"type":"integer","minimum":0,"maximum":9007199254740991}},"required":["bytes","billableBytes","cents"],"additionalProperties":false}},"required":["period","freeBytesPerPhone","centsPerGb","phones","totals"],"additionalProperties":false},"EgressSeries":{"type":"object","properties":{"from":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},"stepHours":{"anyOf":[{"type":"number","const":1},{"type":"number","const":6},{"type":"number","const":24}]},"buckets":{"type":"integer","exclusiveMinimum":0,"maximum":200},"phones":{"type":"array","items":{"type":"object","properties":{"phoneId":{"type":"string"},"bytesOut":{"type":"array","items":{"type":"integer","minimum":0,"maximum":9007199254740991}},"bytesIn":{"type":"array","items":{"type":"integer","minimum":0,"maximum":9007199254740991}}},"required":["phoneId","bytesOut","bytesIn"],"additionalProperties":false}}},"required":["from","stepHours","buckets","phones"],"additionalProperties":false},"Catalog":{"type":"object","properties":{"devices":{"type":"array","items":{"type":"object","properties":{"profileId":{"type":"string","pattern":"^[a-z0-9][a-z0-9._-]*\\/[a-z0-9][a-z0-9._-]*\\/android-(?:13|14|15|16)\\/[A-Za-z0-9._-]+$"},"model":{"type":"string"},"androidVersion":{"anyOf":[{"type":"number","const":13},{"type":"number","const":14},{"type":"number","const":15},{"type":"number","const":16}]}},"required":["profileId","model","androidVersion"],"additionalProperties":false}},"regions":{"type":"array","items":{"type":"object","properties":{"region":{"type":"string"},"freeSlots":{"type":"integer","minimum":0,"maximum":9007199254740991}},"required":["region","freeSlots"],"additionalProperties":false}},"phoneMonthlyCents":{"type":"integer","minimum":0,"maximum":9007199254740991},"paygMonthlyCents":{"default":20000,"type":"integer","minimum":0,"maximum":9007199254740991}},"required":["devices","regions","phoneMonthlyCents","paygMonthlyCents"],"additionalProperties":false},"Billing":{"type":"object","properties":{"balanceCents":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"phoneMonthlyCents":{"type":"integer","minimum":0,"maximum":9007199254740991},"paygMonthlyCents":{"default":20000,"type":"integer","minimum":0,"maximum":9007199254740991},"runningPhones":{"type":"integer","minimum":0,"maximum":9007199254740991},"paygPhones":{"default":0,"type":"integer","minimum":0,"maximum":9007199254740991},"monthlyPhones":{"default":0,"type":"integer","minimum":0,"maximum":9007199254740991},"dueCents":{"default":0,"type":"integer","minimum":0,"maximum":9007199254740991},"entries":{"type":"array","items":{"type":"object","properties":{"id":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"cents":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"kind":{"type":"string","enum":["top_up","phone_hours","egress","adjustment","referral","agent","discount","trial","phone_month","phone_minutes"]},"detail":{"anyOf":[{"type":"string"},{"type":"null"}]},"at":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"}},"required":["cents","kind","detail","at"],"additionalProperties":false}},"exempt":{"default":false,"type":"boolean"},"affordHours":{"default":24,"type":"integer","exclusiveMinimum":0,"maximum":9007199254740991},"stoppedForBalanceDays":{"default":7,"type":"integer","exclusiveMinimum":0,"maximum":9007199254740991},"nextBefore":{"default":null,"anyOf":[{"type":"string"},{"type":"null"}]},"topUpMethods":{"default":["card"],"type":"array","items":{"type":"string","enum":["card","crypto"]}},"cardPayments":{"default":false,"type":"boolean"},"discount":{"default":null,"anyOf":[{"type":"object","properties":{"code":{"type":"string"},"percentOff":{"type":"integer","minimum":1,"maximum":100},"phoneMonthlyCents":{"type":"integer","minimum":0,"maximum":9007199254740991},"redeemedAt":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},"endsAt":{"anyOf":[{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},{"type":"null"}]}},"required":["code","percentOff","phoneMonthlyCents","redeemedAt","endsAt"],"additionalProperties":false},{"type":"null"}]},"trial":{"default":null,"anyOf":[{"type":"object","properties":{"status":{"type":"string","enum":["available","active","ended"]},"cents":{"type":"integer","minimum":0,"maximum":9007199254740991},"agentCents":{"type":"integer","minimum":0,"maximum":9007199254740991},"days":{"type":"integer","exclusiveMinimum":0,"maximum":9007199254740991},"endsAt":{"anyOf":[{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},{"type":"null"}]},"autoTopUpCents":{"type":"integer","exclusiveMinimum":0,"maximum":9007199254740991},"autoTopUpHours":{"type":"integer","exclusiveMinimum":0,"maximum":9007199254740991},"publishableKey":{"default":null,"anyOf":[{"type":"string"},{"type":"null"}]}},"required":["status","cents","agentCents","days","endsAt","autoTopUpCents","autoTopUpHours","publishableKey"],"additionalProperties":false},{"type":"null"}]},"autoTopUp":{"default":null,"anyOf":[{"type":"object","properties":{"enabled":{"type":"boolean"},"startsAt":{"anyOf":[{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},{"type":"null"}]},"cents":{"type":"integer","exclusiveMinimum":0,"maximum":9007199254740991},"hours":{"type":"integer","exclusiveMinimum":0,"maximum":9007199254740991},"card":{"type":"string"},"failure":{"anyOf":[{"type":"string"},{"type":"null"}]},"failedAt":{"anyOf":[{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},{"type":"null"}]}},"required":["enabled","startsAt","cents","hours","card","failure","failedAt"],"additionalProperties":false},{"type":"null"}]}},"required":["balanceCents","phoneMonthlyCents","paygMonthlyCents","runningPhones","paygPhones","monthlyPhones","dueCents","entries","exempt","affordHours","stoppedForBalanceDays","nextBefore","topUpMethods","cardPayments","discount","trial","autoTopUp"],"additionalProperties":false},"RequestLog":{"type":"object","properties":{"requests":{"type":"array","items":{"type":"object","properties":{"id":{"type":"integer","exclusiveMinimum":0,"maximum":9007199254740991},"method":{"type":"string"},"route":{"anyOf":[{"type":"string"},{"type":"null"}]},"path":{"type":"string"},"status":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"latencyMs":{"type":"integer","minimum":0,"maximum":9007199254740991},"keyId":{"anyOf":[{"type":"string","pattern":"^[a-z2-7]{16}$"},{"type":"null"}]},"userId":{"anyOf":[{"type":"string"},{"type":"null"}]},"at":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"}},"required":["id","method","route","path","status","latencyMs","keyId","userId","at"],"additionalProperties":false}},"hours":{"type":"array","items":{"type":"object","properties":{"hour":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},"ok":{"type":"integer","minimum":0,"maximum":9007199254740991},"errors":{"type":"integer","minimum":0,"maximum":9007199254740991}},"required":["hour","ok","errors"],"additionalProperties":false}}},"required":["requests","hours"],"additionalProperties":false},"AssistantThread":{"type":"object","properties":{"id":{"type":"string","pattern":"^at_[a-z0-9]{12,32}$"},"title":{"type":"string"},"phoneId":{"default":null,"anyOf":[{"type":"string","minLength":1,"maxLength":128},{"type":"null"}]},"createdAt":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},"updatedAt":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"}},"required":["id","title","phoneId","createdAt","updatedAt"],"additionalProperties":false},"AssistantStreamEvent":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","const":"text"},"delta":{"type":"string"}},"required":["type","delta"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","const":"message"},"message":{"$ref":"#/components/schemas/AssistantMessageOutput"}},"required":["type","message"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","const":"done"},"end":{"type":"string","enum":["answered","step_cap","token_cap","model_error","closed","error"]},"detail":{"anyOf":[{"type":"string"},{"type":"null"}]}},"required":["type","end","detail"],"additionalProperties":false}],"type":"object"},"ObserveRequestOutput":{"type":"object","properties":{"screenshot":{"type":"object","properties":{"maxEdge":{"default":960,"type":"integer","minimum":240,"maximum":2000},"format":{"default":"jpeg","type":"string","enum":["jpeg","png"]},"quality":{"default":70,"type":"integer","minimum":30,"maximum":95}},"required":["maxEdge","format","quality"],"additionalProperties":false},"uiTree":{"default":false,"type":"boolean"},"foreground":{"default":true,"type":"boolean"},"settle":{"type":"object","properties":{"maxMs":{"default":3000,"type":"integer","minimum":0,"maximum":10000},"quietMs":{"default":500,"type":"integer","minimum":100,"maximum":3000}},"required":["maxMs","quietMs"],"additionalProperties":false}},"required":["uiTree","foreground"],"additionalProperties":false},"ObservationOutput":{"type":"object","properties":{"screenshot":{"type":"object","properties":{"mediaType":{"type":"string","enum":["image/jpeg","image/png"]},"width":{"type":"integer","exclusiveMinimum":0,"maximum":9007199254740991},"height":{"type":"integer","exclusiveMinimum":0,"maximum":9007199254740991},"base64":{"type":"string","maxLength":12582912}},"required":["mediaType","width","height","base64"],"additionalProperties":false},"uiTree":{"type":"object","properties":{"elements":{"maxItems":400,"type":"array","items":{"type":"object","properties":{"index":{"type":"integer","minimum":0,"maximum":9007199254740991},"class":{"type":"string","maxLength":200},"text":{"type":"string","maxLength":500},"desc":{"type":"string","maxLength":500},"resourceId":{"type":"string","maxLength":200},"bounds":{"type":"array","prefixItems":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}]},"clickable":{"type":"boolean"},"scrollable":{"type":"boolean"},"focused":{"type":"boolean"},"enabled":{"type":"boolean"},"checked":{"type":"boolean"},"selected":{"type":"boolean"}},"required":["index","class","text","desc","resourceId","bounds","clickable","scrollable","focused","enabled"],"additionalProperties":false}},"truncated":{"type":"boolean"}},"required":["elements","truncated"],"additionalProperties":false},"foreground":{"type":"object","properties":{"package":{"anyOf":[{"type":"string"},{"type":"null"}]},"activity":{"anyOf":[{"type":"string"},{"type":"null"}]},"keyboardShown":{"type":"boolean"}},"required":["package","activity","keyboardShown"],"additionalProperties":false},"settle":{"type":"object","properties":{"stable":{"type":"boolean"},"waitedMs":{"type":"integer","minimum":0,"maximum":9007199254740991}},"required":["stable","waitedMs"],"additionalProperties":false},"screen":{"type":"object","properties":{"width":{"type":"integer","exclusiveMinimum":0,"maximum":9007199254740991},"height":{"type":"integer","exclusiveMinimum":0,"maximum":9007199254740991}},"required":["width","height"],"additionalProperties":false},"at":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"}},"required":["screen","at"],"additionalProperties":false},"SkillDefinitionOutput":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":80},"app":{"type":"string","maxLength":255,"pattern":"^[a-zA-Z][a-zA-Z0-9_]*(\\.[a-zA-Z][a-zA-Z0-9_]*)+$"},"intent":{"default":"","type":"string","maxLength":500},"workflow":{"minItems":1,"maxItems":32,"type":"array","items":{"$ref":"#/components/schemas/SkillBlock"}},"guardrails":{"default":{"maxMinutes":15,"maxSteps":60,"stopOn":["login wall","captcha"],"maxPhones":0,"uiTree":false,"allowedApps":[],"allowedHosts":[]},"type":"object","properties":{"maxMinutes":{"default":15,"type":"integer","minimum":1,"maximum":60},"maxSteps":{"default":60,"type":"integer","minimum":1,"maximum":200},"stopOn":{"default":["login wall","captcha"],"maxItems":10,"type":"array","items":{"type":"string","minLength":1,"maxLength":80}},"maxPhones":{"default":0,"type":"integer","minimum":0,"maximum":50},"uiTree":{"default":false,"type":"boolean"},"allowedApps":{"default":[],"maxItems":20,"type":"array","items":{"type":"string","maxLength":255,"pattern":"^[a-zA-Z][a-zA-Z0-9_]*(\\.[a-zA-Z][a-zA-Z0-9_]*)+$"}},"allowedHosts":{"default":[],"maxItems":20,"type":"array","items":{"type":"string","maxLength":253,"pattern":"^(?:[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?\\.)+[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?$"}}},"required":["maxMinutes","maxSteps","stopOn","maxPhones","uiTree","allowedApps","allowedHosts"],"additionalProperties":false},"check":{"type":"object","properties":{"app":{"type":"string","maxLength":255,"pattern":"^[a-zA-Z][a-zA-Z0-9_]*(\\.[a-zA-Z][a-zA-Z0-9_]*)+$"},"text":{"minItems":1,"maxItems":5,"type":"array","items":{"type":"string","minLength":1,"maxLength":200}}},"additionalProperties":false}},"required":["name","app","intent","workflow","guardrails"],"additionalProperties":false},"AssistantMessageOutput":{"type":"object","properties":{"seq":{"type":"integer","exclusiveMinimum":0,"maximum":9007199254740991},"role":{"type":"string","enum":["user","assistant","tool"]},"content":{"type":"string"},"toolCalls":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":128},"name":{"type":"string","minLength":1,"maxLength":64},"arguments":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}}},"required":["id","name","arguments"],"additionalProperties":false}},"result":{"anyOf":[{"type":"object","properties":{"callId":{"type":"string"},"name":{"type":"string"},"ok":{"type":"boolean"},"summary":{"type":"string","maxLength":500},"runId":{"anyOf":[{"type":"string","pattern":"^run_[a-z0-9]{12,32}$"},{"type":"null"}]},"phoneIds":{"type":"array","items":{"type":"string"}},"action":{"anyOf":[{"type":"object","properties":{"id":{"type":"string","pattern":"^aa_[a-z0-9]{12,32}$"},"input":{"oneOf":[{"type":"object","properties":{"kind":{"type":"string","const":"allocate_phones"},"profileId":{"type":"string","pattern":"^[a-z0-9][a-z0-9._-]*\\/[a-z0-9][a-z0-9._-]*\\/android-(?:13|14|15|16)\\/[A-Za-z0-9._-]+$"},"count":{"type":"integer","minimum":1,"maximum":50},"region":{"type":"string","minLength":1,"maxLength":64},"plan":{"default":"payg","type":"string","enum":["monthly","payg"]}},"required":["kind","profileId","count","plan"],"additionalProperties":false},{"type":"object","properties":{"kind":{"type":"string","const":"release_phones"},"phoneIds":{"minItems":1,"maxItems":50,"type":"array","items":{"type":"string","minLength":1,"maxLength":128}}},"required":["kind","phoneIds"],"additionalProperties":false},{"type":"object","properties":{"kind":{"type":"string","const":"rotate_exits"},"phoneIds":{"minItems":1,"maxItems":50,"type":"array","items":{"type":"string","minLength":1,"maxLength":128}},"country":{"type":"string","pattern":"^[A-Z]{2}$"},"city":{"type":"string","enum":["Phoenix","Los_Angeles","Charlotte","Atlanta","Chicago","Philadelphia"]}},"required":["kind","phoneIds"],"additionalProperties":false},{"type":"object","properties":{"kind":{"type":"string","const":"set_phone_exit"},"phoneIds":{"minItems":1,"maxItems":50,"type":"array","items":{"type":"string","minLength":1,"maxLength":128}},"proxyId":{"anyOf":[{"type":"string","minLength":1,"maxLength":128},{"type":"null"}]}},"required":["kind","phoneIds","proxyId"],"additionalProperties":false},{"type":"object","properties":{"kind":{"type":"string","const":"phone_power"},"op":{"type":"string","enum":["restart","stop","start"]},"phoneIds":{"minItems":1,"maxItems":50,"type":"array","items":{"type":"string","minLength":1,"maxLength":128}}},"required":["kind","op","phoneIds"],"additionalProperties":false},{"type":"object","properties":{"kind":{"type":"string","const":"respoof_phones"},"phoneIds":{"minItems":1,"maxItems":50,"type":"array","items":{"type":"string","minLength":1,"maxLength":128}},"wipe":{"type":"boolean"}},"required":["kind","phoneIds","wipe"],"additionalProperties":false},{"type":"object","properties":{"kind":{"type":"string","const":"use_secrets"},"tool":{"type":"string","enum":["type_text","send_order","create_skill","update_skill"]},"arguments":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}},"secrets":{"minItems":1,"maxItems":32,"type":"array","items":{"type":"string","pattern":"^[a-z][a-z0-9_]{0,39}$"}},"phoneIds":{"maxItems":50,"type":"array","items":{"type":"string","minLength":1,"maxLength":128}},"app":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}]}},"required":["kind","tool","arguments","secrets","phoneIds","app"],"additionalProperties":false}],"type":"object"},"summary":{"type":"string","maxLength":500},"state":{"type":"string","enum":["pending","confirmed","cancelled","failed"]},"outcome":{"anyOf":[{"type":"string","maxLength":1000},{"type":"null"}]}},"required":["id","input","summary","state","outcome"],"additionalProperties":false},{"type":"null"}]},"question":{"default":null,"anyOf":[{"type":"object","properties":{"prompt":{"type":"string","maxLength":500},"options":{"maxItems":6,"type":"array","items":{"type":"string","maxLength":120}},"multiple":{"type":"boolean"}},"required":["prompt","options","multiple"],"additionalProperties":false},{"type":"null"}]},"plan":{"default":null,"anyOf":[{"maxItems":12,"type":"array","items":{"type":"object","properties":{"text":{"type":"string","maxLength":200},"status":{"type":"string","enum":["pending","doing","done","skipped"]}},"required":["text","status"],"additionalProperties":false}},{"type":"null"}]},"screen":{"default":null,"anyOf":[{"type":"object","properties":{"id":{"anyOf":[{"type":"string","pattern":"^as_[a-z0-9]{12,32}$"},{"type":"null"}]},"phoneId":{"type":"string","minLength":1,"maxLength":128},"width":{"type":"integer","exclusiveMinimum":0,"maximum":9007199254740991},"height":{"type":"integer","exclusiveMinimum":0,"maximum":9007199254740991},"app":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}]}},"required":["id","phoneId","width","height","app"],"additionalProperties":false},{"type":"null"}]},"queuedAt":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},"startedAt":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},"finishedAt":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},"durationMs":{"type":"integer","minimum":0,"maximum":9007199254740991}},"required":["callId","name","ok","summary","runId","phoneIds","action","question","plan","screen"],"additionalProperties":false},{"type":"null"}]},"context":{"default":null,"anyOf":[{"type":"object","properties":{"phoneId":{"type":"string","minLength":1,"maxLength":128},"phoneIds":{"minItems":1,"maxItems":500,"type":"array","items":{"type":"string","minLength":1,"maxLength":128}},"view":{"type":"string","enum":["overview","egress","traffic","rollouts"]}},"additionalProperties":false},{"type":"null"}]},"at":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"}},"required":["seq","role","content","toolCalls","result","context","at"],"additionalProperties":false}},"securitySchemes":{"apiKey":{"type":"http","scheme":"bearer","description":"An API key, `dk_live_…`, from the console's Developers page."}}}}