# Sessions

Source: https://phonebox.dev/docs/api-reference/sessions

> List a phone's billed sessions, with when each one ran, why it ended and what it cost.



A session is one billed period on one phone, from the moment a create or start is admitted until billing stops. [Concepts](/docs/getting-started/concepts#sessions) explains sessions, and [Pricing and credits](/docs/billing/pricing) explains how they are charged.

## List a phone's sessions [#list-a-phones-sessions]

`GET /v1/phones/{id}/sessions` needs the `phones:read` scope.

Lists the phone's sessions, newest first, the open one included. It works in every status, so a deleted phone's sessions stay listed.

| Parameter | Type    | Default | Rules                                   |
| --------- | ------- | ------- | --------------------------------------- |
| `limit`   | integer | 50      | From 1 to 100.                          |
| `cursor`  | string  | None    | The `next_cursor` of the previous page. |

```bash
curl "https://phonebox.dev/v1/phones/ph_7kx2m6q4v3ta/sessions?limit=3" \
  -H "Authorization: Bearer $PHONEBOX_API_KEY"
```

```json title="Response: sessions"
{
  "data": [
    {
      "id": "ses_h4j6k2m7n3p5",
      "started_at": "2026-09-29T16:02:11.730Z",
      "ready_at": "2026-09-29T16:02:48.215Z",
      "ended_at": null,
      "end_reason": null,
      "billed_seconds": null,
      "cost_usd": null,
      "reserved_usd": "7.200000"
    },
    {
      "id": "ses_b5c3d7f2g6h4",
      "started_at": "2026-09-29T15:05:40.052Z",
      "ready_at": null,
      "ended_at": "2026-09-29T15:10:40.603Z",
      "end_reason": "failed",
      "billed_seconds": 0,
      "cost_usd": "0.000000",
      "reserved_usd": "7.200000"
    },
    {
      "id": "ses_x7c3v5b2n6m4",
      "started_at": "2026-09-29T14:20:02.118Z",
      "ready_at": "2026-09-29T14:20:41.309Z",
      "ended_at": "2026-09-29T14:41:33.004Z",
      "end_reason": "parked",
      "billed_seconds": 1291,
      "cost_usd": "1.291000",
      "reserved_usd": "7.200000"
    }
  ],
  "next_cursor": "Hq4Vn8Kp2Lm7Tx3Rz6Wc9Yb5Gd1Fs0Ja"
}
```

| Field            | Type              | Meaning                                                                  |
| ---------------- | ----------------- | ------------------------------------------------------------------------ |
| `id`             | string            | The session's ID: `ses_` followed by 12 characters.                      |
| `started_at`     | timestamp         | When the create or start was admitted. Billing starts here.              |
| `ready_at`       | timestamp or null | When the phone became ready, or `null` if it hasn't.                     |
| `ended_at`       | timestamp or null | When billing stopped, or `null` while the session is open.               |
| `end_reason`     | string or null    | Why the session ended, from the table below, or `null` while it is open. |
| `billed_seconds` | integer or null   | The seconds charged, or `null` while the session is open.                |
| `cost_usd`       | money or null     | What the session cost, or `null` while it is open.                       |
| `reserved_usd`   | money             | The credit the session reserved, renewals included.                      |

A closed session is billed for the seconds from `started_at` to `ended_at`, rounded up, with a minimum of 60 and never more than it reserved. Each second costs $0.001, so `cost_usd` is `billed_seconds` times $0.001. A session that ended before the phone was ever ready costs nothing, with `billed_seconds` at 0, unless you parked or deleted the phone yourself.

| `end_reason`     | Meaning                                                                                                                          |
| ---------------- | -------------------------------------------------------------------------------------------------------------------------------- |
| `parked`         | You parked the phone.                                                                                                            |
| `idle`           | The phone's `idle_timeout` passed after its `last_active_at`, which a request addressing it moves at most once every 15 seconds. |
| `max_duration`   | The session reached its `max_duration`.                                                                                          |
| `deleted`        | You deleted the phone.                                                                                                           |
| `failed`         | The phone failed, or a start couldn't finish in time and the phone parked again.                                                 |
| `unavailable`    | The phone became unavailable, for example for maintenance.                                                                       |
| `project_frozen` | The project was frozen, which parks its running phones.                                                                          |
| `service_paused` | Phonebox was paused for maintenance, which parks every running phone.                                                            |

| Error                   | When                                                                                              |
| ----------------------- | ------------------------------------------------------------------------------------------------- |
| `400 validation_failed` | `limit` is outside 1 to 100, a parameter is given twice, or the cursor is invalid or has expired. |
