Skip to content
Hoody.com

Configure authentication groups and access control rules that govern how requests reach the reverse proxy on a Hoody container or project. Each project and each container owns its own proxy permissions document. Mutating endpoints require an If-Match: file:v<N> header built from the current file_version (read it with GET first); the etag field on the GET response is the precomputed value. The document holds authentication groups, per-group permissions, a fallback default policy, an enable_proxy kill-switch, and (for containers) per-service hooks.

The groups object maps a group name to one of five authentication types. Every type is a gate; the type determines which credentials are accepted. Group names must match ^[A-Za-z0-9_-]{1,50}$.

TypePurpose
jwtVerifies a JWT the client application issued. See the JWT section for the important caveat about Hoody identity claims.
passwordVerifies a username + SHA256-hashed password with a per-group salt.
ipAllows requests whose source IP falls inside an IPv4 CIDR range.
tokenMatches an opaque token from a single HTTP header, cookie, or query parameter.
hoody-identityVerifies the native Hoody identity claim. The supported gate for user identity; carries no key material.

The permissions object maps the same group name to program-level access rules that decide WHICH instances or ports are ALLOWED for each program (e.g. terminal, files, ui, exec, ssh, http).

These endpoints read and mutate the proxy permissions document scoped to a single container.

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

Section titled “GET /api/v1/containers/{id}/proxy/permissions”

Retrieve the full container proxy permissions document.

NameInTypeRequiredDescription
idpathstringYesContainer ID
{
"statusCode": 200,
"message": "Container proxy permissions retrieved successfully",
"data": {
"project": "507f1f77bcf86cd799439011",
"container": "507f1f77bcf86cd799439012",
"groups": {},
"permissions": {},
"default": "deny",
"enable_proxy": true,
"file_version": 3,
"etag": "file:v3"
}
}
import { HoodyClient } from 'hoody-sdk';
const client = new HoodyClient({ baseURL: 'https://api.hoody.com', token: process.env.HOODY_TOKEN });
await client.api.proxyPermissionsContainer.get(id);
Terminal window
curl -X GET "https://api.hoody.com/api/v1/containers/{containerId}/proxy/permissions" \
-H "Authorization: Bearer $HOODY_TOKEN"

PUT /api/v1/containers/{id}/proxy/permissions

Section titled “PUT /api/v1/containers/{id}/proxy/permissions”

Replace the container proxy permissions document. Pass the document body in the request and If-Match: file:v<N> to prevent lost updates. When the header is missing the API returns 428; when stale it returns 412.

NameInTypeRequiredDescription
idpathstringYesContainer ID
if-matchheaderstringNofile:v<N> ETag precondition; read current file_version from GET first
FieldTypeRequiredDescription
projectstringYesProject ID owning this container (24-hex)
containerstringYesContainer ID, must match the path :id (24-hex)
groupsobjectYesAuthentication groups keyed by group name
permissionsobjectYesPer-group program access rules
defaultstringNo"allow" or "deny". Defaults to "deny" if omitted.
enable_proxybooleanNoEnable or disable the proxy. Defaults to true.
hooksobjectNoPer-service proxy hook arrays. See below.

Each entry in groups uses one of the five type values: jwt, password, ip, token, or hoody-identity. The hoody-identity config is { audience (REQUIRED), sources?, allow_types?, users?, max_age_seconds? (>=300), expose_type? } and never carries key material — the trust keyring is operator-owned.

The hooks object maps a service name to a first-match-wins array of { match, script, timeout? } rules. Max 8 per service, 32 per file total. The reject-listed services are logs, proxy, workspaces, and cdp.

{
"statusCode": 200,
"message": "Container proxy permissions updated successfully",
"data": {
"project": "507f1f77bcf86cd799439011",
"container": "507f1f77bcf86cd799439012",
"groups": {},
"permissions": {},
"default": "deny"
}
}
import { HoodyClient } from 'hoody-sdk';
const client = new HoodyClient({ baseURL: 'https://api.hoody.com', token: process.env.HOODY_TOKEN });
await client.api.proxyPermissionsContainer.replace(id, {
project: '507f1f77bcf86cd799439011',
container: '507f1f77bcf86cd799439012',
groups: {
admin: {
type: 'jwt',
algorithm: 'HS256',
secret: 'replace-with-strong-secret',
sources: ['header:Authorization'],
},
},
permissions: {
admin: { terminal: true, files: true },
},
default: 'deny',
enable_proxy: true,
}, { ifMatch: 'file:v3' });
Terminal window
curl -X PUT "https://api.hoody.com/api/v1/containers/{containerId}/proxy/permissions" \
-H "Authorization: Bearer $HOODY_TOKEN" \
-H "Content-Type: application/json" \
-H "If-Match: file:v3" \
-d '{
"project": "507f1f77bcf86cd799439011",
"container": "507f1f77bcf86cd799439012",
"groups": {
"admin": {
"type": "jwt",
"algorithm": "HS256",
"secret": "replace-with-strong-secret",
"sources": ["header:Authorization"]
}
},
"permissions": {
"admin": { "terminal": true, "files": true }
},
"default": "deny",
"enable_proxy": true
}'

