# Proxy Permissions

**Page:** api/proxy-permissions

[Download Raw Markdown](./api/proxy-permissions.md)

---

{/* AUTO-GENERATED — Do not edit manually. Regenerate with: npm run docs:api:generate */}



Proxy permissions define how the Hoody proxy layer authenticates incoming requests and routes them to container programs. A permissions file is a JSON document containing authentication groups (JWT, password, IP, or token), per-group program access rules, and a default deny/allow policy. Project-level permissions apply to every container in the project; container-level permissions override or extend them. Use these endpoints to read, replace, or surgically update these documents. Write operations require an `If-Match: file:v` precondition header (read the current `file_version` via `GET` first) — the server returns `428` if the header is absent and `412` if the version is stale.


The `access` field on a program permission is a **rule defining what is allowed**, not a list of what currently exists. Values: `true`/`false` (allow/deny all), a single port number, an array of port numbers, a port range string like `"8000-8100"`, or the wildcard `"*"`.


## Project proxy permissions

### `GET /api/v1/projects/{id}/proxy/permissions`

Retrieve the complete proxy access control configuration for a project, including authentication groups, program permissions, and default policy.

#### Parameters

| Name | In | Type | Required | Description |
|------|-----|------|----------|-------------|
| `id` | path | string | Yes | Project ID |

#### SDK

```ts
const { data } = await client.api.proxyPermissionsProject.get({ id: "507f1f77bcf86cd799439011" });
```

#### Response



```json
{
  "statusCode": 200,
  "message": "Project proxy permissions retrieved successfully",
  "data": {
    "project": "507f1f77bcf86cd799439011",
    "groups": {},
    "permissions": {},
    "default": "deny"
  }
}
```


```json
{
  "statusCode": 404,
  "error": "Not Found",
  "message": "Project not found"
}
```

| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `PROJECT_NOT_FOUND` | Project not found | The specified project ID does not exist or you do not have access to it | Verify the project ID is correct and that you have permission to access this project |



---

### `PATCH /api/v1/projects/{id}/proxy/permissions`

Replace the entire proxy permissions configuration for a project. Requires `If-Match: file:v` (428 when absent, 412 when stale).

#### Parameters

| Name | In | Type | Required | Description |
|------|-----|------|----------|-------------|
| `id` | path | string | Yes | Project ID |
| `if-match` | header | string | No | `file:v` ETag precondition — read current `file_version` from `GET` first |

#### Request Body

| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `project` | string | Yes | Project ID (must match path `:id`) |
| `groups` | object | Yes | Authentication groups. Key is group name, value is group config. |
| `permissions` | object | Yes | Per-group program permissions. Key is group name, value is map of program → access rule. |
| `default` | string | No | Default access policy when no rules match. One of `"allow"`, `"deny"`. Defaults to `"deny"`. |
| `enable_proxy` | boolean | No | Enable or disable the proxy. Defaults to `true`. |

The `groups` values may include the following auth-type-specific fields:

- **JWT** (`type: "jwt"`): `secret`, `algorithm` (`"HS256"` | `"RS256"` | `"ES256"`), `sources` (e.g. `["header:Authorization"]`), `claims` (optional required claim values).
- **Password** (`type: "password"`): `username`, `password`, `salt`, `algorithm` (`"sha256"`).
- **IP** (`type: "ip"`): `range` (IPv4 CIDR).
- **Token** (`type: "token"`): `header` + `value`, or `cookie` + `value`, or `param` + `value`.

The `permissions` values are access rules per program name (`terminal`, `files`, `ui`, `exec`, etc.). See the note above for the `access` rule grammar.

#### SDK

```ts
await client.api.proxyPermissionsProject.replace({
  id: "507f1f77bcf86cd799439011",
  ifMatch: "file:v3",
  data: {
    project: "507f1f77bcf86cd799439011",
    groups: {
      admin: { type: "jwt", algorithm: "HS256", secret: "shhh", sources: ["header:Authorization"] }
    },
    permissions: {
      admin: { terminal: [1, 2], files: true }
    },
    default: "deny",
    enable_proxy: true
  }
});
```

#### Response



```json
{
  "statusCode": 200,
  "message": "Project proxy permissions updated successfully",
  "data": {
    "project": "507f1f77bcf86cd799439011",
    "groups": {
      "admin": { "type": "jwt", "algorithm": "HS256" }
    },
    "permissions": {
      "admin": { "terminal": true, "files": true }
    },
    "default": "deny",
    "enable_proxy": true
  }
}
```


```json
{
  "statusCode": 400,
  "error": "Bad Request",
  "message": "Invalid permissions configuration"
}
```

| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `VALIDATION_ERROR` | Invalid input parameters | The proxy permissions configuration contains invalid data or missing required fields | Check that all required fields are present and properly formatted according to the schema |
| `INVALID_JWT_CONFIG` | Invalid JWT configuration | JWT authentication group has invalid secret, algorithm, or sources configuration | Ensure JWT secret is valid for the algorithm, sources are properly formatted, and claims are scalar values |
| `INVALID_IP_RANGE` | Invalid IP CIDR range | IP authentication group has an invalid IPv4 CIDR notation | Use valid IPv4 CIDR format like `"192.168.1.0/24"` or `"10.0.0.1/32"` |


```json
{
  "statusCode": 404,
  "error": "Not Found",
  "message": "Project not found"
}
```

| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `PROJECT_NOT_FOUND` | Project not found | The specified project ID does not exist or you do not have access to it | Verify the project ID is correct and that you have permission to access this project |



---

### `PATCH /api/v1/projects/{id}/proxy/permissions/default`

Update the default access policy (`"allow"` or `"deny"`) that applies when a request does not match any authentication group rules.

#### Parameters

| Name | In | Type | Required | Description |
|------|-----|------|----------|-------------|
| `id` | path | string | Yes | Project ID |
| `if-match` | header | string | No | `file:v` ETag precondition — read current `file_version` from `GET` first |

#### Request Body

| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `default` | string | Yes | Default access policy for unmatched requests. One of `"allow"`, `"deny"`. |

#### SDK

```ts
await client.api.proxyPermissionsProject.updateDefault({
  id: "507f1f77bcf86cd799439011",
  ifMatch: "file:v3",
  data: { default: "deny" }
});
```

#### Response



```json
{
  "statusCode": 200,
  "message": "Default policy updated successfully",
  "data": {
    "project": "507f1f77bcf86cd799439011",
    "groups": {},
    "permissions": {},
    "default": "deny"
  }
}
```


```json
{
  "statusCode": 400,
  "error": "Bad Request",
  "message": "Invalid default policy value"
}
```

| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `VALIDATION_ERROR` | Invalid default policy | The default policy must be either `"allow"` or `"deny"` | Provide a valid default value: `"allow"` or `"deny"` |


```json
{
  "statusCode": 404,
  "error": "Not Found",
  "message": "Project not found"
}
```

| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `PROJECT_NOT_FOUND` | Project not found | The specified project ID does not exist or you do not have access to it | Verify the project ID is correct and that you have permission to access this project |



---

### `PATCH /api/v1/projects/{id}/proxy/permissions/state`

Enable or disable the proxy entirely for a project. When disabled, the proxy layer is bypassed and all access control is removed regardless of configured rules.

#### Parameters

| Name | In | Type | Required | Description |
|------|-----|------|----------|-------------|
| `id` | path | string | Yes | Project ID |
| `if-match` | header | string | No | `file:v` ETag precondition — read current `file_version` from `GET` first |

#### Request Body

| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `enable_proxy` | boolean | Yes | Enable or disable the proxy entirely |

#### SDK

```ts
await client.api.proxyPermissionsProject.updateState({
  id: "507f1f77bcf86cd799439011",
  ifMatch: "file:v3",
  data: { enable_proxy: true }
});
```

#### Response



```json
{
  "statusCode": 200,
  "message": "Proxy state updated successfully",
  "data": {
    "project": "507f1f77bcf86cd799439011",
    "groups": {},
    "permissions": {},
    "default": "deny",
    "enable_proxy": false
  }
}
```


```json
{
  "statusCode": 400,
  "error": "Bad Request",
  "message": "Invalid enable_proxy value"
}
```

| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `VALIDATION_ERROR` | Invalid enable_proxy value | The `enable_proxy` field must be a boolean (true or false) | Provide a valid boolean value: `true` to enable proxy, `false` to disable |


```json
{
  "statusCode": 404,
  "error": "Not Found",
  "message": "Project not found"
}
```

| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `PROJECT_NOT_FOUND` | Project not found | The specified project ID does not exist or you do not have access to it | Verify the project ID is correct and that you have permission to access this project |



---

### `DELETE /api/v1/projects/{id}/proxy/permissions`

Remove all proxy access control configuration from a project, reverting it to open access with a default `"allow"` policy. This clears all authentication groups and permission rules.

#### Parameters

| Name | In | Type | Required | Description |
|------|-----|------|----------|-------------|
| `id` | path | string | Yes | Project ID |
| `if-match` | header | string | No | `file:v` ETag precondition — read current `file_version` from `GET` first |

#### SDK

