Appearance
Cloud phones from CI
Run your Android tests on a fresh cloud phone from GitHub Actions, GitLab, Jenkins or any script: start a phone, install your APK, run a test, fetch the reports and stop the phone. You pay £0.02 a minute from your prepaid minutes, as in the browser, and a phone that started is charged at least 10 minutes.
1. Make an API token
Your account → API tokens → Make token. Give it a name, an expiry (7, 30 or 90 days, or a year) and, if you like, its own monthly spending cap and the most phones it may run at once. Your account's spending limit always applies too.
The token is shown once: put it in your CI's secrets straight away (on GitHub: Settings → Secrets and variables → Actions → New repository secret, named BENCHFLEET_TOKEN). We keep only a fingerprint of it.
A token can only start, use and stop its own cloud phones. It cannot buy minutes, change your account or spending limit, or reach phones you started in the browser or the app. Revoke it on the same page and it stops working at once; the page also lists what each token did in the last 90 days, including what was refused.
2. The HTTP API
Everything goes to https://benchfleet.com/api/cloud/v1 with the header Authorization: Bearer <token>:
| Request | What it does |
|---|---|
GET /offers | Android versions, screen sizes, prices |
GET /balance | your minutes, spending limit, and this token's spending this month |
POST /rentals {"offer_id": "bf-android-17", "max_minutes": 30, "screen": "phone", "root": false} | starts a phone (201, its rental) |
GET /rentals, GET /rentals/ID | this token's phones and their state: requested, starting, ready, then released or failed |
POST /rentals/ID/extend {"minutes": 15} | more time |
POST /rentals/ID/release | stops the phone |
POST /rentals/ID/connect | once ready: the phone's address and a one-use pass for 60 seconds |
bash
curl -s -X POST https://benchfleet.com/api/cloud/v1/rentals \
-H "Authorization: Bearer $BENCHFLEET_TOKEN" -H "Content-Type: application/json" \
-d '{"offer_id": "bf-android-17", "max_minutes": 30}'Refusals carry a code: insufficient_balance (buy minutes), spending_limit (your account's limit), token_spending_limit and token_phone_limit (the token's caps), at_capacity (every phone is busy: try again in a few minutes; nothing was charged), rate_limited (with Retry-After).
connect opens the phone itself: a WebSocket to the phone's server with the same commands the browser uses (install, files, shell, log).
Coming soon: a GitHub Action and a command-line tool
They are not available yet; this page will say how to install them once they are. Both will do the whole job in one step: start a phone, install your APKs, run your test command (such as am instrument) in the phone's shell, fetch report files and the phone's log, and always stop the phone, passed or failed. The step or command will fail when your test fails, so your CI shows it like any other test.
Until then, the HTTP API above starts and stops phones from any CI.
What goes where
Your APKs, commands, test output and logs go from your CI straight to the server your phone runs on, and are deleted with the phone. Our account service sees only that a phone was started, for how long, and that a connection was made; never what you install or run. The phone keeps an audit of what was done on it under your account while it runs, deleted with the phone.
When the app is the better choice
The app runs workflows and AI agents on cloud phones as on your own phones (Workflows). Your Maestro, Espresso and Appium tests run in the app as test suites, with controlhub-ci for CI, on the phones attached to your computer; cloud phones are not supported there yet. Without the app, a cloud phone takes shell commands such as am instrument.