PUT /api/v1/containers/{id}/proxy/permissions/groups/{groupName}/jwt

Section titled “PUT /api/v1/containers/{id}/proxy/permissions/groups/{groupName}/jwt”

Create or update a single JWT authentication group on a container.

NameInTypeRequiredDescription
idpathstringYesContainer ID
groupNamepathstringYesGroup name to create or update
if-matchheaderstringNofile:v<N> ETag precondition
FieldTypeRequiredDescription
secretstringYesJWT secret key. For HS256, any string. For RS256/ES256, a PEM-encoded SPKI public key. Max length 8192.
algorithmstringYesOne of "HS256", "RS256", "ES256".
sourcesarray of stringYesToken lookup locations. Each item matches ^(header|cookie):[A-Za-z0-9._-]{1,64}$, e.g. "header:Authorization", "cookie:jwt_token".
claimsobjectNoClaim values that must be present and match exactly. Values must be string, number, or boolean.
{
"statusCode": 200,
"message": "JWT authentication group configured successfully",
"data": {
"project": "507f1f77bcf86cd799439011",
"container": "507f1f77bcf86cd799439012",
"groups": {},
"permissions": {},
"default": "deny"
}
}
import { HoodyClient } from 'hoody-sdk';
const client = new HoodyClient({ baseURL: 'https://api.hoody.com', token: process.env.HOODY_TOKEN });
await client.api.proxyPermissionsContainer.setJwtGroup(id, 'admin', {
secret: 'replace-with-strong-secret',
algorithm: 'HS256',
sources: ['header:Authorization'],
claims: { role: 'admin' },
}, { ifMatch: 'file:v3' });
Terminal window
curl -X PUT "https://api.hoody.com/api/v1/containers/{containerId}/proxy/permissions/groups/admin/jwt" \
-H "Authorization: Bearer $HOODY_TOKEN" \
-H "Content-Type: application/json" \
-H "If-Match: file:v3" \
-d '{
"secret": "replace-with-strong-secret",
"algorithm": "HS256",
"sources": ["header:Authorization"],
"claims": { "role": "admin" }
}'

PUT /api/v1/containers/{id}/proxy/permissions/groups/{groupName}/password

Section titled “PUT /api/v1/containers/{id}/proxy/permissions/groups/{groupName}/password”

Create or update a password authentication group on a container. The stored password is SHA256(salt + password) in lowercase hex; supply either plaintext (which the API hashes server-side) or the precomputed hex digest.

NameInTypeRequiredDescription
idpathstringYesContainer ID
groupNamepathstringYesGroup name to create or update
if-matchheaderstringNofile:v<N> ETag precondition
FieldTypeRequiredDescription
usernamestringYesUsername the client must present
passwordstringYesPlaintext password or pre-hashed SHA256(salt + password) hex digest
saltstringYesPer-group salt. Use a unique value per user/group.
algorithmstringNo"sha256" (only supported value)
{
"statusCode": 200,
"message": "Password authentication group configured successfully",
"data": {
"project": "507f1f77bcf86cd799439011",
"container": "507f1f77bcf86cd799439012",
"groups": {},
"permissions": {},
"default": "deny"
}
}
import { HoodyClient } from 'hoody-sdk';
const client = new HoodyClient({ baseURL: 'https://api.hoody.com', token: process.env.HOODY_TOKEN });
await client.api.proxyPermissionsContainer.setPasswordGroup(id, 'users', {
username: 'admin',
password: 's3cret',
salt: 'unique-salt-value',
algorithm: 'sha256',
}, { ifMatch: 'file:v3' });
Terminal window
curl -X PUT "https://api.hoody.com/api/v1/containers/{containerId}/proxy/permissions/groups/users/password" \
-H "Authorization: Bearer $HOODY_TOKEN" \
-H "Content-Type: application/json" \
-H "If-Match: file:v3" \
-d '{
"username": "admin",
"password": "s3cret",
"salt": "unique-salt-value",
"algorithm": "sha256"
}'

PUT /api/v1/containers/{id}/proxy/permissions/groups/{groupName}/ip

Section titled “PUT /api/v1/containers/{id}/proxy/permissions/groups/{groupName}/ip”

Create or update an IP-range authentication group on a container. The group matches when the request source IP falls inside the IPv4 CIDR range.

NameInTypeRequiredDescription
idpathstringYesContainer ID
groupNamepathstringYesGroup name to create or update
if-matchheaderstringNofile:v<N> ETag precondition
FieldTypeRequiredDescription
rangestringYesIPv4 CIDR range in IP/mask form where mask is 0-32, e.g. 192.168.1.0/24, 10.0.0.0/8, 203.0.113.5/32.
{
"statusCode": 200,
"message": "IP authentication group configured successfully",
"data": {
"project": "507f1f77bcf86cd799439011",
"container": "507f1f77bcf86cd799439012",
"groups": {},
"permissions": {},
"default": "deny"
}
}
import { HoodyClient } from 'hoody-sdk';
const client = new HoodyClient({ baseURL: 'https://api.hoody.com', token: process.env.HOODY_TOKEN });
await client.api.proxyPermissionsContainer.setIpGroup(id, 'office', {
range: '192.168.1.0/24',
}, { ifMatch: 'file:v3' });
Terminal window
curl -X PUT "https://api.hoody.com/api/v1/containers/{containerId}/proxy/permissions/groups/office/ip" \
-H "Authorization: Bearer $HOODY_TOKEN" \
-H "Content-Type: application/json" \
-H "If-Match: file:v3" \
-d '{ "range": "192.168.1.0/24" }'