```ts
await client.api.proxyPermissionsProject.delete({
  id: "507f1f77bcf86cd799439011",
  ifMatch: "file:v3"
});
```

#### Response



```json
{
  "statusCode": 200,
  "message": "Project proxy permissions deleted successfully",
  "data": {
    "project": "507f1f77bcf86cd799439011",
    "groups": {},
    "permissions": {},
    "default": "allow"
  }
}
```


```json
{
  "statusCode": 404,
  "error": "Not Found",
  "message": "Project not found"
}
```

| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `PROJECT_NOT_FOUND` | Project not found | The specified project ID does not exist or you do not have access to it | Verify the project ID is correct and that you have permission to access this project |



---

## Project authentication groups

### `PATCH /api/v1/projects/{id}/proxy/permissions/groups/{groupName}/ip`

Set or replace an IP-based authentication group for a project.

#### Parameters

| Name | In | Type | Required | Description |
|------|-----|------|----------|-------------|
| `id` | path | string | Yes | Project ID |
| `groupName` | path | string | Yes | Group name |
| `if-match` | header | string | No | `file:v` ETag precondition — read current `file_version` from `GET` first |

#### Request Body

| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `range` | string | Yes | IPv4 CIDR range. Format: `IP/mask` (mask 0-32). Example: `"192.168.1.0/24"`. |

#### SDK

```ts
await client.api.proxyPermissionsProject.setIpGroup({
  id: "507f1f77bcf86cd799439011",
  groupName: "office",
  ifMatch: "file:v3",
  data: { range: "192.168.1.0/24" }
});
```

#### Response



```json
{
  "statusCode": 200,
  "message": "IP authentication group configured successfully",
  "data": {
    "project": "507f1f77bcf86cd799439011",
    "groups": {},
    "permissions": {},
    "default": "deny"
  }
}
```


```json
{
  "statusCode": 400,
  "error": "Bad Request",
  "message": "Invalid IP CIDR range"
}
```



---

### `PATCH /api/v1/projects/{id}/proxy/permissions/groups/{groupName}/jwt`

Set or replace a JWT-based authentication group for a project.

#### Parameters

| Name | In | Type | Required | Description |
|------|-----|------|----------|-------------|
| `id` | path | string | Yes | Project ID |
| `groupName` | path | string | Yes | Group name |
| `if-match` | header | string | No | `file:v` ETag precondition — read current `file_version` from `GET` first |

#### Request Body

| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `secret` | string | Yes | JWT secret key. For `HS256`: any string. For `RS256`/`ES256`: PEM-encoded public key. |
| `algorithm` | string | Yes | One of `"HS256"`, `"RS256"`, `"ES256"`. |
| `sources` | array | Yes | Token source locations. Each item matches `^(header\|cookie):Name$`. Example: `["header:Authorization"]`. |
| `claims` | object | No | Required JWT claims that must be present and match exactly. Values must be string, number, or boolean. |

#### SDK

```ts
await client.api.proxyPermissionsProject.setJwtGroup({
  id: "507f1f77bcf86cd799439011",
  groupName: "admin",
  ifMatch: "file:v3",
  data: {
    secret: "super-secret-key",
    algorithm: "HS256",
    sources: ["header:Authorization"],
    claims: { role: "admin" }
  }
});
```

#### Response



```json
{
  "statusCode": 200,
  "message": "JWT authentication group configured successfully",
  "data": {
    "project": "507f1f77bcf86cd799439011",
    "groups": {},
    "permissions": {},
    "default": "deny"
  }
}
```


```json
{
  "statusCode": 400,
  "error": "Bad Request",
  "message": "Invalid JWT configuration"
}
```



---

### `PATCH /api/v1/projects/{id}/proxy/permissions/groups/{groupName}/password`

Set or replace a password-based authentication group for a project.

#### Parameters

| Name | In | Type | Required | Description |
|------|-----|------|----------|-------------|
| `id` | path | string | Yes | Project ID |
| `groupName` | path | string | Yes | Group name |
| `if-match` | header | string | No | `file:v` ETag precondition — read current `file_version` from `GET` first |

#### Request Body

| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `username` | string | Yes | Username for authentication. Must match exactly what the client provides. |
| `password` | string | Yes | Plaintext (will be hashed) or pre-hashed `SHA256(salt+password)` in lowercase hex. |
| `salt` | string | Yes | Salt for password hashing. Should be unique per user/group. |
| `algorithm` | string | No | Hashing algorithm. Currently only `"sha256"`. |

#### SDK

