# Environments

Source: https://opvs.ai/docs/api/environments

## `GET` /api/v1/environments

**List Environments**

The caller's fleet, plus the brand this read was scoped to.

```bash
curl -X GET 'https://app.opvs.ai/api/v1/environments' \
  -H 'Authorization: Bearer <token>'
```

```python
import httpx

resp = httpx.get(
    "https://app.opvs.ai/api/v1/environments",
    headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())
```

```javascript
const resp = await fetch("https://app.opvs.ai/api/v1/environments", {
  method: "GET",
  headers: { "Authorization": "Bearer <token>" }
});
const data = await resp.json();
console.log(data);
```

```go
package main

import (
	"net/http"
)

func main() {
	req, _ := http.NewRequest("GET", "https://app.opvs.ai/api/v1/environments", nil)
	req.Header.Set("Authorization", "Bearer <token>")
	resp, _ := http.DefaultClient.Do(req)
	defer resp.Body.Close()
}
```

**Responses**

- `200` — Successful Response

## `POST` /api/v1/environments

**Create Environment**

**Request body**

```bash
curl -X POST 'https://app.opvs.ai/api/v1/environments' \
  -H 'Authorization: Bearer <token>' \
  -H 'Content-Type: application/json' \
  -d '{
  "name": "string",
  "description": "string",
  "environment_type": "connected",
  "runtime": "claude_code",
  "workspace_path": "/home/agent",
  "sidecar_url": "string",
  "vps_provider": "string",
  "region": "string",
  "desk_kind": "dev_agent"
}'
```

```python
import httpx

resp = httpx.post(
    "https://app.opvs.ai/api/v1/environments",
    headers={"Authorization": "Bearer <token>", "Content-Type": "application/json"},
    json={"name": "string", "description": "string", "environment_type": "connected", "runtime": "claude_code", "workspace_path": "/home/agent", "sidecar_url": "string", "vps_provider": "string", "region": "string", "desk_kind": "dev_agent"},
)
resp.raise_for_status()
print(resp.json())
```

```javascript
const resp = await fetch("https://app.opvs.ai/api/v1/environments", {
  method: "POST",
  headers: { "Authorization": "Bearer <token>", "Content-Type": "application/json" },
  body: JSON.stringify({"name": "string", "description": "string", "environment_type": "connected", "runtime": "claude_code", "workspace_path": "/home/agent", "sidecar_url": "string", "vps_provider": "string", "region": "string", "desk_kind": "dev_agent"})
});
const data = await resp.json();
console.log(data);
```

```go
package main

import (
	"net/http"
	"strings"
)

func main() {
	body := strings.NewReader(`{"name": "string", "description": "string", "environment_type": "connected", "runtime": "claude_code", "workspace_path": "/home/agent", "sidecar_url": "string", "vps_provider": "string", "region": "string", "desk_kind": "dev_agent"}`)
	req, _ := http.NewRequest("POST", "https://app.opvs.ai/api/v1/environments", body)
	req.Header.Set("Authorization", "Bearer <token>")
	req.Header.Set("Content-Type", "application/json")
	resp, _ := http.DefaultClient.Do(req)
	defer resp.Body.Close()
}
```

**Responses**

- `201` — Successful Response
- `422` — Validation Error

## `GET` /api/v1/environments/machines

**List Fleet Machines**

One ``MachineSlots`` view per machine the caller's brand has a desk on.

```bash
curl -X GET 'https://app.opvs.ai/api/v1/environments/machines' \
  -H 'Authorization: Bearer <token>'
```

```python
import httpx

resp = httpx.get(
    "https://app.opvs.ai/api/v1/environments/machines",
    headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())
```

```javascript
const resp = await fetch("https://app.opvs.ai/api/v1/environments/machines", {
  method: "GET",
  headers: { "Authorization": "Bearer <token>" }
});
const data = await resp.json();
console.log(data);
```

```go
package main

import (
	"net/http"
)

func main() {
	req, _ := http.NewRequest("GET", "https://app.opvs.ai/api/v1/environments/machines", nil)
	req.Header.Set("Authorization", "Bearer <token>")
	resp, _ := http.DefaultClient.Do(req)
	defer resp.Body.Close()
}
```

**Responses**

- `200` — Successful Response

## `GET` /api/v1/environments/allowance

**Get Environment Allowance**

How many machines this brand holds, and how many it may hold.

```bash
curl -X GET 'https://app.opvs.ai/api/v1/environments/allowance' \
  -H 'Authorization: Bearer <token>'
```

```python
import httpx

resp = httpx.get(
    "https://app.opvs.ai/api/v1/environments/allowance",
    headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())
```

```javascript
const resp = await fetch("https://app.opvs.ai/api/v1/environments/allowance", {
  method: "GET",
  headers: { "Authorization": "Bearer <token>" }
});
const data = await resp.json();
console.log(data);
```

```go
package main

import (
	"net/http"
)

func main() {
	req, _ := http.NewRequest("GET", "https://app.opvs.ai/api/v1/environments/allowance", nil)
	req.Header.Set("Authorization", "Bearer <token>")
	resp, _ := http.DefaultClient.Do(req)
	defer resp.Body.Close()
}
```

**Responses**

- `200` — Successful Response

## `GET` /api/v1/environments/credentials/reauth-status

**Get Fleet Reauth Status**

Every lapsed subscription login across the caller's whole fleet, in ONE call.

```bash
curl -X GET 'https://app.opvs.ai/api/v1/environments/credentials/reauth-status' \
  -H 'Authorization: Bearer <token>'
```

```python
import httpx

resp = httpx.get(
    "https://app.opvs.ai/api/v1/environments/credentials/reauth-status",
    headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())
```

```javascript
const resp = await fetch("https://app.opvs.ai/api/v1/environments/credentials/reauth-status", {
  method: "GET",
  headers: { "Authorization": "Bearer <token>" }
});
const data = await resp.json();
console.log(data);
```

```go
package main

import (
	"net/http"
)

func main() {
	req, _ := http.NewRequest("GET", "https://app.opvs.ai/api/v1/environments/credentials/reauth-status", nil)
	req.Header.Set("Authorization", "Bearer <token>")
	resp, _ := http.DefaultClient.Do(req)
	defer resp.Body.Close()
}
```

**Responses**

- `200` — Successful Response

## `GET` /api/v1/environments/projections

**Get Fleet Projections**

How many boards and cards each of the brand's machines has written.

```bash
curl -X GET 'https://app.opvs.ai/api/v1/environments/projections' \
  -H 'Authorization: Bearer <token>'
```

```python
import httpx

resp = httpx.get(
    "https://app.opvs.ai/api/v1/environments/projections",
    headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())
```

```javascript
const resp = await fetch("https://app.opvs.ai/api/v1/environments/projections", {
  method: "GET",
  headers: { "Authorization": "Bearer <token>" }
});
const data = await resp.json();
console.log(data);
```

```go
package main

import (
	"net/http"
)

func main() {
	req, _ := http.NewRequest("GET", "https://app.opvs.ai/api/v1/environments/projections", nil)
	req.Header.Set("Authorization", "Bearer <token>")
	resp, _ := http.DefaultClient.Do(req)
	defer resp.Body.Close()
}
```

**Responses**

- `200` — Successful Response

## `POST` /api/v1/environments/{env_id}/regenerate-pat

**Regenerate Environment Pat**

Rotate this environment's install PAT and reveal the new one ONCE.

**Parameters**

- `env_id` (path, string, required)

```bash
curl -X POST 'https://app.opvs.ai/api/v1/environments/{env_id}/regenerate-pat' \
  -H 'Authorization: Bearer <token>'
```

```python
import httpx

resp = httpx.post(
    "https://app.opvs.ai/api/v1/environments/{env_id}/regenerate-pat",
    headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())
```

```javascript
const resp = await fetch("https://app.opvs.ai/api/v1/environments/{env_id}/regenerate-pat", {
  method: "POST",
  headers: { "Authorization": "Bearer <token>" }
});
const data = await resp.json();
console.log(data);
```

```go
package main

import (
	"net/http"
)

func main() {
	req, _ := http.NewRequest("POST", "https://app.opvs.ai/api/v1/environments/{env_id}/regenerate-pat", nil)
	req.Header.Set("Authorization", "Bearer <token>")
	resp, _ := http.DefaultClient.Do(req)
	defer resp.Body.Close()
}
```

**Responses**

- `200` — Successful Response
- `422` — Validation Error

## `GET` /api/v1/environments/{env_id}/slots

**List Machine Slots**

Every desk on this machine — what the "add another here" dialog reads.

**Parameters**

- `env_id` (path, string, required)

```bash
curl -X GET 'https://app.opvs.ai/api/v1/environments/{env_id}/slots' \
  -H 'Authorization: Bearer <token>'
```

```python
import httpx

resp = httpx.get(
    "https://app.opvs.ai/api/v1/environments/{env_id}/slots",
    headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())
```

```javascript
const resp = await fetch("https://app.opvs.ai/api/v1/environments/{env_id}/slots", {
  method: "GET",
  headers: { "Authorization": "Bearer <token>" }
});
const data = await resp.json();
console.log(data);
```

```go
package main

import (
	"net/http"
)

func main() {
	req, _ := http.NewRequest("GET", "https://app.opvs.ai/api/v1/environments/{env_id}/slots", nil)
	req.Header.Set("Authorization", "Bearer <token>")
	resp, _ := http.DefaultClient.Do(req)
	defer resp.Body.Close()
}
```

