Skip to content
Hoody.com

Create, manage, and configure projects, including their permissions, statistics, and proxied-usage analytics. Projects are the top-level organizational unit in Hoody: they own containers, networks, and quotas, and they enforce per-user access through shared permissions. Every endpoint on this page operates against the control-plane API at https://api.hoody.com and requires a JWT in the Authorization header as Bearer <token>.

List every project you own or have been granted access to. Results are paginated and sortable. Each user has exactly one auto-provisioned project flagged is_default: true; the remainder are user-defined.

NameInTypeRequiredDescription
pagequerynumberNoPage number (1-based). Default: 1.
limitquerynumberNoItems per page (max 100). Default: 10.
sort_byquerystringNoField to sort by. One of id, alias, created_at, updated_at. Default: "created_at".
sort_orderquerystringNoSort direction. One of asc, desc. Default: "desc".
realm_idquerystringNoFilter by realm ID. Only returns projects that belong to this realm. Alternative to using realm subdomain in URL.
{
"statusCode": 200,
"message": "Projects retrieved successfully",
"data": {
"projects": [
{
"id": "507f1f77bcf86cd799439011",
"user_id": "507f1f77bcf86cd799439022",
"alias": "Production Environment",
"color": "#3B82F6",
"created_at": "2025-01-10T08:00:00.000Z",
"updated_at": "2025-01-15T10:30:00.000Z",
"max_containers": 50,
"is_default": false,
"realm_ids": []
},
{
"id": "507f1f77bcf86cd799439033",
"user_id": "507f1f77bcf86cd799439022",
"alias": "Development",
"color": "#10B981",
"created_at": "2025-01-05T12:00:00.000Z",
"updated_at": "2025-01-05T12:00:00.000Z",
"max_containers": null,
"is_default": true,
"realm_ids": []
}
],
"pagination": {
"total": 2,
"page": 1,
"limit": 10,
"totalPages": 1
}
}
}
import { HoodyClient } from 'hoody-sdk';
const client = new HoodyClient({ baseURL: 'https://api.hoody.com', token: process.env.HOODY_TOKEN });
for await (const item of client.api.projects.listIterator({ page: 1, limit: 10 })) {
console.log(item);
}

Create a new project to organize and manage containers and resources. Projects act as logical groupings with optional quotas, HEX color coding for dashboards, and multi-realm tenancy.

NameTypeRequiredDescription
aliasstringYesHuman-readable project name (1-100 characters). Must be unique across your projects.
colorstringNoHEX color code for visual organization (3 or 6 digits). The # prefix is auto-added if missing, and the value is auto-normalized to uppercase. If omitted, a random color is generated.
max_containersnumber | nullNoMaximum number of containers allowed in this project. null means unlimited. The quota is enforced during container creation. Minimum: 0.
realm_idsarrayNoRealm IDs to assign this project to. Each entry must be a 24-character hex string. If creating from a realm subdomain, the subdomain realm is automatically included.
{
"alias": "Production Environment",
"color": "#EF4444",
"max_containers": 100,
"realm_ids": [
"507f1f77bcf86cd799439011"
]
}
{
"statusCode": 201,
"message": "Project created successfully",
"data": {
"id": "507f1f77bcf86cd799439011",
"user_id": "507f1f77bcf86cd799439022",
"alias": "Production Environment",
"color": "#EF4444",
"created_at": "2025-01-10T08:00:00.000Z",
"updated_at": "2025-01-10T08:00:00.000Z",
"max_containers": 100,
"is_default": false,
"realm_ids": [
"507f1f77bcf86cd799439011"
]
}
}
import { HoodyClient } from 'hoody-sdk';
const client = new HoodyClient({ baseURL: 'https://api.hoody.com', token: process.env.HOODY_TOKEN });
await client.api.projects.create({
alias: 'Production Environment',
color: '#EF4444',
max_containers: 100,
realm_ids: ['507f1f77bcf86cd799439011'],
});

