---
title: "Create a session"
method: POST
path: "/sessions"
tags: ["Sessions"]
---

# Create a session

`POST /sessions`

## Request

- Base URL: `https://api.phone-harness.com`
- URL: `https://api.phone-harness.com/sessions`
- Auth: HTTP bearer

Allocate an Android phone asynchronously. HTTP 202 means admitted, not ready. Poll the returned id. The deadline includes provisioning. Use one stable Idempotency-Key per logical Start. Pass your account's profile_id (from GET /me) to use your own phone, which is saved when the session ends and comes back the same way next time; omit it for a temporary phone that keeps nothing. Raw capabilities and runtime resource overrides are not supported. Omit provider to use the service default.

## Headers

- `Idempotency-Key` string

## Request body

- CreateSession
  - `platform` 'android' | 'ios': Name what to start together with `kind`; omit both for a temporary Android emulator (`GET /me` → `unnamed` states that rule). Name what you want: `android` + `emulator` for everyone, `ios` + `device` for an account whose own iPhone we have set up.
  - `kind` 'emulator' | 'device': Together with `platform`. `emulator` for the shared Android phones; `device` for your own phone.
  - `profile_id` string: Your account's profile id, from GET /me. The session then uses your own phone: its apps, logins and screen are saved when the session ends and restored for the next session started with the same profile_id. Only one session at a time may hold it, including the save after a session ends (409 profile_running). Omit for a temporary phone.
  - `timeout_seconds` integer: Total session lifetime from admission, including provisioning. Omitting it uses 300 seconds. No unlimited mode; must fit a supported absolute timestamp.

## Response `202`

Admitted or replayed session.

- Session
  - `id` string, required: Opaque session ID.
  - `profile` string, nullable: The profile id this session holds, or null for a temporary phone.
  - `state` 'provisioning' | 'ready' | 'error' | 'closing', required
  - `progress` object: Only while `state` is `provisioning`: where the phone is. `queued` means every boot slot is busy and the phone starts as soon as one frees; `booting` means the phone is starting. `eta_seconds` is a typical remaining time for this start, not a promise; `still_starting` is true once that time is up and the phone is still starting.
    - `phase` 'queued' | 'booting', required
    - `queue_position` integer: Place in line, 1 = next. Present while `phase` is `queued`.
    - `eta_seconds` integer: Typical seconds left until the phone is ready.
    - `still_starting` boolean: True once the typical time is up and the phone is still starting; show that rather than a zero.
  - `platform` 'android' | 'ios': What the phone is: `android` or `ios`.
  - `kind` 'emulator' | 'device': How it runs: an `emulator`, or a real `device` (your own phone on a host).
  - `device` string, nullable, required: Display label in plain words ("Android emulator", "iPhone"); not a device connection address.
  - `close_requested` number, nullable, required: Time closure was requested. Unix time in seconds.
  - `cleanup_pending` boolean, required
  - `cleanup_status` 'complete' | 'allocation_uncertain' | 'pending' | 'null', nullable, required
  - `billing_mode` 'metered' | 'disabled', required
  - `phone` string, nullable, required: Legacy saved-phone ID. Null for a new disposable session.
  - `watch_url` string, uri, required: Sensitive read-only snapshot link. Not the interactive owner viewer.
  - `screen` ScreenSize, required
    - `w` integer, required: Width in device pixels.
    - `h` integer, required: Height in device pixels.
  - `age_s` integer, required: Rounded seconds since creation.
  - `ready_age_s` integer, required: Rounded seconds since readiness, stopped at closure; zero before readiness.
  - `idle_s` integer, required: Rounded seconds since the last activity recorded by the API. Does not extend or replace a selected session deadline.
  - `error` string: Public startup failure, if present.
  - `expires_at` number: Absolute session expiry, including provisioning. Unix time in seconds.
  - `timeout_seconds` integer: Selected finite duration from creation, in seconds.
  - `startup` StartupObservation: Optional startup provenance. Presence is not a latency measurement or a guarantee that prepared starts are available.
    - `mode` 'cold' | 'prepared', required
    - `pool` 'miss' | 'ineligible' | 'disabled' | 'hit', required
    - `preparation_ms` number: Optional preparation duration in milliseconds.
    - `inventory_age_ms` number: Optional inventory age in milliseconds.
  - `request_key` string: Returned in a creation response when an idempotency key was supplied.
  - `adb` SessionAdb: Present once the session is ready and ADB is enabled.
    - `host` string, required: DNS name of the ADB endpoint. Use the returned value.
    - `port` integer, required: TCP port dedicated to this phone while the session lives. Run adb connect host:port.
    - `code` string, required: The unlock code. After connecting, run adb shell unlock <code>. Anyone who has host, port and code can drive the phone until the session ends or the code is reset.
    - `expires_at` number, required: Unix timestamp in seconds when access expires. Never later than the session deadline; ADB access does not extend the session.

## Other responses

- `400`: Invalid creation request.
- `401`: Bad or missing bearer credential.
- `403`: Beta access/rentals unavailable or insufficient credits. Starting requires at least two minutes of credit.
- `409`: Account capacity is full (session_limit), idempotency conflict, or your profile phone is held by a live session or still being saved (profile_running).
- `410`: This keyed create already completed cleanup.
- `500`: Unexpected service error.
- `503`: All phones are in use (`code: phones_busy`, `retry_after_seconds` and a `Retry-After` header; no session was created, retry after the delay), or admission was recorded but the runtime is unavailable (`code: create_request_recorded`).

---

[API](https://skmtc.dev/phone-harness/apis/phone-harness-api.md) - [All operations](https://skmtc.dev/phone-harness/apis/phone-harness-api/llms.txt) - [OpenAPI document](https://skmtc.dev/phone-harness/apis/phone-harness-api/revisions/5af8941102e5?raw)