**Responses**

- `200` — Successful Response
- `422` — Validation Error

## `POST` /api/v1/environments/{env_id}/slots

**Add Machine Slot**

Add a desk to a machine this brand already has (BYO §6.4).

**Parameters**

- `env_id` (path, string, required)

**Request body**

```bash
curl -X POST 'https://app.opvs.ai/api/v1/environments/{env_id}/slots' \
  -H 'Authorization: Bearer <token>' \
  -H 'Content-Type: application/json' \
  -d '{
  "name": "string",
  "description": "string",
  "runtime": "claude_code",
  "workspace_path": "string",
  "persona_id": "string",
  "desk_kind": "dev_agent"
}'
```

```python
import httpx

resp = httpx.post(
    "https://app.opvs.ai/api/v1/environments/{env_id}/slots",
    headers={"Authorization": "Bearer <token>", "Content-Type": "application/json"},
    json={"name": "string", "description": "string", "runtime": "claude_code", "workspace_path": "string", "persona_id": "string", "desk_kind": "dev_agent"},
)
resp.raise_for_status()
print(resp.json())
```

```javascript
const resp = await fetch("https://app.opvs.ai/api/v1/environments/{env_id}/slots", {
  method: "POST",
  headers: { "Authorization": "Bearer <token>", "Content-Type": "application/json" },
  body: JSON.stringify({"name": "string", "description": "string", "runtime": "claude_code", "workspace_path": "string", "persona_id": "string", "desk_kind": "dev_agent"})
});
const data = await resp.json();
console.log(data);
```

```go
package main

import (
	"net/http"
	"strings"
)

func main() {
	body := strings.NewReader(`{"name": "string", "description": "string", "runtime": "claude_code", "workspace_path": "string", "persona_id": "string", "desk_kind": "dev_agent"}`)
	req, _ := http.NewRequest("POST", "https://app.opvs.ai/api/v1/environments/{env_id}/slots", body)
	req.Header.Set("Authorization", "Bearer <token>")
	req.Header.Set("Content-Type", "application/json")
	resp, _ := http.DefaultClient.Do(req)
	defer resp.Body.Close()
}
```

**Responses**

- `201` — Successful Response
- `422` — Validation Error

## `GET` /api/v1/environments/{env_id}/mail-wake

**List Mail Wake Bindings**

**Parameters**

- `env_id` (path, string, required)

```bash
curl -X GET 'https://app.opvs.ai/api/v1/environments/{env_id}/mail-wake' \
  -H 'Authorization: Bearer <token>'
```

```python
import httpx

resp = httpx.get(
    "https://app.opvs.ai/api/v1/environments/{env_id}/mail-wake",
    headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())
```

```javascript
const resp = await fetch("https://app.opvs.ai/api/v1/environments/{env_id}/mail-wake", {
  method: "GET",
  headers: { "Authorization": "Bearer <token>" }
});
const data = await resp.json();
console.log(data);
```

```go
package main

import (
	"net/http"
)

func main() {
	req, _ := http.NewRequest("GET", "https://app.opvs.ai/api/v1/environments/{env_id}/mail-wake", nil)
	req.Header.Set("Authorization", "Bearer <token>")
	resp, _ := http.DefaultClient.Do(req)
	defer resp.Body.Close()
}
```

**Responses**

- `200` — Successful Response
- `422` — Validation Error

## `PUT` /api/v1/environments/{env_id}/mail-wake

**Put Mail Wake Binding**

**Parameters**

- `env_id` (path, string, required)

**Request body**

```bash
curl -X PUT 'https://app.opvs.ai/api/v1/environments/{env_id}/mail-wake' \
  -H 'Authorization: Bearer <token>' \
  -H 'Content-Type: application/json' \
  -d '{
  "address": "string",
  "session_name": "string",
  "enabled": true
}'
```

```python
import httpx

resp = httpx.put(
    "https://app.opvs.ai/api/v1/environments/{env_id}/mail-wake",
    headers={"Authorization": "Bearer <token>", "Content-Type": "application/json"},
    json={"address": "string", "session_name": "string", "enabled": true},
)
resp.raise_for_status()
print(resp.json())
```

```javascript
const resp = await fetch("https://app.opvs.ai/api/v1/environments/{env_id}/mail-wake", {
  method: "PUT",
  headers: { "Authorization": "Bearer <token>", "Content-Type": "application/json" },
  body: JSON.stringify({"address": "string", "session_name": "string", "enabled": true})
});
const data = await resp.json();
console.log(data);
```

```go
package main

import (
	"net/http"
	"strings"
)

func main() {
	body := strings.NewReader(`{"address": "string", "session_name": "string", "enabled": true}`)
	req, _ := http.NewRequest("PUT", "https://app.opvs.ai/api/v1/environments/{env_id}/mail-wake", body)
	req.Header.Set("Authorization", "Bearer <token>")
	req.Header.Set("Content-Type", "application/json")
	resp, _ := http.DefaultClient.Do(req)
	defer resp.Body.Close()
}
```

**Responses**

- `200` — Successful Response
- `422` — Validation Error

## `DELETE` /api/v1/environments/{env_id}/mail-wake/{address}

**Delete Mail Wake Binding**

**Parameters**

- `env_id` (path, string, required)
- `address` (path, string, required)

```bash
curl -X DELETE 'https://app.opvs.ai/api/v1/environments/{env_id}/mail-wake/{address}' \
  -H 'Authorization: Bearer <token>'
```

```python
import httpx

resp = httpx.delete(
    "https://app.opvs.ai/api/v1/environments/{env_id}/mail-wake/{address}",
    headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())
```

```javascript
const resp = await fetch("https://app.opvs.ai/api/v1/environments/{env_id}/mail-wake/{address}", {
  method: "DELETE",
  headers: { "Authorization": "Bearer <token>" }
});
const data = await resp.json();
console.log(data);
```

```go
package main

import (
	"net/http"
)

func main() {
	req, _ := http.NewRequest("DELETE", "https://app.opvs.ai/api/v1/environments/{env_id}/mail-wake/{address}", nil)
	req.Header.Set("Authorization", "Bearer <token>")
	resp, _ := http.DefaultClient.Do(req)
	defer resp.Body.Close()
}
```

**Responses**

- `200` — Successful Response
- `422` — Validation Error

## `GET` /api/v1/environments/{env_id}/capabilities

**Get Environment Capabilities**

**Parameters**

- `env_id` (path, string, required)

```bash
curl -X GET 'https://app.opvs.ai/api/v1/environments/{env_id}/capabilities' \
  -H 'Authorization: Bearer <token>'
```

```python
import httpx

resp = httpx.get(
    "https://app.opvs.ai/api/v1/environments/{env_id}/capabilities",
    headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())
```

```javascript
const resp = await fetch("https://app.opvs.ai/api/v1/environments/{env_id}/capabilities", {
  method: "GET",
  headers: { "Authorization": "Bearer <token>" }
});
const data = await resp.json();
console.log(data);
```

```go
package main

import (
	"net/http"
)

func main() {
	req, _ := http.NewRequest("GET", "https://app.opvs.ai/api/v1/environments/{env_id}/capabilities", nil)
	req.Header.Set("Authorization", "Bearer <token>")
	resp, _ := http.DefaultClient.Do(req)
	defer resp.Body.Close()
}
```

**Responses**

- `200` — Successful Response
- `422` — Validation Error

## `PUT` /api/v1/environments/{env_id}/capabilities

**Put Environment Capabilities**

**Parameters**

- `env_id` (path, string, required)

**Request body**

```bash
curl -X PUT 'https://app.opvs.ai/api/v1/environments/{env_id}/capabilities' \
  -H 'Authorization: Bearer <token>' \
  -H 'Content-Type: application/json' \
  -d '{
  "version": 1,
  "web_search": false,
  "web_fetch": false,
  "browser": false,
  "network_install": false,
  "mcp_servers": [
    {
      "name": "string",
      "transport": "url",
      "command": "string",
      "url": "string",
      "integration_id": 0,
      "login_env": {}
    }
  ],
  "clis": [
    {
      "name": "string",
      "install": "string",
      "check_command": "string",
      "integration_id": 0,
      "login_env": {}
    }
  ],
  "skills": false,
  "media": {
    "images": [
      "string"
    ],
    "video": [
      "string"
    ]
  },
  "scratch_folder": false,
  "output_type": "pr",
  "wall_minutes": 120
}'
```

```python
import httpx

resp = httpx.put(
    "https://app.opvs.ai/api/v1/environments/{env_id}/capabilities",
    headers={"Authorization": "Bearer <token>", "Content-Type": "application/json"},
    json={"version": 1, "web_search": false, "web_fetch": false, "browser": false, "network_install": false, "mcp_servers": [{"name": "string", "transport": "url", "command": "string", "url": "string", "integration_id": 0, "login_env": {}}], "clis": [{"name": "string", "install": "string", "check_command": "string", "integration_id": 0, "login_env": {}}], "skills": false, "media": {"images": ["string"], "video": ["string"]}, "scratch_folder": false, "output_type": "pr", "wall_minutes": 120},
)
resp.raise_for_status()
print(resp.json())
```