Retrieve detailed information about a single project. Set include_permissions=true to also return the access-control list and user details for every user granted a permission on the project.

NameInTypeRequiredDescription
idpathstringYesProject ID.
include_permissionsquerybooleanNoInclude project permissions with user details in response. Default: false.
{
"statusCode": 200,
"message": "Project retrieved successfully",
"data": {
"id": "507f1f77bcf86cd799439011",
"user_id": "507f1f77bcf86cd799439022",
"alias": "Production Environment",
"color": "#3B82F6",
"created_at": "2025-01-10T08:00:00.000Z",
"updated_at": "2025-01-15T10:30:00.000Z",
"max_containers": 50,
"is_default": false,
"realm_ids": [],
"permissions": [
{
"id": "507f1f77bcf86cd799439033",
"project_id": "507f1f77bcf86cd799439011",
"user_id": "507f1f77bcf86cd799439044",
"permission_level": "read",
"created_at": "2025-01-12T14:00:00.000Z",
"updated_at": "2025-01-12T14:00:00.000Z",
"user": {
"id": "507f1f77bcf86cd799439044",
"username": "jane_smith",
"alias": "Jane Smith"
}
}
]
}
}
import { HoodyClient } from 'hoody-sdk';
const client = new HoodyClient({ baseURL: 'https://api.hoody.com', token: process.env.HOODY_TOKEN });
await client.api.projects.get('507f1f77bcf86cd799439011', { include_permissions: true });

Update a project’s alias, color, quotas, or realm membership. You must be the owner or have edit permission.

NameInTypeRequiredDescription
idpathstringYesProject ID to update.
NameTypeRequiredDescription
aliasstringYesNew project name (1-100 characters). Must be unique across your projects.
colorstringNoNew HEX color code (3 or 6 digits). Auto-normalized to uppercase with # prefix.
max_containersnumber | nullNoMaximum number of containers allowed in this project. null means unlimited. The quota is enforced during container creation. Minimum: 0.
realm_idsarrayNoUpdate realm membership. Each entry must be a 24-character hex string. Only unrestricted tokens and admin users can modify realm_ids; realm-restricted tokens cannot change realm membership.
{
"alias": "Production Environment Updated",
"color": "#EF4444",
"max_containers": 75,
"realm_ids": [
"507f1f77bcf86cd799439011"
]
}
{
"statusCode": 200,
"message": "Project updated successfully",
"data": {
"id": "507f1f77bcf86cd799439011",
"user_id": "507f1f77bcf86cd799439022",
"alias": "Production Environment Updated",
"color": "#EF4444",
"created_at": "2025-01-10T08:00:00.000Z",
"updated_at": "2025-01-15T14:45:00.000Z",
"max_containers": 75,
"is_default": false,
"realm_ids": [
"507f1f77bcf86cd799439011"
]
}
}
import { HoodyClient } from 'hoody-sdk';
const client = new HoodyClient({ baseURL: 'https://api.hoody.com', token: process.env.HOODY_TOKEN });
await client.api.projects.update('507f1f77bcf86cd799439011', {
alias: 'Production Environment Updated',
color: '#EF4444',
max_containers: 75,
realm_ids: ['507f1f77bcf86cd799439011'],
});

Update a project’s alias, color, quotas, or realm membership. Accepts the same UpdateProjectRequest body as the PUT version. You must be the owner or have edit permission.