PUT /api/v1/containers/{id}/proxy/permissions/groups/{groupName}/token

Section titled “PUT /api/v1/containers/{id}/proxy/permissions/groups/{groupName}/token”

Create or update a token authentication group on a container. The body must specify exactly one location — header, cookie, or query parameter — and the expected token value.

NameInTypeRequiredDescription
idpathstringYesContainer ID
groupNamepathstringYesGroup name to create or update
if-matchheaderstringNofile:v<N> ETag precondition

One of the following shapes (choose exactly one):

FieldTypeRequiredDescription
headerstringYes (in header variant)HTTP header name to inspect (case-insensitive)
valuestringYes (in header variant)Expected token value, matched exactly
cookiestringYes (in cookie variant)Cookie name to inspect (case-sensitive)
valuestringYes (in cookie variant)Expected token value, matched exactly
paramstringYes (in query variant)Query parameter name to inspect (case-sensitive)
valuestringYes (in query variant)Expected token value, matched exactly
{
"statusCode": 200,
"message": "Token authentication group configured successfully",
"data": {
"project": "507f1f77bcf86cd799439011",
"container": "507f1f77bcf86cd799439012",
"groups": {},
"permissions": {},
"default": "deny"
}
}
import { HoodyClient } from 'hoody-sdk';
const client = new HoodyClient({ baseURL: 'https://api.hoody.com', token: process.env.HOODY_TOKEN });
await client.api.proxyPermissionsContainer.setTokenGroup(id, 'external-api', {
header: 'X-API-Key',
value: 'replace-with-strong-key',
}, { ifMatch: 'file:v3' });
Terminal window
curl -X PUT "https://api.hoody.com/api/v1/containers/{containerId}/proxy/permissions/groups/external-api/token" \
-H "Authorization: Bearer $HOODY_TOKEN" \
-H "Content-Type: application/json" \
-H "If-Match: file:v3" \
-d '{ "header": "X-API-Key", "value": "replace-with-strong-key" }'

PUT /api/v1/containers/{id}/proxy/permissions/permissions/{groupName}

Section titled “PUT /api/v1/containers/{id}/proxy/permissions/permissions/{groupName}”

Set or update the access rule for a single program on a container group. The body selects the program and the rule that decides which instances or ports are ALLOWED for it.

NameInTypeRequiredDescription
idpathstringYesContainer ID
groupNamepathstringYesGroup name
if-matchheaderstringNofile:v<N> ETag precondition
FieldTypeRequiredDescription
programstringYesProgram name (e.g. http, terminal, ssh, files, exec, services, notifications)
accessboolean | number | number[] | stringYesAccess rule. See below.

The access value is an access CONTROL rule defining WHAT IS ALLOWED, not a list of what exists. It accepts any of:

  • true / false — allow/deny every instance or port.
  • A single number — allow only that specific port or index.
  • An array of numbers — allow only those specific ports or indices.
  • A range string "<start>-<end>" — allow only that port range.
  • The wildcard "*" — allow every instance (same as true).

For files, services, notifications, and exec, only the boolean form is allowed.

{
"statusCode": 200,
"message": "Group program permission set successfully",
"data": {
"project": "507f1f77bcf86cd799439011",
"container": "507f1f77bcf86cd799439012",
"groups": {},
"permissions": {},
"default": "deny"
}
}
import { HoodyClient } from 'hoody-sdk';
const client = new HoodyClient({ baseURL: 'https://api.hoody.com', token: process.env.HOODY_TOKEN });
await client.api.proxyPermissionsContainer.setGroup(id, 'admin', {
program: 'http',
access: [80, 443],
}, { ifMatch: 'file:v3' });
Terminal window
curl -X PUT "https://api.hoody.com/api/v1/containers/{containerId}/proxy/permissions/permissions/admin" \
-H "Authorization: Bearer $HOODY_TOKEN" \
-H "Content-Type: application/json" \
-H "If-Match: file:v3" \
-d '{ "program": "http", "access": [80, 443] }'

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

Section titled “PATCH /api/v1/containers/{id}/proxy/permissions/default”

Update only the fallback default policy for the container proxy permissions document.

NameInTypeRequiredDescription
idpathstringYesContainer ID
if-matchheaderstringNofile:v<N> ETag precondition
FieldTypeRequiredDescription
defaultstringYes"allow" or "deny"
{
"statusCode": 200,
"message": "Default policy updated successfully",
"data": {
"project": "507f1f77bcf86cd799439011",
"container": "507f1f77bcf86cd799439012",
"groups": {},
"permissions": {},
"default": "allow"
}
}
import { HoodyClient } from 'hoody-sdk';
const client = new HoodyClient({ baseURL: 'https://api.hoody.com', token: process.env.HOODY_TOKEN });
await client.api.proxyPermissionsContainer.updateDefault(id, { default: 'allow' }, { ifMatch: 'file:v3' });
Terminal window
curl -X PATCH "https://api.hoody.com/api/v1/containers/{containerId}/proxy/permissions/default" \
-H "Authorization: Bearer $HOODY_TOKEN" \
-H "Content-Type: application/json" \
-H "If-Match: file:v3" \
-d '{ "default": "allow" }'

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