```javascript
const resp = await fetch("https://app.opvs.ai/api/v1/environments/{env_id}/capabilities", {
  method: "PUT",
  headers: { "Authorization": "Bearer <token>", "Content-Type": "application/json" },
  body: JSON.stringify({"version": 1, "web_search": false, "web_fetch": false, "browser": false, "network_install": false, "mcp_servers": [{"name": "string", "transport": "url", "command": "string", "url": "string", "integration_id": 0, "login_env": {}}], "clis": [{"name": "string", "install": "string", "check_command": "string", "integration_id": 0, "login_env": {}}], "skills": false, "media": {"images": ["string"], "video": ["string"]}, "scratch_folder": false, "output_type": "pr", "wall_minutes": 120})
});
const data = await resp.json();
console.log(data);
```

```go
package main

import (
	"net/http"
	"strings"
)

func main() {
	body := strings.NewReader(`{"version": 1, "web_search": false, "web_fetch": false, "browser": false, "network_install": false, "mcp_servers": [{"name": "string", "transport": "url", "command": "string", "url": "string", "integration_id": 0, "login_env": {}}], "clis": [{"name": "string", "install": "string", "check_command": "string", "integration_id": 0, "login_env": {}}], "skills": false, "media": {"images": ["string"], "video": ["string"]}, "scratch_folder": false, "output_type": "pr", "wall_minutes": 120}`)
	req, _ := http.NewRequest("PUT", "https://app.opvs.ai/api/v1/environments/{env_id}/capabilities", body)
	req.Header.Set("Authorization", "Bearer <token>")
	req.Header.Set("Content-Type", "application/json")
	resp, _ := http.DefaultClient.Do(req)
	defer resp.Body.Close()
}
```

**Responses**

- `200` — Successful Response
- `422` — Validation Error

## `GET` /api/v1/environments/{env_id}/capabilities/effective

**Get Effective Environment Capabilities**

Return the selected build policy narrowed by this desk's machine.

**Parameters**

- `env_id` (path, string, required)
- `profile` (query, any, optional)

```bash
curl -X GET 'https://app.opvs.ai/api/v1/environments/{env_id}/capabilities/effective' \
  -H 'Authorization: Bearer <token>'
```

```python
import httpx

resp = httpx.get(
    "https://app.opvs.ai/api/v1/environments/{env_id}/capabilities/effective",
    headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())
```

```javascript
const resp = await fetch("https://app.opvs.ai/api/v1/environments/{env_id}/capabilities/effective", {
  method: "GET",
  headers: { "Authorization": "Bearer <token>" }
});
const data = await resp.json();
console.log(data);
```

```go
package main

import (
	"net/http"
)

func main() {
	req, _ := http.NewRequest("GET", "https://app.opvs.ai/api/v1/environments/{env_id}/capabilities/effective", nil)
	req.Header.Set("Authorization", "Bearer <token>")
	resp, _ := http.DefaultClient.Do(req)
	defer resp.Body.Close()
}
```

**Responses**

- `200` — Successful Response
- `422` — Validation Error

## `GET` /api/v1/environments/{env_id}/capabilities/history

**Get Environment Capability History**

**Parameters**

- `env_id` (path, string, required)

```bash
curl -X GET 'https://app.opvs.ai/api/v1/environments/{env_id}/capabilities/history' \
  -H 'Authorization: Bearer <token>'
```

```python
import httpx

resp = httpx.get(
    "https://app.opvs.ai/api/v1/environments/{env_id}/capabilities/history",
    headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())
```

```javascript
const resp = await fetch("https://app.opvs.ai/api/v1/environments/{env_id}/capabilities/history", {
  method: "GET",
  headers: { "Authorization": "Bearer <token>" }
});
const data = await resp.json();
console.log(data);
```

```go
package main

import (
	"net/http"
)

func main() {
	req, _ := http.NewRequest("GET", "https://app.opvs.ai/api/v1/environments/{env_id}/capabilities/history", nil)
	req.Header.Set("Authorization", "Bearer <token>")
	resp, _ := http.DefaultClient.Do(req)
	defer resp.Body.Close()
}
```

**Responses**

- `200` — Successful Response
- `422` — Validation Error

## `GET` /api/v1/environments/{env_id}

**Get Environment**

**Parameters**

- `env_id` (path, string, required)

```bash
curl -X GET 'https://app.opvs.ai/api/v1/environments/{env_id}' \
  -H 'Authorization: Bearer <token>'
```

```python
import httpx

resp = httpx.get(
    "https://app.opvs.ai/api/v1/environments/{env_id}",
    headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())
```

```javascript
const resp = await fetch("https://app.opvs.ai/api/v1/environments/{env_id}", {
  method: "GET",
  headers: { "Authorization": "Bearer <token>" }
});
const data = await resp.json();
console.log(data);
```

```go
package main

import (
	"net/http"
)

func main() {
	req, _ := http.NewRequest("GET", "https://app.opvs.ai/api/v1/environments/{env_id}", nil)
	req.Header.Set("Authorization", "Bearer <token>")
	resp, _ := http.DefaultClient.Do(req)
	defer resp.Body.Close()
}
```

**Responses**

- `200` — Successful Response
- `422` — Validation Error

## `PATCH` /api/v1/environments/{env_id}

**Update Environment**

Patch this box. One of the fields is a CONSENT, and it is gated apart.

**Parameters**

- `env_id` (path, string, required)

**Request body**

```bash
curl -X PATCH 'https://app.opvs.ai/api/v1/environments/{env_id}' \
  -H 'Authorization: Bearer <token>' \
  -H 'Content-Type: application/json' \
  -d '{
  "name": "string",
  "description": "string",
  "runtime": "claude_code",
  "status": "provisioned",
  "sidecar_url": "string",
  "desk_kind": "dev_agent",
  "cotenancy_allowed": true,
  "persona_id": "string"
}'
```

```python
import httpx

resp = httpx.patch(
    "https://app.opvs.ai/api/v1/environments/{env_id}",
    headers={"Authorization": "Bearer <token>", "Content-Type": "application/json"},
    json={"name": "string", "description": "string", "runtime": "claude_code", "status": "provisioned", "sidecar_url": "string", "desk_kind": "dev_agent", "cotenancy_allowed": true, "persona_id": "string"},
)
resp.raise_for_status()
print(resp.json())
```

```javascript
const resp = await fetch("https://app.opvs.ai/api/v1/environments/{env_id}", {
  method: "PATCH",
  headers: { "Authorization": "Bearer <token>", "Content-Type": "application/json" },
  body: JSON.stringify({"name": "string", "description": "string", "runtime": "claude_code", "status": "provisioned", "sidecar_url": "string", "desk_kind": "dev_agent", "cotenancy_allowed": true, "persona_id": "string"})
});
const data = await resp.json();
console.log(data);
```

```go
package main

import (
	"net/http"
	"strings"
)

func main() {
	body := strings.NewReader(`{"name": "string", "description": "string", "runtime": "claude_code", "status": "provisioned", "sidecar_url": "string", "desk_kind": "dev_agent", "cotenancy_allowed": true, "persona_id": "string"}`)
	req, _ := http.NewRequest("PATCH", "https://app.opvs.ai/api/v1/environments/{env_id}", body)
	req.Header.Set("Authorization", "Bearer <token>")
	req.Header.Set("Content-Type", "application/json")
	resp, _ := http.DefaultClient.Do(req)
	defer resp.Body.Close()
}
```

**Responses**

- `200` — Successful Response
- `422` — Validation Error

## `DELETE` /api/v1/environments/{env_id}

**Delete Environment**

Delete this box. Retires its install key; refuses if it is hosting guests.

**Parameters**

- `env_id` (path, string, required)

```bash
curl -X DELETE 'https://app.opvs.ai/api/v1/environments/{env_id}' \
  -H 'Authorization: Bearer <token>'
```

```python
import httpx

resp = httpx.delete(
    "https://app.opvs.ai/api/v1/environments/{env_id}",
    headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())
```

```javascript
const resp = await fetch("https://app.opvs.ai/api/v1/environments/{env_id}", {
  method: "DELETE",
  headers: { "Authorization": "Bearer <token>" }
});
const data = await resp.json();
console.log(data);
```

```go
package main

import (
	"net/http"
)

func main() {
	req, _ := http.NewRequest("DELETE", "https://app.opvs.ai/api/v1/environments/{env_id}", nil)
	req.Header.Set("Authorization", "Bearer <token>")
	resp, _ := http.DefaultClient.Do(req)
	defer resp.Body.Close()
}
```

**Responses**

- `200` — Successful Response
- `422` — Validation Error

## `GET` /api/v1/environments/{env_id}/image

**Get Environment Image**

Stream this box's photo.

**Parameters**

- `env_id` (path, string, required)

```bash
curl -X GET 'https://app.opvs.ai/api/v1/environments/{env_id}/image' \
  -H 'Authorization: Bearer <token>'
```

```python
import httpx

resp = httpx.get(
    "https://app.opvs.ai/api/v1/environments/{env_id}/image",
    headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())
```

```javascript
const resp = await fetch("https://app.opvs.ai/api/v1/environments/{env_id}/image", {
  method: "GET",
  headers: { "Authorization": "Bearer <token>" }
});
const data = await resp.json();
console.log(data);
```

```go
package main

import (
	"net/http"
)

func main() {
	req, _ := http.NewRequest("GET", "https://app.opvs.ai/api/v1/environments/{env_id}/image", nil)
	req.Header.Set("Authorization", "Bearer <token>")
	resp, _ := http.DefaultClient.Do(req)
	defer resp.Body.Close()
}
```

**Responses**

- `200` — Successful Response
- `422` — Validation Error

## `POST` /api/v1/environments/{env_id}/image

**Upload Environment Image**