```ts
await client.api.proxyPermissionsProject.setPasswordGroup({
  id: "507f1f77bcf86cd799439011",
  groupName: "users",
  ifMatch: "file:v3",
  data: {
    username: "admin",
    password: "s3cret",
    salt: "randomsalt123",
    algorithm: "sha256"
  }
});
```

#### Response



```json
{
  "statusCode": 200,
  "message": "Password authentication group configured successfully",
  "data": {
    "project": "507f1f77bcf86cd799439011",
    "groups": {},
    "permissions": {},
    "default": "deny"
  }
}
```


```json
{
  "statusCode": 400,
  "error": "Bad Request",
  "message": "Invalid password configuration"
}
```



---

### `PATCH /api/v1/projects/{id}/proxy/permissions/groups/{groupName}/token`

Set or replace a static-token authentication group for a project. The request body must specify exactly one token location: `header`+`value`, `cookie`+`value`, or `param`+`value`.

#### Parameters

| Name | In | Type | Required | Description |
|------|-----|------|----------|-------------|
| `id` | path | string | Yes | Project ID |
| `groupName` | path | string | Yes | Group name |
| `if-match` | header | string | No | `file:v` ETag precondition — read current `file_version` from `GET` first |

#### Request Body

The body uses a `oneOf` schema. Supply exactly one of these shapes:

| Shape | Fields |
|-------|--------|
| Header | `header` (string, required), `value` (string, required) |
| Cookie | `cookie` (string, required), `value` (string, required) |
| Query param | `param` (string, required), `value` (string, required) |

#### SDK

```ts
await client.api.proxyPermissionsProject.setTokenGroup({
  id: "507f1f77bcf86cd799439011",
  groupName: "api-clients",
  ifMatch: "file:v3",
  data: { header: "X-API-Key", value: "tok_live_abc123" }
});
```

#### Response



```json
{
  "statusCode": 200,
  "message": "Token authentication group configured successfully",
  "data": {
    "project": "507f1f77bcf86cd799439011",
    "groups": {},
    "permissions": {},
    "default": "deny"
  }
}
```


```json
{
  "statusCode": 400,
  "error": "Bad Request",
  "message": "Invalid token configuration"
}
```



---

### `DELETE /api/v1/projects/{id}/proxy/permissions/groups/{groupName}`

Remove an authentication group from a project. This deletes only the group entry; any program permissions that reference the group name are left in place.

#### Parameters

| Name | In | Type | Required | Description |
|------|-----|------|----------|-------------|
| `id` | path | string | Yes | Project ID |
| `groupName` | path | string | Yes | Group name to remove |
| `if-match` | header | string | No | `file:v` ETag precondition — read current `file_version` from `GET` first |

#### SDK

```ts
await client.api.proxyPermissionsProject.removeAuthGroup({
  id: "507f1f77bcf86cd799439011",
  groupName: "office",
  ifMatch: "file:v3"
});
```

#### Response



```json
{
  "statusCode": 200,
  "message": "Authentication group removed successfully",
  "data": {
    "project": "507f1f77bcf86cd799439011",
    "groups": {},
    "permissions": {},
    "default": "deny"
  }
}
```


```json
{
  "statusCode": 404,
  "error": "Not Found",
  "message": "Project or group not found"
}
```



---

## Project group permissions

### `PATCH /api/v1/projects/{id}/proxy/permissions/permissions/{groupName}`

Set a single program access rule for a project's authentication group. The `access` value defines which ports/instances are allowed.

#### Parameters

| Name | In | Type | Required | Description |
|------|-----|------|----------|-------------|
| `id` | path | string | Yes | Project ID |
| `groupName` | path | string | Yes | Group name |
| `if-match` | header | string | No | `file:v` ETag precondition — read current `file_version` from `GET` first |

#### Request Body

| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `program` | string | Yes | Program name to set the access rule for (e.g. `http`, `terminal`, `ssh`, `files`, `exec`, `services`, `notifications`). |
| `access` | boolean \| number \| array \| string | Yes | Access rule. See the access-rule grammar at the top of this page. |

#### SDK

```ts
await client.api.proxyPermissionsProject.setGroup({
  id: "507f1f77bcf86cd799439011",
  groupName: "admin",
  ifMatch: "file:v3",
  data: { program: "http", access: true }
});
```

#### Response



```json
{
  "statusCode": 200,
  "message": "Group program permission set successfully",
  "data": {
    "project": "507f1f77bcf86cd799439011",
    "groups": {},
    "permissions": {},
    "default": "deny"
  }
}
```


```json
{
  "statusCode": 400,
  "error": "Bad Request",
  "message": "Invalid permission value"
}
```



---

### `DELETE /api/v1/projects/{id}/proxy/permissions/permissions/{groupName}`

