---
title: "Create a stateful CUA session"
method: POST
path: "/v1/sessions"
tags: ["sessions"]
---

# Create a stateful CUA session

`POST /v1/sessions`

Persistent session with a managed-inference 10-credit fixed creation price and a 2-hour (7200s) idle TTL, reset on each predict/reset; expires_at is returned. BYOK session creation and every inherited predict debit zero Coasty platform credits. Session create configures and holds the inherited provider key but does not make an inference call, reports zero provider tokens, and does not itself incur provider billing; billing begins when session predict calls Anthropic/OpenAI. Under a test Coasty key, BYOK session create requires an explicit per-request X-LLM-Api-Key plus X-LLM-Provider. A body provider without the key header returns 422 LLM_KEY_NOT_CONFIGURED: Stored provider keys are unavailable for test API keys. Send X-LLM-Api-Key explicitly for direct BYOK. Test auth never reads or uses a stored live provider key. The owning process keeps that fixed create-time BYOK configuration in memory and every later predict inherits it. Deleting or rotating a stored key does not update or revoke an active session; DELETE /v1/sessions/{session_id} (or let it expire), or revoke the key at the provider, to stop further calls. Session creation has no managed request surcharge. A predict/reset against an expired or unknown session is a 404 SESSION_NOT_FOUND. Maintains trajectory across predictions. Concurrent-session limits are tier- and deployment-configured; clients must handle 429 responses instead of hardcoding a tier limit. Read effective deployed pricing from GET /v1/models under pricing.

## Headers

- `Idempotency-Key` string
- `X-LLM-Provider` 'anthropic' | 'openai'
- `X-LLM-Api-Key` string
- `X-LLM-Model` string

## Request body

- CreateSessionRequest
  - `cua_version` 'v1' | 'v3' | 'v4' | 'v5'
  - `model` 'default', nullable — Managed model alias. For BYOK model selection use llm.model.
  - `screen_width` integer
  - `screen_height` integer
  - `max_trajectory_length` integer — Server-side retained-history ceiling. At prediction time provider image 20 is reserved for the current screenshot, so at most the newest 19 prior screenshots are sent. The trajectory surcharge uses the exact prior screenshots actually included after compaction, not this configured ceiling.
  - `system_prompt` string, nullable — Persisted custom prompt. Its full length plus trimmed instructions determines each Session Predict custom-prompt surcharge.
  - `instructions` string, nullable — Persisted appended guidance. Its trimmed length plus system_prompt determines each Session Predict custom-prompt surcharge.
  - `tools` string[], nullable
  - `action_policy` ActionPolicy — Opt-in, fail-closed post-model action enforcement. The complete normalized batch is checked atomically before actions are returned or dispatched. allowed_actions and blocked_actions cannot overlap. Prediction, Session, and Parse surfaces use prediction action names such as type_text; direct Machine routes use command names such as type. Task, Workflow, and Schedule policies are create-time controls inherited across execution and recovery.
    - `allowed_actions` string[], nullable — Optional action allowlist. Values are trimmed and lowercased before validation; duplicates after normalization are rejected. Terminal done/fail/awaiting_human signals remain allowed.
    - `blocked_actions` string[] — Action denylist. Values are trimmed and lowercased before validation; duplicates after normalization are rejected.
    - `blocked_keys` string[] — Keys forbidden in key_press, key_combo, and modifier-bearing actions. Values are trimmed and lowercased; duplicates after normalization are rejected; esc aliases escape.
    - `block_window_close` boolean — Block explicit close commands and common Alt+F4, Ctrl/Cmd+W, and Cmd+Q shortcuts.
    - `max_actions` integer, nullable — Maximum number of actions admitted in one prediction/session step, parsed action batch, or direct Machine batch.
    - `coordinate_bounds` CoordinateBounds — Inclusive coordinate rectangle in the request screenshot's pixel space.
      - `min_x` integer
      - `min_y` integer
      - `max_x` integer, required
      - `max_y` integer, required
  - `metadata` object, nullable — JSON object capped at 16,384 UTF-8 bytes by the server.
  - `llm` LlmConfig — Opt-in BYOK model selection. provider 'managed' (or omitting llm) keeps the platform default. There is deliberately no api_key field (422 if attempted): keys ride the X-LLM-Api-Key header or the encrypted /v1/llm/keys store only. Once BYOK is requested there is NO silent fallback to Coasty's platform LLM keys.
    - `provider` 'managed' | 'anthropic' | 'openai' — Whose LLM account runs the harness. Anything else is 422 LLM_PROVIDER_UNSUPPORTED.
    - `model` string, nullable — Main worker model. Defaults: claude-sonnet-5 (anthropic), gpt-5.6-sol (openai). Model ids are 1-256 characters, begin with a letter or number, and then use only letters, numbers, dot, underscore, colon, slash, plus, at-sign, or hyphen; invalid ids return 422 LLM_MODEL_INVALID. The selected provider can still reject an unknown or inaccessible model. It must be vision-capable.
    - `grounding_model` string, nullable — Override for pixel-coordinate grounding. Defaults to model. Grounding quality is tuned on the platform model; expect best results with the defaults.
    - `compaction_model` string, nullable — Override for trajectory compaction. Defaults to model. A cheaper model here is the classic cost tune.
    - `code_agent_model` string, nullable — Override for the code agent. Defaults to model.