Section titled “PATCH /api/v1/containers/{id}/proxy/permissions/state”

Update only the enable_proxy kill-switch for the container proxy permissions document. Setting false denies every new request that reaches the proxy permission layer with 403, evaluated before authentication groups, permission rules, and the default policy. Containers keep running; only proxy reachability is cut.

NameInTypeRequiredDescription
idpathstringYesContainer ID
if-matchheaderstringNofile:v<N> ETag precondition
FieldTypeRequiredDescription
enable_proxybooleanYestrue to enable, false to disable
{
"statusCode": 200,
"message": "Proxy state updated successfully",
"data": {
"project": "507f1f77bcf86cd799439011",
"container": "507f1f77bcf86cd799439012",
"groups": {},
"permissions": {},
"default": "deny",
"enable_proxy": true
}
}
import { HoodyClient } from 'hoody-sdk';
const client = new HoodyClient({ baseURL: 'https://api.hoody.com', token: process.env.HOODY_TOKEN });
await client.api.proxyPermissionsContainer.updateState(id, { enable_proxy: true }, { ifMatch: 'file:v3' });
Terminal window
curl -X PATCH "https://api.hoody.com/api/v1/containers/{containerId}/proxy/permissions/state" \
-H "Authorization: Bearer $HOODY_TOKEN" \
-H "Content-Type: application/json" \
-H "If-Match: file:v3" \
-d '{ "enable_proxy": true }'

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

Section titled “DELETE /api/v1/containers/{id}/proxy/permissions/groups/{groupName}”

Remove a single authentication group from the container proxy permissions document. The group’s entry under permissions is also removed.

NameInTypeRequiredDescription
idpathstringYesContainer ID
groupNamepathstringYesGroup name to remove
if-matchheaderstringNofile:v<N> ETag precondition
{
"statusCode": 200,
"message": "Authentication group removed successfully",
"data": {
"project": "507f1f77bcf86cd799439011",
"container": "507f1f77bcf86cd799439012",
"groups": {},
"permissions": {},
"default": "deny"
}
}
import { HoodyClient } from 'hoody-sdk';
const client = new HoodyClient({ baseURL: 'https://api.hoody.com', token: process.env.HOODY_TOKEN });
await client.api.proxyPermissionsContainer.removeAuthGroup(id, 'admin', { ifMatch: 'file:v3' });
Terminal window
curl -X DELETE "https://api.hoody.com/api/v1/containers/{containerId}/proxy/permissions/groups/admin" \
-H "Authorization: Bearer $HOODY_TOKEN" \
-H "If-Match: file:v3"

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

Section titled “DELETE /api/v1/containers/{id}/proxy/permissions/permissions/{groupName}”

Remove every program permission for a container group in one call. The authentication group entry under groups is left untouched.

NameInTypeRequiredDescription
idpathstringYesContainer ID
groupNamepathstringYesGroup name
if-matchheaderstringNofile:v<N> ETag precondition
{
"statusCode": 200,
"message": "All group permissions removed successfully",
"data": {
"project": "507f1f77bcf86cd799439011",
"container": "507f1f77bcf86cd799439012",
"groups": {},
"permissions": {},
"default": "deny"
}
}
import { HoodyClient } from 'hoody-sdk';
const client = new HoodyClient({ baseURL: 'https://api.hoody.com', token: process.env.HOODY_TOKEN });
await client.api.proxyPermissionsContainer.removeGroup(id, 'admin', { ifMatch: 'file:v3' });
Terminal window
curl -X DELETE "https://api.hoody.com/api/v1/containers/{containerId}/proxy/permissions/permissions/admin" \
-H "Authorization: Bearer $HOODY_TOKEN" \
-H "If-Match: file:v3"

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

Section titled “DELETE /api/v1/containers/{id}/proxy/permissions/permissions/{groupName}/{program}”

Remove the access rule for a single program on a container group. Other program rules for the same group remain.

NameInTypeRequiredDescription
idpathstringYesContainer ID
groupNamepathstringYesGroup name
programpathstringYesProgram name (e.g. http, ssh, files)
if-matchheaderstringNofile:v<N> ETag precondition
{
"statusCode": 200,
"message": "Program permission removed successfully",
"data": {
"project": "507f1f77bcf86cd799439011",
"container": "507f1f77bcf86cd799439012",
"groups": {},
"permissions": {},
"default": "deny"
}
}
import { HoodyClient } from 'hoody-sdk';
const client = new HoodyClient({ baseURL: 'https://api.hoody.com', token: process.env.HOODY_TOKEN });
await client.api.proxyPermissionsContainer.removeProgram(id, 'admin', 'http', { ifMatch: 'file:v3' });
Terminal window
curl -X DELETE "https://api.hoody.com/api/v1/containers/{containerId}/proxy/permissions/permissions/admin/http" \
-H "Authorization: Bearer $HOODY_TOKEN" \
-H "If-Match: file:v3"

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

