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
}
StatusMeaning
201Session live; embed_url ready to frame
400Bad JSON or missing app
401Bad API key
404No such app in the library
502Device 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.

EndpointDoes
GET {agent_url}/sessions/{agent_session_id}/streamLive screen: multipart/x-mixed-replace JPEG push (what the player uses)
GET {agent_url}/sessions/{agent_session_id}/frameCurrent 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

PropertyValue
Idle timeout15 minutes (no frame fetches) → device wiped
CapacityPer device box (503/502 with detail when full) - free slots when done
APK requirementsx86_64 ABI included; set the package id for auto-launch