Remove all program permissions for a project's group in a single call.

#### Parameters

| Name | In | Type | Required | Description |
|------|-----|------|----------|-------------|
| `id` | path | string | Yes | Project ID |
| `groupName` | path | string | Yes | Group name |
| `if-match` | header | string | No | `file:v` ETag precondition — read current `file_version` from `GET` first |

#### SDK

```ts
await client.api.proxyPermissionsProject.removeGroup({
  id: "507f1f77bcf86cd799439011",
  groupName: "admin",
  ifMatch: "file:v3"
});
```

#### Response



```json
{
  "statusCode": 200,
  "message": "All group permissions removed successfully",
  "data": {
    "project": "507f1f77bcf86cd799439011",
    "groups": {},
    "permissions": {},
    "default": "deny"
  }
}
```



---

### `DELETE /api/v1/projects/{id}/proxy/permissions/permissions/{groupName}/{program}`

Remove a single program permission from a project's group.

#### Parameters

| Name | In | Type | Required | Description |
|------|-----|------|----------|-------------|
| `id` | path | string | Yes | Project ID |
| `groupName` | path | string | Yes | Group name |
| `program` | path | string | Yes | Program name (e.g. `http`, `ssh`, `files`) |
| `if-match` | header | string | No | `file:v` ETag precondition — read current `file_version` from `GET` first |

#### SDK

```ts
await client.api.proxyPermissionsProject.removeProgram({
  id: "507f1f77bcf86cd799439011",
  groupName: "admin",
  program: "http",
  ifMatch: "file:v3"
});
```

#### Response



```json
{
  "statusCode": 200,
  "message": "Program permission removed successfully",
  "data": {
    "project": "507f1f77bcf86cd799439011",
    "groups": {},
    "permissions": {},
    "default": "deny"
  }
}
```



---

## Container proxy permissions

### `GET /api/v1/containers/{id}/proxy/permissions`

Retrieve the complete proxy access control configuration for a single container.

#### Parameters

| Name | In | Type | Required | Description |
|------|-----|------|----------|-------------|
| `id` | path | string | Yes | Container ID |

#### SDK

```ts
const { data } = await client.api.proxyPermissionsContainer.get({ id: "507f1f77bcf86cd799439012" });
```

#### Response



```json
{
  "statusCode": 200,
  "message": "Container proxy permissions retrieved successfully",
  "data": {
    "project": "507f1f77bcf86cd799439011",
    "container": "507f1f77bcf86cd799439012",
    "groups": {},
    "permissions": {},
    "default": "deny"
  }
}
```


```json
{
  "statusCode": 404,
  "error": "Not Found",
  "message": "Container not found"
}
```



---

### `PATCH /api/v1/containers/{id}/proxy/permissions`

Replace the container proxy permissions configuration. Requires `If-Match: file:v` (428 when absent, 412 when stale).

#### Parameters

| Name | In | Type | Required | Description |
|------|-----|------|----------|-------------|
| `id` | path | string | Yes | Container ID |
| `if-match` | header | string | No | `file:v` ETag precondition — read current `file_version` from `GET` first |

#### Request Body

| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `project` | string | Yes | Project ID owning this container |
| `container` | string | Yes | Container ID (must match path `:id`) |
| `groups` | object | Yes | Authentication groups. Key is group name, value is group config. |
| `permissions` | object | Yes | Per-group program permissions. Key is group name, value is map of program → access rule. |
| `default` | string | No | Default access policy. One of `"allow"`, `"deny"`. Defaults to `"deny"`. |
| `enable_proxy` | boolean | No | Enable or disable the proxy. Defaults to `true`. |
| `hooks` | object | No | Per-service proxy hooks. Keys are service names; values are first-match-wins arrays of `{ match, script, timeout? }` rules. Max 8 per service, 32 per file total. Reject-listed services: `logs`, `proxy`, `workspaces`. |

The `groups` value structure and `permissions` value structure are the same as the project-level replace endpoint (see above). The `access` rule grammar is documented at the top of this page.

#### SDK

```ts
await client.api.proxyPermissionsContainer.replace({
  id: "507f1f77bcf86cd799439012",
  ifMatch: "file:v2",
  data: {
    project: "507f1f77bcf86cd799439011",
    container: "507f1f77bcf86cd799439012",
    groups: {
      admin: { type: "jwt" }
    },
    permissions: {
      admin: { terminal: [1, 2], files: true }
    },
    default: "deny"
  }
});
```

#### Response



