# Environments

### List the environments in a project

`GET /accounts/{accountId}/projects/{projectId}/environments`

**Required role:** reader

**Parameters**

- `projectId` _(path)_ · `string` · required
- `accountId` _(path)_ · `string` · required

**Returns**

- `200` · `EnvironmentDto[]`

**Example request**

```bash
curl https://api.koo.io/accounts/:accountId/projects/:projectId/environments \
  -H "Authorization: Bearer kc_your_api_token"
```

**Example response** (`200`)

```json
[
  {
    "id": "acct_01example0000000000000000x",
    "accountId": "acct_01example0000000000000000x",
    "projectId": "project_01example0000000000000000x",
    "name": "my-app",
    "createdAt": "2026-01-01T00:00:00.000Z"
  }
]
```

### Create an environment in a project

`POST /accounts/{accountId}/projects/{projectId}/environments`

**Required role:** admin

Creates the environment with the given immutable identity name (a url-safe word, unique within the project). Services are added separately via the services API.

**Parameters**

- `projectId` _(path)_ · `string` · required
- `accountId` _(path)_ · `string` · required

**Request body**

- `name` · `string` · required — The immutable identity name (url-safe word, 3-16 chars, unique within the project). Pick carefully — it cannot be renamed.

**Returns**

- `200` · `EnvironmentDto`

Attributes of `EnvironmentDto`:

- `id` · `string` · read-only — Unique identifier of the environment.
- `accountId` · `string` · read-only — Id of the account that owns the environment.
- `projectId` · `string` · read-only — Id of the project this environment belongs to.
- `name` · `string` · required — The environment’s IDENTITY: an immutable, project-unique, url-safe word picked at create (e.g. production, staging). There is no separate display name.
- `createdAt` · `string <date-time>` · read-only — Read-only: when the environment was created.

**Example request**

```bash
curl https://api.koo.io/accounts/:accountId/projects/:projectId/environments \
  -X POST \
  -H "Authorization: Bearer kc_your_api_token" \
  -H "Content-Type: application/json" \
  -d '{
      "name": "my-app"
    }'
```

**Example response** (`200`)

```json
{
  "id": "acct_01example0000000000000000x",
  "accountId": "acct_01example0000000000000000x",
  "projectId": "project_01example0000000000000000x",
  "name": "my-app",
  "createdAt": "2026-01-01T00:00:00.000Z"
}
```

### Get an environment with its services + status

`GET /accounts/{accountId}/projects/{projectId}/environments/{environmentId}`

**Required role:** reader

**Parameters**

- `environmentId` _(path)_ · `string` · required
- `projectId` _(path)_ · `string` · required
- `accountId` _(path)_ · `string` · required

**Returns**

- `200` · `EnvironmentDto`

Attributes of `EnvironmentDto`:

- `id` · `string` · read-only — Unique identifier of the environment.
- `accountId` · `string` · read-only — Id of the account that owns the environment.
- `projectId` · `string` · read-only — Id of the project this environment belongs to.
- `name` · `string` · required — The environment’s IDENTITY: an immutable, project-unique, url-safe word picked at create (e.g. production, staging). There is no separate display name.
- `createdAt` · `string <date-time>` · read-only — Read-only: when the environment was created.

**Example request**

```bash
curl https://api.koo.io/accounts/:accountId/projects/:projectId/environments/:environmentId \
  -H "Authorization: Bearer kc_your_api_token"
```

**Example response** (`200`)

```json
{
  "id": "acct_01example0000000000000000x",
  "accountId": "acct_01example0000000000000000x",
  "projectId": "project_01example0000000000000000x",
  "name": "my-app",
  "createdAt": "2026-01-01T00:00:00.000Z"
}
```

### Delete an environment

`DELETE /accounts/{accountId}/projects/{projectId}/environments/{environmentId}`

**Required role:** admin

**Parameters**

- `environmentId` _(path)_ · `string` · required
- `projectId` _(path)_ · `string` · required
- `accountId` _(path)_ · `string` · required

**Returns**

- `204`

**Example request**

```bash
curl https://api.koo.io/accounts/:accountId/projects/:projectId/environments/:environmentId \
  -X DELETE \
  -H "Authorization: Bearer kc_your_api_token"
```

### Clone an environment into a new one

`POST /accounts/{accountId}/projects/{projectId}/environments/{environmentId}/clone`

**Required role:** admin

