Skip to content
Hexel StudioDocs

Organizations, workspaces and environments

How Hexel Studio organizes resources, what a new organization starts with, and how permissions apply to workspaces and environments.

On this page

Hexel Studio organizes everything in three levels:

LevelWhat it isID
OrganizationThe top-level container. Members, service users, groups, roles, policies and billing belong to an organization.org_...
WorkspaceA group of resources inside an organization, for example one per team or product.ws_...
EnvironmentA stage inside a workspace, such as production or development. It has a type, for example PRODUCTION or DEVELOPMENT.env_...

Organizations are isolated from each other. A token or API key for one organization can't read or change anything in another, and a workspace or environment of another organization answers 404, like one that doesn't exist.

What a new organization starts with

When you create an organization, Hexel Studio sets up:

  • You, as the organization's owner, with full access to it.
  • A workspace named Default (slug default, is_default: true).
  • Two environments in it: Production (type PRODUCTION, the workspace's default environment) and Development (type DEVELOPMENT).

You can add more workspaces and environments within your organization's plan limits. See Workspaces and environments for how.

How permissions apply to workspaces and environments

Permissions come from policies. Where a policy applies depends on how it's granted:

Granted byApplies in
A policy attached to a member, group or service userThe whole organization: every workspace and every environment.
A permission set assigned with a workspace_idThat workspace and all its environments.
A permission set assigned with a workspace_id and an environment_idThat environment only.

Access flows down, never up. An organization-wide grant covers every workspace and environment, but a grant in one workspace doesn't help in another workspace or at the organization level.

For example, to give a member the policies of a permission set in one workspace only:

Bash
curl -X POST https://api.hexelstudio.com/v1/permission-sets/<permission-set-id>/assignments \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "principal_type": "USER",
    "principal_id": "<user-id>",
    "workspace_id": "'"$WORKSPACE_ID"'"
  }'

principal_type is USER, SERVICE_USER or GROUP. The call needs iam:permission_set:write, and you can grant only permissions you hold yourself. List the available permission sets with GET /v1/permission-sets.

Which grants a request uses

Each request is checked at one level, and only the grants for that level and the levels above it count:

The request acts onGrants that count
The organization, for example creating a workspaceOrganization-wide grants only
A workspace, for example GET /v1/workspaces/{workspace_id}Organization-wide grants and grants in that workspace
An environment, for example GET /v1/environments/{environment_id}Organization-wide grants and grants in its workspace and in that environment

When the path names a workspace or environment, Hexel Studio takes the scope from the path. For other requests you can select a scope with headers.

Scope headers

HeaderEffect
X-Workspace-IdAlso counts your grants in this workspace.
X-Environment-IdAlso counts your grants in this environment. Send it together with X-Workspace-Id.

The headers only choose which of your grants count; they never grant anything. A request is denied, even for an organization owner, when:

  • X-Environment-Id is sent without X-Workspace-Id.
  • The workspace isn't an active workspace of the token's organization.
  • The environment isn't an active environment of that workspace.
Bash
curl https://api.hexelstudio.com/v1/environments \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  -H "X-Workspace-Id: $WORKSPACE_ID"

The organization never comes from a scope header. It comes from your token or API key. If you send X-Organization-Id, it must equal that organization or the request is refused. See Headers.

Read your workspaces and environments

List the organization's workspaces (needs workspace:workspace:read):

Bash
curl https://api.hexelstudio.com/v1/workspaces \
  -H "Authorization: Bearer $ACCESS_TOKEN"
Response
[
  {
    "id": "ws_3f9c1d2e8a7b4c6d9e0f1a2b3c4d5e6f",
    "organization_id": "org_7b2e4c1a9d8f4e3b8c6a5d4e3f2a1b0c",
    "name": "Default",
    "slug": "default",
    "is_default": true,
    "is_active": true,
    "created_by_user_id": "5d1e9a3c-7b2f-4e8d-9c6a-1f0e2d3c4b5a",
    "created_at": "2026-10-20T09:12:44.512Z",
    "updated_at": "2026-10-20T09:12:44.512Z"
  }
]

List the environments of one workspace (needs env:env:read in that workspace):

Bash
curl "https://api.hexelstudio.com/v1/environments?workspace_id=$WORKSPACE_ID" \
  -H "Authorization: Bearer $ACCESS_TOKEN"
Response
[
  {
    "id": "env_9a8b7c6d5e4f40312a1b2c3d4e5f6a7b",
    "workspace_id": "ws_3f9c1d2e8a7b4c6d9e0f1a2b3c4d5e6f",
    "name": "Production",
    "slug": "production",
    "type": "PRODUCTION",
    "is_default": true,
    "is_protected": true,
    "is_active": true,
    "settings": "{}",
    "created_by_user_id": "5d1e9a3c-7b2f-4e8d-9c6a-1f0e2d3c4b5a",
    "created_at": "2026-10-20T09:12:44.530Z",
    "updated_at": "2026-10-20T09:12:44.530Z"
  },
  {
    "id": "env_1c2d3e4f5a6b47c8d9e0f1a2b3c4d5e6",
    "workspace_id": "ws_3f9c1d2e8a7b4c6d9e0f1a2b3c4d5e6f",
    "name": "Development",
    "slug": "development",
    "type": "DEVELOPMENT",
    "is_default": false,
    "is_protected": false,
    "is_active": true,
    "settings": "{}",
    "created_by_user_id": "5d1e9a3c-7b2f-4e8d-9c6a-1f0e2d3c4b5a",
    "created_at": "2026-10-20T09:12:44.536Z",
    "updated_at": "2026-10-20T09:12:44.536Z"
  }
]

Without workspace_id, the call lists the environments of every workspace in the organization.