```json
{
  "statusCode": 200,
  "message": "Container proxy permissions updated successfully",
  "data": {
    "project": "507f1f77bcf86cd799439011",
    "container": "507f1f77bcf86cd799439012",
    "groups": {},
    "permissions": {},
    "default": "deny"
  }
}
```


```json
{
  "statusCode": 400,
  "error": "Bad Request",
  "message": "Invalid proxy permissions configuration"
}
```



---

### `PATCH /api/v1/containers/{id}/proxy/permissions/default`

Update the container's default access policy.

#### Parameters

| Name | In | Type | Required | Description |
|------|-----|------|----------|-------------|
| `id` | path | string | Yes | Container ID |
| `if-match` | header | string | No | `file:v` ETag precondition — read current `file_version` from `GET` first |

#### Request Body

| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `default` | string | Yes | Default access policy for unmatched requests. One of `"allow"`, `"deny"`. |

#### SDK

```ts
await client.api.proxyPermissionsContainer.updateDefault({
  id: "507f1f77bcf86cd799439012",
  ifMatch: "file:v2",
  data: { default: "allow" }
});
```

#### Response



```json
{
  "statusCode": 200,
  "message": "Default policy updated successfully",
  "data": {
    "project": "507f1f77bcf86cd799439011",
    "container": "507f1f77bcf86cd799439012",
    "groups": {},
    "permissions": {},
    "default": "allow"
  }
}
```



---

### `PATCH /api/v1/containers/{id}/proxy/permissions/state`

Enable or disable the proxy for a single container.

#### Parameters

| Name | In | Type | Required | Description |
|------|-----|------|----------|-------------|
| `id` | path | string | Yes | Container ID |
| `if-match` | header | string | No | `file:v` ETag precondition — read current `file_version` from `GET` first |

#### Request Body

| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `enable_proxy` | boolean | Yes | Enable or disable the proxy entirely |

#### SDK

```ts
await client.api.proxyPermissionsContainer.updateState({
  id: "507f1f77bcf86cd799439012",
  ifMatch: "file:v2",
  data: { enable_proxy: true }
});
```

#### Response



```json
{
  "statusCode": 200,
  "message": "Proxy state updated successfully",
  "data": {
    "project": "507f1f77bcf86cd799439011",
    "container": "507f1f77bcf86cd799439012",
    "groups": {},
    "permissions": {},
    "default": "deny",
    "enable_proxy": true
  }
}
```



---

### `DELETE /api/v1/containers/{id}/proxy/permissions`

Delete the container's proxy permissions document. The container reverts to a default `"allow"` policy with the proxy enabled.

#### Parameters

| Name | In | Type | Required | Description |
|------|-----|------|----------|-------------|
| `id` | path | string | Yes | Container ID |
| `if-match` | header | string | No | `file:v` ETag precondition — read current `file_version` from `GET` first |

#### SDK

```ts
await client.api.proxyPermissionsContainer.delete({
  id: "507f1f77bcf86cd799439012",
  ifMatch: "file:v2"
});
```

#### Response



```json
{
  "statusCode": 200,
  "message": "Container proxy permissions deleted successfully",
  "data": {
    "project": "507f1f77bcf86cd799439011",
    "container": "507f1f77bcf86cd799439012",
    "groups": {},
    "permissions": {},
    "default": "allow"
  }
}
```


```json
{
  "statusCode": 404,
  "error": "Not Found",
  "message": "Container not found"
}
```



---

## Container authentication groups

### `PATCH /api/v1/containers/{id}/proxy/permissions/groups/{groupName}/ip`

Set or replace an IP-based authentication group for a container.

#### Parameters

| Name | In | Type | Required | Description |
|------|-----|------|----------|-------------|
| `id` | path | string | Yes | Container ID |
| `groupName` | path | string | Yes | Group name |
| `if-match` | header | string | No | `file:v` ETag precondition — read current `file_version` from `GET` first |

#### Request Body

| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `range` | string | Yes | IPv4 CIDR range. Format: `IP/mask` (mask 0-32). Example: `"10.0.0.0/8"`. |

#### SDK

```ts
await client.api.proxyPermissionsContainer.setIpGroup({
  id: "507f1f77bcf86cd799439012",
  groupName: "office",
  ifMatch: "file:v2",
  data: { range: "10.0.0.0/8" }
});
```

#### Response



```json
{
  "statusCode": 200,
  "message": "IP authentication group configured successfully",
  "data": {
    "project": "507f1f77bcf86cd799439011",
    "container": "507f1f77bcf86cd799439012",
    "groups": {},
    "permissions": {},
    "default": "deny"
  }
}
```


```json
{
  "statusCode": 400,
  "error": "Bad Request",
  "message": "Invalid IP CIDR range"
}
```



