> ## Documentation Index
> Fetch the complete documentation index at: https://developers.telnyx.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Sessions

> Session lifecycle, allowed domains, and limits.

A browser session is an isolated, short-lived Chromium instance with network access restricted to the domains you allow.

## Create a Session

```bash theme={null}
curl -X POST https://api.telnyx.com/v2/browser_sessions \
  -H "Authorization: Bearer ***" \
  -H "Content-Type: application/json" \
  -d '{
    "policy": {
      "allowed_domains": ["example.com", "*.example.com"]
    },
    "limits": {
      "lifetime_s": 600,
      "idle_timeout_s": 120
    }
  }'
```

### Policy

| Field | Type | Required | Description |
| - | - | - | - |
| `allowed_domains` | string\[] | Yes | 1–50 domain patterns the browser can navigate to. |

### allowed\_domains Matching

Matching is exact-only — no implicit subdomain matching.

| Pattern | Matches | Does NOT match |
| - | - | - |
| `example.com` | `example.com` | `www.example.com`, `api.example.com` |
| `*.example.com` | `www.example.com`, `api.example.com` | `example.com` (the apex) |
| `wikipedia.org` | `wikipedia.org` | `en.wikipedia.org`, `www.wikipedia.org` |
| `*.wikipedia.org` | `en.wikipedia.org`, `www.wikipedia.org` | `wikipedia.org` (the apex) |

To allow a domain **and** all its subdomains, list both:

```json theme={null}
{ "policy": { "allowed_domains": ["wikipedia.org", "*.wikipedia.org"] } }
```

* Wildcard patterns use `*.` prefix — `*.example.com` matches any subdomain but **not** the apex itself.
* Exact patterns (`example.com`) match only that exact hostname.
* IP literals (e.g. `127.0.0.1`) are not allowed.

### Limits

| Field | Type | Default | Min | Max | Description |
| - | - | - | - | - | - |
| `lifetime_s` | int | 900 | 60 | 1800 | Max session duration in seconds. Values above 1800 are rejected (400). |
| `idle_timeout_s` | int | 300 | 30 | — (≤ `lifetime_s`) | Idle timeout in seconds. Must not exceed `lifetime_s`. |

### Idempotency and Concurrent-Session Quota

Pass an optional `idempotency_key` (1–255 characters) in the create request body. Within the same organization, the same key and identical normalized policy, limits, and metadata return the existing session with HTTP 201. Defaults are applied before comparison. A different request with that key returns `409 idempotency_conflict`. A replay does not restart a closed, failed, or expired session.

Creating a new session can return `429 quota_exceeded` with `retryable: true` when the organization's concurrent-session quota is reached. Close unneeded active sessions or wait for capacity before trying again. This is a session quota, not a per-key request-rate limit.

## Session Lifecycle

| Status | Description |
| - | - |
| `provisioning` | Session is starting up. |
| `ready` | Browser is up and accepting actions. |
| `closing` | Session is being shut down. |
| `closed` | Session closed, resources released. |
| `failed` | Session failed (see `failure_reason`, e.g. `provision_timeout` when the session could not start). |
| `expired` | Session exceeded its lifetime or idle timeout. |

## List Sessions

```bash theme={null}
curl -s https://api.telnyx.com/v2/browser_sessions?status=ready \
  -H "Authorization: Bearer ***"
```

Filter by status: `provisioning`, `ready`, `closing`, `closed`, `failed`, `expired`.

## Get Session

```bash theme={null}
curl -s https://api.telnyx.com/v2/browser_sessions/$SESSION_ID \
  -H "Authorization: Bearer ***"
```

## Close Session

```bash theme={null}
curl -X DELETE https://api.telnyx.com/v2/browser_sessions/$SESSION_ID \
  -H "Authorization: Bearer ***"
```

Closing a ready session normally returns `status: "closed"`. An already closed, failed, or expired session is returned unchanged. A provisioning session returns `409 session_not_ready`; poll its state before closing again. A request that cannot be completed reliably can return `503 execution_lost` with `retryable: true`; retrieve the session state before retrying the close.
