# Start a session

`POST /o/{org}/p/{project}/sessions`

Starts one agent run in a fresh sandbox and returns it at once with
`202`; follow it with `GET …/events` or the key's webhook. `{project}` =
`_` runs without a repository; a Project handle runs in that Project's
repository with its connectors.

Started with an API key, the run uses Rush's models, metered on the key
creator's plan, unless `account_id` names one of the creator's own
Anthropic or OpenAI API-key accounts. A key may have `max_concurrent` runs
in progress (default 4); one more is `429 RATE_LIMITED`.

## Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `org` | path | string | yes | The org's slug or id. A caller with no role in the org gets `404`. |
| `project` | path | string | yes | A Project's handle (name) or id, resolved inside `{org}` — OR the reserved sentinel `_` meaning "no Project" (a direct-repo / repo-less dispatch on `POST`; "no Project constraint, resolve by session id alone" everywhere else). A real handle that doesn't match the session's actual Project is `404`.  |

## Request body

- `agent` (string, optional): `claude`, `codex` or `opencode`, optionally pinned to a CLI version: `claude@2.1.291`.
- `prompt` (string, required): The task. At most 256 KiB.
- `model` (string, optional): A model `id` that GET /o/{org}/agents/available lists for this harness. Omitted: the harness default.
- `effort` (string, optional, one of `none`, `minimal`, `low`, `medium`, `high`, `xhigh`, `max`, `auto`): Reasoning effort; must be one the model's row lists.
- `speed` (string, optional, one of `standard`, `fast`): `fast` where the model row lists it in `modes`. OpenCode has none.
- `mode` (string, optional, one of `headless`, `interactive`, default `"headless"`)
- `persistence` (string, optional, one of `resumable`, `ephemeral`, default `"resumable"`): `resumable` parks the sandbox with its disk and memory between turns, free while parked, for 7 idle days; `ephemeral` tears it down when the turn ends.
- `account_id` (string, optional): Run on one of the caller's own Anthropic or OpenAI API-key accounts instead of Rush's models.
- `base_branch` (string, optional): Branch to start from. Not with `on_pr`.
- `on_pr` (integer, optional): Continue on this open pull request's branch.
- `output_schema` (object, optional): A JSON Schema the final answer must match; it comes back as `result.structured` on `/result`, the `done` event and the webhook. claude and codex only (`422 FIELD_UNSUPPORTED_FOR_HARNESS` otherwise). The root is `type: "object"`; every object lists all its `properties` in `required` (make one optional with `type: [T, "null"]`) and sets `additionalProperties: false`; `$ref` stays inside the document; at most 10 levels and 64 KiB. Anything else is `400 OUTPUT_SCHEMA_INVALID`.

## A run with no repository

```bash
curl -X POST "https://api.prix.dev/o/$RUSH_ORG/p/_/sessions" \
  -H "Authorization: Bearer $RUSH_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "agent": "claude",
    "prompt": "Summarize the open issues labelled bug in three bullet points.",
    "persistence": "ephemeral"
  }'
```