Set this box's photo. Replaces any existing one.

**Parameters**

- `env_id` (path, string, required)

**Request body**

```bash
curl -X POST 'https://app.opvs.ai/api/v1/environments/{env_id}/image' \
  -H 'Authorization: Bearer <token>' \
  -H 'Content-Type: application/json' \
  -d '{
  "file": "string"
}'
```

```python
import httpx

resp = httpx.post(
    "https://app.opvs.ai/api/v1/environments/{env_id}/image",
    headers={"Authorization": "Bearer <token>", "Content-Type": "application/json"},
    json={"file": "string"},
)
resp.raise_for_status()
print(resp.json())
```

```javascript
const resp = await fetch("https://app.opvs.ai/api/v1/environments/{env_id}/image", {
  method: "POST",
  headers: { "Authorization": "Bearer <token>", "Content-Type": "application/json" },
  body: JSON.stringify({"file": "string"})
});
const data = await resp.json();
console.log(data);
```

```go
package main

import (
	"net/http"
	"strings"
)

func main() {
	body := strings.NewReader(`{"file": "string"}`)
	req, _ := http.NewRequest("POST", "https://app.opvs.ai/api/v1/environments/{env_id}/image", body)
	req.Header.Set("Authorization", "Bearer <token>")
	req.Header.Set("Content-Type", "application/json")
	resp, _ := http.DefaultClient.Do(req)
	defer resp.Body.Close()
}
```

**Responses**

- `200` — Successful Response
- `422` — Validation Error

## `DELETE` /api/v1/environments/{env_id}/image

**Delete Environment Image**

Remove this box's photo — the row pointer AND the stored object.

**Parameters**

- `env_id` (path, string, required)

```bash
curl -X DELETE 'https://app.opvs.ai/api/v1/environments/{env_id}/image' \
  -H 'Authorization: Bearer <token>'
```

```python
import httpx

resp = httpx.delete(
    "https://app.opvs.ai/api/v1/environments/{env_id}/image",
    headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())
```

```javascript
const resp = await fetch("https://app.opvs.ai/api/v1/environments/{env_id}/image", {
  method: "DELETE",
  headers: { "Authorization": "Bearer <token>" }
});
const data = await resp.json();
console.log(data);
```

```go
package main

import (
	"net/http"
)

func main() {
	req, _ := http.NewRequest("DELETE", "https://app.opvs.ai/api/v1/environments/{env_id}/image", nil)
	req.Header.Set("Authorization", "Bearer <token>")
	resp, _ := http.DefaultClient.Do(req)
	defer resp.Body.Close()
}
```

**Responses**

- `200` — Successful Response
- `422` — Validation Error

## `GET` /api/v1/environments/{env_id}/fs/{path}

**Fs Read**

**Parameters**

- `env_id` (path, string, required)
- `path` (path, string, required)

```bash
curl -X GET 'https://app.opvs.ai/api/v1/environments/{env_id}/fs/{path}' \
  -H 'Authorization: Bearer <token>'
```

```python
import httpx

resp = httpx.get(
    "https://app.opvs.ai/api/v1/environments/{env_id}/fs/{path}",
    headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())
```

```javascript
const resp = await fetch("https://app.opvs.ai/api/v1/environments/{env_id}/fs/{path}", {
  method: "GET",
  headers: { "Authorization": "Bearer <token>" }
});
const data = await resp.json();
console.log(data);
```

```go
package main

import (
	"net/http"
)

func main() {
	req, _ := http.NewRequest("GET", "https://app.opvs.ai/api/v1/environments/{env_id}/fs/{path}", nil)
	req.Header.Set("Authorization", "Bearer <token>")
	resp, _ := http.DefaultClient.Do(req)
	defer resp.Body.Close()
}
```

**Responses**

- `200` — Successful Response
- `422` — Validation Error

## `POST` /api/v1/environments/{env_id}/fs/{path}

**Fs Write**

**Parameters**

- `env_id` (path, string, required)
- `path` (path, string, required)

```bash
curl -X POST 'https://app.opvs.ai/api/v1/environments/{env_id}/fs/{path}' \
  -H 'Authorization: Bearer <token>'
```

```python
import httpx

resp = httpx.post(
    "https://app.opvs.ai/api/v1/environments/{env_id}/fs/{path}",
    headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())
```

```javascript
const resp = await fetch("https://app.opvs.ai/api/v1/environments/{env_id}/fs/{path}", {
  method: "POST",
  headers: { "Authorization": "Bearer <token>" }
});
const data = await resp.json();
console.log(data);
```

```go
package main

import (
	"net/http"
)

func main() {
	req, _ := http.NewRequest("POST", "https://app.opvs.ai/api/v1/environments/{env_id}/fs/{path}", nil)
	req.Header.Set("Authorization", "Bearer <token>")
	resp, _ := http.DefaultClient.Do(req)
	defer resp.Body.Close()
}
```

**Responses**

- `200` — Successful Response
- `422` — Validation Error

## `DELETE` /api/v1/environments/{env_id}/fs/{path}

**Fs Delete**

**Parameters**

- `env_id` (path, string, required)
- `path` (path, string, required)

```bash
curl -X DELETE 'https://app.opvs.ai/api/v1/environments/{env_id}/fs/{path}' \
  -H 'Authorization: Bearer <token>'
```

```python
import httpx

resp = httpx.delete(
    "https://app.opvs.ai/api/v1/environments/{env_id}/fs/{path}",
    headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())
```

```javascript
const resp = await fetch("https://app.opvs.ai/api/v1/environments/{env_id}/fs/{path}", {
  method: "DELETE",
  headers: { "Authorization": "Bearer <token>" }
});
const data = await resp.json();
console.log(data);
```

```go
package main

import (
	"net/http"
)

func main() {
	req, _ := http.NewRequest("DELETE", "https://app.opvs.ai/api/v1/environments/{env_id}/fs/{path}", nil)
	req.Header.Set("Authorization", "Bearer <token>")
	resp, _ := http.DefaultClient.Do(req)
	defer resp.Body.Close()
}
```

**Responses**

- `200` — Successful Response
- `422` — Validation Error

## `POST` /api/v1/environments/{env_id}/fs-move

**Fs Move**

**Parameters**

- `env_id` (path, string, required)

**Request body**

```bash
curl -X POST 'https://app.opvs.ai/api/v1/environments/{env_id}/fs-move' \
  -H 'Authorization: Bearer <token>' \
  -H 'Content-Type: application/json' \
  -d '{}'
```

```python
import httpx

resp = httpx.post(
    "https://app.opvs.ai/api/v1/environments/{env_id}/fs-move",
    headers={"Authorization": "Bearer <token>", "Content-Type": "application/json"},
    json={},
)
resp.raise_for_status()
print(resp.json())
```

```javascript
const resp = await fetch("https://app.opvs.ai/api/v1/environments/{env_id}/fs-move", {
  method: "POST",
  headers: { "Authorization": "Bearer <token>", "Content-Type": "application/json" },
  body: JSON.stringify({})
});
const data = await resp.json();
console.log(data);
```

```go
package main

import (
	"net/http"
	"strings"
)

func main() {
	body := strings.NewReader(`{}`)
	req, _ := http.NewRequest("POST", "https://app.opvs.ai/api/v1/environments/{env_id}/fs-move", body)
	req.Header.Set("Authorization", "Bearer <token>")
	req.Header.Set("Content-Type", "application/json")
	resp, _ := http.DefaultClient.Do(req)
	defer resp.Body.Close()
}
```

**Responses**

- `200` — Successful Response
- `422` — Validation Error

## `POST` /api/v1/environments/{env_id}/claude/inject

**Claude Inject**

**Parameters**

- `env_id` (path, string, required)

**Request body**

```bash
curl -X POST 'https://app.opvs.ai/api/v1/environments/{env_id}/claude/inject' \
  -H 'Authorization: Bearer <token>' \
  -H 'Content-Type: application/json' \
  -d '{}'
```

```python
import httpx

resp = httpx.post(
    "https://app.opvs.ai/api/v1/environments/{env_id}/claude/inject",
    headers={"Authorization": "Bearer <token>", "Content-Type": "application/json"},
    json={},
)
resp.raise_for_status()
print(resp.json())
```

```javascript
const resp = await fetch("https://app.opvs.ai/api/v1/environments/{env_id}/claude/inject", {
  method: "POST",
  headers: { "Authorization": "Bearer <token>", "Content-Type": "application/json" },
  body: JSON.stringify({})
});
const data = await resp.json();
console.log(data);
```

```go
package main

import (
	"net/http"
	"strings"
)

func main() {
	body := strings.NewReader(`{}`)
	req, _ := http.NewRequest("POST", "https://app.opvs.ai/api/v1/environments/{env_id}/claude/inject", body)
	req.Header.Set("Authorization", "Bearer <token>")
	req.Header.Set("Content-Type", "application/json")
	resp, _ := http.DefaultClient.Do(req)
	defer resp.Body.Close()
}
```

**Responses**

- `200` — Successful Response
- `422` — Validation Error

## `GET` /api/v1/environments/{env_id}/claude/skills

**Claude List Skills**

**Parameters**

- `env_id` (path, string, required)

```bash
curl -X GET 'https://app.opvs.ai/api/v1/environments/{env_id}/claude/skills' \
  -H 'Authorization: Bearer <token>'
```

```python
import httpx

resp = httpx.get(
    "https://app.opvs.ai/api/v1/environments/{env_id}/claude/skills",
    headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())
```

