---
id: platform/projects-environments
title: Projects and environments
description: Organize Bex resources into projects and environments, manage membership, and understand configuration and network-policy effects.
keywords: [bex, projects, environments, workspace, isolation]
last_updated: 2026-09-23
---

A workspace is the ownership and membership boundary. A project groups an
application's resources within that workspace; environments separate groupings
such as staging and production. Creating an environment does not clone services,
copy data, or create a PR preview.

Use distinct service names in a workspace, even across environments. A name such
as `production` is descriptive; configure the intended protection and network
settings explicitly.

## Create a project and environment

In the dashboard, create a project in the intended workspace, then add an
environment. For REST, set credentials using the [API guide](./api.md):

```bash
curl --fail-with-body --silent --show-error \
  -X POST "$BEX_API_URL/v1/projects" \
  -H "Authorization: Bearer $BEX_TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{"name":"Shop","ownerId":"YOUR_WORKSPACE_ID","environments":[]}'
```

Use the returned project ID to create an environment separately:

```bash
curl --fail-with-body --silent --show-error \
  -X POST "$BEX_API_URL/v1/environments" \
  -H "Authorization: Bearer $BEX_TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{"name":"Staging","projectId":"YOUR_PROJECT_ID"}'
```

Bex also supports creating the project and its initial environments together:
supply entries such as `{"name":"Staging"}` in the project request's
`environments` array. That creation is atomic; an invalid environment or quota
failure rolls back the project too. The example above uses an empty array and
then the separate endpoint to make both returned IDs explicit.

List projects with `GET /v1/projects?ownerId=…`; `ownerId` is required on that
Bex list endpoint. List environments with `GET /v1/environments?projectId=…`.
Both lists use resource/cursor envelopes. Use returned IDs for later operations.

## Add or move resources

Choose an environment when creating a supported resource, or use the dashboard
move controls for existing resources. Inspect the destination and its policies
before moving services, Postgres, Key Value, or environment groups.

The API also exposes membership-list operations such as
`PUT /v1/environments/{id}/service-links` with `{"serviceIds":["srv-…"]}`.
**This replaces the full list**, not just one membership. Read the current list
and include every service that should remain. Project-level service links have
the same replacement semantics and can clear prior environment assignments.
Use the resource-specific link endpoint for databases or Key Value; do not mix
identifier kinds in a service list.

A move can affect network policy and scoped configuration. Verify connections
and [environment-group](./secrets.md) links afterward. If a move fails, inspect current membership before retrying; the membership
change may already have been saved.

## Configure environment controls

An environment can carry `protectedStatus`, `networkIsolationEnabled`, and
`ipAllowList`. `PATCH /v1/environments/{id}` updates supplied fields while
preserving omitted fields. These controls require appropriate administrative
access; membership changes or deletion that remove existing controls can require
that access too.

Protection is an operation-specific restriction, not a promise that every
mutation behaves like Render's protected environments. Follow returned errors
and confirmation requirements; do not assume a CLI confirmation flag bypasses
the server's checks.

Network isolation concerns private traffic. Check [private networking](./private-network.md)
and any public service/datastore access separately. Moving a service into an
isolated environment can break dependencies outside it. Restrict shared secret
groups to the intended environment and verify their links independently of
network access.

## Rename or delete groupings

Rename with the project's or environment's PATCH endpoint. Renaming a grouping
does not rename its resources or change application configuration.

Bex project/environment deletion removes groupings and clears affected
resource assignments and associated policies; it does **not** serve as a bulk workload deletion
operation. Deleting a project also removes its child environments. This differs
from Render's documented cascading workload deletion. Inspect remaining resources
and their access rules after deleting a grouping, and retire workloads explicitly
when that is the intent.

If a [Blueprint](./blueprints.md) declares the grouping, update that source too
so synchronization does not recreate it. Review [workspace roles](./members.md)
for account access and [migration procedures](./migrate-from-render.md) before
moving an application between platforms.