---

### `PATCH /api/v1/containers/{id}/proxy/permissions/groups/{groupName}/jwt`

Set or replace a JWT-based authentication group for a container.

#### Parameters

| Name | In | Type | Required | Description |
|------|-----|------|----------|-------------|
| `id` | path | string | Yes | Container ID |
| `groupName` | path | string | Yes | Group name |
| `if-match` | header | string | No | `file:v` ETag precondition — read current `file_version` from `GET` first |

#### Request Body

| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `secret` | string | Yes | JWT secret key. For `HS256`: any string. For `RS256`/`ES256`: PEM-encoded public key. |
| `algorithm` | string | Yes | One of `"HS256"`, `"RS256"`, `"ES256"`. |
| `sources` | array | Yes | Token source locations. Each item matches `^(header\|cookie):Name$`. |
| `claims` | object | No | Required JWT claims that must be present and match exactly. Values must be string, number, or boolean. |

#### SDK

```ts
await client.api.proxyPermissionsContainer.setJwtGroup({
  id: "507f1f77bcf86cd799439012",
  groupName: "admin",
  ifMatch: "file:v2",
  data: {
    secret: "container-secret",
    algorithm: "HS256",
    sources: ["cookie:jwt_token"]
  }
});
```

#### Response



```json
{
  "statusCode": 200,
  "message": "JWT authentication group configured successfully",
  "data": {
    "project": "507f1f77bcf86cd799439011",
    "container": "507f1f77bcf86cd799439012",
    "groups": {},
    "permissions": {},
    "default": "deny"
  }
}
```


```json
{
  "statusCode": 400,
  "error": "Bad Request",
  "message": "Invalid JWT configuration"
}
```



---

### `PATCH /api/v1/containers/{id}/proxy/permissions/groups/{groupName}/password`

Set or replace a password-based authentication group for a container.

#### Parameters

| Name | In | Type | Required | Description |
|------|-----|------|----------|-------------|
| `id` | path | string | Yes | Container ID |
| `groupName` | path | string | Yes | Group name |
| `if-match` | header | string | No | `file:v` ETag precondition — read current `file_version` from `GET` first |

#### Request Body

| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `username` | string | Yes | Username for authentication. |
| `password` | string | Yes | Plaintext (will be hashed) or pre-hashed `SHA256(salt+password)` in lowercase hex. |
| `salt` | string | Yes | Salt for password hashing. |
| `algorithm` | string | No | Hashing algorithm. Currently only `"sha256"`. |

#### SDK

```ts
await client.api.proxyPermissionsContainer.setPasswordGroup({
  id: "507f1f77bcf86cd799439012",
  groupName: "users",
  ifMatch: "file:v2",
  data: {
    username: "deployer",
    password: "p@ssw0rd!",
    salt: "container-salt-xyz",
    algorithm: "sha256"
  }
});
```

#### Response



```json
{
  "statusCode": 200,
  "message": "Password authentication group configured successfully",
  "data": {
    "project": "507f1f77bcf86cd799439011",
    "container": "507f1f77bcf86cd799439012",
    "groups": {},
    "permissions": {},
    "default": "deny"
  }
}
```


```json
{
  "statusCode": 400,
  "error": "Bad Request",
  "message": "Invalid password configuration"
}
```



---

### `PATCH /api/v1/containers/{id}/proxy/permissions/groups/{groupName}/token`

Set or replace a static-token authentication group for a container. The request body must specify exactly one token location.

#### Parameters

| Name | In | Type | Required | Description |
|------|-----|------|----------|-------------|
| `id` | path | string | Yes | Container ID |
| `groupName` | path | string | Yes | Group name |
| `if-match` | header | string | No | `file:v` ETag precondition — read current `file_version` from `GET` first |

#### Request Body

The body uses a `oneOf` schema. Supply exactly one of these shapes:

| Shape | Fields |
|-------|--------|
| Header | `header` (string, required), `value` (string, required) |
| Cookie | `cookie` (string, required), `value` (string, required) |
| Query param | `param` (string, required), `value` (string, required) |

#### SDK

```ts
await client.api.proxyPermissionsContainer.setTokenGroup({
  id: "507f1f77bcf86cd799439012",
  groupName: "external-api",
  ifMatch: "file:v2",
  data: { header: "X-Container-Token", value: "tok_container_xyz" }
});
```

#### Response



```json
{
  "statusCode": 200,
  "message": "Token authentication group configured successfully",
  "data": {
    "project": "507f1f77bcf86cd799439011",
    "container": "507f1f77bcf86cd799439012",
    "groups": {},
    "permissions": {},
    "default": "deny"
  }
}
```