## Response `200`

Session created.

- CreateSessionResponse
  - `request_id` string, required
  - `session_id` string, required
  - `cua_version` string, required
  - `screen_size` string, required
  - `created_at` string, date-time, required
  - `expires_at` string, date-time, required
  - `usage` UsageInfo, required
    - `input_tokens` integer
    - `output_tokens` integer
    - `credits_charged` integer
    - `cost_cents` integer — USD-cent amount; the same numeric value as credits_charged (divide by 100 for USD).
    - `breakdown` object[], nullable — Self-auditable per-call cost breakdown; line credits sum to credits_charged. null on free/test/no-charge calls and /v1/parse.
      - `item` 'base' | 'trajectory' | 'hd_images' | 'engine' | 'custom_prompt', required
      - `credits` integer, required
      - `count` integer, nullable — Optional multiplier (e.g. number of HD screenshots billed); omitted where it adds nothing.
    - `billed` boolean — true on a real Coasty wallet debit; false on BYOK, test keys (sk-coasty-test-*), and idempotent replays (all return credits_charged: 0).
    - `llm_provider` 'managed' | 'anthropic' | 'openai' — Effective inference provider. Non-managed values identify provider-direct BYOK execution.
    - `llm_model` string, nullable — Effective BYOK model id; null for managed inference.
    - `llm_key_fingerprint` string, nullable — Non-secret SHA-256 prefix identifying the BYOK key; never the key itself.
    - `llm_key_source` 'header' | 'stored', nullable — Where the effective BYOK key came from; null for managed inference.
    - `platform_cost_exempt` boolean — true for BYOK. Coasty credits/cost are zero. Provider billing occurs only for provider-direct execution. Managed-mode test Task, Workflow, and schedule sandbox execution makes no provider call; test-auth BYOK intent on those async endpoints is rejected before execution.

## Other responses

- `400` — Invalid request body or parameters.
- `401` — Missing, invalid, or revoked API key. Pass `X-API-Key: sk-coasty-live-...` (or test).
- `402` — Insufficient balance for this operation. Direct metered API calls and managed-machine runtime use the prepaid Developer API wallet; scheduled execution is the documented consumer subscription-credit exception. Follow the operation's billing fields and top up the matching balance in the dashboard.
- `403` — API key lacks the required scope or tier-feature is unavailable on the caller's plan.
- `404` — Resource not found in this key's namespace.
- `409` — The resource state conflicts with this operation.
- `413` — The request body exceeds the endpoint limit.
- `422` — The JSON shape is valid but one or more values violate the endpoint contract.
- `429` — Rate or concurrency limit exceeded.
- `500` — Unexpected server error. Retry with exponential backoff.
- `502` — An upstream dependency returned an invalid response.
- `503` — A required service is temporarily unavailable.
- `504` — An upstream dependency timed out.

---

[API](https://skmtc.net/coasty/apis/coasty-public-api.md) · [All operations](https://skmtc.net/coasty/apis/coasty-public-api/llms.txt) · [OpenAPI document](https://skmtc-service-staging.skmtc.workers.dev/v1/apis/coasty/coasty-public-api/revisions/f50d93b0d8a1/schema)