```javascript
const resp = await fetch("https://app.opvs.ai/api/v1/environments/{env_id}/claude/skills", {
  method: "GET",
  headers: { "Authorization": "Bearer <token>" }
});
const data = await resp.json();
console.log(data);
```

```go
package main

import (
	"net/http"
)

func main() {
	req, _ := http.NewRequest("GET", "https://app.opvs.ai/api/v1/environments/{env_id}/claude/skills", nil)
	req.Header.Set("Authorization", "Bearer <token>")
	resp, _ := http.DefaultClient.Do(req)
	defer resp.Body.Close()
}
```

**Responses**

- `200` — Successful Response
- `422` — Validation Error

## `POST` /api/v1/environments/{env_id}/claude/skills/{name}

**Claude Install Skill**

**Parameters**

- `env_id` (path, string, required)
- `name` (path, string, required)

**Request body**

```bash
curl -X POST 'https://app.opvs.ai/api/v1/environments/{env_id}/claude/skills/{name}' \
  -H 'Authorization: Bearer <token>' \
  -H 'Content-Type: application/json' \
  -d '{}'
```

```python
import httpx

resp = httpx.post(
    "https://app.opvs.ai/api/v1/environments/{env_id}/claude/skills/{name}",
    headers={"Authorization": "Bearer <token>", "Content-Type": "application/json"},
    json={},
)
resp.raise_for_status()
print(resp.json())
```

```javascript
const resp = await fetch("https://app.opvs.ai/api/v1/environments/{env_id}/claude/skills/{name}", {
  method: "POST",
  headers: { "Authorization": "Bearer <token>", "Content-Type": "application/json" },
  body: JSON.stringify({})
});
const data = await resp.json();
console.log(data);
```

```go
package main

import (
	"net/http"
	"strings"
)

func main() {
	body := strings.NewReader(`{}`)
	req, _ := http.NewRequest("POST", "https://app.opvs.ai/api/v1/environments/{env_id}/claude/skills/{name}", body)
	req.Header.Set("Authorization", "Bearer <token>")
	req.Header.Set("Content-Type", "application/json")
	resp, _ := http.DefaultClient.Do(req)
	defer resp.Body.Close()
}
```

**Responses**

- `200` — Successful Response
- `422` — Validation Error

## `DELETE` /api/v1/environments/{env_id}/claude/skills/{name}

**Claude Remove Skill**

**Parameters**

- `env_id` (path, string, required)
- `name` (path, string, required)

```bash
curl -X DELETE 'https://app.opvs.ai/api/v1/environments/{env_id}/claude/skills/{name}' \
  -H 'Authorization: Bearer <token>'
```

```python
import httpx

resp = httpx.delete(
    "https://app.opvs.ai/api/v1/environments/{env_id}/claude/skills/{name}",
    headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())
```

```javascript
const resp = await fetch("https://app.opvs.ai/api/v1/environments/{env_id}/claude/skills/{name}", {
  method: "DELETE",
  headers: { "Authorization": "Bearer <token>" }
});
const data = await resp.json();
console.log(data);
```

```go
package main

import (
	"net/http"
)

func main() {
	req, _ := http.NewRequest("DELETE", "https://app.opvs.ai/api/v1/environments/{env_id}/claude/skills/{name}", nil)
	req.Header.Set("Authorization", "Bearer <token>")
	resp, _ := http.DefaultClient.Do(req)
	defer resp.Body.Close()
}
```

**Responses**

- `200` — Successful Response
- `422` — Validation Error

## `POST` /api/v1/environments/{env_id}/claude/plans/current

**Claude Set Plan**

**Parameters**

- `env_id` (path, string, required)

**Request body**

```bash
curl -X POST 'https://app.opvs.ai/api/v1/environments/{env_id}/claude/plans/current' \
  -H 'Authorization: Bearer <token>' \
  -H 'Content-Type: application/json' \
  -d '{}'
```

```python
import httpx

resp = httpx.post(
    "https://app.opvs.ai/api/v1/environments/{env_id}/claude/plans/current",
    headers={"Authorization": "Bearer <token>", "Content-Type": "application/json"},
    json={},
)
resp.raise_for_status()
print(resp.json())
```

```javascript
const resp = await fetch("https://app.opvs.ai/api/v1/environments/{env_id}/claude/plans/current", {
  method: "POST",
  headers: { "Authorization": "Bearer <token>", "Content-Type": "application/json" },
  body: JSON.stringify({})
});
const data = await resp.json();
console.log(data);
```

```go
package main

import (
	"net/http"
	"strings"
)

func main() {
	body := strings.NewReader(`{}`)
	req, _ := http.NewRequest("POST", "https://app.opvs.ai/api/v1/environments/{env_id}/claude/plans/current", body)
	req.Header.Set("Authorization", "Bearer <token>")
	req.Header.Set("Content-Type", "application/json")
	resp, _ := http.DefaultClient.Do(req)
	defer resp.Body.Close()
}
```

**Responses**

- `200` — Successful Response
- `422` — Validation Error

## `GET` /api/v1/environments/{env_id}/routines

**List Routines**

**Parameters**

- `env_id` (path, string, required)

```bash
curl -X GET 'https://app.opvs.ai/api/v1/environments/{env_id}/routines' \
  -H 'Authorization: Bearer <token>'
```

```python
import httpx

resp = httpx.get(
    "https://app.opvs.ai/api/v1/environments/{env_id}/routines",
    headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())
```

```javascript
const resp = await fetch("https://app.opvs.ai/api/v1/environments/{env_id}/routines", {
  method: "GET",
  headers: { "Authorization": "Bearer <token>" }
});
const data = await resp.json();
console.log(data);
```

```go
package main

import (
	"net/http"
)

func main() {
	req, _ := http.NewRequest("GET", "https://app.opvs.ai/api/v1/environments/{env_id}/routines", nil)
	req.Header.Set("Authorization", "Bearer <token>")
	resp, _ := http.DefaultClient.Do(req)
	defer resp.Body.Close()
}
```

**Responses**

- `200` — Successful Response
- `422` — Validation Error

## `PUT` /api/v1/environments/{env_id}/routines

**Replace Routines**

**Parameters**

- `env_id` (path, string, required)

**Request body**

```bash
curl -X PUT 'https://app.opvs.ai/api/v1/environments/{env_id}/routines' \
  -H 'Authorization: Bearer <token>' \
  -H 'Content-Type: application/json' \
  -d '[
  {}
]'
```

```python
import httpx

resp = httpx.put(
    "https://app.opvs.ai/api/v1/environments/{env_id}/routines",
    headers={"Authorization": "Bearer <token>", "Content-Type": "application/json"},
    json=[{}],
)
resp.raise_for_status()
print(resp.json())
```

```javascript
const resp = await fetch("https://app.opvs.ai/api/v1/environments/{env_id}/routines", {
  method: "PUT",
  headers: { "Authorization": "Bearer <token>", "Content-Type": "application/json" },
  body: JSON.stringify([{}])
});
const data = await resp.json();
console.log(data);
```

```go
package main

import (
	"net/http"
	"strings"
)

func main() {
	body := strings.NewReader(`[{}]`)
	req, _ := http.NewRequest("PUT", "https://app.opvs.ai/api/v1/environments/{env_id}/routines", body)
	req.Header.Set("Authorization", "Bearer <token>")
	req.Header.Set("Content-Type", "application/json")
	resp, _ := http.DefaultClient.Do(req)
	defer resp.Body.Close()
}
```

**Responses**

- `200` — Successful Response
- `422` — Validation Error

## `POST` /api/v1/environments/{env_id}/routines/{routine_id}/run

**Run Routine**

**Parameters**

- `env_id` (path, string, required)
- `routine_id` (path, string, required)

```bash
curl -X POST 'https://app.opvs.ai/api/v1/environments/{env_id}/routines/{routine_id}/run' \
  -H 'Authorization: Bearer <token>'
```

```python
import httpx

resp = httpx.post(
    "https://app.opvs.ai/api/v1/environments/{env_id}/routines/{routine_id}/run",
    headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())
```

```javascript
const resp = await fetch("https://app.opvs.ai/api/v1/environments/{env_id}/routines/{routine_id}/run", {
  method: "POST",
  headers: { "Authorization": "Bearer <token>" }
});
const data = await resp.json();
console.log(data);
```

```go
package main

import (
	"net/http"
)

func main() {
	req, _ := http.NewRequest("POST", "https://app.opvs.ai/api/v1/environments/{env_id}/routines/{routine_id}/run", nil)
	req.Header.Set("Authorization", "Bearer <token>")
	resp, _ := http.DefaultClient.Do(req)
	defer resp.Body.Close()
}
```

**Responses**

- `200` — Successful Response
- `422` — Validation Error

## `GET` /api/v1/environments/{env_id}/claude/bundle/preview

**Claude Bundle Preview**

Dry-run: what a role's method bundle WOULD install onto this desk.

**Parameters**

- `env_id` (path, string, required)
- `role` (query, string, required)
- `base_only` (query, boolean, optional)
- `project_id` (query, any, optional)
- `format` (query, any, optional)

```bash
curl -X GET 'https://app.opvs.ai/api/v1/environments/{env_id}/claude/bundle/preview' \
  -H 'Authorization: Bearer <token>'
```

```python
import httpx

resp = httpx.get(
    "https://app.opvs.ai/api/v1/environments/{env_id}/claude/bundle/preview",
    headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())
```