NameInTypeRequiredDescription
idpathstringYesProject ID to update.
NameTypeRequiredDescription
aliasstringYesNew project name (1-100 characters). Must be unique across your projects.
colorstringNoNew HEX color code (3 or 6 digits). Auto-normalized to uppercase with # prefix.
max_containersnumber | nullNoMaximum number of containers allowed in this project. null means unlimited. The quota is enforced during container creation. Minimum: 0.
realm_idsarrayNoUpdate realm membership. Each entry must be a 24-character hex string. Only unrestricted tokens and admin users can modify realm_ids; realm-restricted tokens cannot change realm membership.
{
"alias": "Production v2",
"color": "#10B981",
"max_containers": null
}
{
"statusCode": 200,
"message": "Project updated successfully",
"data": {
"id": "507f1f77bcf86cd799439011",
"user_id": "507f1f77bcf86cd799439022",
"alias": "Production v2",
"color": "#10B981",
"created_at": "2025-01-10T08:00:00.000Z",
"updated_at": "2025-01-15T14:45:00.000Z",
"max_containers": null,
"is_default": false,
"realm_ids": []
}
}
import { HoodyClient } from 'hoody-sdk';
const client = new HoodyClient({ baseURL: 'https://api.hoody.com', token: process.env.HOODY_TOKEN });
await client.api.projects.update('507f1f77bcf86cd799439011', {
alias: 'Production v2',
color: '#10B981',
max_containers: null,
});

Permanently delete a project and all associated resources. If deletion cannot be fully completed, the project remains available so you can retry safely. You must be the owner or have delete permission.

NameInTypeRequiredDescription
idpathstringYesProject ID to delete.
include_deleted_itemsquerybooleanNoInclude a lightweight list of deleted container IDs/names in the response for confirmation UX. Default: false.
{
"statusCode": 200,
"message": "Project deleted successfully",
"data": {
"deleted": {
"containers": 2,
"permissions": 1,
"aliases": 3
},
"deleted_items": {
"containers": [
{
"id": "507f1f77bcf86cd799439011",
"name": "web-app"
},
{
"id": "507f1f77bcf86cd799439012",
"name": "worker"
}
]
}
}
}
import { HoodyClient } from 'hoody-sdk';
const client = new HoodyClient({ baseURL: 'https://api.hoody.com', token: process.env.HOODY_TOKEN });
await client.api.projects.delete('507f1f77bcf86cd799439011', { include_deleted_items: true });

List all users who have been granted access to this project, along with their permission levels. Supports pagination and sorting.

NameInTypeRequiredDescription
idpathstringYesProject ID.
pagequerynumberNoPage number (1-based).
limitquerynumberNoItems per page.
sort_byquerystringNoField to sort by. One of id, user_id, permission_level, created_at, updated_at.
sort_orderquerystringNoSort direction. One of asc, desc.
{
"statusCode": 200,
"message": "Project permissions retrieved successfully",
"data": {
"permissions": [
{
"id": "507f1f77bcf86cd799439033",
"project_id": "507f1f77bcf86cd799439011",
"user_id": "507f1f77bcf86cd799439044",
"permission_level": "read",
"created_at": "2025-01-12T14:00:00.000Z",
"updated_at": "2025-01-12T14:00:00.000Z",
"user": {
"id": "507f1f77bcf86cd799439044",
"username": "jane_smith",
"alias": "Jane Smith"
}
},
{
"id": "507f1f77bcf86cd799439055",
"project_id": "507f1f77bcf86cd799439011",
"user_id": "507f1f77bcf86cd799439066",
"permission_level": "edit",
"created_at": "2025-01-13T09:30:00.000Z",
"updated_at": "2025-01-14T16:20:00.000Z",
"user": {
"id": "507f1f77bcf86cd799439066",
"username": "bob_jones",
"alias": "Bob Jones"
}
}
],
"pagination": {
"total": 2,
"page": 1,
"limit": 10,
"totalPages": 1
}
}
}
import { HoodyClient } from 'hoody-sdk';
const client = new HoodyClient({ baseURL: 'https://api.hoody.com', token: process.env.HOODY_TOKEN });
for await (const item of client.api.projects.listPermissionsIterator('507f1f77bcf86cd799439011', { page: 1, limit: 10 })) {
console.log(item);
}

Grant another user access to your project with a specific permission level. You must be the owner or have edit permission.