Section titled “DELETE /api/v1/containers/{id}/proxy/permissions”

Delete the entire container proxy permissions document.

NameInTypeRequiredDescription
idpathstringYesContainer ID
if-matchheaderstringNofile:v<N> ETag precondition
{
"statusCode": 200,
"message": "Container proxy permissions deleted successfully",
"data": {
"project": "507f1f77bcf86cd799439011",
"container": "507f1f77bcf86cd799439012",
"groups": {},
"permissions": {},
"default": "allow"
}
}
import { HoodyClient } from 'hoody-sdk';
const client = new HoodyClient({ baseURL: 'https://api.hoody.com', token: process.env.HOODY_TOKEN });
await client.api.proxyPermissionsContainer.delete(id, { ifMatch: 'file:v3' });
Terminal window
curl -X DELETE "https://api.hoody.com/api/v1/containers/{containerId}/proxy/permissions" \
-H "Authorization: Bearer $HOODY_TOKEN" \
-H "If-Match: file:v3"

These endpoints read and mutate the proxy permissions document scoped to an entire project. A project’s document applies to every container in the project that does not set its own container-level override.

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

Section titled “GET /api/v1/projects/{id}/proxy/permissions”

Retrieve the full project proxy permissions document, including authentication groups, program permissions, default policy, and the proxy enable state.

NameInTypeRequiredDescription
idpathstringYesProject ID
{
"statusCode": 200,
"message": "Project proxy permissions retrieved successfully",
"data": {
"project": "507f1f77bcf86cd799439011",
"groups": {},
"permissions": {},
"default": "deny",
"enable_proxy": true,
"file_version": 3,
"etag": "file:v3"
}
}
import { HoodyClient } from 'hoody-sdk';
const client = new HoodyClient({ baseURL: 'https://api.hoody.com', token: process.env.HOODY_TOKEN });
await client.api.proxyPermissionsProject.get(id);
Terminal window
curl -X GET "https://api.hoody.com/api/v1/projects/{projectId}/proxy/permissions" \
-H "Authorization: Bearer $HOODY_TOKEN"

PUT /api/v1/projects/{id}/proxy/permissions

Section titled “PUT /api/v1/projects/{id}/proxy/permissions”

Replace the project proxy permissions document. Pass the document body in the request and If-Match: file:v<N> to prevent lost updates. When the header is missing the API returns 428; when stale it returns 412.

NameInTypeRequiredDescription
idpathstringYesProject ID
if-matchheaderstringNofile:v<N> ETag precondition; read current file_version from GET first
FieldTypeRequiredDescription
projectstringYesProject ID, must match the path :id (24-hex)
groupsobjectYesAuthentication groups keyed by group name
permissionsobjectYesPer-group program access rules
defaultstringNo"allow" or "deny". Defaults to "deny".
enable_proxybooleanNoEnable or disable the proxy. Defaults to true.

Each entry in groups uses one of the five type values: jwt, password, ip, token, or hoody-identity. The hoody-identity config is { audience (REQUIRED), sources?, allow_types?, users?, max_age_seconds? (>=300), expose_type? } and never carries key material — the trust keyring is operator-owned.

{
"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
}
}
import { HoodyClient } from 'hoody-sdk';
const client = new HoodyClient({ baseURL: 'https://api.hoody.com', token: process.env.HOODY_TOKEN });
await client.api.proxyPermissionsProject.replace(id, {
project: '507f1f77bcf86cd799439011',
groups: {
admin: {
type: 'jwt',
algorithm: 'HS256',
secret: 'replace-with-strong-secret',
sources: ['header:Authorization'],
},
},
permissions: {
admin: { terminal: true, files: true },
},
default: 'deny',
enable_proxy: true,
}, { ifMatch: 'file:v3' });
Terminal window
curl -X PUT "https://api.hoody.com/api/v1/projects/{projectId}/proxy/permissions" \
-H "Authorization: Bearer $HOODY_TOKEN" \
-H "Content-Type: application/json" \
-H "If-Match: file:v3" \
-d '{
"project": "507f1f77bcf86cd799439011",
"groups": {
"admin": {
"type": "jwt",
"algorithm": "HS256",
"secret": "replace-with-strong-secret",
"sources": ["header:Authorization"]
}
},
"permissions": {
"admin": { "terminal": true, "files": true }
},
"default": "deny",
"enable_proxy": true
}'

PUT /api/v1/projects/{id}/proxy/permissions/groups/{groupName}/jwt

Section titled “PUT /api/v1/projects/{id}/proxy/permissions/groups/{groupName}/jwt”

Create or update a single JWT authentication group on a project.