```javascript
const resp = await fetch("https://app.opvs.ai/api/v1/environments/{env_id}/claude/bundle/preview", {
  method: "GET",
  headers: { "Authorization": "Bearer <token>" }
});
const data = await resp.json();
console.log(data);
```

```go
package main

import (
	"net/http"
)

func main() {
	req, _ := http.NewRequest("GET", "https://app.opvs.ai/api/v1/environments/{env_id}/claude/bundle/preview", nil)
	req.Header.Set("Authorization", "Bearer <token>")
	resp, _ := http.DefaultClient.Do(req)
	defer resp.Body.Close()
}
```

**Responses**

- `200` — Successful Response
- `422` — Validation Error

## `POST` /api/v1/environments/{env_id}/claude/bundle

**Claude Install Bundle**

Install the OPVS control-plane image (role method bundle) onto this workstation.

**Parameters**

- `env_id` (path, string, required)

**Request body**

```bash
curl -X POST 'https://app.opvs.ai/api/v1/environments/{env_id}/claude/bundle' \
  -H 'Authorization: Bearer <token>' \
  -H 'Content-Type: application/json' \
  -d '{
  "role": "string",
  "base_only": false,
  "project": {
    "project_id": "string",
    "name": "string",
    "commands": [
      "string"
    ],
    "skills": [
      "string"
    ],
    "rules": [
      "string"
    ],
    "command_bodies": {},
    "skill_bodies": {}
  },
  "mirror_to_docs": true
}'
```

```python
import httpx

resp = httpx.post(
    "https://app.opvs.ai/api/v1/environments/{env_id}/claude/bundle",
    headers={"Authorization": "Bearer <token>", "Content-Type": "application/json"},
    json={"role": "string", "base_only": false, "project": {"project_id": "string", "name": "string", "commands": ["string"], "skills": ["string"], "rules": ["string"], "command_bodies": {}, "skill_bodies": {}}, "mirror_to_docs": true},
)
resp.raise_for_status()
print(resp.json())
```

```javascript
const resp = await fetch("https://app.opvs.ai/api/v1/environments/{env_id}/claude/bundle", {
  method: "POST",
  headers: { "Authorization": "Bearer <token>", "Content-Type": "application/json" },
  body: JSON.stringify({"role": "string", "base_only": false, "project": {"project_id": "string", "name": "string", "commands": ["string"], "skills": ["string"], "rules": ["string"], "command_bodies": {}, "skill_bodies": {}}, "mirror_to_docs": true})
});
const data = await resp.json();
console.log(data);
```

```go
package main

import (
	"net/http"
	"strings"
)

func main() {
	body := strings.NewReader(`{"role": "string", "base_only": false, "project": {"project_id": "string", "name": "string", "commands": ["string"], "skills": ["string"], "rules": ["string"], "command_bodies": {}, "skill_bodies": {}}, "mirror_to_docs": true}`)
	req, _ := http.NewRequest("POST", "https://app.opvs.ai/api/v1/environments/{env_id}/claude/bundle", body)
	req.Header.Set("Authorization", "Bearer <token>")
	req.Header.Set("Content-Type", "application/json")
	resp, _ := http.DefaultClient.Do(req)
	defer resp.Body.Close()
}
```

**Responses**

- `200` — Successful Response
- `422` — Validation Error

## `POST` /api/v1/environments/{env_id}/sync

**Trigger Sync**

**Parameters**

- `env_id` (path, string, required)

```bash
curl -X POST 'https://app.opvs.ai/api/v1/environments/{env_id}/sync' \
  -H 'Authorization: Bearer <token>'
```

```python
import httpx

resp = httpx.post(
    "https://app.opvs.ai/api/v1/environments/{env_id}/sync",
    headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())
```

```javascript
const resp = await fetch("https://app.opvs.ai/api/v1/environments/{env_id}/sync", {
  method: "POST",
  headers: { "Authorization": "Bearer <token>" }
});
const data = await resp.json();
console.log(data);
```

```go
package main

import (
	"net/http"
)

func main() {
	req, _ := http.NewRequest("POST", "https://app.opvs.ai/api/v1/environments/{env_id}/sync", nil)
	req.Header.Set("Authorization", "Bearer <token>")
	resp, _ := http.DefaultClient.Do(req)
	defer resp.Body.Close()
}
```

**Responses**

- `200` — Successful Response
- `422` — Validation Error

## `GET` /api/v1/environments/{env_id}/health

**Env Health**

**Parameters**

- `env_id` (path, string, required)

```bash
curl -X GET 'https://app.opvs.ai/api/v1/environments/{env_id}/health' \
  -H 'Authorization: Bearer <token>'
```

```python
import httpx

resp = httpx.get(
    "https://app.opvs.ai/api/v1/environments/{env_id}/health",
    headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())
```

```javascript
const resp = await fetch("https://app.opvs.ai/api/v1/environments/{env_id}/health", {
  method: "GET",
  headers: { "Authorization": "Bearer <token>" }
});
const data = await resp.json();
console.log(data);
```

```go
package main

import (
	"net/http"
)

func main() {
	req, _ := http.NewRequest("GET", "https://app.opvs.ai/api/v1/environments/{env_id}/health", nil)
	req.Header.Set("Authorization", "Bearer <token>")
	resp, _ := http.DefaultClient.Do(req)
	defer resp.Body.Close()
}
```

**Responses**

- `200` — Successful Response
- `422` — Validation Error

## `POST` /api/v1/environments/{env_id}/session

**Open Session**

**Parameters**

- `env_id` (path, string, required)

**Request body**

```bash
curl -X POST 'https://app.opvs.ai/api/v1/environments/{env_id}/session' \
  -H 'Authorization: Bearer <token>' \
  -H 'Content-Type: application/json' \
  -d '{}'
```

```python
import httpx

resp = httpx.post(
    "https://app.opvs.ai/api/v1/environments/{env_id}/session",
    headers={"Authorization": "Bearer <token>", "Content-Type": "application/json"},
    json={},
)
resp.raise_for_status()
print(resp.json())
```

```javascript
const resp = await fetch("https://app.opvs.ai/api/v1/environments/{env_id}/session", {
  method: "POST",
  headers: { "Authorization": "Bearer <token>", "Content-Type": "application/json" },
  body: JSON.stringify({})
});
const data = await resp.json();
console.log(data);
```

```go
package main

import (
	"net/http"
	"strings"
)

func main() {
	body := strings.NewReader(`{}`)
	req, _ := http.NewRequest("POST", "https://app.opvs.ai/api/v1/environments/{env_id}/session", body)
	req.Header.Set("Authorization", "Bearer <token>")
	req.Header.Set("Content-Type", "application/json")
	resp, _ := http.DefaultClient.Do(req)
	defer resp.Body.Close()
}
```

**Responses**

- `200` — Successful Response
- `422` — Validation Error

## `DELETE` /api/v1/environments/{env_id}/session/{name}

**Kill Session**

**Parameters**

- `env_id` (path, string, required)
- `name` (path, string, required)

```bash
curl -X DELETE 'https://app.opvs.ai/api/v1/environments/{env_id}/session/{name}' \
  -H 'Authorization: Bearer <token>'
```

```python
import httpx

resp = httpx.delete(
    "https://app.opvs.ai/api/v1/environments/{env_id}/session/{name}",
    headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())
```

```javascript
const resp = await fetch("https://app.opvs.ai/api/v1/environments/{env_id}/session/{name}", {
  method: "DELETE",
  headers: { "Authorization": "Bearer <token>" }
});
const data = await resp.json();
console.log(data);
```

```go
package main

import (
	"net/http"
)

func main() {
	req, _ := http.NewRequest("DELETE", "https://app.opvs.ai/api/v1/environments/{env_id}/session/{name}", nil)
	req.Header.Set("Authorization", "Bearer <token>")
	resp, _ := http.DefaultClient.Do(req)
	defer resp.Body.Close()
}
```

**Responses**

- `200` — Successful Response
- `422` — Validation Error

## `GET` /api/v1/environments/{env_id}/openhands-gui

**Openhands Gui Status**

**Parameters**

- `env_id` (path, string, required)

```bash
curl -X GET 'https://app.opvs.ai/api/v1/environments/{env_id}/openhands-gui' \
  -H 'Authorization: Bearer <token>'
```

```python
import httpx

resp = httpx.get(
    "https://app.opvs.ai/api/v1/environments/{env_id}/openhands-gui",
    headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())
```

```javascript
const resp = await fetch("https://app.opvs.ai/api/v1/environments/{env_id}/openhands-gui", {
  method: "GET",
  headers: { "Authorization": "Bearer <token>" }
});
const data = await resp.json();
console.log(data);
```

```go
package main

import (
	"net/http"
)

func main() {
	req, _ := http.NewRequest("GET", "https://app.opvs.ai/api/v1/environments/{env_id}/openhands-gui", nil)
	req.Header.Set("Authorization", "Bearer <token>")
	resp, _ := http.DefaultClient.Do(req)
	defer resp.Body.Close()
}
```

**Responses**

- `200` — Successful Response
- `422` — Validation Error

## `DELETE` /api/v1/environments/{env_id}/openhands-gui

**Openhands Gui Stop**

**Parameters**

- `env_id` (path, string, required)

```bash
curl -X DELETE 'https://app.opvs.ai/api/v1/environments/{env_id}/openhands-gui' \
  -H 'Authorization: Bearer <token>'
```

```python
import httpx

resp = httpx.delete(
    "https://app.opvs.ai/api/v1/environments/{env_id}/openhands-gui",
    headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())
```