```json
{
  "statusCode": 400,
  "error": "Bad Request",
  "message": "Invalid token configuration"
}
```



---

### `DELETE /api/v1/containers/{id}/proxy/permissions/groups/{groupName}`

Remove an authentication group from a container.

#### Parameters

| Name | In | Type | Required | Description |
|------|-----|------|----------|-------------|
| `id` | path | string | Yes | Container ID |
| `groupName` | path | string | Yes | Group name to remove |
| `if-match` | header | string | No | `file:v` ETag precondition — read current `file_version` from `GET` first |

#### SDK

```ts
await client.api.proxyPermissionsContainer.removeAuthGroup({
  id: "507f1f77bcf86cd799439012",
  groupName: "office",
  ifMatch: "file:v2"
});
```

#### Response



```json
{
  "statusCode": 200,
  "message": "Authentication group removed successfully",
  "data": {
    "project": "507f1f77bcf86cd799439011",
    "container": "507f1f77bcf86cd799439012",
    "groups": {},
    "permissions": {},
    "default": "deny"
  }
}
```


```json
{
  "statusCode": 404,
  "error": "Not Found",
  "message": "Container or group not found"
}
```



---

## Container group permissions

### `PATCH /api/v1/containers/{id}/proxy/permissions/permissions/{groupName}`

Set a single program access rule for a container's authentication group.

#### Parameters

| Name | In | Type | Required | Description |
|------|-----|------|----------|-------------|
| `id` | path | string | Yes | Container ID |
| `groupName` | path | string | Yes | Group name |
| `if-match` | header | string | No | `file:v` ETag precondition — read current `file_version` from `GET` first |

#### Request Body

| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `program` | string | Yes | Program name (e.g. `http`, `terminal`, `ssh`, `files`, `exec`, `services`, `notifications`). |
| `access` | boolean \| number \| array \| string | Yes | Access rule. See the access-rule grammar at the top of this page. |

#### SDK

```ts
await client.api.proxyPermissionsContainer.setGroup({
  id: "507f1f77bcf86cd799439012",
  groupName: "admin",
  ifMatch: "file:v2",
  data: { program: "http", access: [80, 443] }
});
```

#### Response



```json
{
  "statusCode": 200,
  "message": "Group program permission set successfully",
  "data": {
    "project": "507f1f77bcf86cd799439011",
    "container": "507f1f77bcf86cd799439012",
    "groups": {},
    "permissions": {},
    "default": "deny"
  }
}
```


```json
{
  "statusCode": 400,
  "error": "Bad Request",
  "message": "Invalid permission value"
}
```



---

### `DELETE /api/v1/containers/{id}/proxy/permissions/permissions/{groupName}`

Remove all program permissions for a container's group.

#### Parameters

| Name | In | Type | Required | Description |
|------|-----|------|----------|-------------|
| `id` | path | string | Yes | Container ID |
| `groupName` | path | string | Yes | Group name |
| `if-match` | header | string | No | `file:v` ETag precondition — read current `file_version` from `GET` first |

#### SDK

```ts
await client.api.proxyPermissionsContainer.removeGroup({
  id: "507f1f77bcf86cd799439012",
  groupName: "admin",
  ifMatch: "file:v2"
});
```

#### Response



```json
{
  "statusCode": 200,
  "message": "All group permissions removed successfully",
  "data": {
    "project": "507f1f77bcf86cd799439011",
    "container": "507f1f77bcf86cd799439012",
    "groups": {},
    "permissions": {},
    "default": "deny"
  }
}
```



---

### `DELETE /api/v1/containers/{id}/proxy/permissions/permissions/{groupName}/{program}`

Remove a single program permission from a container's group.

#### Parameters

| Name | In | Type | Required | Description |
|------|-----|------|----------|-------------|
| `id` | path | string | Yes | Container ID |
| `groupName` | path | string | Yes | Group name |
| `program` | path | string | Yes | Program name (e.g. `http`, `ssh`, `files`) |
| `if-match` | header | string | No | `file:v` ETag precondition — read current `file_version` from `GET` first |

#### SDK

```ts
await client.api.proxyPermissionsContainer.removeProgram({
  id: "507f1f77bcf86cd799439012",
  groupName: "admin",
  program: "http",
  ifMatch: "file:v2"
});
```

#### Response



```json
{
  "statusCode": 200,
  "message": "Program permission removed successfully",
  "data": {
    "project": "507f1f77bcf86cd799439011",
    "container": "507f1f77bcf86cd799439012",
    "groups": {},
    "permissions": {},
    "default": "deny"
  }
}
```