NameInTypeRequiredDescription
idpathstringYesProject ID
groupNamepathstringYesGroup name to create or update
if-matchheaderstringNofile:v<N> ETag precondition
FieldTypeRequiredDescription
secretstringYesJWT secret key. For HS256, any string. For RS256/ES256, a PEM-encoded SPKI public key. Max length 8192.
algorithmstringYesOne of "HS256", "RS256", "ES256".
sourcesarray of stringYesToken lookup locations. Each item matches ^(header|cookie):[A-Za-z0-9._-]{1,64}$, e.g. "header:Authorization", "cookie:jwt_token".
claimsobjectNoClaim values that must be present and match exactly. Values must be string, number, or boolean.
{
"statusCode": 200,
"message": "JWT authentication group configured successfully",
"data": {
"project": "507f1f77bcf86cd799439011",
"groups": {},
"permissions": {},
"default": "deny"
}
}
import { HoodyClient } from 'hoody-sdk';
const client = new HoodyClient({ baseURL: 'https://api.hoody.com', token: process.env.HOODY_TOKEN });
await client.api.proxyPermissionsProject.setJwtGroup(id, 'admin', {
secret: 'replace-with-strong-secret',
algorithm: 'HS256',
sources: ['header:Authorization'],
claims: { role: 'admin' },
}, { ifMatch: 'file:v3' });
Terminal window
curl -X PUT "https://api.hoody.com/api/v1/projects/{projectId}/proxy/permissions/groups/admin/jwt" \
-H "Authorization: Bearer $HOODY_TOKEN" \
-H "Content-Type: application/json" \
-H "If-Match: file:v3" \
-d '{
"secret": "replace-with-strong-secret",
"algorithm": "HS256",
"sources": ["header:Authorization"],
"claims": { "role": "admin" }
}'

PUT /api/v1/projects/{id}/proxy/permissions/groups/{groupName}/password

Section titled “PUT /api/v1/projects/{id}/proxy/permissions/groups/{groupName}/password”

Create or update a password authentication group on a project.

NameInTypeRequiredDescription
idpathstringYesProject ID
groupNamepathstringYesGroup name to create or update
if-matchheaderstringNofile:v<N> ETag precondition
FieldTypeRequiredDescription
usernamestringYesUsername the client must present
passwordstringYesPlaintext password or pre-hashed SHA256(salt + password) hex digest
saltstringYesPer-group salt. Use a unique value per user/group.
algorithmstringNo"sha256" (only supported value)
{
"statusCode": 200,
"message": "Password authentication group configured successfully",
"data": {
"project": "507f1f77bcf86cd799439011",
"groups": {},
"permissions": {},
"default": "deny"
}
}
import { HoodyClient } from 'hoody-sdk';
const client = new HoodyClient({ baseURL: 'https://api.hoody.com', token: process.env.HOODY_TOKEN });
await client.api.proxyPermissionsProject.setPasswordGroup(id, 'users', {
username: 'admin',
password: 's3cret',
salt: 'unique-salt-value',
algorithm: 'sha256',
}, { ifMatch: 'file:v3' });
Terminal window
curl -X PUT "https://api.hoody.com/api/v1/projects/{projectId}/proxy/permissions/groups/users/password" \
-H "Authorization: Bearer $HOODY_TOKEN" \
-H "Content-Type: application/json" \
-H "If-Match: file:v3" \
-d '{
"username": "admin",
"password": "s3cret",
"salt": "unique-salt-value",
"algorithm": "sha256"
}'

PUT /api/v1/projects/{id}/proxy/permissions/groups/{groupName}/ip

Section titled “PUT /api/v1/projects/{id}/proxy/permissions/groups/{groupName}/ip”

Create or update an IP-range authentication group on a project. The group matches when the request source IP falls inside the IPv4 CIDR range.

NameInTypeRequiredDescription
idpathstringYesProject ID
groupNamepathstringYesGroup name to create or update
if-matchheaderstringNofile:v<N> ETag precondition
FieldTypeRequiredDescription
rangestringYesIPv4 CIDR range in IP/mask form where mask is 0-32, e.g. 192.168.1.0/24, 10.0.0.0/8, 203.0.113.5/32.
{
"statusCode": 200,
"message": "IP authentication group configured successfully",
"data": {
"project": "507f1f77bcf86cd799439011",
"groups": {},
"permissions": {},
"default": "deny"
}
}
import { HoodyClient } from 'hoody-sdk';
const client = new HoodyClient({ baseURL: 'https://api.hoody.com', token: process.env.HOODY_TOKEN });
await client.api.proxyPermissionsProject.setIpGroup(id, 'office', {
range: '192.168.1.0/24',
}, { ifMatch: 'file:v3' });
Terminal window
curl -X PUT "https://api.hoody.com/api/v1/projects/{projectId}/proxy/permissions/groups/office/ip" \
-H "Authorization: Bearer $HOODY_TOKEN" \
-H "Content-Type: application/json" \
-H "If-Match: file:v3" \
-d '{ "range": "192.168.1.0/24" }'

PUT /api/v1/projects/{id}/proxy/permissions/groups/{groupName}/token

Section titled “PUT /api/v1/projects/{id}/proxy/permissions/groups/{groupName}/token”

Create or update a token authentication group on a project. The body must specify exactly one location — header, cookie, or query parameter — and the expected token value.

NameInTypeRequiredDescription
idpathstringYesProject ID
groupNamepathstringYesGroup name to create or update
if-matchheaderstringNofile:v<N> ETag precondition

One of the following shapes (choose exactly one):