```javascript
const resp = await fetch("https://app.opvs.ai/api/v1/environments/{env_id}/openhands-gui", {
  method: "DELETE",
  headers: { "Authorization": "Bearer <token>" }
});
const data = await resp.json();
console.log(data);
```

```go
package main

import (
	"net/http"
)

func main() {
	req, _ := http.NewRequest("DELETE", "https://app.opvs.ai/api/v1/environments/{env_id}/openhands-gui", nil)
	req.Header.Set("Authorization", "Bearer <token>")
	resp, _ := http.DefaultClient.Do(req)
	defer resp.Body.Close()
}
```

**Responses**

- `200` — Successful Response
- `422` — Validation Error

## `POST` /api/v1/environments/{env_id}/openhands-gui/start

**Openhands Gui Start**

**Parameters**

- `env_id` (path, string, required)

```bash
curl -X POST 'https://app.opvs.ai/api/v1/environments/{env_id}/openhands-gui/start' \
  -H 'Authorization: Bearer <token>'
```

```python
import httpx

resp = httpx.post(
    "https://app.opvs.ai/api/v1/environments/{env_id}/openhands-gui/start",
    headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())
```

```javascript
const resp = await fetch("https://app.opvs.ai/api/v1/environments/{env_id}/openhands-gui/start", {
  method: "POST",
  headers: { "Authorization": "Bearer <token>" }
});
const data = await resp.json();
console.log(data);
```

```go
package main

import (
	"net/http"
)

func main() {
	req, _ := http.NewRequest("POST", "https://app.opvs.ai/api/v1/environments/{env_id}/openhands-gui/start", nil)
	req.Header.Set("Authorization", "Bearer <token>")
	resp, _ := http.DefaultClient.Do(req)
	defer resp.Body.Close()
}
```

**Responses**

- `200` — Successful Response
- `422` — Validation Error

## `DELETE` /api/v1/environments/{env_id}/wg/peer

**Wg Remove Peer**

**Parameters**

- `env_id` (path, string, required)

```bash
curl -X DELETE 'https://app.opvs.ai/api/v1/environments/{env_id}/wg/peer' \
  -H 'Authorization: Bearer <token>'
```

```python
import httpx

resp = httpx.delete(
    "https://app.opvs.ai/api/v1/environments/{env_id}/wg/peer",
    headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())
```

```javascript
const resp = await fetch("https://app.opvs.ai/api/v1/environments/{env_id}/wg/peer", {
  method: "DELETE",
  headers: { "Authorization": "Bearer <token>" }
});
const data = await resp.json();
console.log(data);
```

```go
package main

import (
	"net/http"
)

func main() {
	req, _ := http.NewRequest("DELETE", "https://app.opvs.ai/api/v1/environments/{env_id}/wg/peer", nil)
	req.Header.Set("Authorization", "Bearer <token>")
	resp, _ := http.DefaultClient.Do(req)
	defer resp.Body.Close()
}
```

**Responses**

- `200` — Successful Response
- `422` — Validation Error

## `GET` /api/v1/environments/{env_id}/credentials/reauth-status

**Get Credential Reauth Status**

Dashboard-facing: the env's current interactive-credential re-auth flags.

**Parameters**

- `env_id` (path, string, required)

```bash
curl -X GET 'https://app.opvs.ai/api/v1/environments/{env_id}/credentials/reauth-status' \
  -H 'Authorization: Bearer <token>'
```

```python
import httpx

resp = httpx.get(
    "https://app.opvs.ai/api/v1/environments/{env_id}/credentials/reauth-status",
    headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())
```

```javascript
const resp = await fetch("https://app.opvs.ai/api/v1/environments/{env_id}/credentials/reauth-status", {
  method: "GET",
  headers: { "Authorization": "Bearer <token>" }
});
const data = await resp.json();
console.log(data);
```

```go
package main

import (
	"net/http"
)

func main() {
	req, _ := http.NewRequest("GET", "https://app.opvs.ai/api/v1/environments/{env_id}/credentials/reauth-status", nil)
	req.Header.Set("Authorization", "Bearer <token>")
	resp, _ := http.DefaultClient.Do(req)
	defer resp.Body.Close()
}
```

**Responses**

- `200` — Successful Response
- `422` — Validation Error

## `GET` /api/v1/environments/{env_id}/observations

**List Environment Observations**

Return newest-first observations without exposing another brand's env.

**Parameters**

- `env_id` (path, string, required)
- `since` (query, any, optional)
- `kind` (query, any, optional)

```bash
curl -X GET 'https://app.opvs.ai/api/v1/environments/{env_id}/observations' \
  -H 'Authorization: Bearer <token>'
```

```python
import httpx

resp = httpx.get(
    "https://app.opvs.ai/api/v1/environments/{env_id}/observations",
    headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())
```

```javascript
const resp = await fetch("https://app.opvs.ai/api/v1/environments/{env_id}/observations", {
  method: "GET",
  headers: { "Authorization": "Bearer <token>" }
});
const data = await resp.json();
console.log(data);
```

```go
package main

import (
	"net/http"
)

func main() {
	req, _ := http.NewRequest("GET", "https://app.opvs.ai/api/v1/environments/{env_id}/observations", nil)
	req.Header.Set("Authorization", "Bearer <token>")
	resp, _ := http.DefaultClient.Do(req)
	defer resp.Body.Close()
}
```

**Responses**

- `200` — Successful Response
- `422` — Validation Error

## List Environments

`GET https://app.opvs.ai/api/v1/environments`

Also as: CLI `opvs machines list` · MCP `tool_call software-factory.listEnvironments` · skill `software-factory`

The caller's fleet, plus the brand this read was scoped to.

## Create Environment

`POST https://app.opvs.ai/api/v1/environments`

Also as: MCP `tool_call software-factory.createEnvironment` · skill `software-factory`

| Code | When | What to do |
| --- | --- | --- |
| 422 | Validation Error |  |

## List Fleet Machines

`GET https://app.opvs.ai/api/v1/environments/machines`

Also as: MCP `tool_call software-factory.listFleetMachines` · skill `software-factory`

One ``MachineSlots`` view per machine the caller's brand has a desk on.

## Get Environment Allowance

`GET https://app.opvs.ai/api/v1/environments/allowance`

Also as: MCP `tool_call software-factory.getEnvironmentAllowance` · skill `software-factory`

How many machines this brand holds, and how many it may hold.

## Get Fleet Reauth Status

`GET https://app.opvs.ai/api/v1/environments/credentials/reauth-status`

Also as: MCP `tool_call software-factory.getFleetReauthStatus` · skill `software-factory`

Every lapsed subscription login across the caller's whole fleet, in ONE call.

## Get Fleet Projections

`GET https://app.opvs.ai/api/v1/environments/projections`

Also as: MCP `tool_call software-factory.getFleetProjections` · skill `software-factory`

How many boards and cards each of the brand's machines has written.

## Regenerate Environment Pat

`POST https://app.opvs.ai/api/v1/environments/{env_id}/regenerate-pat`

Also as: MCP `tool_call software-factory.regenerateEnvironmentPat` · skill `software-factory`

Rotate this environment's install PAT and reveal the new one ONCE.

| Code | When | What to do |
| --- | --- | --- |
| 422 | Validation Error |  |

## List Machine Slots

`GET https://app.opvs.ai/api/v1/environments/{env_id}/slots`

Also as: MCP `tool_call software-factory.listMachineSlots` · skill `software-factory`

Every desk on this machine — what the "add another here" dialog reads.

| Code | When | What to do |
| --- | --- | --- |
| 422 | Validation Error |  |

## Add Machine Slot

`POST https://app.opvs.ai/api/v1/environments/{env_id}/slots`

Also as: MCP `tool_call software-factory.addMachineSlot` · skill `software-factory`

Add a desk to a machine this brand already has (BYO §6.4).

| Code | When | What to do |
| --- | --- | --- |
| 422 | Validation Error |  |

## List Mail Wake Bindings

`GET https://app.opvs.ai/api/v1/environments/{env_id}/mail-wake`

Also as: MCP `tool_call software-factory.listMailWake` · skill `software-factory`

| Code | When | What to do |
| --- | --- | --- |
| 422 | Validation Error |  |

## Put Mail Wake Binding

`PUT https://app.opvs.ai/api/v1/environments/{env_id}/mail-wake`

Also as: MCP `tool_call software-factory.setMailWake` · skill `software-factory`

| Code | When | What to do |
| --- | --- | --- |
| 422 | Validation Error |  |

## Delete Mail Wake Binding

`DELETE https://app.opvs.ai/api/v1/environments/{env_id}/mail-wake/{address}`

Also as: MCP `tool_call software-factory.deleteMailWake` · skill `software-factory`

| Code | When | What to do |
| --- | --- | --- |
| 422 | Validation Error |  |

## Get Environment Capabilities

`GET https://app.opvs.ai/api/v1/environments/{env_id}/capabilities`

Also as: MCP `tool_call software-factory.getEnvironmentCapabilities` · skill `software-factory`

| Code | When | What to do |
| --- | --- | --- |
| 422 | Validation Error |  |

## Put Environment Capabilities

`PUT https://app.opvs.ai/api/v1/environments/{env_id}/capabilities`

Also as: MCP `tool_call software-factory.setEnvironmentCapabilities` · skill `software-factory`

| Code | When | What to do |
| --- | --- | --- |
| 422 | Validation Error |  |