```typescript
const org = process.env.RUSH_ORG;

const res = await fetch(`https://api.prix.dev/o/${org}/p/_/sessions`, {
  method: "POST",
  headers: {
    Authorization: `Bearer ${process.env.RUSH_API_KEY}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    agent: "claude",
    prompt: "Summarize the open issues labelled bug in three bullet points.",
    persistence: "ephemeral",
  }),
});

console.log(res.status, await res.json());
```

```python
import os

import requests

org = os.environ["RUSH_ORG"]

res = requests.post(
    f"https://api.prix.dev/o/{org}/p/_/sessions",
    headers={"Authorization": f"Bearer {os.environ['RUSH_API_KEY']}"},
    json={
        "agent": "claude",
        "prompt": "Summarize the open issues labelled bug in three bullet points.",
        "persistence": "ephemeral",
    },
)

print(res.status_code, res.json())
```

## A run that must answer in a JSON shape

```bash
curl -X POST "https://api.prix.dev/o/$RUSH_ORG/p/_/sessions" \
  -H "Authorization: Bearer $RUSH_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "agent": "codex",
    "model": "gpt-5.5",
    "effort": "high",
    "prompt": "Read package.json and report the test command.",
    "output_schema": {
      "type": "object",
      "properties": {
        "test_command": {
          "type": "string"
        }
      },
      "required": ["test_command"],
      "additionalProperties": false
    }
  }'
```

```typescript
const org = process.env.RUSH_ORG;

const res = await fetch(`https://api.prix.dev/o/${org}/p/_/sessions`, {
  method: "POST",
  headers: {
    Authorization: `Bearer ${process.env.RUSH_API_KEY}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    agent: "codex",
    model: "gpt-5.5",
    effort: "high",
    prompt: "Read package.json and report the test command.",
    output_schema: {
      type: "object",
      properties: {
        test_command: {
          type: "string",
        },
      },
      required: ["test_command"],
      additionalProperties: false,
    },
  }),
});

console.log(res.status, await res.json());
```

```python
import os

import requests

org = os.environ["RUSH_ORG"]

res = requests.post(
    f"https://api.prix.dev/o/{org}/p/_/sessions",
    headers={"Authorization": f"Bearer {os.environ['RUSH_API_KEY']}"},
    json={
        "agent": "codex",
        "model": "gpt-5.5",
        "effort": "high",
        "prompt": "Read package.json and report the test command.",
        "output_schema": {
            "type": "object",
            "properties": {
                "test_command": {
                    "type": "string",
                },
            },
            "required": ["test_command"],
            "additionalProperties": False,
        },
    },
)

print(res.status_code, res.json())
```

## Responses

### 202

The session, as created. `status` is `queued`, `allocating` or `running` depending on admission.

- `execution_id` (string, required)
- `kind` (string, required, one of `cloud`, `local`)
- `org_id` (string | null, optional)
- `project_id` (string | null, optional)
- `agent` (string | null, optional): The harness.
- `status` (string, required, one of `queued`, `allocating`, `running`, `paused`, `input_required`, `needs_review`, `completed`, `failed`, `cancelled`, `expired`): `paused` is a resumable session parked between turns; `needs_review` finished without the proof it was asked for.
- `persistence_mode` (string | null, optional, one of `ephemeral`, `resumable`, `null`)
- `machine_state` (string | null, optional): The sandbox's own lifecycle (preparing, running, pausing, paused, resuming…), separate from `status`.
- `sandbox_generation` (integer | null, optional): Increments on every resume.
- `prompt` (string | null, optional)
- `repo_owner` (string | null, optional)
- `repo_name` (string | null, optional)
- `branch` (string | null, optional)
- `pr_url` (string | null, optional)
- `summary` (string | null, optional)
- `error` (string | null, optional)
- `started_by` (object | null, optional)
  - `name` (string | null, optional)
  - `avatar_url` (string | null, optional)
- `input_tokens` (integer | null, optional)
- `output_tokens` (integer | null, optional)
- `cache_read_tokens` (integer | null, optional)
- `cache_write_tokens` (integer | null, optional)
- `total_tokens` (integer | null, optional): Uncached input plus cache writes plus output; null when the run reported none.
- `reasoning_tokens` (integer | null, optional)
- `total_cost_usd` (number | null, optional)
- `model` (string | null, optional)
- `tool_calls_count` (integer | null, optional)
- `tool_errors_count` (integer | null, optional)
- `turns_count` (integer | null, optional)
- `files_produced` (integer | null, optional)
- `attachments` (array of object, optional): Files the caller attached when starting the run.
  - `id` (string, required)
  - `name` (string, required)
  - `mime` (string, required)
  - `size` (integer, required)
  - `expired_at` (string | null, required)
- `artifacts` (array of ArtifactFile, optional): The first 6 artifacts; `artifact_count` has the total.
  - `name` (string, required)
  - `size` (integer, required): Bytes.
  - `content_type` (string, required)
- `artifact_count` (integer, optional)
- `harness_version_requested` (string | null, optional)
- `harness_version_resolved` (string | null, optional)
- `profile_id` (string | null, optional): The saved agent the run started from.
- `profile_revision` (integer | null, optional)
- `profile_digest` (string | null, optional)
- `requested_overrides` (object | null, optional)
  - `model` (string, optional)
  - `effort` (string, optional)
  - `speed` (string, optional)
- `agent_profile` (object | null, optional)
  - `id` (string, optional)
  - `name` (string, optional)
- `effective` (object | null, optional): What a saved-agent run actually ran with.
  - `model` (string | null, optional)
  - `effort` (string | null, optional)
  - `speed` (string | null, optional)
  - `harness_version` (string | null, optional)
  - `catalog_revision` (string | null, optional)
  - `image_digest` (string | null, optional)
- `snapshot` (object | null, optional): The saved-agent configuration the run was pinned to.
- `effective_config` (object | null, optional): What the sandbox loaded (harness version, plugins, hooks, commands), as the runtime reported it.
- `session_capture` (string | null, optional, one of `complete`, `partial`, `failed`, `null`)
- `created_at` (string, required)
- `updated_at` (string | null, optional)

### 400

The body is invalid: no `prompt`, no `agent` on a `_` run, an unknown
`effort`, `speed` or `persistence`, a malformed repository, or an
`output_schema` outside the accepted subset (`code`
`OUTPUT_SCHEMA_INVALID`).

### 401

No bearer, an unknown, revoked or expired one, or an API key on a route keys cannot call.

### 402

The plan does not cover this run: `PLAN_REQUIRED` (Rush's models need
a paid plan), `TOKEN_LIMIT_REACHED`, `COMPUTE_LIMIT_REACHED`,
`WEEKLY_COMPUTE_LIMIT_REACHED`, `SPEND_CAP_REACHED` or
`PAYMENT_METHOD_REQUIRED`.

### 403

The repository is not in a GitHub App installation linked to the caller (`INSTALLATION_NOT_LINKED`, `REPO_NOT_IN_INSTALLATION`).

### 404

No such resource for the caller, including one that exists in an org the caller cannot see.

### 409

The Project's GitHub App installation is suspended, `on_pr` names a pull request that is not open, or a saved agent's catalog changed since it was reviewed (`CATALOG_REFRESH_REQUIRED`).

### 413

An attached payload is over its size limit.

### 422

A field the run cannot honor: an agent outside `claude`, `codex`,
`opencode` (`UNSUPPORTED_AGENT`); a `model` the harness does not list
in `GET /o/{org}/agents/available` (`error_code` `MODEL_UNSUPPORTED`);
`output_schema` on `opencode` (`FIELD_UNSUPPORTED_FOR_HARNESS`); or a
saved agent or sources on a key run (`API_KEY_FIELD_UNSUPPORTED`).

### 429

The API key already has `max_concurrent` runs in progress (`RATE_LIMITED`).

## Example response (202)

```json
{
  "execution_id": "3f9c2a71d04b8e65",
  "kind": "cloud",
  "project_id": null,
  "agent": "claude",
  "status": "queued",
  "persistence_mode": "ephemeral",
  "prompt": "Summarize the open issues labelled bug in three bullet points.",
  "created_at": "2026-10-06T15:02:11.000Z"
}
```