FieldTypeRequiredDescription
headerstringYes (in header variant)HTTP header name to inspect (case-insensitive)
valuestringYes (in header variant)Expected token value, matched exactly
cookiestringYes (in cookie variant)Cookie name to inspect (case-sensitive)
valuestringYes (in cookie variant)Expected token value, matched exactly
paramstringYes (in query variant)Query parameter name to inspect (case-sensitive)
valuestringYes (in query variant)Expected token value, matched exactly
{
"statusCode": 200,
"message": "Token authentication group configured successfully",
"data": {
"project": "507f1f77bcf86cd799439011",
"groups": {},
"permissions": {},
"default": "deny"
}
}
import { HoodyClient } from 'hoody-sdk';
const client = new HoodyClient({ baseURL: 'https://api.hoody.com', token: process.env.HOODY_TOKEN });
await client.api.proxyPermissionsProject.setTokenGroup(id, 'api-clients', {
header: 'X-API-Key',
value: 'replace-with-strong-key',
}, { ifMatch: 'file:v3' });
Terminal window
curl -X PUT "https://api.hoody.com/api/v1/projects/{projectId}/proxy/permissions/groups/api-clients/token" \
-H "Authorization: Bearer $HOODY_TOKEN" \
-H "Content-Type: application/json" \
-H "If-Match: file:v3" \
-d '{ "header": "X-API-Key", "value": "replace-with-strong-key" }'

PUT /api/v1/projects/{id}/proxy/permissions/permissions/{groupName}

Section titled “PUT /api/v1/projects/{id}/proxy/permissions/permissions/{groupName}”

Set or update the access rule for a single program on a project group.

NameInTypeRequiredDescription
idpathstringYesProject ID
groupNamepathstringYesGroup name
if-matchheaderstringNofile:v<N> ETag precondition
FieldTypeRequiredDescription
programstringYesProgram name (e.g. http, terminal, ssh, files, exec, services, notifications)
accessboolean | number | number[] | stringYesAccess rule. See below.

The access value is an access CONTROL rule defining WHAT IS ALLOWED, not a list of what exists. It accepts any of:

  • true / false — allow/deny every instance or port.
  • A single number — allow only that specific port or index.
  • An array of numbers — allow only those specific ports or indices.
  • A range string "<start>-<end>" — allow only that port range.
  • The wildcard "*" — allow every instance (same as true).

For files, services, notifications, and exec, only the boolean form is allowed.

{
"statusCode": 200,
"message": "Group program permission set successfully",
"data": {
"project": "507f1f77bcf86cd799439011",
"groups": {},
"permissions": {},
"default": "deny"
}
}
import { HoodyClient } from 'hoody-sdk';
const client = new HoodyClient({ baseURL: 'https://api.hoody.com', token: process.env.HOODY_TOKEN });
await client.api.proxyPermissionsProject.setGroup(id, 'admin', {
program: 'http',
access: [8080],
}, { ifMatch: 'file:v3' });
Terminal window
curl -X PUT "https://api.hoody.com/api/v1/projects/{projectId}/proxy/permissions/permissions/admin" \
-H "Authorization: Bearer $HOODY_TOKEN" \
-H "Content-Type: application/json" \
-H "If-Match: file:v3" \
-d '{ "program": "http", "access": [8080] }'

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

Section titled “PATCH /api/v1/projects/{id}/proxy/permissions/default”

Update the fallback default policy for the project proxy permissions document. This is the policy evaluated for requests that match no authentication group rules.

NameInTypeRequiredDescription
idpathstringYesProject ID
if-matchheaderstringNofile:v<N> ETag precondition
FieldTypeRequiredDescription
defaultstringYes"allow" or "deny"
{
"statusCode": 200,
"message": "Default policy updated successfully",
"data": {
"project": "507f1f77bcf86cd799439011",
"groups": {},
"permissions": {},
"default": "deny"
}
}
import { HoodyClient } from 'hoody-sdk';
const client = new HoodyClient({ baseURL: 'https://api.hoody.com', token: process.env.HOODY_TOKEN });
await client.api.proxyPermissionsProject.updateDefault(id, { default: 'deny' }, { ifMatch: 'file:v3' });
Terminal window
curl -X PATCH "https://api.hoody.com/api/v1/projects/{projectId}/proxy/permissions/default" \
-H "Authorization: Bearer $HOODY_TOKEN" \
-H "Content-Type: application/json" \
-H "If-Match: file:v3" \
-d '{ "default": "deny" }'

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

Section titled “PATCH /api/v1/projects/{id}/proxy/permissions/state”

Update the enable_proxy kill-switch for the project proxy permissions document. Disabling the project kill-switch denies every new request that reaches the proxy permission layer with 403, evaluated before authentication groups, permission rules, and the default policy, so no configured rule can re-open access while the switch is off. Containers keep running; only proxy reachability is cut.

The project value applies only to containers that do not set their own enable_proxy. To reliably disable a single container, use the container-level state endpoint.

