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

# Environment Variables API

> List environments and manage environment variables programmatically

These endpoints let you browse [environments](/environments) and manage their environment variables programmatically. Use them to bulk-import config from another secrets manager, keep credentials in sync with CI, or build dashboards on top of Autosana.

All requests require an API key in the `X-API-Key` header. See [API Reference](/api-reference) for authentication and the standard `401` / `403` / `429` / `500` error shapes shared by every endpoint on this page.

<Warning>
  **Secret values are write-only through the API.** When `is_secret=true`, the value is stored encrypted in vault and is never returned by any read endpoint — list and get responses always render secret values as `"***"`. There is no API path to retrieve a decrypted secret.
</Warning>

<Note>
  Environments themselves (create / rename / delete) are managed from the [dashboard](https://autosana.ai/settings?tab=environments). The API surface here covers env vars and read access to the environments that contain them.
</Note>

***

## List Environments

Returns every environment in your organization with its env vars nested. Plaintext values come back in full; secret values are masked as `"***"`.

<Note>
  **GET** `/api/v1/environments` — Returns `200 OK`
</Note>

### Example Request

```bash theme={null}
curl -X GET https://backend.autosana.ai/api/v1/environments \
  -H "X-API-Key: YOUR_API_KEY"
```

### Response Fields

<ResponseField name="environments" type="array">
  List of environments.

  <Expandable title="Environment object">
    <ResponseField name="id" type="string">
      Unique identifier (UUID).
    </ResponseField>

    <ResponseField name="name" type="string">
      Environment name (e.g. "Staging", "Production").
    </ResponseField>

    <ResponseField name="env_vars" type="array">
      Environment variables, alphabetically by `key`.

      <Expandable title="Env var object">
        <ResponseField name="id" type="string">
          Unique identifier (UUID).
        </ResponseField>

        <ResponseField name="environment_id" type="string">
          UUID of the parent environment.
        </ResponseField>

        <ResponseField name="key" type="string">
          Variable name (referenced from flows as `${env:KEY}`).
        </ResponseField>

        <ResponseField name="value" type="string | null">
          Plaintext value, or `"***"` placeholder when `is_secret=true`. **Never** the decrypted secret.
        </ResponseField>

        <ResponseField name="is_secret" type="boolean">
          Whether the value is stored encrypted in vault.
        </ResponseField>

        <ResponseField name="description" type="string | null">
          Optional human-readable note.
        </ResponseField>

        <ResponseField name="created_at" type="string">
          ISO 8601 timestamp.
        </ResponseField>

        <ResponseField name="updated_at" type="string">
          ISO 8601 timestamp.
        </ResponseField>
      </Expandable>
    </ResponseField>
  </Expandable>
</ResponseField>

<ResponseField name="count" type="integer">
  Total number of environments returned.
</ResponseField>

#### Example Response

```json theme={null}
{
  "environments": [
    {
      "id": "770e8400-e29b-41d4-a716-446655440099",
      "name": "Staging",
      "env_vars": [
        {
          "id": "880e8400-e29b-41d4-a716-446655440010",
          "environment_id": "770e8400-e29b-41d4-a716-446655440099",
          "key": "API_TOKEN",
          "value": "***",
          "is_secret": true,
          "description": null,
          "created_at": "2026-01-15T10:30:00Z",
          "updated_at": "2026-01-15T10:30:00Z"
        },
        {
          "id": "880e8400-e29b-41d4-a716-446655440011",
          "environment_id": "770e8400-e29b-41d4-a716-446655440099",
          "key": "API_URL",
          "value": "https://staging.api.example.com",
          "is_secret": false,
          "description": "Staging API base URL",
          "created_at": "2026-01-15T10:31:00Z",
          "updated_at": "2026-01-15T10:31:00Z"
        }
      ]
    }
  ],
  "count": 1
}
```

***

## Create Env Var

<Note>
  **POST** `/api/v1/env-vars` — Returns `201 Created`. Returns `409 Conflict` if an env var with the same `key` already exists on this environment.
</Note>

### Request Body

<ParamField body="environment_id" type="string" required>
  UUID of the environment this variable belongs to.
</ParamField>

<ParamField body="key" type="string" required>
  Variable name (1–255 characters). Referenced from flows and curl hooks as `${env:KEY}`.
</ParamField>

<ParamField body="value" type="string" required>
  Variable value — must be a non-empty string. Empty values are rejected with `422` because they're indistinguishable from "unset" at consumption time. For secrets, this is written to vault and never returned by any read endpoint.
</ParamField>

<ParamField body="description" type="string">
  Optional human-readable note.
</ParamField>

<ParamField body="is_secret" type="boolean">
  Defaults to `false`. When `true`, the value is stored encrypted in vault and is never readable back through the API.
</ParamField>

### Example Request (plaintext)

```bash theme={null}
curl -X POST https://backend.autosana.ai/api/v1/env-vars \
  -H "X-API-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "environment_id": "770e8400-e29b-41d4-a716-446655440099",
    "key": "API_URL",
    "value": "https://staging.api.example.com",
    "description": "Staging API base URL"
  }'
```

### Example Request (secret)

```bash theme={null}
curl -X POST https://backend.autosana.ai/api/v1/env-vars \
  -H "X-API-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "environment_id": "770e8400-e29b-41d4-a716-446655440099",
    "key": "API_TOKEN",
    "value": "abc123...super-secret",
    "is_secret": true
  }'
```

#### Example Response

```json theme={null}
{
  "id": "880e8400-e29b-41d4-a716-446655440010",
  "environment_id": "770e8400-e29b-41d4-a716-446655440099",
  "key": "API_TOKEN",
  "value": "***",
  "is_secret": true,
  "description": null,
  "created_at": "2026-01-15T10:30:00Z",
  "updated_at": "2026-01-15T10:30:00Z"
}
```

***

## Get Env Var

<Note>
  **GET** `/api/v1/env-vars/{env_var_id}` — Returns `200 OK` with the same shape as items in [List Environments](#list-environments)' `env_vars`, or `404` if the var does not exist. Secret values are returned as `"***"`.
</Note>

<ParamField path="env_var_id" type="string" required>
  UUID of the env var.
</ParamField>

```bash theme={null}
curl -X GET https://backend.autosana.ai/api/v1/env-vars/ENV_VAR_UUID \
  -H "X-API-Key: YOUR_API_KEY"
```

***

## Update Env Var

Update an env var. Only provided fields change; omitted fields are unchanged.

<Note>
  **PATCH** `/api/v1/env-vars/{env_var_id}` — Returns `200 OK`. `400` if no recognized fields are provided. `404` if the var does not exist. `409` if renaming `key` collides with another env var in the same environment. `422` for invalid transitions (see below).
</Note>

<Tip>
  **No-op PATCHes don't bump `updated_at`.** If the body resolves to no actual state change — e.g. `{"is_secret": true}` on a row that's already a secret — the endpoint returns the unchanged row without writing to the DB. Don't rely on PATCH to act as a heartbeat.
</Tip>

<ParamField path="env_var_id" type="string" required>
  UUID of the env var.
</ParamField>

<ParamField body="key" type="string">
  New variable name (1–255 characters). **Note:** any flows or curl hooks that reference the old name as `${env:OLD_KEY}` must be updated in lockstep — there is no automatic rewrite. Collisions with another env var in the same environment return `409`.
</ParamField>

<ParamField body="value" type="string">
  New value. Omit to keep the existing value unchanged. Required when changing `is_secret` in either direction (the API never re-uses the existing value across a secret/plaintext transition). `null` is treated as "no change", not "clear" — there is no way to clear a value without deleting the row.
</ParamField>

<ParamField body="description" type="string | null">
  New description. Pass `""` or `null` to explicitly clear (this is the only field where `null` clears rather than meaning "no change").
</ParamField>

<ParamField body="is_secret" type="boolean">
  Move the var between plaintext and vault-encrypted storage. Switching the flag in either direction requires `value`.
</ParamField>

### Secret transition rules

| Existing state | Request                                | Result                                                                |
| -------------- | -------------------------------------- | --------------------------------------------------------------------- |
| Plaintext      | `value: "new"`                         | Plaintext value rewritten in place.                                   |
| Plaintext      | `is_secret: true`, no `value`          | **422** — promoting to secret requires a `value`.                     |
| Plaintext      | `is_secret: true`, `value: "secret-x"` | New vault row written; row repointed to it.                           |
| Secret         | `value: "rotated"`                     | New vault row written, old one cleaned up after the row is repointed. |
| Secret         | `is_secret: false`, no `value`         | **422** — demoting to plaintext requires a `value`.                   |
| Secret         | `is_secret: false`, `value: "plain"`   | Old vault row cleaned up, plaintext value written.                    |

### Example Request

```bash theme={null}
# Rotate an existing secret
curl -X PATCH https://backend.autosana.ai/api/v1/env-vars/ENV_VAR_UUID \
  -H "X-API-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "value": "new-rotated-secret-value" }'

# Promote a plaintext var to a secret
curl -X PATCH https://backend.autosana.ai/api/v1/env-vars/ENV_VAR_UUID \
  -H "X-API-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "is_secret": true, "value": "secret-only-known-at-rotation" }'
```

***

## Delete Env Var

Deletes the env var. If the var is a secret, its vault entry is cleaned up too.

<Note>
  **DELETE** `/api/v1/env-vars/{env_var_id}` — Returns `204 No Content`, or `404` if the var does not exist.
</Note>

<ParamField path="env_var_id" type="string" required>
  UUID of the env var.
</ParamField>

```bash theme={null}
curl -X DELETE https://backend.autosana.ai/api/v1/env-vars/ENV_VAR_UUID \
  -H "X-API-Key: YOUR_API_KEY"
```

<Warning>
  Deleting a variable will cause any flows or hooks that reference `${env:VARIABLE_NAME}` to fail. Update or remove references before deleting.
</Warning>
