API reference
Bearer-key REST for sessions, plus the per-session device endpoints the player uses.
Authentication
Service calls authenticate with Authorization: Bearer <key>. Keys are configured
by the operator (EMUTIZE_API_KEYS). 401 means a missing or unknown key.
GET / POST /api/v1/apps/
The app library, for builders. POST either JSON
{"url": "<https apk url>", "name", "package_id"} - Emutize fetches the
artifact server-side (built for EAS URLs) - or multipart (file = the APK,
name, package_id). Re-POSTing the same name replaces the
previous build (201 created / 200 replaced). APKs must include the x86_64 ABI.
POST /api/v1/sessions/
Boot a fresh device, install the app, auto-launch it.
POST /api/v1/sessions/
Authorization: Bearer emtz_xxx
Content-Type: application/json
{ "app": "MyApp" } // library name, or numeric id
201 Created
{
"session_id": 7,
"app": "MyApp",
"backend": "redroid",
"embed_url": "https://app.emutize.com/devices/embed/7/?token=...",
"agent_url": "https://agent.emutize.com",
"agent_session_id": "f6a87a6f7a6b44e48444900abb812347",
"token": "dFEgadTk...",
"warning": "..." // present only if install succeeded but auto-launch failed
}
| Status | Meaning |
|---|---|
| 201 | Session live; embed_url ready to frame |
| 400 | Bad JSON or missing app |
| 401 | Bad API key |
| 404 | No such app in the library |
| 502 | Device plane failed (capacity, install error) - body has detail |
GET /api/v1/sessions/<id>/
200 { "session_id": 7, "status": "active", "app": "MyApp" }
DELETE /api/v1/sessions/<id>/
Ends the session and wipes the device. Returns 204. Idempotent in effect - an
already-dead session still 204s after marking itself ended.
Device endpoints (per-session token)
The embed player uses these against agent_url; you can too (e.g. for screenshots).
Auth: X-Session-Token header or ?token= query param.
| Endpoint | Does |
|---|---|
GET {agent_url}/sessions/{agent_session_id}/stream | Live screen: multipart/x-mixed-replace JPEG push (what the player uses) |
GET {agent_url}/sessions/{agent_session_id}/frame | Current screen as a single JPEG/PNG (screenshots, thumbnails) |
POST .../input | {"type":"tap","x":540,"y":1200} · swipe (x1,y1,x2,y2,duration_ms) · text · key (code) |
GET .../ (session info) | 404 once the session is gone - cheap liveness probe |
Lifecycle & limits
| Property | Value |
|---|---|
| Idle timeout | 15 minutes (no frame fetches) → device wiped |
| Capacity | Per device box (503/502 with detail when full) - free slots when done |
| APK requirements | x86_64 ABI included; set the package id for auto-launch |