NameInTypeRequiredDescription
idpathstringYesProject ID
if-matchheaderstringNofile:v<N> ETag precondition
FieldTypeRequiredDescription
enable_proxybooleanYestrue to enable, false to disable
{
"statusCode": 200,
"message": "Proxy state updated successfully",
"data": {
"project": "507f1f77bcf86cd799439011",
"groups": {},
"permissions": {},
"default": "deny",
"enable_proxy": false
}
}
import { HoodyClient } from 'hoody-sdk';
const client = new HoodyClient({ baseURL: 'https://api.hoody.com', token: process.env.HOODY_TOKEN });
await client.api.proxyPermissionsProject.updateState(id, { enable_proxy: false }, { ifMatch: 'file:v3' });
Terminal window
curl -X PATCH "https://api.hoody.com/api/v1/projects/{projectId}/proxy/permissions/state" \
-H "Authorization: Bearer $HOODY_TOKEN" \
-H "Content-Type: application/json" \
-H "If-Match: file:v3" \
-d '{ "enable_proxy": false }'

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

Section titled “DELETE /api/v1/projects/{id}/proxy/permissions/groups/{groupName}”

Remove a single authentication group from the project proxy permissions document. The group’s entry under permissions is also removed.

NameInTypeRequiredDescription
idpathstringYesProject ID
groupNamepathstringYesGroup name to remove
if-matchheaderstringNofile:v<N> ETag precondition
{
"statusCode": 200,
"message": "Authentication group removed successfully",
"data": {
"project": "507f1f77bcf86cd799439011",
"groups": {},
"permissions": {},
"default": "deny"
}
}
import { HoodyClient } from 'hoody-sdk';
const client = new HoodyClient({ baseURL: 'https://api.hoody.com', token: process.env.HOODY_TOKEN });
await client.api.proxyPermissionsProject.removeAuthGroup(id, 'admin', { ifMatch: 'file:v3' });
Terminal window
curl -X DELETE "https://api.hoody.com/api/v1/projects/{projectId}/proxy/permissions/groups/admin" \
-H "Authorization: Bearer $HOODY_TOKEN" \
-H "If-Match: file:v3"

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

Section titled “DELETE /api/v1/projects/{id}/proxy/permissions/permissions/{groupName}”

Remove every program permission for a project group in one call. The authentication group entry under groups is left untouched.

NameInTypeRequiredDescription
idpathstringYesProject ID
groupNamepathstringYesGroup name
if-matchheaderstringNofile:v<N> ETag precondition
{
"statusCode": 200,
"message": "All group permissions removed successfully",
"data": {
"project": "507f1f77bcf86cd799439011",
"groups": {},
"permissions": {},
"default": "deny"
}
}
import { HoodyClient } from 'hoody-sdk';
const client = new HoodyClient({ baseURL: 'https://api.hoody.com', token: process.env.HOODY_TOKEN });
await client.api.proxyPermissionsProject.removeGroup(id, 'admin', { ifMatch: 'file:v3' });
Terminal window
curl -X DELETE "https://api.hoody.com/api/v1/projects/{projectId}/proxy/permissions/permissions/admin" \
-H "Authorization: Bearer $HOODY_TOKEN" \
-H "If-Match: file:v3"

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

Section titled “DELETE /api/v1/projects/{id}/proxy/permissions/permissions/{groupName}/{program}”

Remove the access rule for a single program on a project group. Other program rules for the same group remain.

NameInTypeRequiredDescription
idpathstringYesProject ID
groupNamepathstringYesGroup name
programpathstringYesProgram name (e.g. http, ssh, files)
if-matchheaderstringNofile:v<N> ETag precondition
{
"statusCode": 200,
"message": "Program permission removed successfully",
"data": {
"project": "507f1f77bcf86cd799439011",
"groups": {},
"permissions": {},
"default": "deny"
}
}
import { HoodyClient } from 'hoody-sdk';
const client = new HoodyClient({ baseURL: 'https://api.hoody.com', token: process.env.HOODY_TOKEN });
await client.api.proxyPermissionsProject.removeProgram(id, 'admin', 'http', { ifMatch: 'file:v3' });
Terminal window
curl -X DELETE "https://api.hoody.com/api/v1/projects/{projectId}/proxy/permissions/permissions/admin/http" \
-H "Authorization: Bearer $HOODY_TOKEN" \
-H "If-Match: file:v3"

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

Section titled “DELETE /api/v1/projects/{id}/proxy/permissions”

Remove all proxy access control configuration from the project. The project reverts to the default open-access posture with the default policy set to "allow".

NameInTypeRequiredDescription
idpathstringYesProject ID
if-matchheaderstringNofile:v<N> ETag precondition
{
"statusCode": 200,
"message": "Project proxy permissions deleted successfully",
"data": {
"project": "507f1f77bcf86cd799439011",
"groups": {},
"permissions": {},
"default": "allow",
"enable_proxy": true
}
}
import { HoodyClient } from 'hoody-sdk';
const client = new HoodyClient({ baseURL: 'https://api.hoody.com', token: process.env.HOODY_TOKEN });
await client.api.proxyPermissionsProject.delete(id, { ifMatch: 'file:v3' });
Terminal window
curl -X DELETE "https://api.hoody.com/api/v1/projects/{projectId}/proxy/permissions" \
-H "Authorization: Bearer $HOODY_TOKEN" \
-H "If-Match: file:v3"