Creates a new environment in the same project (with a fresh slug, inheriting the source's locations) and copies the source's services — their specs, variables (ordinary values, connections, and aliases), toggles and volume sizes. Sensitive values and volume DATA are NOT copied (the response's `sensitiveVariablesToSet` and `environmentSensitiveVariablesToSet` list the variable names to re-enter), and custom domains are not copied. Managed databases clone as fresh, empty instances. Send an `Idempotency-Key` header to make a retried clone safe (the key is scoped per source environment).

**Parameters**

- `environmentId` _(path)_ · `string` · required
- `projectId` _(path)_ · `string` · required
- `accountId` _(path)_ · `string` · required

**Request body**

- `name` · `string` · required — The immutable identity name for the clone (url-safe word, unique within the project).

**Returns**

- `200` · `CloneResultDto`

Attributes of `CloneResultDto`:

- `environment` · `object` · read-only — The newly created environment (a clone of the source).
- `sensitiveVariablesToSet` · `object[]` · read-only — Per-service sensitive variables whose name was carried to the clone but whose value must be set.
- `environmentSensitiveVariablesToSet` · `string[]` · read-only — Names of the environment-scoped sensitive variables carried to the clone WITHOUT a value — a sensitive value never leaves its environment (§7); each must be (re-)entered on the clone.

**Example request**

```bash
curl https://api.koo.io/accounts/:accountId/projects/:projectId/environments/:environmentId/clone \
  -X POST \
  -H "Authorization: Bearer kc_your_api_token" \
  -H "Content-Type: application/json" \
  -d '{
      "name": "my-app"
    }'
```

**Example response** (`200`)

```json
{
  "environment": {
    "id": "acct_01example0000000000000000x",
    "accountId": "acct_01example0000000000000000x",
    "projectId": "project_01example0000000000000000x",
    "name": "my-app",
    "createdAt": "2026-01-01T00:00:00.000Z"
  },
  "sensitiveVariablesToSet": [
    {
      "serviceName": "example",
      "names": [
        "example"
      ]
    }
  ],
  "environmentSensitiveVariablesToSet": [
    "example"
  ]
}
```

### Promote a source environment’s services onto this one

`POST /accounts/{accountId}/projects/{projectId}/environments/{environmentId}/promote`

**Required role:** editor

Overwrites THIS environment's services, config and images to match the source environment (`sourceId` in the body). This environment's custom domains and its own sensitive values are preserved; the source's variables — ordinary values, connections, and aliases — are promoted, along with its service specs, toggles and image sources. Set `dryRun` to preview exactly what will be created, updated, deleted, and destroyed. `confirmServiceDeletions` is required when the promote would delete a service or destroy a volume.

**Parameters**

- `environmentId` _(path)_ · `string` · required
- `projectId` _(path)_ · `string` · required
- `accountId` _(path)_ · `string` · required

**Request body**

- `sourceId` · `string` · required — Id of the source environment whose services are promoted onto this one.
- `confirmServiceDeletions` · `boolean` · optional — Acknowledge the destructive effects of the promote: services present in this environment but absent from the source are deleted, and any persistent volume the promote removes is destroyed. Required when the promote would delete a service or destroy a volume.
- `dryRun` · `boolean` · optional — Preview the changes without applying them — returns what would be created, updated, deleted, and destroyed.

**Returns**

- `200` · `PromoteResultDto`

Attributes of `PromoteResultDto`:

- `dryRun` · `boolean` · read-only — Whether this was a preview (no changes applied).
- `preview` · `object` · read-only — The changes the promote made (or would make, on a dry run).
- `environment` · `object | null` · read-only — A deployment target inside a project; its services + domains are fetched separately.

**Example request**

```bash
curl https://api.koo.io/accounts/:accountId/projects/:projectId/environments/:environmentId/promote \
  -X POST \
  -H "Authorization: Bearer kc_your_api_token" \
  -H "Content-Type: application/json" \
  -d '{
      "sourceId": "source_01example0000000000000000x"
    }'
```

**Example response** (`200`)

```json
{
  "dryRun": true,
  "preview": {
    "services": {
      "create": [
        {
          "name": "my-app",
          "type": "web"
        }
      ],
      "update": [
        {
          "name": "my-app",
          "willRedeploy": true
        }
      ],
      "delete": [
        {
          "name": "my-app",
          "type": "web"
        }
      ]
    },
    "volumesDestroyed": [
      {
        "serviceName": "example",
        "mountPath": "example",
        "sizeGb": 1
      }
    ],
    "domainsOrphaned": [
      {
        "hostname": "example",
        "serviceName": "example"
      }
    ],
    "sensitiveVariablesSkipped": [
      {
        "serviceName": "example",
        "names": [
          "example"
        ]
      }
    ],
    "blockers": [
      {
        "serviceName": "example",
        "reason": "example",
        "detail": "example"
      }
    ]
  },
  "environment": {
    "id": "acct_01example0000000000000000x",
    "accountId": "acct_01example0000000000000000x",
    "projectId": "project_01example0000000000000000x",
    "name": "my-app",
    "createdAt": "2026-01-01T00:00:00.000Z"
  }
}
```
