# Project Environment

Source: https://opvs.ai/docs/api/project-environment

## `GET` /api/v1/project-env

**List Env Vars**

List variables. Config values are returned; **secret values never are.**

**Parameters**

- `project_id` (query, any, optional) — Omit for the brand defaults. Supply a project to see what that project inherits alongside what it overrides.
- `overrides_only` (query, boolean, optional) — With project_id, return only that project's own overrides.

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

```python
import httpx

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

```javascript
const resp = await fetch("https://app.opvs.ai/api/v1/project-env", {
  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/project-env", 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/project-env

**Put Env Var**

Create or replace one variable. PUT, not PATCH — edit means replace.

**Parameters**

- `project_id` (query, any, optional) — Omit to set the brand default; supply a project to override it there.

**Request body**

```bash
curl -X PUT 'https://app.opvs.ai/api/v1/project-env' \
  -H 'Authorization: Bearer <token>' \
  -H 'Content-Type: application/json' \
  -d '{
  "name": "string",
  "kind": "config",
  "value": "string",
  "integration_id": 0,
  "integration_field": "string",
  "restricted_project_ids": [
    "00000000-0000-0000-0000-000000000000"
  ],
  "job_types": [
    "string"
  ]
}'
```

```python
import httpx

resp = httpx.put(
    "https://app.opvs.ai/api/v1/project-env",
    headers={"Authorization": "Bearer <token>", "Content-Type": "application/json"},
    json={"name": "string", "kind": "config", "value": "string", "integration_id": 0, "integration_field": "string", "restricted_project_ids": ["00000000-0000-0000-0000-000000000000"], "job_types": ["string"]},
)
resp.raise_for_status()
print(resp.json())
```

```javascript
const resp = await fetch("https://app.opvs.ai/api/v1/project-env", {
  method: "PUT",
  headers: { "Authorization": "Bearer <token>", "Content-Type": "application/json" },
  body: JSON.stringify({"name": "string", "kind": "config", "value": "string", "integration_id": 0, "integration_field": "string", "restricted_project_ids": ["00000000-0000-0000-0000-000000000000"], "job_types": ["string"]})
});
const data = await resp.json();
console.log(data);
```

```go
package main

import (
	"net/http"
	"strings"
)

func main() {
	body := strings.NewReader(`{"name": "string", "kind": "config", "value": "string", "integration_id": 0, "integration_field": "string", "restricted_project_ids": ["00000000-0000-0000-0000-000000000000"], "job_types": ["string"]}`)
	req, _ := http.NewRequest("PUT", "https://app.opvs.ai/api/v1/project-env", 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/project-env/resolved

**Resolved Env**

Preview the effective map: which names a build gets, and where each came from.

**Parameters**

- `project_id` (query, any, optional) — Omit to preview the brand-level map.

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

```python
import httpx

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

```javascript
const resp = await fetch("https://app.opvs.ai/api/v1/project-env/resolved", {
  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/project-env/resolved", 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/project-env/credential-options

**Credential Options**

Metadata-only credential options for Project Settings or provisioning.

**Parameters**

- `include_provisioner_only` (query, boolean, optional) — Include machine-provisioning credentials. Reserved for the Add a machine flow; project-secret writes still refuse these providers.

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

```python
import httpx

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

```javascript
const resp = await fetch("https://app.opvs.ai/api/v1/project-env/credential-options", {
  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/project-env/credential-options", 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/project-env/leases

**Env Leases**

Names-only delivery history for one project; values never enter this path.

**Parameters**

- `project_id` (query, string, required) — Project whose delivery history to read.
- `limit` (query, integer, optional)

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

```python
import httpx

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

```javascript
const resp = await fetch("https://app.opvs.ai/api/v1/project-env/leases", {
  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/project-env/leases", 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/project-env/audit

**Env Audit**

Who set or removed which variable, and when. Names only — never values.

**Parameters**

- `limit` (query, integer, optional)

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

```python
import httpx

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

```javascript
const resp = await fetch("https://app.opvs.ai/api/v1/project-env/audit", {
  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/project-env/audit", 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/project-env/{name}

**Delete Env Var**

Delete one variable.

**Parameters**

- `name` (path, string, required)
- `project_id` (query, any, optional) — Omit to delete the brand default. Supply a project to delete only that project's override — the project then goes back to inheriting.

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

```python
import httpx

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

```javascript
const resp = await fetch("https://app.opvs.ai/api/v1/project-env/{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/project-env/{name}", nil)
	req.Header.Set("Authorization", "Bearer <token>")
	resp, _ := http.DefaultClient.Do(req)
	defer resp.Body.Close()
}
```

**Responses**

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

## List Env Vars

`GET https://app.opvs.ai/api/v1/project-env`

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

List variables. Config values are returned; **secret values never are.**

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

## Put Env Var

`PUT https://app.opvs.ai/api/v1/project-env`

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

Create or replace one variable. PUT, not PATCH — edit means replace.

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

## Resolved Env

`GET https://app.opvs.ai/api/v1/project-env/resolved`

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

Preview the effective map: which names a build gets, and where each came from.

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

## Credential Options

`GET https://app.opvs.ai/api/v1/project-env/credential-options`

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

Metadata-only credential options for Project Settings or provisioning.

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

## Env Leases

`GET https://app.opvs.ai/api/v1/project-env/leases`

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

Names-only delivery history for one project; values never enter this path.

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

## Env Audit

`GET https://app.opvs.ai/api/v1/project-env/audit`

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

Who set or removed which variable, and when. Names only — never values.

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

## Delete Env Var

`DELETE https://app.opvs.ai/api/v1/project-env/{name}`

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

Delete one variable.

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