NameInTypeRequiredDescription
idpathstringYesProject ID.
NameTypeRequiredDescription
user_idstringYesUser ID to grant access to. Must be a 24-character hexadecimal string.
permission_levelstringYesAccess level. One of read (view only), edit (modify), delete (destroy).
{
"user_id": "507f1f77bcf86cd799439044",
"permission_level": "edit"
}
{
"statusCode": 201,
"message": "Project permission added successfully",
"data": {
"id": "507f1f77bcf86cd799439033",
"project_id": "507f1f77bcf86cd799439011",
"user_id": "507f1f77bcf86cd799439044",
"permission_level": "edit",
"created_at": "2025-01-12T14:00:00.000Z",
"updated_at": "2025-01-12T14:00:00.000Z",
"user": {
"id": "507f1f77bcf86cd799439044",
"username": "jane_smith",
"alias": "Jane Smith"
}
}
}
import { HoodyClient } from 'hoody-sdk';
const client = new HoodyClient({ baseURL: 'https://api.hoody.com', token: process.env.HOODY_TOKEN });
await client.api.projects.createPermission('507f1f77bcf86cd799439011', {
user_id: '507f1f77bcf86cd799439044',
permission_level: 'edit',
});

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

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

Change a user’s permission level for a project. You must be the owner or have edit permission.

NameInTypeRequiredDescription
idpathstringYesProject ID.
permissionIdpathstringYesPermission ID to update.
NameTypeRequiredDescription
permission_levelstringYesNew permission level. One of read, edit, delete.
{
"permission_level": "edit"
}
{
"statusCode": 200,
"message": "Project permission updated successfully",
"data": {
"id": "507f1f77bcf86cd799439033",
"project_id": "507f1f77bcf86cd799439011",
"user_id": "507f1f77bcf86cd799439044",
"permission_level": "edit",
"created_at": "2025-01-12T14:00:00.000Z",
"updated_at": "2025-01-15T14:45:00.000Z",
"user": {
"id": "507f1f77bcf86cd799439044",
"username": "jane_smith",
"alias": "Jane Smith"
}
}
}
import { HoodyClient } from 'hoody-sdk';
const client = new HoodyClient({ baseURL: 'https://api.hoody.com', token: process.env.HOODY_TOKEN });
await client.api.projects.updatePermission('507f1f77bcf86cd799439011', '507f1f77bcf86cd799439033', {
permission_level: 'edit',
});

PATCH /api/v1/projects/{id}/permissions/{permissionId}

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

Update a user’s permission level for a project. Accepts the same UpdateProjectPermissionRequest body as the PUT version. You must be the owner or have edit permission.

NameInTypeRequiredDescription
idpathstringYesProject ID.
permissionIdpathstringYesPermission ID to update.
NameTypeRequiredDescription
permission_levelstringYesNew permission level. One of read, edit, delete.
{
"permission_level": "read"
}
{
"statusCode": 200,
"message": "Project permission updated successfully",
"data": {
"id": "507f1f77bcf86cd799439033",
"project_id": "507f1f77bcf86cd799439011",
"user_id": "507f1f77bcf86cd799439044",
"permission_level": "read",
"created_at": "2025-01-12T14:00:00.000Z",
"updated_at": "2025-01-15T14:45:00.000Z",
"user": {
"id": "507f1f77bcf86cd799439044",
"username": "jane_smith",
"alias": "Jane Smith"
}
}
}
import { HoodyClient } from 'hoody-sdk';
const client = new HoodyClient({ baseURL: 'https://api.hoody.com', token: process.env.HOODY_TOKEN });
await client.api.projects.updatePermission('507f1f77bcf86cd799439011', '507f1f77bcf86cd799439033', {
permission_level: 'read',
});

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

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

Revoke a user’s access to a project. The user will immediately lose all access. You must be the owner or have edit permission.