## Get Effective Environment Capabilities

`GET https://app.opvs.ai/api/v1/environments/{env_id}/capabilities/effective`

Also as: MCP `tool_call software-factory.getEffectiveEnvironmentCapabilities` · skill `software-factory`

Return the selected build policy narrowed by this desk's machine.

| Code | When | What to do |
| --- | --- | --- |
| 422 | Validation Error |  |

## Get Environment Capability History

`GET https://app.opvs.ai/api/v1/environments/{env_id}/capabilities/history`

Also as: MCP `tool_call software-factory.getEnvironmentCapabilityHistory` · skill `software-factory`

| Code | When | What to do |
| --- | --- | --- |
| 422 | Validation Error |  |

## Get Environment

`GET https://app.opvs.ai/api/v1/environments/{env_id}`

Also as: CLI `opvs machines get` · MCP `tool_call software-factory.getEnvironment` · skill `software-factory`

| Code | When | What to do |
| --- | --- | --- |
| 422 | Validation Error |  |

## Update Environment

`PATCH https://app.opvs.ai/api/v1/environments/{env_id}`

Also as: MCP `tool_call software-factory.updateEnvironment` · skill `software-factory`

Patch this box. One of the fields is a CONSENT, and it is gated apart.

| Code | When | What to do |
| --- | --- | --- |
| 422 | Validation Error |  |

## Delete Environment

`DELETE https://app.opvs.ai/api/v1/environments/{env_id}`

Also as: MCP `tool_call software-factory.deleteEnvironment` · skill `software-factory`

Delete this box. Retires its install key; refuses if it is hosting guests.

| Code | When | What to do |
| --- | --- | --- |
| 422 | Validation Error |  |

## Get Environment Image

`GET https://app.opvs.ai/api/v1/environments/{env_id}/image`

Also as: API only

Stream this box's photo.

| Code | When | What to do |
| --- | --- | --- |
| 422 | Validation Error |  |

## Upload Environment Image

`POST https://app.opvs.ai/api/v1/environments/{env_id}/image`

Also as: API only

Set this box's photo. Replaces any existing one.

| Code | When | What to do |
| --- | --- | --- |
| 422 | Validation Error |  |

## Delete Environment Image

`DELETE https://app.opvs.ai/api/v1/environments/{env_id}/image`

Also as: MCP `tool_call software-factory.deleteEnvironmentImage` · skill `software-factory`

Remove this box's photo — the row pointer AND the stored object.

| Code | When | What to do |
| --- | --- | --- |
| 422 | Validation Error |  |

## Fs Read

`GET https://app.opvs.ai/api/v1/environments/{env_id}/fs/{path}`

Also as: MCP `tool_call software-factory.deskFsRead` · skill `software-factory`

| Code | When | What to do |
| --- | --- | --- |
| 422 | Validation Error |  |

## Fs Write

`POST https://app.opvs.ai/api/v1/environments/{env_id}/fs/{path}`

Also as: API only

| Code | When | What to do |
| --- | --- | --- |
| 422 | Validation Error |  |

## Fs Delete

`DELETE https://app.opvs.ai/api/v1/environments/{env_id}/fs/{path}`

Also as: MCP `tool_call software-factory.deskFsDelete` · skill `software-factory`

| Code | When | What to do |
| --- | --- | --- |
| 422 | Validation Error |  |

## Fs Move

`POST https://app.opvs.ai/api/v1/environments/{env_id}/fs-move`

Also as: MCP `tool_call software-factory.deskFsMove` · skill `software-factory`

| Code | When | What to do |
| --- | --- | --- |
| 422 | Validation Error |  |

## Claude Inject

`POST https://app.opvs.ai/api/v1/environments/{env_id}/claude/inject`

Also as: MCP `tool_call software-factory.claudeInject` · skill `software-factory`

| Code | When | What to do |
| --- | --- | --- |
| 422 | Validation Error |  |

## Claude List Skills

`GET https://app.opvs.ai/api/v1/environments/{env_id}/claude/skills`

Also as: MCP `tool_call software-factory.claudeListSkills` · skill `software-factory`

| Code | When | What to do |
| --- | --- | --- |
| 422 | Validation Error |  |

## Claude Install Skill

`POST https://app.opvs.ai/api/v1/environments/{env_id}/claude/skills/{name}`

Also as: API only

| Code | When | What to do |
| --- | --- | --- |
| 422 | Validation Error |  |

## Claude Remove Skill

`DELETE https://app.opvs.ai/api/v1/environments/{env_id}/claude/skills/{name}`

Also as: MCP `tool_call software-factory.claudeRemoveSkill` · skill `software-factory`

| Code | When | What to do |
| --- | --- | --- |
| 422 | Validation Error |  |

## Claude Set Plan

`POST https://app.opvs.ai/api/v1/environments/{env_id}/claude/plans/current`

Also as: MCP `tool_call software-factory.claudeSetPlan` · skill `software-factory`

| Code | When | What to do |
| --- | --- | --- |
| 422 | Validation Error |  |

## List Routines

`GET https://app.opvs.ai/api/v1/environments/{env_id}/routines`

Also as: MCP `tool_call software-factory.listRoutines` · skill `software-factory`

| Code | When | What to do |
| --- | --- | --- |
| 422 | Validation Error |  |

## Replace Routines

`PUT https://app.opvs.ai/api/v1/environments/{env_id}/routines`

Also as: API only

| Code | When | What to do |
| --- | --- | --- |
| 422 | Validation Error |  |

## Run Routine

`POST https://app.opvs.ai/api/v1/environments/{env_id}/routines/{routine_id}/run`

Also as: MCP `tool_call software-factory.runRoutine` · skill `software-factory`

| Code | When | What to do |
| --- | --- | --- |
| 422 | Validation Error |  |

## Claude Bundle Preview

`GET https://app.opvs.ai/api/v1/environments/{env_id}/claude/bundle/preview`

Also as: MCP `tool_call software-factory.claudeBundlePreview` · skill `software-factory`

Dry-run: what a role's method bundle WOULD install onto this desk.

| Code | When | What to do |
| --- | --- | --- |
| 422 | Validation Error |  |

## Claude Install Bundle

`POST https://app.opvs.ai/api/v1/environments/{env_id}/claude/bundle`

Also as: MCP `tool_call software-factory.claudeInstallBundle` · skill `software-factory`

Install the OPVS control-plane image (role method bundle) onto this workstation.

| Code | When | What to do |
| --- | --- | --- |
| 422 | Validation Error |  |

## Trigger Sync

`POST https://app.opvs.ai/api/v1/environments/{env_id}/sync`

Also as: MCP `tool_call software-factory.triggerDeskSync` · skill `software-factory`

| Code | When | What to do |
| --- | --- | --- |
| 422 | Validation Error |  |

## Env Health

`GET https://app.opvs.ai/api/v1/environments/{env_id}/health`

Also as: MCP `tool_call software-factory.getEnvironmentHealth` · skill `software-factory`

| Code | When | What to do |
| --- | --- | --- |
| 422 | Validation Error |  |

## Open Session

`POST https://app.opvs.ai/api/v1/environments/{env_id}/session`

Also as: MCP `tool_call software-factory.openDeskSession` · skill `software-factory`

| Code | When | What to do |
| --- | --- | --- |
| 422 | Validation Error |  |

## Kill Session

`DELETE https://app.opvs.ai/api/v1/environments/{env_id}/session/{name}`

Also as: MCP `tool_call software-factory.killDeskSession` · skill `software-factory`

| Code | When | What to do |
| --- | --- | --- |
| 422 | Validation Error |  |

## Openhands Gui Status

`GET https://app.opvs.ai/api/v1/environments/{env_id}/openhands-gui`

Also as: MCP `tool_call software-factory.openhandsGuiStatus` · skill `software-factory`

| Code | When | What to do |
| --- | --- | --- |
| 422 | Validation Error |  |

## Openhands Gui Stop

`DELETE https://app.opvs.ai/api/v1/environments/{env_id}/openhands-gui`

Also as: MCP `tool_call software-factory.stopOpenhandsGui` · skill `software-factory`

| Code | When | What to do |
| --- | --- | --- |
| 422 | Validation Error |  |

## Openhands Gui Start

`POST https://app.opvs.ai/api/v1/environments/{env_id}/openhands-gui/start`

Also as: MCP `tool_call software-factory.startOpenhandsGui` · skill `software-factory`

| Code | When | What to do |
| --- | --- | --- |
| 422 | Validation Error |  |

## Wg Remove Peer

`DELETE https://app.opvs.ai/api/v1/environments/{env_id}/wg/peer`

Also as: MCP `tool_call software-factory.removeWireguardPeer` · skill `software-factory`

| Code | When | What to do |
| --- | --- | --- |
| 422 | Validation Error |  |

## Get Credential Reauth Status

`GET https://app.opvs.ai/api/v1/environments/{env_id}/credentials/reauth-status`

Also as: MCP `tool_call software-factory.getEnvironmentReauthStatus` · skill `software-factory`

Dashboard-facing: the env's current interactive-credential re-auth flags.

| Code | When | What to do |
| --- | --- | --- |
| 422 | Validation Error |  |

## List Environment Observations

`GET https://app.opvs.ai/api/v1/environments/{env_id}/observations`

Also as: MCP `tool_call software-factory.listEnvironmentObservations` · skill `software-factory`

Return newest-first observations without exposing another brand's env.

| Code | When | What to do |
| --- | --- | --- |
| 422 | Validation Error |  |
