{"openapi":"3.1.0","info":{"title":"Phonebox API","version":"1.0.0","description":"Cloud Android phones for AI agents. Every request needs Authorization: Bearer pbx_…, except terminal setup (POST /v1/setup and POST /v1/setup/token), which is how a terminal gets a key. Errors use one envelope: {error:{type,code,message,retryable,next,request_id,details}}. Enum values in responses, such as a phone's status and an error's code and type, may grow: treat one you don't know as unknown, and never fail on it."},"servers":[{"url":"https://phonebox.dev"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","description":"A project API key (pbx_…). Use it only on servers and in agents, never in browser code."}},"schemas":{"Phone":{"type":"object","properties":{"id":{"type":"string","pattern":"^ph_[a-z2-7]{12}$"},"object":{"type":"string","const":"phone"},"name":{"type":"string"},"status":{"type":"string","enum":["creating","starting","ready","parking","parked","unavailable","failed","deleted"]},"country":{"type":["string","null"]},"metadata":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{"type":"string"}},"created_at":{"type":"string","format":"date-time","description":"ISO 8601 timestamp (UTC)"},"last_active_at":{"anyOf":[{"type":"string","format":"date-time","description":"ISO 8601 timestamp (UTC)"},{"type":"null"}]},"session":{"anyOf":[{"type":"object","properties":{"id":{"type":"string","pattern":"^ses_[a-z2-7]{12}$"},"started_at":{"type":"string","format":"date-time","description":"ISO 8601 timestamp (UTC)"},"ready_at":{"anyOf":[{"type":"string","format":"date-time","description":"ISO 8601 timestamp (UTC)"},{"type":"null"}]},"idle_timeout":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"max_duration":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"parks_at":{"type":"string","format":"date-time","description":"ISO 8601 timestamp (UTC)"},"park_reason":{"type":"string","enum":["idle","max_duration"]},"reserved_usd":{"type":"string","pattern":"^-?\\d+\\.\\d{6}$","description":"US dollars as a decimal string with six places, such as 0.060000"}},"required":["id","started_at","ready_at","idle_timeout","max_duration","parks_at","park_reason","reserved_usd"]},{"type":"null"}]},"failure":{"anyOf":[{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"at":{"type":"string","format":"date-time","description":"ISO 8601 timestamp (UTC)"}},"required":["code","message","at"]},{"type":"null"}]}},"required":["id","object","name","status","country","metadata","created_at","last_active_at","session","failure"]},"Upload":{"type":"object","properties":{"object":{"type":"string","const":"upload"},"id":{"type":"string","pattern":"^upl_[a-z2-7]{12}$"},"status":{"type":"string","enum":["awaiting_file","processing","ready","invalid_apk","too_large","storage_full","failed","duplicate","deleted"]},"package":{"description":"The package the APK's manifest declares, once read.","type":["string","null"]},"version_code":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}]},"version_name":{"type":["string","null"]},"min_sdk":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}]},"size_bytes":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}]},"sha256":{"anyOf":[{"type":"string","pattern":"^[0-9a-f]{64}$"},{"type":"null"}],"description":"The file's SHA-256, in hex."},"created_at":{"type":"string","format":"date-time","description":"ISO 8601 timestamp (UTC)"},"expires_at":{"type":"string","format":"date-time","description":"When Phonebox deletes the upload: 7 days after its last install, or its creation if never installed; an hour after creation while it waits for its file."},"error":{"anyOf":[{"type":"object","properties":{"code":{"type":"string","enum":["validation_failed","invalid_request","invalid_api_key","key_expired","key_revoked","unauthorized","insufficient_credits","spend_limit_reached","project_frozen","insufficient_scope","phone_not_allowed","browser_requests_not_allowed","setup_denied","not_found","phone_not_found","file_not_found","app_not_found","upload_not_found","recording_not_found","method_not_allowed","phone_not_running","phone_starting","phone_parking","phone_deleted","phone_failed","idempotency_conflict","running_limit_reached","phone_limit_reached","install_in_progress","version_downgrade","upload_not_ready","storage_limit_reached","clipboard_unavailable","recording_in_progress","recording_not_ready","recording_limit_reached","duplicate_upload","setup_expired","setup_used","key_limit","payload_too_large","target_not_found","ambiguous_target","stale_snapshot","no_focused_field","wait_timeout","app_not_available","invalid_apk","install_failed","feature_unavailable","rate_limited","provider_error","action_outcome_unknown","upload_failed","capacity_unavailable","phone_unavailable","service_paused","storage_full","billing_not_configured","platform_not_configured","provider_timeout","internal_error"]},"message":{"type":"string"},"next":{"type":["string","null"]}},"required":["code","message","next"]},{"type":"null"}],"description":"Why the upload ended without becoming ready."}},"required":["object","id","status","package","version_code","version_name","min_sdk","size_bytes","sha256","created_at","expires_at","error"]},"Recording":{"type":"object","properties":{"object":{"type":"string","const":"recording"},"id":{"type":"string","pattern":"^rec_[a-z2-7]{12}$"},"phone":{"type":"string","pattern":"^ph_[a-z2-7]{12}$"},"name":{"type":["string","null"]},"status":{"type":"string","enum":["recording","processing","ready","failed"],"description":"recording, then processing once stopped, then ready to download; or failed."},"started_at":{"type":"string","format":"date-time","description":"ISO 8601 timestamp (UTC)"},"ended_at":{"anyOf":[{"type":"string","format":"date-time","description":"ISO 8601 timestamp (UTC)"},{"type":"null"}]},"duration_ms":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}]},"size_bytes":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}]},"expires_at":{"type":"string","format":"date-time","description":"When Phonebox deletes the recording: 7 days after it started."}},"required":["object","id","phone","name","status","started_at","ended_at","duration_ms","size_bytes","expires_at"]},"Error":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string","enum":["invalid_request_error","authentication_error","billing_error","permission_error","not_found_error","conflict_error","rate_limit_error","provider_error","api_error"]},"code":{"type":"string","enum":["validation_failed","invalid_request","invalid_api_key","key_expired","key_revoked","unauthorized","insufficient_credits","spend_limit_reached","project_frozen","insufficient_scope","phone_not_allowed","browser_requests_not_allowed","setup_denied","not_found","phone_not_found","file_not_found","app_not_found","upload_not_found","recording_not_found","method_not_allowed","phone_not_running","phone_starting","phone_parking","phone_deleted","phone_failed","idempotency_conflict","running_limit_reached","phone_limit_reached","install_in_progress","version_downgrade","upload_not_ready","storage_limit_reached","clipboard_unavailable","recording_in_progress","recording_not_ready","recording_limit_reached","duplicate_upload","setup_expired","setup_used","key_limit","payload_too_large","target_not_found","ambiguous_target","stale_snapshot","no_focused_field","wait_timeout","app_not_available","invalid_apk","install_failed","feature_unavailable","rate_limited","provider_error","action_outcome_unknown","upload_failed","capacity_unavailable","phone_unavailable","service_paused","storage_full","billing_not_configured","platform_not_configured","provider_timeout","internal_error"]},"message":{"type":"string"},"retryable":{"type":"boolean"},"next":{"type":["string","null"]},"request_id":{"type":"string","pattern":"^req_[a-z2-7]{12}$"},"details":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}}},"required":["type","code","message","retryable","next","request_id","details"]}},"required":["error"]}},"responses":{"Error400":{"description":"Invalid request; details.issues lists each problem as {path, message}","headers":{"X-Request-Id":{"description":"This request's ID (req_…). Quote it when you contact support.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"Error401":{"description":"Missing or invalid key","headers":{"X-Request-Id":{"description":"This request's ID (req_…). Quote it when you contact support.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"Error402":{"description":"Insufficient credits, spending limit reached, or the project is frozen","headers":{"X-Request-Id":{"description":"This request's ID (req_…). Quote it when you contact support.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"Error403":{"description":"Insufficient scope, a phone this key can't use, a browser request, or a setup request that was declined","headers":{"X-Request-Id":{"description":"This request's ID (req_…). Quote it when you contact support.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"Error404":{"description":"Not found","headers":{"X-Request-Id":{"description":"This request's ID (req_…). Quote it when you contact support.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"Error409":{"description":"Conflict: the phone's status doesn't allow this, a phone limit is reached, the Idempotency-Key was used with another body, another install is still running on the phone, a newer version of the app is on the phone, an upload that isn't ready, the project's upload storage is full, the clipboard can't be read, a recording is already running or isn't ready, the project keeps 20 recordings, a setup request that expired or already delivered its key, the project has 50 active keys","headers":{"X-Request-Id":{"description":"This request's ID (req_…). Quote it when you contact support.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"Error413":{"description":"Body too large","headers":{"X-Request-Id":{"description":"This request's ID (req_…). Quote it when you contact support.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"Error422":{"description":"The request can't be applied, such as an app that isn't in Phonebox's app library, a file that isn't an APK, an install the phone refused, or a feature this phone doesn't offer (feature_unavailable)","headers":{"X-Request-Id":{"description":"This request's ID (req_…). Quote it when you contact support.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"Error429":{"description":"Rate limited","headers":{"X-Request-Id":{"description":"This request's ID (req_…). Quote it when you contact support.","schema":{"type":"string"}},"Retry-After":{"description":"Seconds to wait before trying again.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"Error500":{"description":"Unexpected server error; keep the request ID","headers":{"X-Request-Id":{"description":"This request's ID (req_…). Quote it when you contact support.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"Error502":{"description":"The phone service returned an error, or didn't confirm the action","headers":{"X-Request-Id":{"description":"This request's ID (req_…). Quote it when you contact support.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"Error503":{"description":"No capacity, the phone is briefly unavailable, Phonebox is paused, or payments aren't connected. A batch refused with this error body did nothing on the phone; a 502 or 504 without it, from a proxy or the platform, leaves the outcome unknown.","headers":{"X-Request-Id":{"description":"This request's ID (req_…). Quote it when you contact support.","schema":{"type":"string"}},"Retry-After":{"description":"Seconds to wait before trying again.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"Error504":{"description":"The phone didn't respond in time","headers":{"X-Request-Id":{"description":"This request's ID (req_…). Quote it when you contact support.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"paths":{"/v1/phones":{"post":{"operationId":"phoneCreate","summary":"Create a phone","tags":["phone"],"parameters":[{"name":"Idempotency-Key","in":"header","required":false,"schema":{"type":"string","pattern":"^[A-Za-z0-9][A-Za-z0-9_.:-]{7,127}$"},"description":"Send one with every create: without it, a create whose reply was lost can't be told apart from one that failed. The same key and body return the same phone, as it is now, for 24 hours."}],"requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":80},"country":{"type":"string","enum":["AR","AU","AT","BE","BR","CA","CL","CO","CZ","DK","EG","FI","FR","DE","GR","HK","IN","ID","IE","IL","IT","JP","KE","MY","MX","NL","NZ","NG","NO","PH","PL","PT","RO","SA","SG","ZA","KR","ES","SE","CH","TW","TH","TR","UA","AE","GB","US","VN"]},"metadata":{"type":"object","propertyNames":{"type":"string","minLength":1,"maxLength":40,"pattern":"^[A-Za-z0-9][A-Za-z0-9_:-]*$"},"additionalProperties":{"type":"string","maxLength":256}},"idle_timeout":{"type":"integer","minimum":60,"maximum":3600},"max_duration":{"type":"integer","minimum":60,"maximum":10800},"wait":{"default":true,"type":"boolean"}},"additionalProperties":false}}}},"responses":{"201":{"description":"The phone is ready.","headers":{"X-Request-Id":{"description":"This request's ID (req_…). Quote it when you contact support.","schema":{"type":"string"}},"Location":{"description":"The phone's path, /v1/phones/{id}.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Phone"}}}},"202":{"description":"The phone was created but isn't ready yet: wait was false, the ~50 s wait ran out, or the wait itself failed. Poll GET /v1/phones/{id}?wait=ready while the phone is creating or starting; any other status ends the loop, so read status and failure and act on them (a failed phone never becomes ready). If the key was revoked meanwhile, the poll answers 401 key_revoked. A replayed Idempotency-Key answers with the phone as it is now, a failed one included.","headers":{"X-Request-Id":{"description":"This request's ID (req_…). Quote it when you contact support.","schema":{"type":"string"}},"Location":{"description":"The phone's path, /v1/phones/{id}.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Phone"}}}},"400":{"$ref":"#/components/responses/Error400"},"401":{"$ref":"#/components/responses/Error401"},"402":{"$ref":"#/components/responses/Error402"},"403":{"$ref":"#/components/responses/Error403"},"404":{"$ref":"#/components/responses/Error404"},"409":{"$ref":"#/components/responses/Error409"},"413":{"$ref":"#/components/responses/Error413"},"422":{"$ref":"#/components/responses/Error422"},"429":{"$ref":"#/components/responses/Error429"},"500":{"$ref":"#/components/responses/Error500"},"502":{"$ref":"#/components/responses/Error502"},"503":{"$ref":"#/components/responses/Error503"},"504":{"$ref":"#/components/responses/Error504"}}},"get":{"operationId":"phoneList","summary":"List phones","tags":["phone"],"parameters":[{"name":"status","in":"query","schema":{"description":"Only the phones in this status. Without it, every phone but deleted and failed ones: ask for failed to list those.","type":"string","enum":["creating","starting","ready","parking","parked","unavailable","failed","deleted"]}},{"name":"limit","in":"query","schema":{"default":50,"type":"integer","minimum":1,"maximum":100}},{"name":"cursor","in":"query","schema":{"type":"string","maxLength":500}},{"name":"metadata","in":"query","style":"deepObject","explode":true,"required":false,"description":"Only phones with this metadata value: one key at a time, as metadata[customer]=acme.","schema":{"type":"object","propertyNames":{"type":"string","minLength":1,"maxLength":40,"pattern":"^[A-Za-z0-9][A-Za-z0-9_:-]*$"},"additionalProperties":{"type":"string"},"maxProperties":1}}],"responses":{"200":{"description":"A page of phones, newest first.","headers":{"X-Request-Id":{"description":"This request's ID (req_…). Quote it when you contact support.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","pattern":"^ph_[a-z2-7]{12}$"},"object":{"type":"string","const":"phone"},"name":{"type":"string"},"status":{"type":"string","enum":["creating","starting","ready","parking","parked","unavailable","failed","deleted"]},"country":{"type":["string","null"]},"metadata":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{"type":"string"}},"created_at":{"type":"string","format":"date-time","description":"ISO 8601 timestamp (UTC)"},"last_active_at":{"anyOf":[{"type":"string","format":"date-time","description":"ISO 8601 timestamp (UTC)"},{"type":"null"}]},"session":{"anyOf":[{"type":"object","properties":{"id":{"type":"string","pattern":"^ses_[a-z2-7]{12}$"},"started_at":{"type":"string","format":"date-time","description":"ISO 8601 timestamp (UTC)"},"ready_at":{"anyOf":[{"type":"string","format":"date-time","description":"ISO 8601 timestamp (UTC)"},{"type":"null"}]},"idle_timeout":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"max_duration":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"parks_at":{"type":"string","format":"date-time","description":"ISO 8601 timestamp (UTC)"},"park_reason":{"type":"string","enum":["idle","max_duration"]},"reserved_usd":{"type":"string","pattern":"^-?\\d+\\.\\d{6}$","description":"US dollars as a decimal string with six places, such as 0.060000"}},"required":["id","started_at","ready_at","idle_timeout","max_duration","parks_at","park_reason","reserved_usd"]},{"type":"null"}]},"failure":{"anyOf":[{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"at":{"type":"string","format":"date-time","description":"ISO 8601 timestamp (UTC)"}},"required":["code","message","at"]},{"type":"null"}]}},"required":["id","object","name","status","country","metadata","created_at","last_active_at","session","failure"]}},"next_cursor":{"description":"Pass as cursor for the next page; null on the last page.","type":["string","null"]}},"required":["data","next_cursor"]}}}},"400":{"$ref":"#/components/responses/Error400"},"401":{"$ref":"#/components/responses/Error401"},"402":{"$ref":"#/components/responses/Error402"},"403":{"$ref":"#/components/responses/Error403"},"404":{"$ref":"#/components/responses/Error404"},"409":{"$ref":"#/components/responses/Error409"},"413":{"$ref":"#/components/responses/Error413"},"422":{"$ref":"#/components/responses/Error422"},"429":{"$ref":"#/components/responses/Error429"},"500":{"$ref":"#/components/responses/Error500"},"502":{"$ref":"#/components/responses/Error502"},"503":{"$ref":"#/components/responses/Error503"},"504":{"$ref":"#/components/responses/Error504"}}}},"/v1/phones/{id}":{"get":{"operationId":"phoneGet","summary":"Get a phone","tags":["phone"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"wait","in":"query","schema":{"type":"string","enum":["ready","parked"]}},{"name":"timeout","in":"query","schema":{"default":50,"type":"integer","minimum":1,"maximum":55}}],"responses":{"200":{"description":"The phone. With wait, long-polls up to timeout seconds, and answers at once when the phone can't reach that status without a new request. Poll again only while it is creating or starting (wait=ready) or parking (wait=parked).","headers":{"X-Request-Id":{"description":"This request's ID (req_…). Quote it when you contact support.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Phone"}}}},"400":{"$ref":"#/components/responses/Error400"},"401":{"$ref":"#/components/responses/Error401"},"402":{"$ref":"#/components/responses/Error402"},"403":{"$ref":"#/components/responses/Error403"},"404":{"$ref":"#/components/responses/Error404"},"409":{"$ref":"#/components/responses/Error409"},"413":{"$ref":"#/components/responses/Error413"},"422":{"$ref":"#/components/responses/Error422"},"429":{"$ref":"#/components/responses/Error429"},"500":{"$ref":"#/components/responses/Error500"},"502":{"$ref":"#/components/responses/Error502"},"503":{"$ref":"#/components/responses/Error503"},"504":{"$ref":"#/components/responses/Error504"}}},"patch":{"operationId":"phoneUpdate","summary":"Update a phone","tags":["phone"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":80},"metadata":{"type":"object","propertyNames":{"type":"string","minLength":1,"maxLength":40,"pattern":"^[A-Za-z0-9][A-Za-z0-9_:-]*$"},"additionalProperties":{"type":"string","maxLength":256}}},"additionalProperties":false}}}},"responses":{"200":{"description":"The updated phone.","headers":{"X-Request-Id":{"description":"This request's ID (req_…). Quote it when you contact support.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Phone"}}}},"400":{"$ref":"#/components/responses/Error400"},"401":{"$ref":"#/components/responses/Error401"},"402":{"$ref":"#/components/responses/Error402"},"403":{"$ref":"#/components/responses/Error403"},"404":{"$ref":"#/components/responses/Error404"},"409":{"$ref":"#/components/responses/Error409"},"413":{"$ref":"#/components/responses/Error413"},"422":{"$ref":"#/components/responses/Error422"},"429":{"$ref":"#/components/responses/Error429"},"500":{"$ref":"#/components/responses/Error500"},"502":{"$ref":"#/components/responses/Error502"},"503":{"$ref":"#/components/responses/Error503"},"504":{"$ref":"#/components/responses/Error504"}}},"delete":{"operationId":"phoneDelete","summary":"Delete a phone","tags":["phone"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"The deleted phone. Needs phones:delete.","headers":{"X-Request-Id":{"description":"This request's ID (req_…). Quote it when you contact support.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Phone"}}}},"400":{"$ref":"#/components/responses/Error400"},"401":{"$ref":"#/components/responses/Error401"},"402":{"$ref":"#/components/responses/Error402"},"403":{"$ref":"#/components/responses/Error403"},"404":{"$ref":"#/components/responses/Error404"},"409":{"$ref":"#/components/responses/Error409"},"413":{"$ref":"#/components/responses/Error413"},"422":{"$ref":"#/components/responses/Error422"},"429":{"$ref":"#/components/responses/Error429"},"500":{"$ref":"#/components/responses/Error500"},"502":{"$ref":"#/components/responses/Error502"},"503":{"$ref":"#/components/responses/Error503"},"504":{"$ref":"#/components/responses/Error504"}}}},"/v1/phones/{id}/start":{"post":{"operationId":"phoneStart","summary":"Start a phone","tags":["phone"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"object","properties":{"idle_timeout":{"type":"integer","minimum":60,"maximum":3600},"max_duration":{"type":"integer","minimum":60,"maximum":10800},"wait":{"default":true,"type":"boolean"}},"additionalProperties":false}}}},"responses":{"200":{"description":"The phone is ready.","headers":{"X-Request-Id":{"description":"This request's ID (req_…). Quote it when you contact support.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Phone"}}}},"202":{"description":"The phone is still starting. Poll GET /v1/phones/{id}?wait=ready while it is starting.","headers":{"X-Request-Id":{"description":"This request's ID (req_…). Quote it when you contact support.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Phone"}}}},"400":{"$ref":"#/components/responses/Error400"},"401":{"$ref":"#/components/responses/Error401"},"402":{"$ref":"#/components/responses/Error402"},"403":{"$ref":"#/components/responses/Error403"},"404":{"$ref":"#/components/responses/Error404"},"409":{"$ref":"#/components/responses/Error409"},"413":{"$ref":"#/components/responses/Error413"},"422":{"$ref":"#/components/responses/Error422"},"429":{"$ref":"#/components/responses/Error429"},"500":{"$ref":"#/components/responses/Error500"},"502":{"$ref":"#/components/responses/Error502"},"503":{"$ref":"#/components/responses/Error503"},"504":{"$ref":"#/components/responses/Error504"}}}},"/v1/phones/{id}/park":{"post":{"operationId":"phonePark","summary":"Park a phone","tags":["phone"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"object","properties":{"wait":{"default":true,"type":"boolean"}},"additionalProperties":false}}}},"responses":{"200":{"description":"The phone is parked.","headers":{"X-Request-Id":{"description":"This request's ID (req_…). Quote it when you contact support.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Phone"}}}},"202":{"description":"The phone is still parking. Poll GET /v1/phones/{id}?wait=parked while it is parking.","headers":{"X-Request-Id":{"description":"This request's ID (req_…). Quote it when you contact support.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Phone"}}}},"400":{"$ref":"#/components/responses/Error400"},"401":{"$ref":"#/components/responses/Error401"},"402":{"$ref":"#/components/responses/Error402"},"403":{"$ref":"#/components/responses/Error403"},"404":{"$ref":"#/components/responses/Error404"},"409":{"$ref":"#/components/responses/Error409"},"413":{"$ref":"#/components/responses/Error413"},"422":{"$ref":"#/components/responses/Error422"},"429":{"$ref":"#/components/responses/Error429"},"500":{"$ref":"#/components/responses/Error500"},"502":{"$ref":"#/components/responses/Error502"},"503":{"$ref":"#/components/responses/Error503"},"504":{"$ref":"#/components/responses/Error504"}}}},"/v1/phones/{id}/heartbeat":{"post":{"operationId":"phoneHeartbeat","summary":"Keep a phone awake","tags":["phone"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"The phone, with its idle clock reset.","headers":{"X-Request-Id":{"description":"This request's ID (req_…). Quote it when you contact support.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Phone"}}}},"400":{"$ref":"#/components/responses/Error400"},"401":{"$ref":"#/components/responses/Error401"},"402":{"$ref":"#/components/responses/Error402"},"403":{"$ref":"#/components/responses/Error403"},"404":{"$ref":"#/components/responses/Error404"},"409":{"$ref":"#/components/responses/Error409"},"413":{"$ref":"#/components/responses/Error413"},"422":{"$ref":"#/components/responses/Error422"},"429":{"$ref":"#/components/responses/Error429"},"500":{"$ref":"#/components/responses/Error500"},"502":{"$ref":"#/components/responses/Error502"},"503":{"$ref":"#/components/responses/Error503"},"504":{"$ref":"#/components/responses/Error504"}}}},"/v1/phones/{id}/sessions":{"get":{"operationId":"phoneSessions","summary":"List a phone's sessions","tags":["phone"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"limit","in":"query","schema":{"default":50,"type":"integer","minimum":1,"maximum":100}},{"name":"cursor","in":"query","schema":{"type":"string","maxLength":500}}],"responses":{"200":{"description":"Sessions, newest first.","headers":{"X-Request-Id":{"description":"This request's ID (req_…). Quote it when you contact support.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","pattern":"^ses_[a-z2-7]{12}$"},"started_at":{"type":"string","format":"date-time","description":"ISO 8601 timestamp (UTC)"},"ready_at":{"anyOf":[{"type":"string","format":"date-time","description":"ISO 8601 timestamp (UTC)"},{"type":"null"}]},"ended_at":{"anyOf":[{"type":"string","format":"date-time","description":"ISO 8601 timestamp (UTC)"},{"type":"null"}]},"end_reason":{"anyOf":[{"type":"string","enum":["parked","idle","max_duration","deleted","failed","unavailable","project_frozen","service_paused"]},{"type":"null"}]},"billed_seconds":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}]},"cost_usd":{"anyOf":[{"type":"string","pattern":"^-?\\d+\\.\\d{6}$","description":"US dollars as a decimal string with six places, such as 0.060000"},{"type":"null"}]},"reserved_usd":{"type":"string","pattern":"^-?\\d+\\.\\d{6}$","description":"US dollars as a decimal string with six places, such as 0.060000"}},"required":["id","started_at","ready_at","ended_at","end_reason","billed_seconds","cost_usd","reserved_usd"]}},"next_cursor":{"description":"Pass as cursor for the next page; null on the last page.","type":["string","null"]}},"required":["data","next_cursor"]}}}},"400":{"$ref":"#/components/responses/Error400"},"401":{"$ref":"#/components/responses/Error401"},"402":{"$ref":"#/components/responses/Error402"},"403":{"$ref":"#/components/responses/Error403"},"404":{"$ref":"#/components/responses/Error404"},"409":{"$ref":"#/components/responses/Error409"},"413":{"$ref":"#/components/responses/Error413"},"422":{"$ref":"#/components/responses/Error422"},"429":{"$ref":"#/components/responses/Error429"},"500":{"$ref":"#/components/responses/Error500"},"502":{"$ref":"#/components/responses/Error502"},"503":{"$ref":"#/components/responses/Error503"},"504":{"$ref":"#/components/responses/Error504"}}}},"/v1/phones/{id}/observe":{"get":{"operationId":"phoneObserve","summary":"Observe the screen","tags":["phone"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"screenshot","in":"query","schema":{"default":"none","type":"string","enum":["none","jpeg","png"]}},{"name":"max_width","in":"query","schema":{"type":"integer","minimum":160,"maximum":2000}},{"name":"format","in":"query","schema":{"default":"json","type":"string","enum":["json","text"]}}],"responses":{"200":{"description":"The screen as numbered elements. With format=text, the same list as plain text, with its snapshot in X-Snapshot-Id.","headers":{"X-Request-Id":{"description":"This request's ID (req_…). Quote it when you contact support.","schema":{"type":"string"}},"X-Snapshot-Id":{"description":"With format=text: the snapshot the element refs belong to.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"type":"object","properties":{"snapshot_id":{"type":"string","pattern":"^snp_[a-z2-7]{12}$"},"taken_at":{"type":"string","format":"date-time","description":"ISO 8601 timestamp (UTC)"},"app":{"type":"object","properties":{"package":{"type":["string","null"]},"activity":{"type":["string","null"]}},"required":["package","activity"]},"keyboard":{"type":"object","properties":{"visible":{"type":"boolean"},"focused_editable":{"type":"boolean"}},"required":["visible","focused_editable"]},"screen":{"type":"object","properties":{"width":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"height":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["width","height"]},"elements":{"type":"array","items":{"type":"object","properties":{"ref":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"type":{"type":"string"},"text":{"type":["string","null"]},"desc":{"type":["string","null"]},"id":{"type":["string","null"]},"bounds":{"type":"array","prefixItems":[{"type":"number"},{"type":"number"},{"type":"number"},{"type":"number"}],"items":false,"minItems":4,"maxItems":4},"center":{"type":"array","prefixItems":[{"type":"number"},{"type":"number"}],"items":false,"minItems":2,"maxItems":2},"state":{"type":"array","items":{"type":"string"}}},"required":["ref","type","text","desc","id","bounds","center","state"]}},"truncated":{"type":"boolean"},"text":{"type":"string"},"screenshot":{"type":"object","properties":{"format":{"type":"string","enum":["jpeg","png"]},"width":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"height":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"scale":{"type":"number"},"data":{"type":"string"}},"required":["format","width","height","scale","data"]}},"required":["snapshot_id","taken_at","app","keyboard","screen","elements","truncated","text"]}},"text/plain":{"schema":{"type":"string"}}}},"400":{"$ref":"#/components/responses/Error400"},"401":{"$ref":"#/components/responses/Error401"},"402":{"$ref":"#/components/responses/Error402"},"403":{"$ref":"#/components/responses/Error403"},"404":{"$ref":"#/components/responses/Error404"},"409":{"$ref":"#/components/responses/Error409"},"413":{"$ref":"#/components/responses/Error413"},"422":{"$ref":"#/components/responses/Error422"},"429":{"$ref":"#/components/responses/Error429"},"500":{"$ref":"#/components/responses/Error500"},"502":{"$ref":"#/components/responses/Error502"},"503":{"$ref":"#/components/responses/Error503"},"504":{"$ref":"#/components/responses/Error504"}}}},"/v1/phones/{id}/screenshot":{"get":{"operationId":"phoneScreenshot","summary":"Take a screenshot","tags":["phone"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"format","in":"query","schema":{"default":"png","type":"string","enum":["png","jpeg"]}},{"name":"max_width","in":"query","schema":{"type":"integer","minimum":160,"maximum":2000}},{"name":"quality","in":"query","schema":{"default":70,"type":"integer","minimum":30,"maximum":95}}],"responses":{"200":{"description":"The screen as an image, under 4 MB.","headers":{"X-Request-Id":{"description":"This request's ID (req_…). Quote it when you contact support.","schema":{"type":"string"}},"X-Screen-Width":{"description":"The phone's screen width in device pixels.","schema":{"type":"integer"}},"X-Screen-Height":{"description":"The phone's screen height in device pixels.","schema":{"type":"integer"}},"X-Screen-Scale":{"description":"The image's width over the screen's: below 1 when max_width, or the 4 MB limit, made it narrower. Device pixels = image pixels / scale.","schema":{"type":"number"}}},"content":{"image/png":{"schema":{"type":"string","contentMediaType":"image/png"}},"image/jpeg":{"schema":{"type":"string","contentMediaType":"image/jpeg"}}}},"400":{"$ref":"#/components/responses/Error400"},"401":{"$ref":"#/components/responses/Error401"},"402":{"$ref":"#/components/responses/Error402"},"403":{"$ref":"#/components/responses/Error403"},"404":{"$ref":"#/components/responses/Error404"},"409":{"$ref":"#/components/responses/Error409"},"413":{"$ref":"#/components/responses/Error413"},"422":{"$ref":"#/components/responses/Error422"},"429":{"$ref":"#/components/responses/Error429"},"500":{"$ref":"#/components/responses/Error500"},"502":{"$ref":"#/components/responses/Error502"},"503":{"$ref":"#/components/responses/Error503"},"504":{"$ref":"#/components/responses/Error504"}}}},"/v1/phones/{id}/actions":{"post":{"operationId":"phoneActions","summary":"Run actions","tags":["phone"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"actions":{"minItems":1,"maxItems":20,"type":"array","items":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","const":"tap"},"target":{"anyOf":[{"type":"object","properties":{"x":{"type":"integer","minimum":0,"maximum":10000},"y":{"type":"integer","minimum":0,"maximum":10000}},"required":["x","y"],"additionalProperties":false},{"type":"object","properties":{"ref":{"type":"integer","minimum":1,"maximum":1000},"snapshot_id":{"type":"string","pattern":"^snp_[a-z2-7]{12}$"}},"required":["ref","snapshot_id"],"additionalProperties":false},{"type":"object","properties":{"text":{"type":"string","minLength":1,"maxLength":500},"nth":{"type":"integer","minimum":1,"maximum":50}},"required":["text"],"additionalProperties":false},{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":300}},"required":["id"],"additionalProperties":false},{"type":"object","properties":{"desc":{"type":"string","minLength":1,"maxLength":500}},"required":["desc"],"additionalProperties":false}]}},"required":["type","target"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","const":"double_tap"},"target":{"anyOf":[{"type":"object","properties":{"x":{"type":"integer","minimum":0,"maximum":10000},"y":{"type":"integer","minimum":0,"maximum":10000}},"required":["x","y"],"additionalProperties":false},{"type":"object","properties":{"ref":{"type":"integer","minimum":1,"maximum":1000},"snapshot_id":{"type":"string","pattern":"^snp_[a-z2-7]{12}$"}},"required":["ref","snapshot_id"],"additionalProperties":false},{"type":"object","properties":{"text":{"type":"string","minLength":1,"maxLength":500},"nth":{"type":"integer","minimum":1,"maximum":50}},"required":["text"],"additionalProperties":false},{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":300}},"required":["id"],"additionalProperties":false},{"type":"object","properties":{"desc":{"type":"string","minLength":1,"maxLength":500}},"required":["desc"],"additionalProperties":false}]}},"required":["type","target"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","const":"long_press"},"target":{"anyOf":[{"type":"object","properties":{"x":{"type":"integer","minimum":0,"maximum":10000},"y":{"type":"integer","minimum":0,"maximum":10000}},"required":["x","y"],"additionalProperties":false},{"type":"object","properties":{"ref":{"type":"integer","minimum":1,"maximum":1000},"snapshot_id":{"type":"string","pattern":"^snp_[a-z2-7]{12}$"}},"required":["ref","snapshot_id"],"additionalProperties":false},{"type":"object","properties":{"text":{"type":"string","minLength":1,"maxLength":500},"nth":{"type":"integer","minimum":1,"maximum":50}},"required":["text"],"additionalProperties":false},{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":300}},"required":["id"],"additionalProperties":false},{"type":"object","properties":{"desc":{"type":"string","minLength":1,"maxLength":500}},"required":["desc"],"additionalProperties":false}]},"duration_ms":{"default":800,"type":"integer","minimum":300,"maximum":5000}},"required":["type","target"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","const":"swipe"},"from":{"type":"object","properties":{"x":{"type":"integer","minimum":0,"maximum":10000},"y":{"type":"integer","minimum":0,"maximum":10000}},"required":["x","y"],"additionalProperties":false},"to":{"type":"object","properties":{"x":{"type":"integer","minimum":0,"maximum":10000},"y":{"type":"integer","minimum":0,"maximum":10000}},"required":["x","y"],"additionalProperties":false},"duration_ms":{"default":300,"type":"integer","minimum":50,"maximum":5000}},"required":["type","from","to"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","const":"scroll"},"direction":{"type":"string","enum":["up","down","left","right"]},"target":{"anyOf":[{"type":"object","properties":{"x":{"type":"integer","minimum":0,"maximum":10000},"y":{"type":"integer","minimum":0,"maximum":10000}},"required":["x","y"],"additionalProperties":false},{"type":"object","properties":{"ref":{"type":"integer","minimum":1,"maximum":1000},"snapshot_id":{"type":"string","pattern":"^snp_[a-z2-7]{12}$"}},"required":["ref","snapshot_id"],"additionalProperties":false},{"type":"object","properties":{"text":{"type":"string","minLength":1,"maxLength":500},"nth":{"type":"integer","minimum":1,"maximum":50}},"required":["text"],"additionalProperties":false},{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":300}},"required":["id"],"additionalProperties":false},{"type":"object","properties":{"desc":{"type":"string","minLength":1,"maxLength":500}},"required":["desc"],"additionalProperties":false}]},"amount":{"default":0.6,"type":"number","minimum":0.1,"maximum":1}},"required":["type","direction"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","const":"type"},"text":{"type":"string","minLength":1,"maxLength":5000},"clear":{"default":false,"type":"boolean"},"submit":{"default":false,"type":"boolean"}},"required":["type","text"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","const":"key"},"key":{"anyOf":[{"type":"string","enum":["enter","delete","tab","escape","space","up","down","left","right","page_up","page_down","move_home","move_end","menu","search","volume_up","volume_down"]},{"type":"integer","minimum":0,"maximum":400}]}},"required":["type","key"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","const":"back"}},"required":["type"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","const":"home"}},"required":["type"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","const":"recents"}},"required":["type"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","const":"notifications"}},"required":["type"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","const":"open_app"},"package":{"type":"string","maxLength":255,"pattern":"^[A-Za-z][A-Za-z0-9_]*(\\.[A-Za-z0-9_]+)+$"},"activity":{"type":"string","maxLength":300}},"required":["type","package"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","const":"close_app"},"package":{"type":"string","maxLength":255,"pattern":"^[A-Za-z][A-Za-z0-9_]*(\\.[A-Za-z0-9_]+)+$"},"clear_data":{"default":false,"type":"boolean"}},"required":["type","package"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","const":"open_url"},"url":{"type":"string","minLength":3,"maxLength":2000},"package":{"type":"string","maxLength":255,"pattern":"^[A-Za-z][A-Za-z0-9_]*(\\.[A-Za-z0-9_]+)+$"}},"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","properties":{"type":{"type":"string","const":"wait_for"},"target":{"anyOf":[{"type":"object","properties":{"text":{"type":"string","minLength":1,"maxLength":500},"nth":{"type":"integer","minimum":1,"maximum":50}},"required":["text"],"additionalProperties":false},{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":300}},"required":["id"],"additionalProperties":false},{"type":"object","properties":{"desc":{"type":"string","minLength":1,"maxLength":500}},"required":["desc"],"additionalProperties":false}]},"gone":{"default":false,"type":"boolean"},"timeout_ms":{"default":10000,"type":"integer","minimum":100,"maximum":30000}},"required":["type","target"],"additionalProperties":false}]}},"observe":{"default":"ui","type":"string","enum":["none","ui","screenshot","both"]}},"required":["actions"],"additionalProperties":false}}}},"responses":{"200":{"description":"One result per action run; the batch stops at the first failure. If nothing reached the phone, the request itself fails.","headers":{"X-Request-Id":{"description":"This request's ID (req_…). Quote it when you contact support.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"type":"object","properties":{"results":{"type":"array","items":{"type":"object","properties":{"index":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"type":{"type":"string","enum":["tap","double_tap","long_press","swipe","scroll","type","key","back","home","recents","notifications","open_app","close_app","open_url","wait","wait_for"]},"ok":{"type":"boolean"},"ms":{"type":"number"},"resolved":{"type":"object","properties":{"ref":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"center":{"type":"array","prefixItems":[{"type":"number"},{"type":"number"}],"items":false,"minItems":2,"maxItems":2}},"required":["center"]},"error":{"description":"Why the action failed. retryable is false once part of it reached the phone (details.partial). After 90 s a batch starts no more actions: the next one fails with provider_timeout without running, and details.not_run counts it and the actions after it.","type":"object","properties":{"code":{"type":"string","enum":["validation_failed","invalid_request","invalid_api_key","key_expired","key_revoked","unauthorized","insufficient_credits","spend_limit_reached","project_frozen","insufficient_scope","phone_not_allowed","browser_requests_not_allowed","setup_denied","not_found","phone_not_found","file_not_found","app_not_found","upload_not_found","recording_not_found","method_not_allowed","phone_not_running","phone_starting","phone_parking","phone_deleted","phone_failed","idempotency_conflict","running_limit_reached","phone_limit_reached","install_in_progress","version_downgrade","upload_not_ready","storage_limit_reached","clipboard_unavailable","recording_in_progress","recording_not_ready","recording_limit_reached","duplicate_upload","setup_expired","setup_used","key_limit","payload_too_large","target_not_found","ambiguous_target","stale_snapshot","no_focused_field","wait_timeout","app_not_available","invalid_apk","install_failed","feature_unavailable","rate_limited","provider_error","action_outcome_unknown","upload_failed","capacity_unavailable","phone_unavailable","service_paused","storage_full","billing_not_configured","platform_not_configured","provider_timeout","internal_error"]},"message":{"type":"string"},"retryable":{"type":"boolean"},"next":{"type":["string","null"]},"details":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}}},"required":["code","message","retryable","next","details"]}},"required":["index","type","ok","ms"]}},"completed":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"observation":{"description":"The screen after the batch; a stopped batch includes its elements. It is left out when the screen couldn't be read, or not in time.","type":"object","properties":{"snapshot_id":{"type":"string","pattern":"^snp_[a-z2-7]{12}$"},"taken_at":{"type":"string","format":"date-time","description":"ISO 8601 timestamp (UTC)"},"app":{"type":"object","properties":{"package":{"type":["string","null"]},"activity":{"type":["string","null"]}},"required":["package","activity"]},"keyboard":{"type":"object","properties":{"visible":{"type":"boolean"},"focused_editable":{"type":"boolean"}},"required":["visible","focused_editable"]},"screen":{"type":"object","properties":{"width":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"height":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["width","height"]},"elements":{"type":"array","items":{"type":"object","properties":{"ref":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"type":{"type":"string"},"text":{"type":["string","null"]},"desc":{"type":["string","null"]},"id":{"type":["string","null"]},"bounds":{"type":"array","prefixItems":[{"type":"number"},{"type":"number"},{"type":"number"},{"type":"number"}],"items":false,"minItems":4,"maxItems":4},"center":{"type":"array","prefixItems":[{"type":"number"},{"type":"number"}],"items":false,"minItems":2,"maxItems":2},"state":{"type":"array","items":{"type":"string"}}},"required":["ref","type","text","desc","id","bounds","center","state"]}},"truncated":{"type":"boolean"},"text":{"type":"string"},"screenshot":{"type":"object","properties":{"format":{"type":"string","enum":["jpeg","png"]},"width":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"height":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"scale":{"type":"number"},"data":{"type":"string"}},"required":["format","width","height","scale","data"]}}}},"required":["results","completed"]}}}},"400":{"$ref":"#/components/responses/Error400"},"401":{"$ref":"#/components/responses/Error401"},"402":{"$ref":"#/components/responses/Error402"},"403":{"$ref":"#/components/responses/Error403"},"404":{"$ref":"#/components/responses/Error404"},"409":{"$ref":"#/components/responses/Error409"},"413":{"$ref":"#/components/responses/Error413"},"422":{"$ref":"#/components/responses/Error422"},"429":{"$ref":"#/components/responses/Error429"},"500":{"$ref":"#/components/responses/Error500"},"502":{"$ref":"#/components/responses/Error502"},"503":{"$ref":"#/components/responses/Error503"},"504":{"$ref":"#/components/responses/Error504"}}}},"/v1/phones/{id}/apps":{"get":{"operationId":"appsList","summary":"List apps","tags":["apps"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Installed apps.","headers":{"X-Request-Id":{"description":"This request's ID (req_…). Quote it when you contact support.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"package":{"type":"string"},"label":{"type":"string"},"version_name":{"type":"string"},"version_code":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"system":{"type":"boolean"}},"required":["package","label","version_name","version_code","system"]}}},"required":["data"]}}}},"400":{"$ref":"#/components/responses/Error400"},"401":{"$ref":"#/components/responses/Error401"},"402":{"$ref":"#/components/responses/Error402"},"403":{"$ref":"#/components/responses/Error403"},"404":{"$ref":"#/components/responses/Error404"},"409":{"$ref":"#/components/responses/Error409"},"413":{"$ref":"#/components/responses/Error413"},"422":{"$ref":"#/components/responses/Error422"},"429":{"$ref":"#/components/responses/Error429"},"500":{"$ref":"#/components/responses/Error500"},"502":{"$ref":"#/components/responses/Error502"},"503":{"$ref":"#/components/responses/Error503"},"504":{"$ref":"#/components/responses/Error504"}}},"post":{"operationId":"appsInstall","summary":"Install an app","description":"Installs an app in the background: by package, from Phonebox's app library, or by upload, your own APK (POST /v1/apps/uploads). By package it doesn't reach Google Play: install a Play Store app from the Play Store app on the phone instead. With replace, an upload's app is uninstalled first, which deletes its data.","tags":["apps"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"package":{"description":"An app in Phonebox's app library, by its package name.","type":"string","maxLength":255,"pattern":"^[A-Za-z][A-Za-z0-9_]*(\\.[A-Za-z0-9_]+)+$"},"upload":{"description":"An upload of your own APK (upl_…) whose status is ready.","type":"string","pattern":"^upl_[a-z2-7]{12}$"},"replace":{"description":"With upload: uninstall the app first when it is on the phone, which deletes its data. Use it for a build signed with another key, or an older version_code.","type":"boolean"}},"additionalProperties":false}}}},"responses":{"202":{"description":"The install started in the background. Follow it in GET /v1/phones/{id}/apps/installs: an install by upload succeeds once the phone lists its package at the upload's version_code.","headers":{"X-Request-Id":{"description":"This request's ID (req_…). Quote it when you contact support.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"type":"object","properties":{"package":{"type":"string","description":"The app's package: for an upload, the package its APK declares."},"upload":{"description":"The upload being installed, for an install by upload.","type":"string","pattern":"^upl_[a-z2-7]{12}$"},"install":{"description":"This install's ID, for an install by upload: its row in the phone's installs has it.","type":"string","pattern":"^ins_[a-z2-7]{12}$"},"status":{"type":"string","const":"running"}},"required":["package","status"]}}}},"400":{"$ref":"#/components/responses/Error400"},"401":{"$ref":"#/components/responses/Error401"},"402":{"$ref":"#/components/responses/Error402"},"403":{"$ref":"#/components/responses/Error403"},"404":{"$ref":"#/components/responses/Error404"},"409":{"$ref":"#/components/responses/Error409"},"413":{"$ref":"#/components/responses/Error413"},"422":{"$ref":"#/components/responses/Error422"},"429":{"$ref":"#/components/responses/Error429"},"500":{"$ref":"#/components/responses/Error500"},"502":{"$ref":"#/components/responses/Error502"},"503":{"$ref":"#/components/responses/Error503"},"504":{"$ref":"#/components/responses/Error504"}}}},"/v1/phones/{id}/apps/installs":{"get":{"operationId":"appsInstalls","summary":"List app installs","tags":["apps"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Recent installs and their status.","headers":{"X-Request-Id":{"description":"This request's ID (req_…). Quote it when you contact support.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"package":{"type":"string"},"upload":{"anyOf":[{"type":"string","pattern":"^upl_[a-z2-7]{12}$"},{"type":"null"}],"description":"The upload this install put on the phone, or null for an app from the library."},"install":{"anyOf":[{"type":"string","pattern":"^ins_[a-z2-7]{12}$"},{"type":"null"}],"description":"The install's ID, for an install by upload, as its start answered; null for an app from the library."},"status":{"type":"string","enum":["running","succeeded","failed"],"description":"An install by upload succeeds only once the phone lists its package at the upload's version_code."},"error":{"description":"A failed install's reason as a machine code, such as install_failed.","type":["string","null"]},"next":{"description":"What to do about a failed install, when Phonebox can tell.","type":["string","null"]},"started_at":{"anyOf":[{"type":"string","format":"date-time","description":"ISO 8601 timestamp (UTC)"},{"type":"null"}]},"updated_at":{"anyOf":[{"type":"string","format":"date-time","description":"ISO 8601 timestamp (UTC)"},{"type":"null"}]}},"required":["package","upload","install","status","error","next","started_at","updated_at"]}}},"required":["data"]}}}},"400":{"$ref":"#/components/responses/Error400"},"401":{"$ref":"#/components/responses/Error401"},"402":{"$ref":"#/components/responses/Error402"},"403":{"$ref":"#/components/responses/Error403"},"404":{"$ref":"#/components/responses/Error404"},"409":{"$ref":"#/components/responses/Error409"},"413":{"$ref":"#/components/responses/Error413"},"422":{"$ref":"#/components/responses/Error422"},"429":{"$ref":"#/components/responses/Error429"},"500":{"$ref":"#/components/responses/Error500"},"502":{"$ref":"#/components/responses/Error502"},"503":{"$ref":"#/components/responses/Error503"},"504":{"$ref":"#/components/responses/Error504"}}}},"/v1/phones/{id}/apps/{package}":{"delete":{"operationId":"appsUninstall","summary":"Uninstall an app","tags":["apps"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"package","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"The app was uninstalled.","headers":{"X-Request-Id":{"description":"This request's ID (req_…). Quote it when you contact support.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"type":"object","properties":{"package":{"type":"string"},"uninstalled":{"type":"boolean","const":true}},"required":["package","uninstalled"]}}}},"400":{"$ref":"#/components/responses/Error400"},"401":{"$ref":"#/components/responses/Error401"},"402":{"$ref":"#/components/responses/Error402"},"403":{"$ref":"#/components/responses/Error403"},"404":{"$ref":"#/components/responses/Error404"},"409":{"$ref":"#/components/responses/Error409"},"413":{"$ref":"#/components/responses/Error413"},"422":{"$ref":"#/components/responses/Error422"},"429":{"$ref":"#/components/responses/Error429"},"500":{"$ref":"#/components/responses/Error500"},"502":{"$ref":"#/components/responses/Error502"},"503":{"$ref":"#/components/responses/Error503"},"504":{"$ref":"#/components/responses/Error504"}}}},"/v1/phones/{id}/files":{"get":{"operationId":"filesList","summary":"List files","tags":["files"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"path","in":"query","schema":{"default":"/sdcard","type":"string","maxLength":1024,"pattern":"^\\/(sdcard|storage\\/emulated\\/0)(\\/[^/\\0]+)*\\/?$","description":"A path under /sdcard (or /storage/emulated/0), with no . or .. segments."}}],"responses":{"200":{"description":"The directory's entries.","headers":{"X-Request-Id":{"description":"This request's ID (req_…). Quote it when you contact support.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"type":"object","properties":{"path":{"type":"string"},"data":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string"},"type":{"type":"string","enum":["file","directory","other"]},"size":{"type":"number"},"modified_at":{"anyOf":[{"type":"string","format":"date-time","description":"ISO 8601 timestamp (UTC)"},{"type":"null"}]}},"required":["name","type","size","modified_at"]}}},"required":["path","data"]}}}},"400":{"$ref":"#/components/responses/Error400"},"401":{"$ref":"#/components/responses/Error401"},"402":{"$ref":"#/components/responses/Error402"},"403":{"$ref":"#/components/responses/Error403"},"404":{"$ref":"#/components/responses/Error404"},"409":{"$ref":"#/components/responses/Error409"},"413":{"$ref":"#/components/responses/Error413"},"422":{"$ref":"#/components/responses/Error422"},"429":{"$ref":"#/components/responses/Error429"},"500":{"$ref":"#/components/responses/Error500"},"502":{"$ref":"#/components/responses/Error502"},"503":{"$ref":"#/components/responses/Error503"},"504":{"$ref":"#/components/responses/Error504"}}},"put":{"operationId":"filesUpload","summary":"Upload a file","tags":["files"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"path","in":"query","required":true,"schema":{"type":"string","maxLength":1024,"pattern":"^\\/(sdcard|storage\\/emulated\\/0)(\\/[^/\\0]+)*\\/?$","description":"A path under /sdcard (or /storage/emulated/0), with no . or .. segments."}}],"requestBody":{"description":"The file's bytes, at most 4 MB.","required":true,"content":{"application/octet-stream":{"schema":{"type":"string","contentMediaType":"application/octet-stream"}}}},"responses":{"201":{"description":"The file was written.","headers":{"X-Request-Id":{"description":"This request's ID (req_…). Quote it when you contact support.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"type":"object","properties":{"path":{"type":"string"},"size":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["path","size"]}}}},"400":{"$ref":"#/components/responses/Error400"},"401":{"$ref":"#/components/responses/Error401"},"402":{"$ref":"#/components/responses/Error402"},"403":{"$ref":"#/components/responses/Error403"},"404":{"$ref":"#/components/responses/Error404"},"409":{"$ref":"#/components/responses/Error409"},"413":{"$ref":"#/components/responses/Error413"},"422":{"$ref":"#/components/responses/Error422"},"429":{"$ref":"#/components/responses/Error429"},"500":{"$ref":"#/components/responses/Error500"},"502":{"$ref":"#/components/responses/Error502"},"503":{"$ref":"#/components/responses/Error503"},"504":{"$ref":"#/components/responses/Error504"}}},"delete":{"operationId":"filesDelete","summary":"Delete a file","tags":["files"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"path","in":"query","required":true,"schema":{"type":"string","maxLength":1024,"pattern":"^\\/(sdcard|storage\\/emulated\\/0)(\\/[^/\\0]+)*\\/?$","description":"A path under /sdcard (or /storage/emulated/0), with no . or .. segments."}}],"responses":{"200":{"description":"The file was deleted. Directories are refused with 400 validation_failed; delete folders in the phone’s Files app.","headers":{"X-Request-Id":{"description":"This request's ID (req_…). Quote it when you contact support.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"type":"object","properties":{"path":{"type":"string","description":"The deleted file. Directories are refused before any contents are deleted."},"deleted":{"type":"boolean","const":true}},"required":["path","deleted"]}}}},"400":{"$ref":"#/components/responses/Error400"},"401":{"$ref":"#/components/responses/Error401"},"402":{"$ref":"#/components/responses/Error402"},"403":{"$ref":"#/components/responses/Error403"},"404":{"$ref":"#/components/responses/Error404"},"409":{"$ref":"#/components/responses/Error409"},"413":{"$ref":"#/components/responses/Error413"},"422":{"$ref":"#/components/responses/Error422"},"429":{"$ref":"#/components/responses/Error429"},"500":{"$ref":"#/components/responses/Error500"},"502":{"$ref":"#/components/responses/Error502"},"503":{"$ref":"#/components/responses/Error503"},"504":{"$ref":"#/components/responses/Error504"}}}},"/v1/phones/{id}/files/content":{"get":{"operationId":"filesDownload","summary":"Download a file","tags":["files"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"path","in":"query","required":true,"schema":{"type":"string","maxLength":1024,"pattern":"^\\/(sdcard|storage\\/emulated\\/0)(\\/[^/\\0]+)*\\/?$","description":"A path under /sdcard (or /storage/emulated/0), with no . or .. segments."}}],"responses":{"200":{"description":"The file's bytes, at most 4 MB.","headers":{"X-Request-Id":{"description":"This request's ID (req_…). Quote it when you contact support.","schema":{"type":"string"}},"Content-Disposition":{"description":"attachment, with the file's name.","schema":{"type":"string"}}},"content":{"application/octet-stream":{"schema":{"type":"string","contentMediaType":"application/octet-stream"}}}},"400":{"$ref":"#/components/responses/Error400"},"401":{"$ref":"#/components/responses/Error401"},"402":{"$ref":"#/components/responses/Error402"},"403":{"$ref":"#/components/responses/Error403"},"404":{"$ref":"#/components/responses/Error404"},"409":{"$ref":"#/components/responses/Error409"},"413":{"$ref":"#/components/responses/Error413"},"422":{"$ref":"#/components/responses/Error422"},"429":{"$ref":"#/components/responses/Error429"},"500":{"$ref":"#/components/responses/Error500"},"502":{"$ref":"#/components/responses/Error502"},"503":{"$ref":"#/components/responses/Error503"},"504":{"$ref":"#/components/responses/Error504"}}}},"/v1/phones/{id}/clipboard":{"get":{"operationId":"deviceClipboardGet","summary":"Read the clipboard","tags":["device"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"The clipboard text.","headers":{"X-Request-Id":{"description":"This request's ID (req_…). Quote it when you contact support.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"type":"object","properties":{"text":{"type":"string"}},"required":["text"]}}}},"400":{"$ref":"#/components/responses/Error400"},"401":{"$ref":"#/components/responses/Error401"},"402":{"$ref":"#/components/responses/Error402"},"403":{"$ref":"#/components/responses/Error403"},"404":{"$ref":"#/components/responses/Error404"},"409":{"$ref":"#/components/responses/Error409"},"413":{"$ref":"#/components/responses/Error413"},"422":{"$ref":"#/components/responses/Error422"},"429":{"$ref":"#/components/responses/Error429"},"500":{"$ref":"#/components/responses/Error500"},"502":{"$ref":"#/components/responses/Error502"},"503":{"$ref":"#/components/responses/Error503"},"504":{"$ref":"#/components/responses/Error504"}}},"put":{"operationId":"deviceClipboardSet","summary":"Set the clipboard","tags":["device"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"text":{"type":"string","minLength":1,"maxLength":10000,"description":"Text to replace the phone's clipboard, 1 to 10,000 characters. Empty text cannot clear the clipboard."}},"required":["text"],"additionalProperties":false}}}},"responses":{"200":{"description":"The clipboard was set.","headers":{"X-Request-Id":{"description":"This request's ID (req_…). Quote it when you contact support.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"type":"object","properties":{"text":{"type":"string"}},"required":["text"]}}}},"400":{"$ref":"#/components/responses/Error400"},"401":{"$ref":"#/components/responses/Error401"},"402":{"$ref":"#/components/responses/Error402"},"403":{"$ref":"#/components/responses/Error403"},"404":{"$ref":"#/components/responses/Error404"},"409":{"$ref":"#/components/responses/Error409"},"413":{"$ref":"#/components/responses/Error413"},"422":{"$ref":"#/components/responses/Error422"},"429":{"$ref":"#/components/responses/Error429"},"500":{"$ref":"#/components/responses/Error500"},"502":{"$ref":"#/components/responses/Error502"},"503":{"$ref":"#/components/responses/Error503"},"504":{"$ref":"#/components/responses/Error504"}}}},"/v1/phones/{id}/location":{"put":{"operationId":"deviceLocationSet","summary":"Set the location","tags":["device"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"lat":{"type":"number","minimum":-90,"maximum":90},"lng":{"type":"number","minimum":-180,"maximum":180},"timezone_from_location":{"default":true,"description":"Also set the phone's timezone to the one at this location. The default is true, so the clock matches the place.","type":"boolean"}},"required":["lat","lng"],"additionalProperties":false}}}},"responses":{"200":{"description":"The mock location is set, and with timezone_from_location (the default) the timezone found there.","headers":{"X-Request-Id":{"description":"This request's ID (req_…). Quote it when you contact support.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"type":"object","properties":{"lat":{"type":"number"},"lng":{"type":"number"},"timezone":{"description":"The timezone set to match the location, or null when timezone_from_location was false, or the phone can't change its timezone or refused the one found.","type":["string","null"]}},"required":["lat","lng","timezone"]}}}},"400":{"$ref":"#/components/responses/Error400"},"401":{"$ref":"#/components/responses/Error401"},"402":{"$ref":"#/components/responses/Error402"},"403":{"$ref":"#/components/responses/Error403"},"404":{"$ref":"#/components/responses/Error404"},"409":{"$ref":"#/components/responses/Error409"},"413":{"$ref":"#/components/responses/Error413"},"422":{"$ref":"#/components/responses/Error422"},"429":{"$ref":"#/components/responses/Error429"},"500":{"$ref":"#/components/responses/Error500"},"502":{"$ref":"#/components/responses/Error502"},"503":{"$ref":"#/components/responses/Error503"},"504":{"$ref":"#/components/responses/Error504"}}},"delete":{"operationId":"deviceLocationReset","summary":"Reset the location","tags":["device"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"The mock location was removed and, where the phone can change it, the timezone set to the default location's.","headers":{"X-Request-Id":{"description":"This request's ID (req_…). Quote it when you contact support.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"type":"object","properties":{"reset":{"type":"boolean","const":true}},"required":["reset"]}}}},"400":{"$ref":"#/components/responses/Error400"},"401":{"$ref":"#/components/responses/Error401"},"402":{"$ref":"#/components/responses/Error402"},"403":{"$ref":"#/components/responses/Error403"},"404":{"$ref":"#/components/responses/Error404"},"409":{"$ref":"#/components/responses/Error409"},"413":{"$ref":"#/components/responses/Error413"},"422":{"$ref":"#/components/responses/Error422"},"429":{"$ref":"#/components/responses/Error429"},"500":{"$ref":"#/components/responses/Error500"},"502":{"$ref":"#/components/responses/Error502"},"503":{"$ref":"#/components/responses/Error503"},"504":{"$ref":"#/components/responses/Error504"}}},"get":{"operationId":"deviceLocationGet","summary":"Read the location","tags":["device"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"The location the phone reports to apps. Until one is set, it is the phone's default.","headers":{"X-Request-Id":{"description":"This request's ID (req_…). Quote it when you contact support.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"type":"object","properties":{"lat":{"type":"number"},"lng":{"type":"number"}},"required":["lat","lng"]}}}},"400":{"$ref":"#/components/responses/Error400"},"401":{"$ref":"#/components/responses/Error401"},"402":{"$ref":"#/components/responses/Error402"},"403":{"$ref":"#/components/responses/Error403"},"404":{"$ref":"#/components/responses/Error404"},"409":{"$ref":"#/components/responses/Error409"},"413":{"$ref":"#/components/responses/Error413"},"422":{"$ref":"#/components/responses/Error422"},"429":{"$ref":"#/components/responses/Error429"},"500":{"$ref":"#/components/responses/Error500"},"502":{"$ref":"#/components/responses/Error502"},"503":{"$ref":"#/components/responses/Error503"},"504":{"$ref":"#/components/responses/Error504"}}}},"/v1/phones/{id}/locale":{"put":{"operationId":"deviceLocale","summary":"Set the locale","tags":["device"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"locale":{"type":"string","pattern":"^[a-z]{2,3}(-[A-Z][a-z]{3})?(-(?:[A-Z]{2}|\\d{3}))?$"}},"required":["locale"],"additionalProperties":false}}}},"responses":{"200":{"description":"The locale is set.","headers":{"X-Request-Id":{"description":"This request's ID (req_…). Quote it when you contact support.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"type":"object","properties":{"locale":{"type":"string"}},"required":["locale"]}}}},"400":{"$ref":"#/components/responses/Error400"},"401":{"$ref":"#/components/responses/Error401"},"402":{"$ref":"#/components/responses/Error402"},"403":{"$ref":"#/components/responses/Error403"},"404":{"$ref":"#/components/responses/Error404"},"409":{"$ref":"#/components/responses/Error409"},"413":{"$ref":"#/components/responses/Error413"},"422":{"$ref":"#/components/responses/Error422"},"429":{"$ref":"#/components/responses/Error429"},"500":{"$ref":"#/components/responses/Error500"},"502":{"$ref":"#/components/responses/Error502"},"503":{"$ref":"#/components/responses/Error503"},"504":{"$ref":"#/components/responses/Error504"}}},"get":{"operationId":"deviceLocaleGet","summary":"Read the locale","tags":["device"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"The phone's locale, as PUT /locale takes it.","headers":{"X-Request-Id":{"description":"This request's ID (req_…). Quote it when you contact support.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"type":"object","properties":{"locale":{"type":"string"}},"required":["locale"]}}}},"400":{"$ref":"#/components/responses/Error400"},"401":{"$ref":"#/components/responses/Error401"},"402":{"$ref":"#/components/responses/Error402"},"403":{"$ref":"#/components/responses/Error403"},"404":{"$ref":"#/components/responses/Error404"},"409":{"$ref":"#/components/responses/Error409"},"413":{"$ref":"#/components/responses/Error413"},"422":{"$ref":"#/components/responses/Error422"},"429":{"$ref":"#/components/responses/Error429"},"500":{"$ref":"#/components/responses/Error500"},"502":{"$ref":"#/components/responses/Error502"},"503":{"$ref":"#/components/responses/Error503"},"504":{"$ref":"#/components/responses/Error504"}}}},"/v1/phones/{id}/timezone":{"put":{"operationId":"deviceTimezone","summary":"Set the timezone","tags":["device"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"timezone":{"type":"string","description":"An IANA time zone, spelled exactly, such as Europe/Berlin or America/New_York."}},"required":["timezone"],"additionalProperties":false}}}},"responses":{"200":{"description":"The timezone is set.","headers":{"X-Request-Id":{"description":"This request's ID (req_…). Quote it when you contact support.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"type":"object","properties":{"timezone":{"type":"string"}},"required":["timezone"]}}}},"400":{"$ref":"#/components/responses/Error400"},"401":{"$ref":"#/components/responses/Error401"},"402":{"$ref":"#/components/responses/Error402"},"403":{"$ref":"#/components/responses/Error403"},"404":{"$ref":"#/components/responses/Error404"},"409":{"$ref":"#/components/responses/Error409"},"413":{"$ref":"#/components/responses/Error413"},"422":{"$ref":"#/components/responses/Error422"},"429":{"$ref":"#/components/responses/Error429"},"500":{"$ref":"#/components/responses/Error500"},"502":{"$ref":"#/components/responses/Error502"},"503":{"$ref":"#/components/responses/Error503"},"504":{"$ref":"#/components/responses/Error504"}}},"get":{"operationId":"deviceTimezoneGet","summary":"Read the timezone","tags":["device"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"The phone's timezone, or null while it uses its default.","headers":{"X-Request-Id":{"description":"This request's ID (req_…). Quote it when you contact support.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"type":"object","properties":{"timezone":{"description":"The IANA time zone, or null when the phone uses its default.","type":["string","null"]}},"required":["timezone"]}}}},"400":{"$ref":"#/components/responses/Error400"},"401":{"$ref":"#/components/responses/Error401"},"402":{"$ref":"#/components/responses/Error402"},"403":{"$ref":"#/components/responses/Error403"},"404":{"$ref":"#/components/responses/Error404"},"409":{"$ref":"#/components/responses/Error409"},"413":{"$ref":"#/components/responses/Error413"},"422":{"$ref":"#/components/responses/Error422"},"429":{"$ref":"#/components/responses/Error429"},"500":{"$ref":"#/components/responses/Error500"},"502":{"$ref":"#/components/responses/Error502"},"503":{"$ref":"#/components/responses/Error503"},"504":{"$ref":"#/components/responses/Error504"}}}},"/v1/phones/{id}/reboot":{"post":{"operationId":"deviceReboot","summary":"Reboot","tags":["device"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"202":{"description":"The phone is restarting; wait for ready. At most one reboot per 10 minutes.","headers":{"X-Request-Id":{"description":"This request's ID (req_…). Quote it when you contact support.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Phone"}}}},"400":{"$ref":"#/components/responses/Error400"},"401":{"$ref":"#/components/responses/Error401"},"402":{"$ref":"#/components/responses/Error402"},"403":{"$ref":"#/components/responses/Error403"},"404":{"$ref":"#/components/responses/Error404"},"409":{"$ref":"#/components/responses/Error409"},"413":{"$ref":"#/components/responses/Error413"},"422":{"$ref":"#/components/responses/Error422"},"429":{"$ref":"#/components/responses/Error429"},"500":{"$ref":"#/components/responses/Error500"},"502":{"$ref":"#/components/responses/Error502"},"503":{"$ref":"#/components/responses/Error503"},"504":{"$ref":"#/components/responses/Error504"}}}},"/v1/phones/{id}/device":{"get":{"operationId":"deviceInfo","summary":"Get device info","tags":["device"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"The phone's brand, model, Android version, screen and carrier. Nothing else about its hardware or identity is returned.","headers":{"X-Request-Id":{"description":"This request's ID (req_…). Quote it when you contact support.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"type":"object","properties":{"brand":{"type":["string","null"]},"model":{"type":["string","null"]},"android_version":{"description":"The Android version, such as 15.","type":["string","null"]},"screen":{"anyOf":[{"type":"object","properties":{"width":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"height":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"density":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}],"description":"Dots per inch."}},"required":["width","height","density"]},{"type":"null"}],"description":"The screen in device pixels."},"carrier":{"description":"The mobile carrier's name, when the phone reports one.","type":["string","null"]}},"required":["brand","model","android_version","screen","carrier"]}}}},"400":{"$ref":"#/components/responses/Error400"},"401":{"$ref":"#/components/responses/Error401"},"402":{"$ref":"#/components/responses/Error402"},"403":{"$ref":"#/components/responses/Error403"},"404":{"$ref":"#/components/responses/Error404"},"409":{"$ref":"#/components/responses/Error409"},"413":{"$ref":"#/components/responses/Error413"},"422":{"$ref":"#/components/responses/Error422"},"429":{"$ref":"#/components/responses/Error429"},"500":{"$ref":"#/components/responses/Error500"},"502":{"$ref":"#/components/responses/Error502"},"503":{"$ref":"#/components/responses/Error503"},"504":{"$ref":"#/components/responses/Error504"}}}},"/v1/phones/{id}/reset":{"post":{"operationId":"deviceReset","summary":"Reset","description":"Wipes the phone back to a clean state: installed apps and their data, files, signed-in accounts and the clipboard are deleted. The phone keeps its ID and session, goes to starting, and is billed as running time until it is ready again. Needs phones:delete. It is sent once and never retried.","tags":["device"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"202":{"description":"The phone is resetting; wait for ready. wiped lists what was deleted.","headers":{"X-Request-Id":{"description":"This request's ID (req_…). Quote it when you contact support.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"type":"object","properties":{"phone":{"type":"object","properties":{"id":{"type":"string","pattern":"^ph_[a-z2-7]{12}$"},"object":{"type":"string","const":"phone"},"name":{"type":"string"},"status":{"type":"string","enum":["creating","starting","ready","parking","parked","unavailable","failed","deleted"]},"country":{"type":["string","null"]},"metadata":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{"type":"string"}},"created_at":{"type":"string","format":"date-time","description":"ISO 8601 timestamp (UTC)"},"last_active_at":{"anyOf":[{"type":"string","format":"date-time","description":"ISO 8601 timestamp (UTC)"},{"type":"null"}]},"session":{"anyOf":[{"type":"object","properties":{"id":{"type":"string","pattern":"^ses_[a-z2-7]{12}$"},"started_at":{"type":"string","format":"date-time","description":"ISO 8601 timestamp (UTC)"},"ready_at":{"anyOf":[{"type":"string","format":"date-time","description":"ISO 8601 timestamp (UTC)"},{"type":"null"}]},"idle_timeout":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"max_duration":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"parks_at":{"type":"string","format":"date-time","description":"ISO 8601 timestamp (UTC)"},"park_reason":{"type":"string","enum":["idle","max_duration"]},"reserved_usd":{"type":"string","pattern":"^-?\\d+\\.\\d{6}$","description":"US dollars as a decimal string with six places, such as 0.060000"}},"required":["id","started_at","ready_at","idle_timeout","max_duration","parks_at","park_reason","reserved_usd"]},{"type":"null"}]},"failure":{"anyOf":[{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"at":{"type":"string","format":"date-time","description":"ISO 8601 timestamp (UTC)"}},"required":["code","message","at"]},{"type":"null"}]}},"required":["id","object","name","status","country","metadata","created_at","last_active_at","session","failure"],"description":"The phone, now starting: wait for ready before you use it."},"wiped":{"type":"array","items":{"type":"string","enum":["apps","files","accounts","clipboard"]},"description":"What the reset deleted: installed apps and their data, files, signed-in accounts and the clipboard."}},"required":["phone","wiped"]}}}},"400":{"$ref":"#/components/responses/Error400"},"401":{"$ref":"#/components/responses/Error401"},"402":{"$ref":"#/components/responses/Error402"},"403":{"$ref":"#/components/responses/Error403"},"404":{"$ref":"#/components/responses/Error404"},"409":{"$ref":"#/components/responses/Error409"},"413":{"$ref":"#/components/responses/Error413"},"422":{"$ref":"#/components/responses/Error422"},"429":{"$ref":"#/components/responses/Error429"},"500":{"$ref":"#/components/responses/Error500"},"502":{"$ref":"#/components/responses/Error502"},"503":{"$ref":"#/components/responses/Error503"},"504":{"$ref":"#/components/responses/Error504"}}}},"/v1/phones/{id}/recordings":{"post":{"operationId":"recordingsStart","summary":"Start a recording","description":"Starts recording the phone's screen. One recording runs at a time per phone; a project keeps at most 20, each deleted 7 days after it starts.","tags":["recordings"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"description":"A name to tell the recording apart, up to 80 characters.","type":"string","minLength":1,"maxLength":80}},"additionalProperties":false}}}},"responses":{"201":{"description":"The recording, now recording.","headers":{"X-Request-Id":{"description":"This request's ID (req_…). Quote it when you contact support.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Recording"}}}},"400":{"$ref":"#/components/responses/Error400"},"401":{"$ref":"#/components/responses/Error401"},"402":{"$ref":"#/components/responses/Error402"},"403":{"$ref":"#/components/responses/Error403"},"404":{"$ref":"#/components/responses/Error404"},"409":{"$ref":"#/components/responses/Error409"},"413":{"$ref":"#/components/responses/Error413"},"422":{"$ref":"#/components/responses/Error422"},"429":{"$ref":"#/components/responses/Error429"},"500":{"$ref":"#/components/responses/Error500"},"502":{"$ref":"#/components/responses/Error502"},"503":{"$ref":"#/components/responses/Error503"},"504":{"$ref":"#/components/responses/Error504"}}},"get":{"operationId":"recordingsList","summary":"List recordings","tags":["recordings"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"The phone's recordings, newest first.","headers":{"X-Request-Id":{"description":"This request's ID (req_…). Quote it when you contact support.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"object":{"type":"string","const":"recording"},"id":{"type":"string","pattern":"^rec_[a-z2-7]{12}$"},"phone":{"type":"string","pattern":"^ph_[a-z2-7]{12}$"},"name":{"type":["string","null"]},"status":{"type":"string","enum":["recording","processing","ready","failed"],"description":"recording, then processing once stopped, then ready to download; or failed."},"started_at":{"type":"string","format":"date-time","description":"ISO 8601 timestamp (UTC)"},"ended_at":{"anyOf":[{"type":"string","format":"date-time","description":"ISO 8601 timestamp (UTC)"},{"type":"null"}]},"duration_ms":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}]},"size_bytes":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}]},"expires_at":{"type":"string","format":"date-time","description":"When Phonebox deletes the recording: 7 days after it started."}},"required":["object","id","phone","name","status","started_at","ended_at","duration_ms","size_bytes","expires_at"]}}},"required":["data"]}}}},"400":{"$ref":"#/components/responses/Error400"},"401":{"$ref":"#/components/responses/Error401"},"402":{"$ref":"#/components/responses/Error402"},"403":{"$ref":"#/components/responses/Error403"},"404":{"$ref":"#/components/responses/Error404"},"409":{"$ref":"#/components/responses/Error409"},"413":{"$ref":"#/components/responses/Error413"},"422":{"$ref":"#/components/responses/Error422"},"429":{"$ref":"#/components/responses/Error429"},"500":{"$ref":"#/components/responses/Error500"},"502":{"$ref":"#/components/responses/Error502"},"503":{"$ref":"#/components/responses/Error503"},"504":{"$ref":"#/components/responses/Error504"}}}},"/v1/phones/{id}/recordings/{rid}/stop":{"post":{"operationId":"recordingsStop","summary":"Stop a recording","tags":["recordings"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"rid","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"The recording, stopped: processing until its video is ready. One already stopped is answered as it is.","headers":{"X-Request-Id":{"description":"This request's ID (req_…). Quote it when you contact support.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Recording"}}}},"400":{"$ref":"#/components/responses/Error400"},"401":{"$ref":"#/components/responses/Error401"},"402":{"$ref":"#/components/responses/Error402"},"403":{"$ref":"#/components/responses/Error403"},"404":{"$ref":"#/components/responses/Error404"},"409":{"$ref":"#/components/responses/Error409"},"413":{"$ref":"#/components/responses/Error413"},"422":{"$ref":"#/components/responses/Error422"},"429":{"$ref":"#/components/responses/Error429"},"500":{"$ref":"#/components/responses/Error500"},"502":{"$ref":"#/components/responses/Error502"},"503":{"$ref":"#/components/responses/Error503"},"504":{"$ref":"#/components/responses/Error504"}}}},"/v1/phones/{id}/recordings/{rid}/video":{"get":{"operationId":"recordingsVideo","summary":"Download a recording","tags":["recordings"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"rid","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"The recording's video.","headers":{"X-Request-Id":{"description":"This request's ID (req_…). Quote it when you contact support.","schema":{"type":"string"}},"Content-Disposition":{"description":"attachment, named after the recording's ID.","schema":{"type":"string"}}},"content":{"video/mp4":{"schema":{"type":"string","contentMediaType":"video/mp4"}}}},"400":{"$ref":"#/components/responses/Error400"},"401":{"$ref":"#/components/responses/Error401"},"402":{"$ref":"#/components/responses/Error402"},"403":{"$ref":"#/components/responses/Error403"},"404":{"$ref":"#/components/responses/Error404"},"409":{"$ref":"#/components/responses/Error409"},"413":{"$ref":"#/components/responses/Error413"},"422":{"$ref":"#/components/responses/Error422"},"429":{"$ref":"#/components/responses/Error429"},"500":{"$ref":"#/components/responses/Error500"},"502":{"$ref":"#/components/responses/Error502"},"503":{"$ref":"#/components/responses/Error503"},"504":{"$ref":"#/components/responses/Error504"}}}},"/v1/phones/{id}/recordings/{rid}":{"delete":{"operationId":"recordingsDelete","summary":"Delete a recording","description":"Deletes the recording and its video. A recording that is still running is stopped first; one on a phone that isn't running can't be, and answers recording_in_progress.","tags":["recordings"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"rid","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"The recording and its video were deleted.","headers":{"X-Request-Id":{"description":"This request's ID (req_…). Quote it when you contact support.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","pattern":"^rec_[a-z2-7]{12}$"},"deleted":{"type":"boolean","const":true}},"required":["id","deleted"]}}}},"400":{"$ref":"#/components/responses/Error400"},"401":{"$ref":"#/components/responses/Error401"},"402":{"$ref":"#/components/responses/Error402"},"403":{"$ref":"#/components/responses/Error403"},"404":{"$ref":"#/components/responses/Error404"},"409":{"$ref":"#/components/responses/Error409"},"413":{"$ref":"#/components/responses/Error413"},"422":{"$ref":"#/components/responses/Error422"},"429":{"$ref":"#/components/responses/Error429"},"500":{"$ref":"#/components/responses/Error500"},"502":{"$ref":"#/components/responses/Error502"},"503":{"$ref":"#/components/responses/Error503"},"504":{"$ref":"#/components/responses/Error504"}}}},"/v1/phones/{id}/live":{"post":{"operationId":"phoneLive","summary":"Create a live view link","tags":["phone"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"object","properties":{"expires_in":{"default":3600,"type":"integer","minimum":60,"maximum":86400}},"additionalProperties":false}}}},"responses":{"201":{"description":"A link to watch and control the phone. Anyone with it can control the phone.","headers":{"X-Request-Id":{"description":"This request's ID (req_…). Quote it when you contact support.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"type":"object","properties":{"url":{"type":"string","format":"uri"},"expires_at":{"type":"string","format":"date-time","description":"ISO 8601 timestamp (UTC)"}},"required":["url","expires_at"]}}}},"400":{"$ref":"#/components/responses/Error400"},"401":{"$ref":"#/components/responses/Error401"},"402":{"$ref":"#/components/responses/Error402"},"403":{"$ref":"#/components/responses/Error403"},"404":{"$ref":"#/components/responses/Error404"},"409":{"$ref":"#/components/responses/Error409"},"413":{"$ref":"#/components/responses/Error413"},"422":{"$ref":"#/components/responses/Error422"},"429":{"$ref":"#/components/responses/Error429"},"500":{"$ref":"#/components/responses/Error500"},"502":{"$ref":"#/components/responses/Error502"},"503":{"$ref":"#/components/responses/Error503"},"504":{"$ref":"#/components/responses/Error504"}}}},"/v1/apps/library":{"get":{"operationId":"appsLibrary","summary":"Search the app library","description":"Searches the apps a phone can install by package with POST /v1/phones/{id}/apps: the store's and the system's. Nothing here is from another account. Pages hold up to 50 apps.","tags":["apps"],"parameters":[{"name":"query","in":"query","schema":{"default":"","description":"Part of a package name or app name, such as WhatsApp. Leave it out to list the library.","type":"string","maxLength":100}},{"name":"cursor","in":"query","schema":{"description":"next_cursor from the page before, to read the next page.","type":"string","pattern":"^[1-9][0-9]{0,3}$"}}],"responses":{"200":{"description":"A page of installable apps.","headers":{"X-Request-Id":{"description":"This request's ID (req_…). Quote it when you contact support.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"package":{"type":"string","description":"The package to install with POST /v1/phones/{id}/apps."},"label":{"type":"string"},"version_code":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"version_name":{"type":"string"}},"required":["package","label","version_code","version_name"]}},"next_cursor":{"description":"Pass as cursor for the next page; null on the last page.","type":["string","null"]}},"required":["data","next_cursor"]}}}},"400":{"$ref":"#/components/responses/Error400"},"401":{"$ref":"#/components/responses/Error401"},"402":{"$ref":"#/components/responses/Error402"},"403":{"$ref":"#/components/responses/Error403"},"404":{"$ref":"#/components/responses/Error404"},"409":{"$ref":"#/components/responses/Error409"},"413":{"$ref":"#/components/responses/Error413"},"422":{"$ref":"#/components/responses/Error422"},"429":{"$ref":"#/components/responses/Error429"},"500":{"$ref":"#/components/responses/Error500"},"502":{"$ref":"#/components/responses/Error502"},"503":{"$ref":"#/components/responses/Error503"},"504":{"$ref":"#/components/responses/Error504"}}}},"/v1/apps/uploads":{"post":{"operationId":"uploadsCreate","summary":"Create an upload","description":"Creates an upload of your own APK and a one-off URL for its file: POST the APK's bytes there with upload_headers within an hour, then complete the upload with the storageId it answers. At most 500 MiB a file and 500 MiB of uploads per project, and 50 new uploads a day; the project needs credits. Completing with a file the project already has ready answers with that upload.","tags":["uploads"],"parameters":[],"requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"object","properties":{},"additionalProperties":false}}}},"responses":{"201":{"description":"The upload, waiting for its file, with where to send it.","headers":{"X-Request-Id":{"description":"This request's ID (req_…). Quote it when you contact support.","schema":{"type":"string"}},"Location":{"description":"The upload's path, /v1/apps/uploads/{id}.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"type":"object","properties":{"object":{"type":"string","const":"upload"},"id":{"type":"string","pattern":"^upl_[a-z2-7]{12}$"},"status":{"type":"string","enum":["awaiting_file","processing","ready","invalid_apk","too_large","storage_full","failed","duplicate","deleted"]},"package":{"description":"The package the APK's manifest declares, once read.","type":["string","null"]},"version_code":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}]},"version_name":{"type":["string","null"]},"min_sdk":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}]},"size_bytes":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}]},"sha256":{"anyOf":[{"type":"string","pattern":"^[0-9a-f]{64}$"},{"type":"null"}],"description":"The file's SHA-256, in hex."},"created_at":{"type":"string","format":"date-time","description":"ISO 8601 timestamp (UTC)"},"expires_at":{"type":"string","format":"date-time","description":"When Phonebox deletes the upload: 7 days after its last install, or its creation if never installed; an hour after creation while it waits for its file."},"error":{"anyOf":[{"type":"object","properties":{"code":{"type":"string","enum":["validation_failed","invalid_request","invalid_api_key","key_expired","key_revoked","unauthorized","insufficient_credits","spend_limit_reached","project_frozen","insufficient_scope","phone_not_allowed","browser_requests_not_allowed","setup_denied","not_found","phone_not_found","file_not_found","app_not_found","upload_not_found","recording_not_found","method_not_allowed","phone_not_running","phone_starting","phone_parking","phone_deleted","phone_failed","idempotency_conflict","running_limit_reached","phone_limit_reached","install_in_progress","version_downgrade","upload_not_ready","storage_limit_reached","clipboard_unavailable","recording_in_progress","recording_not_ready","recording_limit_reached","duplicate_upload","setup_expired","setup_used","key_limit","payload_too_large","target_not_found","ambiguous_target","stale_snapshot","no_focused_field","wait_timeout","app_not_available","invalid_apk","install_failed","feature_unavailable","rate_limited","provider_error","action_outcome_unknown","upload_failed","capacity_unavailable","phone_unavailable","service_paused","storage_full","billing_not_configured","platform_not_configured","provider_timeout","internal_error"]},"message":{"type":"string"},"next":{"type":["string","null"]}},"required":["code","message","next"]},{"type":"null"}],"description":"Why the upload ended without becoming ready."},"upload_url":{"type":"string","format":"uri","description":"Send the APK's bytes here with upload_method and upload_headers, within an hour. The answer is {\"storageId\": \"…\"}."},"upload_method":{"type":"string","const":"POST"},"upload_headers":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{"type":"string"}},"max_bytes":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["object","id","status","package","version_code","version_name","min_sdk","size_bytes","sha256","created_at","expires_at","error","upload_url","upload_method","upload_headers","max_bytes"]}}}},"400":{"$ref":"#/components/responses/Error400"},"401":{"$ref":"#/components/responses/Error401"},"402":{"$ref":"#/components/responses/Error402"},"403":{"$ref":"#/components/responses/Error403"},"404":{"$ref":"#/components/responses/Error404"},"409":{"$ref":"#/components/responses/Error409"},"413":{"$ref":"#/components/responses/Error413"},"422":{"$ref":"#/components/responses/Error422"},"429":{"$ref":"#/components/responses/Error429"},"500":{"$ref":"#/components/responses/Error500"},"502":{"$ref":"#/components/responses/Error502"},"503":{"$ref":"#/components/responses/Error503"},"504":{"$ref":"#/components/responses/Error504"}}},"get":{"operationId":"uploadsList","summary":"List uploads","tags":["uploads"],"parameters":[{"name":"limit","in":"query","schema":{"default":50,"type":"integer","minimum":1,"maximum":100}},{"name":"cursor","in":"query","schema":{"type":"string","maxLength":500}}],"responses":{"200":{"description":"The project's uploads, newest first, without deleted ones.","headers":{"X-Request-Id":{"description":"This request's ID (req_…). Quote it when you contact support.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"object":{"type":"string","const":"upload"},"id":{"type":"string","pattern":"^upl_[a-z2-7]{12}$"},"status":{"type":"string","enum":["awaiting_file","processing","ready","invalid_apk","too_large","storage_full","failed","duplicate","deleted"]},"package":{"description":"The package the APK's manifest declares, once read.","type":["string","null"]},"version_code":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}]},"version_name":{"type":["string","null"]},"min_sdk":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}]},"size_bytes":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}]},"sha256":{"anyOf":[{"type":"string","pattern":"^[0-9a-f]{64}$"},{"type":"null"}],"description":"The file's SHA-256, in hex."},"created_at":{"type":"string","format":"date-time","description":"ISO 8601 timestamp (UTC)"},"expires_at":{"type":"string","format":"date-time","description":"When Phonebox deletes the upload: 7 days after its last install, or its creation if never installed; an hour after creation while it waits for its file."},"error":{"anyOf":[{"type":"object","properties":{"code":{"type":"string","enum":["validation_failed","invalid_request","invalid_api_key","key_expired","key_revoked","unauthorized","insufficient_credits","spend_limit_reached","project_frozen","insufficient_scope","phone_not_allowed","browser_requests_not_allowed","setup_denied","not_found","phone_not_found","file_not_found","app_not_found","upload_not_found","recording_not_found","method_not_allowed","phone_not_running","phone_starting","phone_parking","phone_deleted","phone_failed","idempotency_conflict","running_limit_reached","phone_limit_reached","install_in_progress","version_downgrade","upload_not_ready","storage_limit_reached","clipboard_unavailable","recording_in_progress","recording_not_ready","recording_limit_reached","duplicate_upload","setup_expired","setup_used","key_limit","payload_too_large","target_not_found","ambiguous_target","stale_snapshot","no_focused_field","wait_timeout","app_not_available","invalid_apk","install_failed","feature_unavailable","rate_limited","provider_error","action_outcome_unknown","upload_failed","capacity_unavailable","phone_unavailable","service_paused","storage_full","billing_not_configured","platform_not_configured","provider_timeout","internal_error"]},"message":{"type":"string"},"next":{"type":["string","null"]}},"required":["code","message","next"]},{"type":"null"}],"description":"Why the upload ended without becoming ready."}},"required":["object","id","status","package","version_code","version_name","min_sdk","size_bytes","sha256","created_at","expires_at","error"]}},"next_cursor":{"description":"Pass as cursor for the next page; null on the last page.","type":["string","null"]}},"required":["data","next_cursor"]}}}},"400":{"$ref":"#/components/responses/Error400"},"401":{"$ref":"#/components/responses/Error401"},"402":{"$ref":"#/components/responses/Error402"},"403":{"$ref":"#/components/responses/Error403"},"404":{"$ref":"#/components/responses/Error404"},"409":{"$ref":"#/components/responses/Error409"},"413":{"$ref":"#/components/responses/Error413"},"422":{"$ref":"#/components/responses/Error422"},"429":{"$ref":"#/components/responses/Error429"},"500":{"$ref":"#/components/responses/Error500"},"502":{"$ref":"#/components/responses/Error502"},"503":{"$ref":"#/components/responses/Error503"},"504":{"$ref":"#/components/responses/Error504"}}}},"/v1/apps/uploads/{id}":{"get":{"operationId":"uploadsGet","summary":"Get an upload","tags":["uploads"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"wait","in":"query","schema":{"description":"ready: wait until the upload is processed, or has failed.","type":"string","enum":["ready"]}},{"name":"timeout","in":"query","schema":{"default":50,"type":"integer","minimum":1,"maximum":55}}],"responses":{"200":{"description":"The upload. With wait=ready, long-polls up to timeout seconds while it is processing, and answers at once in any other status. Poll again only while it is processing.","headers":{"X-Request-Id":{"description":"This request's ID (req_…). Quote it when you contact support.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Upload"}}}},"400":{"$ref":"#/components/responses/Error400"},"401":{"$ref":"#/components/responses/Error401"},"402":{"$ref":"#/components/responses/Error402"},"403":{"$ref":"#/components/responses/Error403"},"404":{"$ref":"#/components/responses/Error404"},"409":{"$ref":"#/components/responses/Error409"},"413":{"$ref":"#/components/responses/Error413"},"422":{"$ref":"#/components/responses/Error422"},"429":{"$ref":"#/components/responses/Error429"},"500":{"$ref":"#/components/responses/Error500"},"502":{"$ref":"#/components/responses/Error502"},"503":{"$ref":"#/components/responses/Error503"},"504":{"$ref":"#/components/responses/Error504"}}},"delete":{"operationId":"uploadsDelete","summary":"Delete an upload","tags":["uploads"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"The deleted upload. Apps installed from it stay on their phones.","headers":{"X-Request-Id":{"description":"This request's ID (req_…). Quote it when you contact support.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Upload"}}}},"400":{"$ref":"#/components/responses/Error400"},"401":{"$ref":"#/components/responses/Error401"},"402":{"$ref":"#/components/responses/Error402"},"403":{"$ref":"#/components/responses/Error403"},"404":{"$ref":"#/components/responses/Error404"},"409":{"$ref":"#/components/responses/Error409"},"413":{"$ref":"#/components/responses/Error413"},"422":{"$ref":"#/components/responses/Error422"},"429":{"$ref":"#/components/responses/Error429"},"500":{"$ref":"#/components/responses/Error500"},"502":{"$ref":"#/components/responses/Error502"},"503":{"$ref":"#/components/responses/Error503"},"504":{"$ref":"#/components/responses/Error504"}}}},"/v1/apps/uploads/{id}/complete":{"post":{"operationId":"uploadsComplete","summary":"Complete an upload","tags":["uploads"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"storage_id":{"description":"The storageId the upload URL answered with, as {\"storageId\": \"…\"}.","type":"string","minLength":1,"maxLength":128,"pattern":"^[\\w;:-]+$"},"storageId":{"description":"The same, named as the upload URL answers it, so its answer can be sent on as it is.","type":"string","minLength":1,"maxLength":128,"pattern":"^[\\w;:-]+$"}},"additionalProperties":false}}}},"responses":{"200":{"description":"The file is one the project already has ready: the answer is that ready upload, another ID, so install it; this upload becomes a duplicate naming it. Otherwise the upload as it is: it had already been completed with this file, or its file is over the size limit (too_large).","headers":{"X-Request-Id":{"description":"This request's ID (req_…). Quote it when you contact support.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Upload"}}}},"202":{"description":"The file arrived: the upload is processing. Wait with GET /v1/apps/uploads/{id}?wait=ready.","headers":{"X-Request-Id":{"description":"This request's ID (req_…). Quote it when you contact support.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Upload"}}}},"400":{"$ref":"#/components/responses/Error400"},"401":{"$ref":"#/components/responses/Error401"},"402":{"$ref":"#/components/responses/Error402"},"403":{"$ref":"#/components/responses/Error403"},"404":{"$ref":"#/components/responses/Error404"},"409":{"$ref":"#/components/responses/Error409"},"413":{"$ref":"#/components/responses/Error413"},"422":{"$ref":"#/components/responses/Error422"},"429":{"$ref":"#/components/responses/Error429"},"500":{"$ref":"#/components/responses/Error500"},"502":{"$ref":"#/components/responses/Error502"},"503":{"$ref":"#/components/responses/Error503"},"504":{"$ref":"#/components/responses/Error504"}}}},"/v1/account":{"get":{"operationId":"accountGet","summary":"Get the account","tags":["account"],"parameters":[],"responses":{"200":{"description":"Balance, limits, price, and the countries a phone can be created in.","headers":{"X-Request-Id":{"description":"This request's ID (req_…). Quote it when you contact support.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"type":"object","properties":{"project":{"type":"string"},"balance_usd":{"type":"string","pattern":"^-?\\d+\\.\\d{6}$","description":"US dollars as a decimal string with six places, such as 0.060000"},"reserved_usd":{"type":"string","pattern":"^-?\\d+\\.\\d{6}$","description":"US dollars as a decimal string with six places, such as 0.060000"},"spend_limit_usd":{"type":"string","pattern":"^-?\\d+\\.\\d{6}$","description":"US dollars as a decimal string with six places, such as 0.060000"},"spent_this_month_usd":{"type":"string","pattern":"^-?\\d+\\.\\d{6}$","description":"US dollars as a decimal string with six places, such as 0.060000"},"limits":{"type":"object","properties":{"phones":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"running":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["phones","running"]},"running":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Phones with an open session: creating, starting or ready."},"phones":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Phones that count toward the phone limit: every phone that isn't deleted or failed. A key limited to certain phones counts only those."},"price":{"type":"object","properties":{"per_minute_usd":{"type":"string","pattern":"^-?\\d+\\.\\d{6}$","description":"US dollars as a decimal string with six places, such as 0.060000"},"minimum_seconds":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["per_minute_usd","minimum_seconds"]},"countries":{"type":"array","items":{"type":"object","properties":{"code":{"type":"string"},"name":{"type":"string"}},"required":["code","name"]},"description":"The countries a phone can be created in, sorted by name: pass a code as country when you create one."}},"required":["project","balance_usd","reserved_usd","spend_limit_usd","spent_this_month_usd","limits","running","phones","price","countries"]}}}},"400":{"$ref":"#/components/responses/Error400"},"401":{"$ref":"#/components/responses/Error401"},"402":{"$ref":"#/components/responses/Error402"},"403":{"$ref":"#/components/responses/Error403"},"404":{"$ref":"#/components/responses/Error404"},"409":{"$ref":"#/components/responses/Error409"},"413":{"$ref":"#/components/responses/Error413"},"422":{"$ref":"#/components/responses/Error422"},"429":{"$ref":"#/components/responses/Error429"},"500":{"$ref":"#/components/responses/Error500"},"502":{"$ref":"#/components/responses/Error502"},"503":{"$ref":"#/components/responses/Error503"},"504":{"$ref":"#/components/responses/Error504"}}}},"/v1/credits/checkout":{"post":{"operationId":"creditsCheckout","summary":"Create a checkout link","description":"Creates a checkout page where a person buys credits for the key's project. The credit arrives once the payment does: poll GET /v1/account until balance_usd shows it. Needs phones:control. At most 10 an hour per project.","tags":["credits"],"parameters":[],"requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"object","properties":{"amount_usd":{"default":10,"description":"The credit to buy, in whole US dollars.","type":"integer","minimum":10,"maximum":1000}},"additionalProperties":false}}}},"responses":{"201":{"description":"The checkout page's link, and the credit it buys.","headers":{"X-Request-Id":{"description":"This request's ID (req_…). Quote it when you contact support.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"type":"object","properties":{"url":{"type":"string","format":"uri","description":"The checkout page. Give it to a person: it takes the payment and adds the credit to the key's project."},"amount_usd":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"The credit this checkout buys, in whole US dollars, before tax and any discount."}},"required":["url","amount_usd"]}}}},"400":{"$ref":"#/components/responses/Error400"},"401":{"$ref":"#/components/responses/Error401"},"402":{"$ref":"#/components/responses/Error402"},"403":{"$ref":"#/components/responses/Error403"},"404":{"$ref":"#/components/responses/Error404"},"409":{"$ref":"#/components/responses/Error409"},"413":{"$ref":"#/components/responses/Error413"},"422":{"$ref":"#/components/responses/Error422"},"429":{"$ref":"#/components/responses/Error429"},"500":{"$ref":"#/components/responses/Error500"},"502":{"$ref":"#/components/responses/Error502"},"503":{"$ref":"#/components/responses/Error503"},"504":{"$ref":"#/components/responses/Error504"}}}},"/v1/setup":{"post":{"operationId":"setupStart","summary":"Start terminal setup","security":[],"description":"Starts a setup request for a terminal or an agent that has no API key yet. Keep setup_token secret, show the person verification_url and user_code, and poll POST /v1/setup/token every interval seconds. At most 10 a minute per IP address.","tags":["setup"],"parameters":[],"requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"object","properties":{"client":{"type":"string","minLength":1,"maxLength":60,"pattern":"^[\\x20-\\x7E]+$"}},"additionalProperties":false}}}},"responses":{"201":{"description":"The request. It can be confirmed for expires_in seconds.","headers":{"X-Request-Id":{"description":"This request's ID (req_…). Quote it when you contact support.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"type":"object","properties":{"setup_token":{"type":"string","pattern":"^pbs_[A-Za-z0-9_-]{43}$","description":"The terminal's secret: send it to POST /v1/setup/token. Never show it."},"user_code":{"type":"string","pattern":"^[A-HJKMNP-Z2-9]{4}-[A-HJKMNP-Z2-9]{4}$","description":"The code the person checks against their terminal."},"verification_url":{"type":"string","format":"uri","description":"Where the person signs in and confirms the code."},"expires_in":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Seconds until the request can no longer be confirmed."},"interval":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Seconds to wait between polls of POST /v1/setup/token."}},"required":["setup_token","user_code","verification_url","expires_in","interval"]}}}},"400":{"$ref":"#/components/responses/Error400"},"401":{"$ref":"#/components/responses/Error401"},"402":{"$ref":"#/components/responses/Error402"},"403":{"$ref":"#/components/responses/Error403"},"404":{"$ref":"#/components/responses/Error404"},"409":{"$ref":"#/components/responses/Error409"},"413":{"$ref":"#/components/responses/Error413"},"422":{"$ref":"#/components/responses/Error422"},"429":{"$ref":"#/components/responses/Error429"},"500":{"$ref":"#/components/responses/Error500"},"502":{"$ref":"#/components/responses/Error502"},"503":{"$ref":"#/components/responses/Error503"},"504":{"$ref":"#/components/responses/Error504"}}}},"/v1/setup/token":{"post":{"operationId":"setupToken","summary":"Poll terminal setup","security":[],"description":"Asks whether the person has confirmed the setup request. It answers approved once, with a new agent key that is listed and revocable in the console; a later poll fails with setup_used. At most 60 a minute per token.","tags":["setup"],"parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"setup_token":{"type":"string","pattern":"^pbs_[A-Za-z0-9_-]{43}$"}},"required":["setup_token"],"additionalProperties":false}}}},"responses":{"200":{"description":"pending until the person confirms the code; then approved, with the key and its project's name.","headers":{"X-Request-Id":{"description":"This request's ID (req_…). Quote it when you contact support.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"status":{"type":"string","const":"pending"}},"required":["status"]},{"type":"object","properties":{"status":{"type":"string","const":"approved"},"api_key":{"type":"string","pattern":"^pbx_[A-Za-z0-9_-]{43}$","description":"The new agent key. It is sent once: store it now."},"project":{"type":"string","description":"The name of the project the key belongs to."}},"required":["status","api_key","project"]}]}}}},"400":{"$ref":"#/components/responses/Error400"},"401":{"$ref":"#/components/responses/Error401"},"402":{"$ref":"#/components/responses/Error402"},"403":{"$ref":"#/components/responses/Error403"},"404":{"$ref":"#/components/responses/Error404"},"409":{"$ref":"#/components/responses/Error409"},"413":{"$ref":"#/components/responses/Error413"},"422":{"$ref":"#/components/responses/Error422"},"429":{"$ref":"#/components/responses/Error429"},"500":{"$ref":"#/components/responses/Error500"},"502":{"$ref":"#/components/responses/Error502"},"503":{"$ref":"#/components/responses/Error503"},"504":{"$ref":"#/components/responses/Error504"}}}}}}