NameInTypeRequiredDescription
idpathstringYesProject ID.
permissionIdpathstringYesPermission ID to remove.
{
"statusCode": 200,
"message": "Project permission removed successfully"
}
import { HoodyClient } from 'hoody-sdk';
const client = new HoodyClient({ baseURL: 'https://api.hoody.com', token: process.env.HOODY_TOKEN });
await client.api.projects.deletePermission('507f1f77bcf86cd799439011', '507f1f77bcf86cd799439033');

Get aggregated resource usage statistics for all containers in a project. Returns stats for each container plus summary metadata with total counts and processing time.

Each entry’s started_at is when that container was started, or null when it is not known, for example in the placeholder entry returned for a container whose statistics could not be read.

NameInTypeRequiredDescription
idpathstringYesUnique identifier of the project.
{
"statusCode": 200,
"message": "Project statistics retrieved successfully",
"data": {
"stats": [
{
"id": "507f1f77bcf86cd799439011",
"project_id": "507f1f77bcf86cd799439033",
"project_name": "Production Environment",
"server_name": "node-example-1",
"status": "Running",
"status_code": 103,
"processes": 143,
"started_at": "2025-12-03T18:39:53Z",
"cpu": {
"usage": 17303605000,
"allocated_time": 24000000000,
"usage_percent": 0.08
},
"memory": {
"usage": 1474666496,
"total": 131503332000,
"usage_percent": 1.12,
"swap_usage": 0,
"swap_usage_peak": 0,
"usage_peak": 0
},
"disk": {
"root": {
"total": 0,
"usage": 11081670656
}
},
"network": [],
"processing_time": "3ms"
}
],
"summary": {
"project_id": "507f1f77bcf86cd799439033",
"project_name": "Production Environment",
"container_count": 29,
"total_processing_time": "1506ms"
}
}
}
import { HoodyClient } from 'hoody-sdk';
const client = new HoodyClient({ baseURL: 'https://api.hoody.com', token: process.env.HOODY_TOKEN });
await client.api.projects.getStats('507f1f77bcf86cd799439011');

Per-month proxied request counts and response bytes for every container in the project. Expired and suspended containers ARE included. Counts COMPLETED, ROUTED, non-excluded HTTP responses only; forward-proxy/CONNECT egress, direct SSH, raw container egress, and WebSocket sessions until they close are excluded.

NameInTypeRequiredDescription
fromquerystringYesFirst month, inclusive (YYYY-MM).
toquerystringYesLast month, inclusive (YYYY-MM). Max 12 months.
idpathstringYesProject ID.
{
"statusCode": 200,
"message": "Proxy usage retrieved successfully",
"data": {
"from": "2025-01",
"to": "2025-03",
"excludes_deleted_containers": true,
"retrieval_complete": true,
"coverage_complete": false,
"months_capped": false,
"totals": {
"requests": 1284931,
"response_bytes": 8437129834,
"exact": true
},
"retention": {
"enforced": false,
"retained_from": "2025-01"
},
"sources": [
{
"status": "ok",
"reader_stale": false
}
],
"containers": {
"507f1f77bcf86cd799439077": {
"2025-01": {
"month": "2025-01",
"updated": "2025-02-01T00:00:00.000Z",
"days": {
"01": {
"requests": 1234,
"response_bytes": 567890,
"slots": 1440,
"active_slots": 1200,
"kits": { "web": 800, "general": 400 },
"slot_ms": 86400000
}
},
"totals": {
"requests": 38154,
"response_bytes": 17599120,
"exact": true
},
"measurement": {
"excluded_kits": []
}
}
}
}
}
}
import { HoodyClient } from 'hoody-sdk';
const client = new HoodyClient({ baseURL: 'https://api.hoody.com', token: process.env.HOODY_TOKEN });
await client.api.projects.getProxyUsage('507f1f77bcf86cd799439011', { from: '2025-01', to: '2025-03' });

Per-month proxied request counts and response bytes for a single container. Reports live containers on current placement. Counts COMPLETED, ROUTED, non-excluded HTTP responses only; forward-proxy/CONNECT egress, direct SSH, raw container egress, and WebSocket sessions until they close are excluded.

