Эндпоинты телефонов
Все эндпоинты /v1/phones для облачных телефонов, приложений, экрана в реальном времени, прямого управления и запусков агента — с параметрами, лимитами, ответами и ошибками.
API облачных телефонов находится по адресу https://lovelyrouter.com/v1/phones. Аутентифицируйте каждый запрос своим API-ключом в заголовке Authorization: Bearer $LOVELY_API_KEY (Аутентификация). Тела запросов передаются в JSON, кроме загрузки APK и скриншотов. Телефон стоит $1.20 за час активной работы, с поминутной оплатой с предоплаченного баланса; см. сколько стоит телефон.
Пошаговое описание смотрите в обзоре облачных телефонов. Координаты везде задаются в пикселях скриншота, короткая сторона которого — 540 пикселей: 540×1200 в вертикальном положении, 1200×540, когда телефон повёрнут горизонтально (игра, видео). Какой из вариантов сейчас, показывают width и height скриншота.
Объект телефона#
Атрибуты
idstringph_ и 20 символов.
objectstringВсегда phone.
statusstringstarting (около минуты, дольше, пока устанавливаются стартовые приложения), ready, failed или deleted.
namestring | nullВаша метка.
userstring | nullId вашего конечного пользователя, если вы его задали.
metadataobject | nullДанные, которые вы сохранили вместе с телефоном.
startup_appsarrayПо одной записи на каждое приложение из apps: source, status (pending, installed или failed), packages (имена установленных пакетов) и error.
created_atready_atВремя в секундах Unix.
deletes_after_idle_atinteger | nullКогда телефон будет удалён, если до этого им не воспользуются (через 1 час после последней активности).
awake_secondsintegerОплаченное на данный момент время активной работы.
charge_usdnumberСколько телефон стоил на данный момент.
end_reasonstring | nullПочему он был удалён: deleted (вами), idle, balance или failed.
errorstring | nullПочему он не запустился.
Создание телефона#
/v1/phonesСоздаёт телефон и, пока он запускается, возвращает 201 с объектом телефона. Следите за ним через Получение телефона с wait. На балансе должно хватать на 15 минут работы телефона. У каждого аккаунта одновременно может быть 3 телефона.
Параметры тела запроса
appsarray of stringsДо 20 приложений, которые нужно установить до перехода телефона в ready: ссылки https:// на файлы .apk, .apks или .xapk либо имена загруженных APK. Неудачная установка не приводит к сбою телефона; проверяйте startup_apps.
namestringМетка, до 80 символов.
userstringId вашего конечного пользователя (до 200 символов), чтобы выводить его телефоны через GET /v1/phones?user=.
metadataobjectДо 4 КБ ваших собственных данных.
waitintegerСколько секунд удерживать запрос, пока телефон не будет готов, до 50.
curl https://lovelyrouter.com/v1/phones \
-H "Authorization: Bearer $LOVELY_API_KEY" \
-H "content-type: application/json" \
-d '{"apps": ["https://f-droid.org/F-Droid.apk"], "wait": 50}'{
"id": "ph_2758eedebf08496f87e0",
"object": "phone",
"status": "starting",
"name": null,
"user": null,
"metadata": null,
"startup_apps": [{ "source": "https://f-droid.org/F-Droid.apk", "status": "pending" }],
"created_at": 1793308400,
"ready_at": null,
"last_active_at": 1793308400,
"deletes_after_idle_at": 1793312000,
"awake_seconds": 0,
"charge_usd": 0,
"deleted_at": null,
"end_reason": null,
"error": null,
"price_per_hour_usd": 1.20
}Получение телефона#
/v1/phones/{id}Возвращает объект телефона. С wait (в секундах, до 50) запрос к телефону в статусе starting удерживается, пока тот не будет готов.
Список телефонов#
/v1/phonesВозвращает {"object": "list", "data": [phone, …]}, сначала новые. user= оставляет телефоны одного конечного пользователя; all=1 включает удалённые.
Удаление телефона#
/v1/phones/{id}Удаляет телефон вместе с его приложениями и данными, останавливает его запуск и рассчитывает последние минуты. Возвращает объект телефона со статусом deleted. Телефон также удаляется сам через 1 час без активности.
Получение скриншота#
/v1/phones/{id}/screenshotВозвращает текущий экран как изображение WebP (image/webp, 540 пикселей по короткой стороне). С format=json возвращает {screenshot, width, height, app, elements} с изображением в base64.
curl https://lovelyrouter.com/v1/phones/ph_2758eedebf08496f87e0/screenshot \
-H "Authorization: Bearer $LOVELY_API_KEY" -o screen.webpСписок элементов#
/v1/phones/{id}/elementsЧто находится на экране, по дереву представлений Android: {"app", "activity", "width", "height", "data": [element, …]}. У каждого элемента есть id, type (Button, EditText, TextView…), text, desc (метка специальных возможностей), resource (id представления), x и y (его центр), w и h, а также flags (clickable, long-clickable, scrollable, editable, checked/unchecked, focused, selected, password, disabled). На экранах, отрисованных без представлений (игры, некоторые canvas), элементов мало: используйте скриншот.
Отправка действия#
/v1/phones/{id}/actionsВыполняет одно действие на телефоне и возвращает {"ok": true} (или ok: false с error). Добавьте "screenshot": true, чтобы получить screenshot (WebP в base64) после того, как экран успокоится. Возвращает 409, пока телефоном управляет запуск агента.
Действия
{"action": "tap", "x", "y"}Нажать на точку.
{"action": "long_press", "x", "y", "ms"?}Нажать и удерживать (по умолчанию 800 мс).
{"action": "swipe", "x", "y", "to_x", "to_y", "ms"?}Провести от одной точки к другой (по умолчанию 300 мс).
{"action": "scroll", "direction", "x"?, "y"?}up, down, left или right; down показывает то, что ниже. В заданной точке или в центре экрана.
{"action": "type", "text", "clear"?, "submit"?}Ввести текст в поле с фокусом, на любом языке. clear сначала очищает поле; submit затем нажимает Enter.
{"action": "key", "key"}back, home, enter, recents, delete, tab, escape, search, menu, power, volume_up, volume_down или wakeup.
{"action": "open_url", "url"}Открыть ссылку: веб-страницу в Chrome или ссылку на приложение (market://, собственная схема приложения).
{"action": "launch", "package"}Открыть установленное приложение, например org.fdroid.fdroid.
{"action": "stop_app", "package"}Принудительно остановить приложение.
{"action": "wait", "seconds"}До 60 секунд.
{"action": "rotate", "orientation"}Повернуть телефон: portrait или landscape. Приложение, зафиксированное в одной ориентации (многие игры), её сохраняет. Экран в реальном времени поворачивается следом.
{"action": "shell", "command"}Команда adb shell на телефоне; в ответе есть output.
curl https://lovelyrouter.com/v1/phones/ph_2758eedebf08496f87e0/actions \
-H "Authorization: Bearer $LOVELY_API_KEY" \
-H "content-type: application/json" \
-d '{"action": "type", "text": "天气 Tokyo", "submit": true}'Получение ссылки на экран в реальном времени#
/v1/phones/{id}/screenВозвращает {"url", "expires_at"}: страницу с экраном телефона в реальном времени. Любой, у кого есть ссылка, может смотреть на телефон и управлять им мышью и клавиатурой, поэтому передавайте её только тому, кто должен им пользоваться. Страницу можно встроить в iframe.
Параметры тела запроса
ttl_secondsintegerПо умолчанию 3600Сколько действует ссылка: от 60 до 86 400. Уже открытый экран продолжает работать.
view_onlybooleanОткрывает страницу в режиме только просмотра. Это настройка отображения, а не разрешение: зритель может её отключить.
Установка приложения#
/v1/phones/{id}/appsСкачивает и устанавливает приложение и отвечает, когда всё готово: {"ok", "packages", "error"} (422, если установка не удалась). Установка уже имеющегося приложения обновляет его.
Параметры тела запроса
urlstringСсылка https:// на файл .apk, .apks или .xapk.
apkstringИли имя загруженного APK.
GET /v1/phones/{id}/apps выводит имена пакетов установленных приложений, а DELETE /v1/phones/{id}/apps/{package} удаляет одно из них.
Загрузка APK#
/v1/phones/apks/{name}Сохраняет APK, чтобы его можно было установить на любой телефон по name (буквы, цифры, _, ., -; до 80 символов). Отправьте файл телом запроса, до 100 МБ; файл побольше (до 500 МБ) загружайте частями. Подходят файлы .apk, .apks и .xapk; игровые данные .xapk (файлы OBB) копируются на телефон при установке. Загрузка под тем же именем заменяет файл. Возвращает 201 с {name, bytes, sha256}. Каждый аккаунт может хранить 50 файлов, а хранение сверх 1 ГБ оплачивается.
GET /v1/phones/apks выводит их список, а DELETE /v1/phones/apks/{name} удаляет один из них.
curl -X PUT https://lovelyrouter.com/v1/phones/apks/myapp.apk \
-H "Authorization: Bearer $LOVELY_API_KEY" \
--data-binary @myapp.apkЗагрузка большого APK#
/v1/phones/apks/{name}/uploadsФайл больше 100 МБ, до 500 МБ, загружайте частями. Начните с указания размера файла, отправьте каждую часть, затем завершите загрузку. Результат тот же, что и при Загрузке APK: файл сохраняется под name и заменяет файл с таким именем.
Параметры тела запроса
bytesintegerОбязательноРазмер файла в байтах, до 524 288 000 (500 МБ).
Возвращается 201 с {id, part_size, parts, parts_done, expires_at}. Затем:
PUT /v1/phones/apks/{name}/uploads/{id}/{n}для каждой частиnот 1 доparts, с байтами файла начиная с(n-1) × part_sizeв теле. Каждая часть занимаетpart_sizeбайт (50 МБ), кроме последней, в которой остаток. Части можно отправлять в любом порядке или одновременно, а повторно отправленная часть заменяет предыдущую.POST /v1/phones/apks/{name}/uploads/{id}/completeобъединяет части и возвращает201с{name, bytes, sha256}или409со списком ещё не полученных частей.
GET /v1/phones/apks/{name}/uploads/{id} показывает, какие части пришли (parts_done), а DELETE по этому адресу отменяет загрузку. Загрузка, не завершённая в течение 24 часов, отбрасывается.
Хранение#
Первый 1 ГБ загруженных APK хранится бесплатно. Сверх этого хранение стоит $0.30 за ГБ в месяц и списывается с баланса каждый час. Удаляйте ненужные APK через DELETE /v1/phones/apks/{name}. Для загрузки баланс должен быть больше нуля.
# 120 MB file: 3 parts
curl https://lovelyrouter.com/v1/phones/apks/game.xapk/uploads \
-H "Authorization: Bearer $LOVELY_API_KEY" \
-H "content-type: application/json" \
-d "{\"bytes\": $(stat -c %s game.xapk)}"
split -b 50M -d -a 2 game.xapk part.
for n in 1 2 3; do
curl -X PUT https://lovelyrouter.com/v1/phones/apks/game.xapk/uploads/upl_.../$n \
-H "Authorization: Bearer $LOVELY_API_KEY" \
--data-binary @part.0$((n-1))
done
curl -X POST https://lovelyrouter.com/v1/phones/apks/game.xapk/uploads/upl_.../complete \
-H "Authorization: Bearer $LOVELY_API_KEY"Объект запуска#
Атрибуты
idstringprun_ и 20 символов.
objectstringВсегда phone.run.
phone_idstringТелефон, на котором выполняется запуск.
statusstringqueued (телефон запускается), running, waiting (агент задал вам вопрос), succeeded, failed или stopped (вами или по достижении max_steps).
goalmodelТо, что вы отправили.
stepsintegerЧисло шагов на данный момент.
questionstring | nullВо время waiting: что агенту нужно от вас.
answerstring | nullРезультат, когда запуск завершён.
errorstring | nullПочему запуск завершился сбоем или был остановлен.
llm_usdnumberСтоимость токенов модели (задаётся по окончании запуска).
tracearrayС trace=1: для каждого шага step, note (что агент увидел и почему так поступил), action, args, app, ok, error и ms, а также unchanged: true, если действие оставило экран в точности прежним.
Запуск агента#
/v1/phones/runsСоздаёт телефон и запускает на нём агента или запускает его на одном из ваших телефонов, указанном в phone_id. Возвращает 202 с объектом запуска. Телефон выполняет одну цель за раз: 409, пока на нём активен другой запуск.
Параметры тела запроса
goalstringОбязательноЧто сделать, простыми словами, со всеми значениями, которые нужны для задачи. До 10 000 символов.
phone_idstringВыполнить на этом телефоне вместо нового. POST /v1/phones/{id}/runs делает то же самое.
appsnameДля нового телефона, как в Создании телефона.
modestringПо умолчанию smartsmart: модель решает каждый шаг (по несколько секунд на шаг). fast: быстрая модель принятия решений выбирает почти каждый шаг гораздо быстрее секунды (она всегда действует, что подходит для игр), а model только пишет ответ или вопрос для вас. См. Быстрый режим.
planbooleanПо умолчанию trueТолько в быстром режиме: рядом с быстрой моделью работает модель-тренер (входит в цену телефона). Она пишет короткую стратегию для цели (для игры — какие ходы предпочитать) и заметку о текущей ситуации и переписывает их каждые несколько шагов или когда запуск, похоже, застрял. Быстрая модель никогда её не ждёт: на каждом шаге используется последняя версия. Запуск показывает их в strategy, situation и sidecar_updates.
modelstringПо умолчанию gemini-3.8-flashЛюбая модель чата из GET /v1/models. Её токены оплачиваются по обычной цене.
max_stepsintegerПо умолчанию 40От 1 до 200. Запуск, достигший этого предела, завершается как stopped с error reached the step limit (N).
waitintegerСколько секунд удерживать запрос, пока запуск не завершится или не задаст вопрос, до 50.
Получение запуска#
/v1/phones/runs/{id}Возвращает объект запуска. wait (до 50 секунд) удерживает запрос, пока запуск не завершится или не задаст вам вопрос; trace=1 добавляет шаги, а after_step=N дополнительно отвечает, как только у запуска станет больше N шагов. GET /v1/phones/runs?phone_id= выводит запуски, сначала новые.
Ответ на вопрос запуска#
/v1/phones/runs/{id}/replyОтвечает на question запуска через {"answer": "…"}; запуск продолжается. Возвращает 409, если запуск не ожидает ответа.
Остановка запуска#
/v1/phones/runs/{id}/stopОстанавливает запуск после текущего шага. Телефон остаётся.
Ошибки#
| Статус | Когда | | - | - | | 400 | Поле отсутствует или указано неверно; в сообщении сказано, какое именно. | | 402 | Баланса не хватает для запуска телефона, или он исчерпан. | | 404 | В вашем аккаунте нет такого телефона, запуска или APK. | | 409 | Телефон ещё запускается или занят запуском агента. | | 410 | Телефон удалён. | | 413 | APK слишком велик для одного запроса (больше 100 МБ: загрузите его частями) или больше 500 МБ. | | 422 | Приложение не установилось; причина указана в error. | | 429 | У вас уже есть 3 телефона или 50 загруженных APK. | | 503 | Сейчас заняты все телефоны; повторите попытку через несколько минут. |