Lovely Routerドキュメント
キーを取得
API リファレンス

スマホのエンドポイント

クラウドスマホ、アプリ、ライブ画面、直接操作、エージェントの実行を扱う /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 でわかります。

スマホオブジェクト#

属性

idstring

ph_ に続く 20 文字。

objectstring

常に phone。

statusstring

starting(約 1 分。起動時のアプリをインストール中はさらにかかります)、ready、failed、deleted のいずれか。

namestring | null

あなたが付けたラベル。

userstring | null

設定した場合、あなたのエンドユーザーの ID。

metadataobject | null

スマホと一緒に保存したデータ。

startup_appsarray

apps に指定したアプリごとに 1 項目。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

起動に失敗した理由。

スマホを作成する#

POST/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
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}'
Response
{
  "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
}

スマホを取得する#

GET/v1/phones/{id}

スマホオブジェクトを返します。wait(秒、最大 50)を付けると、starting のスマホは準備ができるまでリクエストを待機させます。

スマホを一覧表示する#

GET/v1/phones

{"object": "list", "data": [phone, …]} を新しい順に返します。user= で 1 人のエンドユーザーのスマホに絞り込み、all=1 で削除済みのものも含めます。

スマホを削除する#

DELETE/v1/phones/{id}

スマホをアプリやデータごと削除し、実行中の処理を止め、最後の数分を精算します。ステータスが deleted のスマホオブジェクトを返します。スマホは 1 時間操作がないと自動でも削除されます。

スクリーンショットを取得する#

GET/v1/phones/{id}/screenshot

現在の画面を WebP 画像(image/webp、短辺 540 ピクセル)で返します。format=json を付けると、画像を base64 にした {screenshot, width, height, app, elements} を返します。

cURL
curl https://lovelyrouter.com/v1/phones/ph_2758eedebf08496f87e0/screenshot \
  -H "Authorization: Bearer $LOVELY_API_KEY" -o screen.webp

要素を一覧表示する#

GET/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)が含まれます。ビューを使わずに描画される画面(ゲームや一部のキャンバス)では要素がほとんど取れないため、スクリーンショットを使ってください。

操作を送る#

POST/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
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}'
POST/v1/phones/{id}/screen

{"url", "expires_at"} を返します。スマホのライブ画面を表示するページです。リンクを持っている人は誰でも、マウスとキーボードでスマホを見て操作できるため、使うべき人にだけ共有してください。iframe で埋め込むこともできます。

ボディパラメータ

ttl_secondsintegerデフォルト 3600

リンクの有効期間。60〜86,400 秒。すでに開いている画面は引き続き使えます。

view_onlyboolean

ページを表示専用モードで開きます。これは表示の設定で、権限ではありません。閲覧者が解除できます。

アプリをインストールする#

POST/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 をアップロードする#

PUT/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
curl -X PUT https://lovelyrouter.com/v1/phones/apks/myapp.apk \
  -H "Authorization: Bearer $LOVELY_API_KEY" \
  --data-binary @myapp.apk

大きな APK をパートに分けてアップロードする#

POST/v1/phones/apks/{name}/uploads

100 MB を超える(最大 500 MB の)ファイルはパートに分けてアップロードします。ファイルのサイズを伝え、各パートを送り、最後に完了させます。結果は APK をアップロードする と同じで、name で保存され、同じ名前のファイルを置き換えます。

Body parameters

bytesinteger必須

ファイルのサイズ(バイト)。最大 524,288,000(500 MB)。

201 と {id, part_size, parts, parts_done, expires_at} を返します。続けて:

  1. 1 から parts までの各パート n について、PUT /v1/phones/apks/{name}/uploads/{id}/{n} を呼び、ファイルの (n-1) × part_size バイト目からのデータをボディとして送ります。最後のパート以外はすべて part_size バイト(50 MB)で、最後のパートは残りの部分です。パートは任意の順序で、または同時に送れます。同じパートを送り直すと前のものが置き換わります。
  2. 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 より多い残高が必要です。

cURL
# 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"

実行オブジェクト#

属性

idstring

prun_ に続く 20 文字。

objectstring

常に phone.run。

phone_idstring

実行しているスマホ。

statusstring

queued(スマホが起動中)、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 も付きます。

実行を開始する#

POST/v1/phones/runs

スマホを作成してエージェントを開始します。phone_id を指定すると、手持ちのスマホで開始します。202 と実行オブジェクトを返します。1 台のスマホで同時に実行できるゴールは 1 つだけで、別の実行が動いている間は 409 になります。

ボディパラメータ

goalstring必須

やることを普段の言葉で。タスクに必要な値はすべて含めてください。最大 10,000 文字。

phone_idstring

新しいスマホではなく、このスマホで実行します。POST /v1/phones/{id}/runs でも同じです。

appsname

新しいスマホ用。スマホを作成すると同じです。

modestringデフォルト smart

smart:モデルがすべてのステップを決めます(1 ステップ数秒)。fast:高速な判断モデルがほぼすべてのステップを 1 秒未満で選び(必ず行動するのでゲーム向き)、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。

実行を取得する#

GET/v1/phones/runs/{id}

実行オブジェクトを返します。wait(最大 50 秒)を付けると、実行が終わるかあなたへの質問が発生するまでリクエストを待機させます。trace=1 でステップを含めます。after_step=N を付けると、ステップ数が N を超えた時点でも返ります。GET /v1/phones/runs?phone_id= は実行を新しい順に一覧にします。

実行に返信する#

POST/v1/phones/runs/{id}/reply

実行の question に {"answer": "…"} で答えます。実行はそのまま続きます。実行が待機中でない場合は 409 を返します。

実行を停止する#

POST/v1/phones/runs/{id}/stop

現在のステップが終わった後に実行を停止します。スマホはそのまま残ります。

エラー#

| ステータス | 発生する場合 | | - | - | | 400 | フィールドが不足しているか誤っています。どのフィールドかはメッセージに示されます。 | | 402 | 残高がスマホの起動に足りないか、使い切りました。 | | 404 | そのスマホ、実行、APK はあなたのアカウントにありません。 | | 409 | スマホがまだ起動中か、実行で使用中です。 | | 410 | スマホは削除されています。 | | 413 | APK が 1 回のリクエストには大きすぎる(100 MB 超はパートに分けてアップロード)か、500 MB を超えています。 | | 422 | アプリをインストールできませんでした。理由は error に示されます。 | | 429 | すでにスマホが 3 台あるか、APK を 50 個アップロード済みです。 | | 503 | 現在すべてのスマホが使用中です。数分後にもう一度お試しください。 |