NameInTypeRequiredDescription
fromquerystringYesFirst month, inclusive (YYYY-MM).
toquerystringYesLast month, inclusive (YYYY-MM). Max 12 months.
idpathstringYesContainer ID.
{
"statusCode": 200,
"message": "Proxy usage retrieved successfully",
"data": {
"from": "2025-01",
"to": "2025-01",
"excludes_deleted_containers": true,
"retrieval_complete": true,
"coverage_complete": false,
"months_capped": false,
"totals": {
"requests": 38154,
"response_bytes": 17599120,
"exact": true
},
"retention": {
"enforced": false,
"retained_from": "2025-01"
},
"sources": [
{
"status": "ok",
"reader_stale": false
}
],
"containers": {
"507f1f77bcf86cd799439077": {
"2025-01": {
"month": "2025-01",
"updated": "2025-02-01T00:00:00.000Z",
"days": {
"01": {
"requests": 1234,
"response_bytes": 567890,
"slots": 1440,
"active_slots": 1200,
"kits": { "web": 800, "general": 400 },
"slot_ms": 86400000
}
},
"totals": {
"requests": 38154,
"response_bytes": 17599120,
"exact": true
},
"measurement": {
"excluded_kits": []
}
}
}
}
}
}
import { HoodyClient } from 'hoody-sdk';
const client = new HoodyClient({ baseURL: 'https://api.hoody.com', token: process.env.HOODY_TOKEN });
await client.api.containers.getProxyUsage('507f1f77bcf86cd799439077', { from: '2025-01', to: '2025-01' });

Live CPU, memory, and disk counters for a rented physical server (whole-box exclusive) or a subserver slice. Served from a short-TTL cache so it can be polled frequently. Requires a first-party JWT.

NameInTypeRequiredDescription
idpathstringYesRental ID (server or subserver).
{
"statusCode": 200,
"message": "Runtime info retrieved successfully",
"data": {
"scope": "server",
"ts": "2025-12-03T18:39:53.000Z",
"cache_age_ms": 412,
"stale": false,
"uptime_s": 3124561,
"cores": 32,
"load": { "1": 0.42, "5": 0.55, "15": 0.61 },
"cpu": { "busy_pct": 18.4 },
"mem": { "used_bytes": 274877906944, "total_bytes": 515396075520, "pct": 53.3 },
"swap": { "used_bytes": 0, "total_bytes": 8589934592 },
"storage": { "used_bytes": 1610612736000, "total_bytes": 3221225472000, "pct": 50.0 }
}
}
import { HoodyClient } from 'hoody-sdk';
const client = new HoodyClient({ baseURL: 'https://api.hoody.com', token: process.env.HOODY_TOKEN });
await client.api.servers.getStats('507f1f77bcf86cd799439099');

Returns the same payload as GET /rentals/{id}/runtime. Accepts the same parameters and emits the same error codes.

NameInTypeRequiredDescription
idpathstringYesServer or subserver ID.
{
"statusCode": 200,
"message": "Runtime info retrieved successfully",
"data": {
"scope": "subserver",
"ts": "2025-12-03T18:39:53.000Z",
"cache_age_ms": 318,
"stale": false,
"health": "ok",
"cpu": { "usage_cores": 1.42, "usage_pct": 35.5, "limit_cores": 4 },
"mem": { "used_bytes": 4294967296, "limit_bytes": 8589934592, "pct": 50.0 },
"disk": { "used_bytes": 16106127360, "limit_bytes": 53687091200, "pct": 30.0 },
"pids": { "current": 87, "max": 512 },
"io": { "read_bytes": 4194304000, "write_bytes": 2097152000 }
}
}
Terminal window
curl -X GET "https://api.hoody.com/api/v1/servers/507f1f77bcf86cd799439099/runtime" \
-H "Authorization: Bearer <token>"