スマホのエンドポイント
クラウドスマホ、アプリ、ライブ画面、直接操作、エージェントの実行を扱う /v1/phones のすべてのエンドポイントについて、パラメータ、制限、レスポンス、エラーを説明します。
クラウドスマホ API は https://lovelyrouter.com/v1/phones 以下にあります。すべてのリクエストは、API キーを Authorization: Bearer $LOVELY_API_KEY として送って認証します(認証)。リクエストボディは、APK のアップロードとスクリーンショットを除いて JSON です。スマホは起動中 1 時間あたり $1.20 で、プリペイド残高から分単位で課金されます。詳しくはスマホの料金を参照してください。
使い方の流れを知るには、まずクラウドスマホの概要をお読みください。座標はすべてスクリーンショットのピクセル単位で、スクリーンショットの短辺は 540 ピクセルです。縦向きなら 540×1200、スマホが横向き(ゲームや動画)なら 1200×540 です。どちらかはスクリーンショットの width と height でわかります。
スマホオブジェクト#
属性
idstringph_ に続く 20 文字。
objectstring常に phone。
statusstringstarting(約 1 分。起動時のアプリをインストール中はさらにかかります)、ready、failed、deleted のいずれか。
namestring | nullあなたが付けたラベル。
userstring | null設定した場合、あなたのエンドユーザーの ID。
metadataobject | nullスマホと一緒に保存したデータ。
startup_appsarrayapps に指定したアプリごとに 1 項目。source、status(pending、installed、failed)、packages(インストールされたパッケージ名)、error を含みます。
created_atready_atUnix 秒。
deletes_after_idle_atinteger | nullそれまでに使われなければスマホが削除される日時(最後の操作から 1 時間後)。
awake_secondsintegerこれまでに課金された起動時間。
charge_usdnumberスマホにこれまでにかかった費用。
end_reasonstring | null削除された理由。deleted(あなたが削除)、idle、balance、failed のいずれか。
errorstring | null起動に失敗した理由。
スマホを作成する#
/v1/phonesスマホを作成し、起動中のスマホオブジェクトを 201 で返します。続けて wait を付けてスマホを取得するを呼び出してください。残高にスマホ 15 分分の金額が必要です。1 つのアカウントで同時に持てるスマホは 3 台までです。
ボディパラメータ
appsarray of stringsスマホが ready になる前にインストールするアプリ(最大 20 個)。.apk、.apks、.xapk ファイルへの https:// リンク、またはアップロード済みの APK の名前です。インストールに失敗してもスマホの起動は失敗しません。startup_apps を確認してください。
namestringラベル。最大 80 文字。
userstringあなたのエンドユーザーの ID(最大 200 文字)。GET /v1/phones?user= でそのユーザーのスマホを一覧できます。
metadataobject最大 4 KB の独自データ。
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{"object": "list", "data": [phone, …]} を新しい順に返します。user= で 1 人のエンドユーザーのスマホに絞り込み、all=1 で削除済みのものも含めます。
スマホを削除する#
/v1/phones/{id}スマホをアプリやデータごと削除し、実行中の処理を止め、最後の数分を精算します。ステータスが deleted のスマホオブジェクトを返します。スマホは 1 時間操作がないと自動でも削除されます。
スクリーンショットを取得する#
/v1/phones/{id}/screenshot現在の画面を WebP 画像(image/webp、短辺 540 ピクセル)で返します。format=json を付けると、画像を base64 にした {screenshot, width, height, app, elements} を返します。
curl https://lovelyrouter.com/v1/phones/ph_2758eedebf08496f87e0/screenshot \
-H "Authorization: Bearer $LOVELY_API_KEY" -o screen.webp要素を一覧表示する#
/v1/phones/{id}/elementsAndroid のビューツリーから取得した画面上の要素です:{"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)が含まれます。ビューを使わずに描画される画面(ゲームや一部のキャンバス)では要素がほとんど取れないため、スクリーンショットを使ってください。
操作を送る#
/v1/phones/{id}/actionsスマホで 1 つの操作を行い、{"ok": true}(または error 付きの ok: false)を返します。"screenshot": true を付けると、画面が落ち着いた後の screenshot(base64 の WebP)が返ります。エージェントの実行がスマホを操作している間は 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"}リンクを開きます。Web ページなら Chrome で、アプリリンク(market:// やアプリ独自のスキーム)ならそのアプリで開きます。
{"action": "launch", "package"}インストール済みのアプリを開きます(例:org.fdroid.fdroid)。
{"action": "stop_app", "package"}アプリを強制停止します。
{"action": "rotate", "orientation"}スマホの向きを変えます:portrait(縦)または landscape(横)。向きが固定されたアプリ(多くのゲーム)はそのままです。ライブ画面も追従します。
{"action": "wait", "seconds"}最大 60 秒。
{"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.apk、.apks、.xapk ファイルへの https:// リンク。
apkstringまたはアップロード済みの APK の名前。
GET /v1/phones/{id}/apps はインストール済みアプリのパッケージ名を一覧にし、DELETE /v1/phones/{id}/apps/{package} は 1 つをアンインストールします。
APK をアップロードする#
/v1/phones/apks/{name}APK を保存し、どのスマホにも name(英字、数字、_、.、-。最大 80 文字)でインストールできるようにします。ファイルはリクエストボディとして送信し、最大 100 MB です。それより大きいファイル(最大 500 MB)はパートに分けてアップロードします。.apk、.apks、.xapk のどれでも使え、.xapk をインストールするとゲームデータ(OBB ファイル)もスマホにコピーされます。同じ名前にアップロードするとファイルが置き換わります。201 と {name, bytes, sha256} を返します。1 つのアカウントで保存できるのは 50 個までで、1 GB を超えるストレージは課金されます。
GET /v1/phones/apks で一覧を取得し、DELETE /v1/phones/apks/{name} で 1 つを削除します。
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}/uploads100 MB を超える(最大 500 MB の)ファイルはパートに分けてアップロードします。ファイルのサイズを伝え、各パートを送り、最後に完了させます。結果は APK をアップロードする と同じで、name で保存され、同じ名前のファイルを置き換えます。
Body parameters
bytesinteger必須ファイルのサイズ(バイト)。最大 524,288,000(500 MB)。
201 と {id, part_size, parts, parts_done, expires_at} を返します。続けて:
- 1 から
partsまでの各パートnについて、PUT /v1/phones/apks/{name}/uploads/{id}/{n}を呼び、ファイルの(n-1) × part_sizeバイト目からのデータをボディとして送ります。最後のパート以外はすべてpart_sizeバイト(50 MB)で、最後のパートは残りの部分です。パートは任意の順序で、または同時に送れます。同じパートを送り直すと前のものが置き換わります。 POST /v1/phones/apks/{name}/uploads/{id}/completeでパートを結合し、201と{name, bytes, sha256}を返します。足りないパートがある場合は409でそのパートを示します。
GET /v1/phones/apks/{name}/uploads/{id} で届いたパート(parts_done)を確認でき、DELETE でアップロードを取りやめます。24 時間以内に完了しなかったアップロードは破棄されます。
ストレージ#
アップロードした APK の最初の 1 GB は無料で保存されます。それを超える分は 1 GB あたり月 $0.30 で、1 時間ごとに残高から差し引かれます。不要になった APK は DELETE /v1/phones/apks/{name} で削除してください。アップロードには 0 より多い残高が必要です。
# 120 MB のファイル:3 パート
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 | nullwaiting の間、エージェントがあなたに求めていること。
answerstring | null完了したときの結果。
errorstring | null失敗または停止した理由。
llm_usdnumberモデルのトークンにかかった費用(実行終了時に設定)。
tracearraytrace=1 を付けた場合、各ステップの step、note(エージェントが何を見て、なぜその操作をしたか)、action、args、app、ok、error、ms。操作のあと画面がまったく変わらなかった場合は unchanged: true も付きます。
実行を開始する#
/v1/phones/runsスマホを作成してエージェントを開始します。phone_id を指定すると、手持ちのスマホで開始します。202 と実行オブジェクトを返します。1 台のスマホで同時に実行できるゴールは 1 つだけで、別の実行が動いている間は 409 になります。
ボディパラメータ
goalstring必須やることを普段の言葉で。タスクに必要な値はすべて含めてください。最大 10,000 文字。
phone_idstring新しいスマホではなく、このスマホで実行します。POST /v1/phones/{id}/runs でも同じです。
appsname新しいスマホ用。スマホを作成すると同じです。
modestringデフォルト smartsmart:モデルがすべてのステップを決めます(1 ステップ数秒)。fast:高速な判断モデルがほぼすべてのステップを 1 秒未満で選び(必ず行動するのでゲーム向き)、model は回答やあなたへの質問を書くときだけ使います。高速モードを参照してください。
planbooleanデフォルト true高速モードのみ:コーチ役のモデルが高速モデルの横で動きます(料金はスマホの料金に含まれます)。ゴールのための短い戦略(ゲームならどの手を優先するか)と今の状況についてのメモを書き、数ステップごと、または実行が行き詰まったように見えるときに書き直します。高速モデルはそれを待たず、各ステップで最新の版を使います。内容は実行オブジェクトの strategy、situation、sidecar_updates に入ります。
modelstringデフォルト gemini-3.8-flashGET /v1/models にある任意のチャットモデル。トークンは通常料金で課金されます。
max_stepsintegerデフォルト 401〜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 を返します。
エラー#
| ステータス | 発生する場合 | | - | - | | 400 | フィールドが不足しているか誤っています。どのフィールドかはメッセージに示されます。 | | 402 | 残高がスマホの起動に足りないか、使い切りました。 | | 404 | そのスマホ、実行、APK はあなたのアカウントにありません。 | | 409 | スマホがまだ起動中か、実行で使用中です。 | | 410 | スマホは削除されています。 | | 413 | APK が 1 回のリクエストには大きすぎる(100 MB 超はパートに分けてアップロード)か、500 MB を超えています。 | | 422 | アプリをインストールできませんでした。理由は error に示されます。 | | 429 | すでにスマホが 3 台あるか、APK を 50 個アップロード済みです。 | | 503 | 現在すべてのスマホが使用中です。数分後にもう一度お試しください。 |