Projects
Section titled “Projects”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>.
Project management
Section titled “Project management”GET /api/v1/projects/
Section titled “GET /api/v1/projects/”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.
Parameters
Section titled “Parameters”| Name | In | Type | Required | Description |
|---|---|---|---|---|
page | query | number | No | Page number (1-based). Default: 1. |
limit | query | number | No | Items per page (max 100). Default: 10. |
sort_by | query | string | No | Field to sort by. One of id, alias, created_at, updated_at. Default: "created_at". |
sort_order | query | string | No | Sort direction. One of asc, desc. Default: "desc". |
realm_id | query | string | No | Filter by realm ID. Only returns projects that belong to this realm. Alternative to using realm subdomain in URL. |
Response
Section titled “Response”{ "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 } }}{ "statusCode": 400, "error": "Bad Request", "message": "Invalid parameter value"}| Error Code | Title | Description | Resolution |
|---|---|---|---|
INVALID_PARAMETER_VALUE | Invalid parameter value | A parameter value is outside the allowed range or format | Ensure parameter values meet the documented constraints (min/max, format, regex) |
{ "statusCode": 401, "error": "Unauthorized", "message": "Authentication token required"}| Error Code | Title | Description | Resolution |
|---|---|---|---|
MISSING_TOKEN | Authentication token missing | No authentication token was provided in the request | Include a valid JWT token in the Authorization header as Bearer <token> |
INVALID_TOKEN | Invalid authentication token | The provided authentication token is malformed or invalid | Obtain a new token by logging in again or using a valid auth token |
TOKEN_EXPIRED | Authentication token expired | The provided authentication token has expired | Obtain a new token by logging in again or refreshing your session |
AUTH_TOKEN_LINEAGE_REVOKED | Parent auth token no longer valid | The auth token was created by another auth token, and that token (or one above it) has been revoked, disabled or has expired, so this one no longer authenticates | Create a new auth token from a valid one, or sign in again |
INVALID_CREDENTIALS | Invalid credentials | The provided username/email or password is incorrect | Verify your credentials and try again, or use the password reset feature |
EMAIL_NOT_VERIFIED | Email not verified | Returned by the login endpoint when the password is correct but the account’s email address has not been verified yet. It is only returned after the password has been checked. The response carries data.email so the client can offer a ‘resend verification email’ action without asking again. | Complete email verification by clicking the link sent to your inbox, or call /auth/resend-verification to receive a new link, or complete a password reset which also implicitly verifies the email. |
INVALID_OTP_CODE | Invalid OTP code | The provided 2FA code is incorrect or has expired | Generate a new code from your authenticator app and try again |
{ "statusCode": 403, "error": "Forbidden", "message": "Insufficient permissions"}| Error Code | Title | Description | Resolution |
|---|---|---|---|
INSUFFICIENT_PERMISSIONS | Insufficient permissions | You do not have the required permissions to perform this action | Ask the resource owner to grant you access |
ACCOUNT_BANNED | Account banned | Your account has been banned and cannot access this resource | Contact support for information about your account status |
Validation Error: the request does not match the operation schema, or its JSON body cannot be parsed. message names each failing check, and data, when present, lists them one entry per failing field.
{ "statusCode": 422, "error": "Validation Error", "message": "Validation failed: /name must NOT have fewer than 3 characters"}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);}curl -X GET "https://api.hoody.com/api/v1/projects/?page=1&limit=10" \ -H "Authorization: Bearer <token>"POST /api/v1/projects/
Section titled “POST /api/v1/projects/”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.
Request body
Section titled “Request body”| Name | Type | Required | Description |
|---|---|---|---|
alias | string | Yes | Human-readable project name (1-100 characters). Must be unique across your projects. |
color | string | No | HEX 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_containers | number | null | No | Maximum number of containers allowed in this project. null means unlimited. The quota is enforced during container creation. Minimum: 0. |
realm_ids | array | No | Realm 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" ]}Response
Section titled “Response”{ "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" ] }}{ "statusCode": 400, "error": "Bad Request", "message": "Invalid alias format"}| Error Code | Title | Description | Resolution |
|---|---|---|---|
VALIDATION_ERROR | Invalid input parameters | One or more request parameters failed validation | Check the error message for specific field requirements and correct your input |
MISSING_REQUIRED_FIELD | Required field missing | One or more required fields are missing from the request | Include all required fields as specified in the API documentation |
INVALID_ALIAS_FORMAT | Invalid alias format | Project alias must be between 1-100 characters | Provide a valid alias following the format requirements: 1-100 characters |
INVALID_COLOR_FORMAT | Invalid color format | Color must be a valid HEX color code (3 or 6 digits) | Provide a valid HEX color like #RGB or #RRGGBB (e.g., #F00 or #FF0000) |
INVALID_QUOTA_VALUE | Invalid quota value | Quota values must be non-negative numbers or null | Provide a valid quota value (0 or higher) or null for unlimited |
{ "statusCode": 401, "error": "Unauthorized", "message": "Authentication token required"}| Error Code | Title | Description | Resolution |
|---|---|---|---|
MISSING_TOKEN | Authentication token missing | No authentication token was provided in the request | Include a valid JWT token in the Authorization header as Bearer <token> |
INVALID_TOKEN | Invalid authentication token | The provided authentication token is malformed or invalid | Obtain a new token by logging in again or using a valid auth token |
TOKEN_EXPIRED | Authentication token expired | The provided authentication token has expired | Obtain a new token by logging in again or refreshing your session |
AUTH_TOKEN_LINEAGE_REVOKED | Parent auth token no longer valid | The auth token was created by another auth token, and that token (or one above it) has been revoked, disabled or has expired, so this one no longer authenticates | Create a new auth token from a valid one, or sign in again |
INVALID_CREDENTIALS | Invalid credentials | The provided username/email or password is incorrect | Verify your credentials and try again, or use the password reset feature |
EMAIL_NOT_VERIFIED | Email not verified | Returned by the login endpoint when the password is correct but the account’s email address has not been verified yet. It is only returned after the password has been checked. The response carries data.email so the client can offer a ‘resend verification email’ action without asking again. | Complete email verification by clicking the link sent to your inbox, or call /auth/resend-verification to receive a new link, or complete a password reset which also implicitly verifies the email. |
INVALID_OTP_CODE | Invalid OTP code | The provided 2FA code is incorrect or has expired | Generate a new code from your authenticator app and try again |
{ "statusCode": 403, "error": "Forbidden", "message": "Insufficient permissions"}| Error Code | Title | Description | Resolution |
|---|---|---|---|
INSUFFICIENT_PERMISSIONS | Insufficient permissions | You do not have the required permissions to perform this action | Ask the resource owner to grant you access |
ACCOUNT_BANNED | Account banned | Your account has been banned and cannot access this resource | Contact support for information about your account status |
{ "statusCode": 409, "error": "Conflict", "message": "Project alias already exists"}| Error Code | Title | Description | Resolution |
|---|---|---|---|
DUPLICATE_ALIAS | Project alias already exists | The provided project alias is already in use by another project in your account | Choose a different, unique project alias |
Validation Error: the request does not match the operation schema, or its JSON body cannot be parsed. message names each failing check, and data, when present, lists them one entry per failing field.
{ "statusCode": 422, "error": "Validation Error", "message": "Validation failed: /name must NOT have fewer than 3 characters"}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'],});curl -X POST "https://api.hoody.com/api/v1/projects/" \ -H "Authorization: Bearer <token>" \ -H "Content-Type: application/json" \ -d '{ "alias": "Production Environment", "color": "#EF4444", "max_containers": 100, "realm_ids": ["507f1f77bcf86cd799439011"] }'GET /api/v1/projects/{id}
Section titled “GET /api/v1/projects/{id}”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.
Parameters
Section titled “Parameters”| Name | In | Type | Required | Description |
|---|---|---|---|---|
id | path | string | Yes | Project ID. |
include_permissions | query | boolean | No | Include project permissions with user details in response. Default: false. |
Response
Section titled “Response”{ "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" } } ] }}{ "statusCode": 400, "error": "Bad Request", "message": "Invalid ID format"}| Error Code | Title | Description | Resolution |
|---|---|---|---|
INVALID_ID_FORMAT | Invalid ID format | The provided ID must be a 24-character hexadecimal string | Ensure the ID is exactly 24 characters long and contains only hexadecimal characters (0-9, a-f) |
INVALID_PARAMETER_VALUE | Invalid parameter value | A parameter value is outside the allowed range or format | Ensure parameter values meet the documented constraints (min/max, format, regex) |
{ "statusCode": 401, "error": "Unauthorized", "message": "Authentication token required"}| Error Code | Title | Description | Resolution |
|---|---|---|---|
MISSING_TOKEN | Authentication token missing | No authentication token was provided in the request | Include a valid JWT token in the Authorization header as Bearer <token> |
INVALID_TOKEN | Invalid authentication token | The provided authentication token is malformed or invalid | Obtain a new token by logging in again or using a valid auth token |
TOKEN_EXPIRED | Authentication token expired | The provided authentication token has expired | Obtain a new token by logging in again or refreshing your session |
AUTH_TOKEN_LINEAGE_REVOKED | Parent auth token no longer valid | The auth token was created by another auth token, and that token (or one above it) has been revoked, disabled or has expired, so this one no longer authenticates | Create a new auth token from a valid one, or sign in again |
EMAIL_NOT_VERIFIED | Email not verified | Returned by the login endpoint when the password is correct but the account’s email address has not been verified yet. It is only returned after the password has been checked. The response carries data.email so the client can offer a ‘resend verification email’ action without asking again. | Complete email verification by clicking the link sent to your inbox, or call /auth/resend-verification to receive a new link, or complete a password reset which also implicitly verifies the email. |
INVALID_OTP_CODE | Invalid OTP code | The provided 2FA code is incorrect or has expired | Generate a new code from your authenticator app and try again |
{ "statusCode": 403, "error": "Forbidden", "message": "Insufficient permissions"}| Error Code | Title | Description | Resolution |
|---|---|---|---|
INSUFFICIENT_PERMISSIONS | Insufficient permissions | You do not have the required permissions to perform this action | Contact the resource owner or administrator to request access |
ACCOUNT_BANNED | Account banned | Your account has been banned and cannot access this resource | Contact support for information about your account status |
{ "statusCode": 404, "error": "Not Found", "message": "Project not found"}| Error Code | Title | Description | Resolution |
|---|---|---|---|
PROJECT_NOT_FOUND | Project not found | The requested project does not exist or has been deleted | Verify the project ID is correct and that you have access to this project |
Validation Error: the request does not match the operation schema, or its JSON body cannot be parsed. message names each failing check, and data, when present, lists them one entry per failing field.
{ "statusCode": 422, "error": "Validation Error", "message": "Validation failed: /name must NOT have fewer than 3 characters"}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 });curl -X GET "https://api.hoody.com/api/v1/projects/507f1f77bcf86cd799439011?include_permissions=true" \ -H "Authorization: Bearer <token>"PUT /api/v1/projects/{id}
Section titled “PUT /api/v1/projects/{id}”Update a project’s alias, color, quotas, or realm membership. You must be the owner or have edit permission.
Parameters
Section titled “Parameters”| Name | In | Type | Required | Description |
|---|---|---|---|---|
id | path | string | Yes | Project ID to update. |
Request body
Section titled “Request body”| Name | Type | Required | Description |
|---|---|---|---|
alias | string | Yes | New project name (1-100 characters). Must be unique across your projects. |
color | string | No | New HEX color code (3 or 6 digits). Auto-normalized to uppercase with # prefix. |
max_containers | number | null | No | Maximum number of containers allowed in this project. null means unlimited. The quota is enforced during container creation. Minimum: 0. |
realm_ids | array | No | Update 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" ]}Response
Section titled “Response”{ "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" ] }}{ "statusCode": 400, "error": "Bad Request", "message": "Invalid ID format"}| Error Code | Title | Description | Resolution |
|---|---|---|---|
VALIDATION_ERROR | Invalid input parameters | One or more request parameters failed validation | Check the error message for specific field requirements and correct your input |
INVALID_ID_FORMAT | Invalid ID format | The provided ID must be a 24-character hexadecimal string | Ensure the ID is exactly 24 characters long and contains only hexadecimal characters (0-9, a-f) |
INVALID_ALIAS_FORMAT | Invalid alias format | Project alias must be between 1-100 characters | Provide a valid alias following the format requirements: 1-100 characters |
INVALID_COLOR_FORMAT | Invalid color format | Color must be a valid HEX color code (3 or 6 digits) | Provide a valid HEX color like #RGB or #RRGGBB (e.g., #F00 or #FF0000) |
INVALID_QUOTA_VALUE | Invalid quota value | Quota values must be non-negative numbers or null | Provide a valid quota value (0 or higher) or null for unlimited |
{ "statusCode": 401, "error": "Unauthorized", "message": "Authentication token required"}| Error Code | Title | Description | Resolution |
|---|---|---|---|
MISSING_TOKEN | Authentication token missing | No authentication token was provided in the request | Include a valid JWT token in the Authorization header as Bearer <token> |
INVALID_TOKEN | Invalid authentication token | The provided authentication token is malformed or invalid | Obtain a new token by logging in again or using a valid auth token |
TOKEN_EXPIRED | Authentication token expired | The provided authentication token has expired | Obtain a new token by logging in again or refreshing your session |
AUTH_TOKEN_LINEAGE_REVOKED | Parent auth token no longer valid | The auth token was created by another auth token, and that token (or one above it) has been revoked, disabled or has expired, so this one no longer authenticates | Create a new auth token from a valid one, or sign in again |
EMAIL_NOT_VERIFIED | Email not verified | Returned by the login endpoint when the password is correct but the account’s email address has not been verified yet. It is only returned after the password has been checked. The response carries data.email so the client can offer a ‘resend verification email’ action without asking again. | Complete email verification by clicking the link sent to your inbox, or call /auth/resend-verification to receive a new link, or complete a password reset which also implicitly verifies the email. |
INVALID_OTP_CODE | Invalid OTP code | The provided 2FA code is incorrect or has expired | Generate a new code from your authenticator app and try again |
{ "statusCode": 403, "error": "Forbidden", "message": "Insufficient permissions"}| Error Code | Title | Description | Resolution |
|---|---|---|---|
INSUFFICIENT_PERMISSIONS | Insufficient permissions | You do not have the required permissions to perform this action | Contact the resource owner or administrator to request access |
ACCOUNT_BANNED | Account banned | Your account has been banned and cannot access this resource | Contact support for information about your account status |
{ "statusCode": 404, "error": "Not Found", "message": "Project not found"}| Error Code | Title | Description | Resolution |
|---|---|---|---|
PROJECT_NOT_FOUND | Project not found | The requested project does not exist or has been deleted | Verify the project ID is correct and that you have access to this project |
{ "statusCode": 409, "error": "Conflict", "message": "Project alias already exists"}| Error Code | Title | Description | Resolution |
|---|---|---|---|
DUPLICATE_ALIAS | Project alias already exists | The provided project alias is already in use by another project in your account | Choose a different, unique project alias |
Validation Error: the request does not match the operation schema, or its JSON body cannot be parsed. message names each failing check, and data, when present, lists them one entry per failing field.
{ "statusCode": 422, "error": "Validation Error", "message": "Validation failed: /name must NOT have fewer than 3 characters"}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'],});curl -X PUT "https://api.hoody.com/api/v1/projects/507f1f77bcf86cd799439011" \ -H "Authorization: Bearer <token>" \ -H "Content-Type: application/json" \ -d '{ "alias": "Production Environment Updated", "color": "#EF4444", "max_containers": 75, "realm_ids": ["507f1f77bcf86cd799439011"] }'PATCH /api/v1/projects/{id}
Section titled “PATCH /api/v1/projects/{id}”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.
Parameters
Section titled “Parameters”| Name | In | Type | Required | Description |
|---|---|---|---|---|
id | path | string | Yes | Project ID to update. |
Request body
Section titled “Request body”| Name | Type | Required | Description |
|---|---|---|---|
alias | string | Yes | New project name (1-100 characters). Must be unique across your projects. |
color | string | No | New HEX color code (3 or 6 digits). Auto-normalized to uppercase with # prefix. |
max_containers | number | null | No | Maximum number of containers allowed in this project. null means unlimited. The quota is enforced during container creation. Minimum: 0. |
realm_ids | array | No | Update 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}Response
Section titled “Response”{ "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": [] }}{ "statusCode": 400, "error": "Bad Request", "message": "Invalid ID format"}| Error Code | Title | Description | Resolution |
|---|---|---|---|
VALIDATION_ERROR | Invalid input parameters | One or more request parameters failed validation | Check the error message for specific field requirements and correct your input |
INVALID_ID_FORMAT | Invalid ID format | The provided ID must be a 24-character hexadecimal string | Ensure the ID is exactly 24 characters long and contains only hexadecimal characters (0-9, a-f) |
INVALID_ALIAS_FORMAT | Invalid alias format | Project alias must be between 1-100 characters | Provide a valid alias following the format requirements: 1-100 characters |
INVALID_COLOR_FORMAT | Invalid color format | Color must be a valid HEX color code (3 or 6 digits) | Provide a valid HEX color like #RGB or #RRGGBB (e.g., #F00 or #FF0000) |
INVALID_QUOTA_VALUE | Invalid quota value | Quota values must be non-negative numbers or null | Provide a valid quota value (0 or higher) or null for unlimited |
{ "statusCode": 401, "error": "Unauthorized", "message": "Authentication token required"}| Error Code | Title | Description | Resolution |
|---|---|---|---|
MISSING_TOKEN | Authentication token missing | No authentication token was provided in the request | Include a valid JWT token in the Authorization header as Bearer <token> |
INVALID_TOKEN | Invalid authentication token | The provided authentication token is malformed or invalid | Obtain a new token by logging in again or using a valid auth token |
TOKEN_EXPIRED | Authentication token expired | The provided authentication token has expired | Obtain a new token by logging in again or refreshing your session |
AUTH_TOKEN_LINEAGE_REVOKED | Parent auth token no longer valid | The auth token was created by another auth token, and that token (or one above it) has been revoked, disabled or has expired, so this one no longer authenticates | Create a new auth token from a valid one, or sign in again |
EMAIL_NOT_VERIFIED | Email not verified | Returned by the login endpoint when the password is correct but the account’s email address has not been verified yet. It is only returned after the password has been checked. The response carries data.email so the client can offer a ‘resend verification email’ action without asking again. | Complete email verification by clicking the link sent to your inbox, or call /auth/resend-verification to receive a new link, or complete a password reset which also implicitly verifies the email. |
INVALID_OTP_CODE | Invalid OTP code | The provided 2FA code is incorrect or has expired | Generate a new code from your authenticator app and try again |
{ "statusCode": 403, "error": "Forbidden", "message": "Insufficient permissions"}| Error Code | Title | Description | Resolution |
|---|---|---|---|
INSUFFICIENT_PERMISSIONS | Insufficient permissions | You do not have the required permissions to perform this action | Contact the resource owner or administrator to request access |
ACCOUNT_BANNED | Account banned | Your account has been banned and cannot access this resource | Contact support for information about your account status |
{ "statusCode": 404, "error": "Not Found", "message": "Project not found"}| Error Code | Title | Description | Resolution |
|---|---|---|---|
PROJECT_NOT_FOUND | Project not found | The requested project does not exist or has been deleted | Verify the project ID is correct and that you have access to this project |
{ "statusCode": 409, "error": "Conflict", "message": "Project alias already exists"}| Error Code | Title | Description | Resolution |
|---|---|---|---|
DUPLICATE_ALIAS | Project alias already exists | The provided project alias is already in use by another project in your account | Choose a different, unique project alias |
Validation Error: the request does not match the operation schema, or its JSON body cannot be parsed. message names each failing check, and data, when present, lists them one entry per failing field.
{ "statusCode": 422, "error": "Validation Error", "message": "Validation failed: /name must NOT have fewer than 3 characters"}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,});curl -X PATCH "https://api.hoody.com/api/v1/projects/507f1f77bcf86cd799439011" \ -H "Authorization: Bearer <token>" \ -H "Content-Type: application/json" \ -d '{ "alias": "Production v2", "color": "#10B981", "max_containers": null }'DELETE /api/v1/projects/{id}
Section titled “DELETE /api/v1/projects/{id}”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.
Parameters
Section titled “Parameters”| Name | In | Type | Required | Description |
|---|---|---|---|---|
id | path | string | Yes | Project ID to delete. |
include_deleted_items | query | boolean | No | Include a lightweight list of deleted container IDs/names in the response for confirmation UX. Default: false. |
Response
Section titled “Response”{ "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" } ] } }}{ "statusCode": 400, "error": "Bad Request", "message": "Invalid ID format"}| Error Code | Title | Description | Resolution |
|---|---|---|---|
INVALID_ID_FORMAT | Invalid ID format | The provided ID must be a 24-character hexadecimal string | Ensure the ID is exactly 24 characters long and contains only hexadecimal characters (0-9, a-f) |
{ "statusCode": 401, "error": "Unauthorized", "message": "Authentication token required"}| Error Code | Title | Description | Resolution |
|---|---|---|---|
MISSING_TOKEN | Authentication token missing | No authentication token was provided in the request | Include a valid JWT token in the Authorization header as Bearer <token> |
INVALID_TOKEN | Invalid authentication token | The provided authentication token is malformed or invalid | Obtain a new token by logging in again or using a valid auth token |
TOKEN_EXPIRED | Authentication token expired | The provided authentication token has expired | Obtain a new token by logging in again or refreshing your session |
AUTH_TOKEN_LINEAGE_REVOKED | Parent auth token no longer valid | The auth token was created by another auth token, and that token (or one above it) has been revoked, disabled or has expired, so this one no longer authenticates | Create a new auth token from a valid one, or sign in again |
EMAIL_NOT_VERIFIED | Email not verified | Returned by the login endpoint when the password is correct but the account’s email address has not been verified yet. It is only returned after the password has been checked. The response carries data.email so the client can offer a ‘resend verification email’ action without asking again. | Complete email verification by clicking the link sent to your inbox, or call /auth/resend-verification to receive a new link, or complete a password reset which also implicitly verifies the email. |
INVALID_OTP_CODE | Invalid OTP code | The provided 2FA code is incorrect or has expired | Generate a new code from your authenticator app and try again |
{ "statusCode": 403, "error": "Forbidden", "message": "Insufficient permissions"}| Error Code | Title | Description | Resolution |
|---|---|---|---|
INSUFFICIENT_PERMISSIONS | Insufficient permissions | You do not have the required permissions to perform this action | Contact the resource owner or administrator to request access |
ACCOUNT_BANNED | Account banned | Your account has been banned and cannot access this resource | Contact support for information about your account status |
{ "statusCode": 404, "error": "Not Found", "message": "Project not found"}| Error Code | Title | Description | Resolution |
|---|---|---|---|
PROJECT_NOT_FOUND | Project not found | The requested project does not exist or has been deleted | Verify the project ID is correct and that you have access to this project |
{ "statusCode": 409, "error": "Conflict", "message": "Resource already exists"}| Error Code | Title | Description | Resolution |
|---|---|---|---|
RESOURCE_ALREADY_EXISTS | Resource already exists | A resource with this identifier already exists | Use a different identifier or update the existing resource instead |
{ "statusCode": 422, "error": "Unprocessable Entity", "message": "Project contains active containers"}| Error Code | Title | Description | Resolution |
|---|---|---|---|
PROJECT_HAS_CONTAINERS | Project has active containers | Cannot delete project because it contains active containers | Delete all containers in this project first, then try again |
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 });curl -X DELETE "https://api.hoody.com/api/v1/projects/507f1f77bcf86cd799439011?include_deleted_items=true" \ -H "Authorization: Bearer <token>"Project permissions
Section titled “Project permissions”GET /api/v1/projects/{id}/permissions
Section titled “GET /api/v1/projects/{id}/permissions”List all users who have been granted access to this project, along with their permission levels. Supports pagination and sorting.
Parameters
Section titled “Parameters”| Name | In | Type | Required | Description |
|---|---|---|---|---|
id | path | string | Yes | Project ID. |
page | query | number | No | Page number (1-based). |
limit | query | number | No | Items per page. |
sort_by | query | string | No | Field to sort by. One of id, user_id, permission_level, created_at, updated_at. |
sort_order | query | string | No | Sort direction. One of asc, desc. |
Response
Section titled “Response”{ "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 } }}{ "statusCode": 400, "error": "Bad Request", "message": "Bad Request"}{ "statusCode": 401, "error": "Unauthorized", "message": "Unauthorized"}| Error Code | Title | Description | Resolution |
|---|---|---|---|
MISSING_TOKEN | Authentication token missing | No authentication token was provided in the request | Include a valid JWT token in the Authorization header as Bearer <token> |
INVALID_TOKEN | Invalid authentication token | The provided authentication token is malformed or invalid | Obtain a new token by logging in again or using a valid auth token |
TOKEN_EXPIRED | Authentication token expired | The provided authentication token has expired | Obtain a new token by logging in again or refreshing your session |
AUTH_TOKEN_LINEAGE_REVOKED | Parent auth token no longer valid | The auth token was created by another auth token, and that token (or one above it) has been revoked, disabled or has expired, so this one no longer authenticates | Create a new auth token from a valid one, or sign in again |
INVALID_CREDENTIALS | Invalid credentials | The provided username/email or password is incorrect | Verify your credentials and try again, or use the password reset feature |
EMAIL_NOT_VERIFIED | Email not verified | Returned by the login endpoint when the password is correct but the account’s email address has not been verified yet. It is only returned after the password has been checked. The response carries data.email so the client can offer a ‘resend verification email’ action without asking again. | Complete email verification by clicking the link sent to your inbox, or call /auth/resend-verification to receive a new link, or complete a password reset which also implicitly verifies the email. |
INVALID_OTP_CODE | Invalid OTP code | The provided 2FA code is incorrect or has expired | Generate a new code from your authenticator app and try again |
{ "statusCode": 403, "error": "Forbidden", "message": "Forbidden"}| Error Code | Title | Description | Resolution |
|---|---|---|---|
INSUFFICIENT_PERMISSIONS | Insufficient permissions | You do not have the required permissions to perform this action | Ask the resource owner to grant you access |
ACCOUNT_BANNED | Account banned | Your account has been banned and cannot access this resource | Contact support for information about your account status |
{ "statusCode": 404, "error": "Not Found", "message": "Not Found"}Validation Error: the request does not match the operation schema, or its JSON body cannot be parsed. message names each failing check, and data, when present, lists them one entry per failing field.
{ "statusCode": 422, "error": "Validation Error", "message": "Validation failed: /name must NOT have fewer than 3 characters"}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);}curl -X GET "https://api.hoody.com/api/v1/projects/507f1f77bcf86cd799439011/permissions?page=1&limit=10" \ -H "Authorization: Bearer <token>"POST /api/v1/projects/{id}/permissions
Section titled “POST /api/v1/projects/{id}/permissions”Grant another user access to your project with a specific permission level. You must be the owner or have edit permission.
Parameters
Section titled “Parameters”| Name | In | Type | Required | Description |
|---|---|---|---|---|
id | path | string | Yes | Project ID. |
Request body
Section titled “Request body”| Name | Type | Required | Description |
|---|---|---|---|
user_id | string | Yes | User ID to grant access to. Must be a 24-character hexadecimal string. |
permission_level | string | Yes | Access level. One of read (view only), edit (modify), delete (destroy). |
{ "user_id": "507f1f77bcf86cd799439044", "permission_level": "edit"}Response
Section titled “Response”{ "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" } }}{ "statusCode": 400, "error": "Bad Request", "message": "Validation failed"}| Error Code | Title | Description | Resolution |
|---|---|---|---|
VALIDATION_ERROR | Invalid input parameters | One or more request parameters failed validation | Check the error message for specific field requirements and correct your input |
INVALID_ID_FORMAT | Invalid ID format | The provided ID must be a 24-character hexadecimal string | Ensure the ID is exactly 24 characters long and contains only hexadecimal characters (0-9, a-f) |
MISSING_REQUIRED_FIELD | Required field missing | One or more required fields are missing from the request | Include all required fields as specified in the API documentation |
{ "statusCode": 401, "error": "Unauthorized", "message": "Authentication token required"}| Error Code | Title | Description | Resolution |
|---|---|---|---|
MISSING_TOKEN | Authentication token missing | No authentication token was provided in the request | Include a valid JWT token in the Authorization header as Bearer <token> |
INVALID_TOKEN | Invalid authentication token | The provided authentication token is malformed or invalid | Obtain a new token by logging in again or using a valid auth token |
TOKEN_EXPIRED | Authentication token expired | The provided authentication token has expired | Obtain a new token by logging in again or refreshing your session |
AUTH_TOKEN_LINEAGE_REVOKED | Parent auth token no longer valid | The auth token was created by another auth token, and that token (or one above it) has been revoked, disabled or has expired, so this one no longer authenticates | Create a new auth token from a valid one, or sign in again |
EMAIL_NOT_VERIFIED | Email not verified | Returned by the login endpoint when the password is correct but the account’s email address has not been verified yet. It is only returned after the password has been checked. The response carries data.email so the client can offer a ‘resend verification email’ action without asking again. | Complete email verification by clicking the link sent to your inbox, or call /auth/resend-verification to receive a new link, or complete a password reset which also implicitly verifies the email. |
INVALID_OTP_CODE | Invalid OTP code | The provided 2FA code is incorrect or has expired | Generate a new code from your authenticator app and try again |
{ "statusCode": 403, "error": "Forbidden", "message": "Insufficient permissions"}| Error Code | Title | Description | Resolution |
|---|---|---|---|
INSUFFICIENT_PERMISSIONS | Insufficient permissions | You do not have the required permissions to perform this action | Contact the resource owner or administrator to request access |
ACCOUNT_BANNED | Account banned | Your account has been banned and cannot access this resource | Contact support for information about your account status |
{ "statusCode": 404, "error": "Not Found", "message": "Project not found"}| Error Code | Title | Description | Resolution |
|---|---|---|---|
PROJECT_NOT_FOUND | Project not found | The requested project does not exist or has been deleted | Verify the project ID is correct and that you have access to this project |
RESOURCE_NOT_FOUND | Resource not found | The requested resource does not exist or has been deleted | Verify the resource ID and ensure it exists |
{ "statusCode": 409, "error": "Conflict", "message": "User already has permission for this project"}| Error Code | Title | Description | Resolution |
|---|---|---|---|
PERMISSION_ALREADY_EXISTS | Permission already exists | This user already has a permission for this project | Update the existing permission instead of creating a new one |
CANNOT_GRANT_SELF_PERMISSION | Cannot grant permission to self | You cannot grant permissions to yourself | As the owner, you already have full access to this project |
Validation Error: the request does not match the operation schema, or its JSON body cannot be parsed. message names each failing check, and data, when present, lists them one entry per failing field.
{ "statusCode": 422, "error": "Validation Error", "message": "Validation failed: /name must NOT have fewer than 3 characters"}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',});curl -X POST "https://api.hoody.com/api/v1/projects/507f1f77bcf86cd799439011/permissions" \ -H "Authorization: Bearer <token>" \ -H "Content-Type: application/json" \ -d '{ "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.
Parameters
Section titled “Parameters”| Name | In | Type | Required | Description |
|---|---|---|---|---|
id | path | string | Yes | Project ID. |
permissionId | path | string | Yes | Permission ID to update. |
Request body
Section titled “Request body”| Name | Type | Required | Description |
|---|---|---|---|
permission_level | string | Yes | New permission level. One of read, edit, delete. |
{ "permission_level": "edit"}Response
Section titled “Response”{ "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" } }}{ "statusCode": 400, "error": "Bad Request", "message": "Validation failed"}| Error Code | Title | Description | Resolution |
|---|---|---|---|
VALIDATION_ERROR | Invalid input parameters | One or more request parameters failed validation | Check the error message for specific field requirements and correct your input |
INVALID_ID_FORMAT | Invalid ID format | The provided ID must be a 24-character hexadecimal string | Ensure the ID is exactly 24 characters long and contains only hexadecimal characters (0-9, a-f) |
MISSING_REQUIRED_FIELD | Required field missing | One or more required fields are missing from the request | Include all required fields as specified in the API documentation |
{ "statusCode": 401, "error": "Unauthorized", "message": "Authentication token required"}| Error Code | Title | Description | Resolution |
|---|---|---|---|
MISSING_TOKEN | Authentication token missing | No authentication token was provided in the request | Include a valid JWT token in the Authorization header as Bearer <token> |
INVALID_TOKEN | Invalid authentication token | The provided authentication token is malformed or invalid | Obtain a new token by logging in again or using a valid auth token |
TOKEN_EXPIRED | Authentication token expired | The provided authentication token has expired | Obtain a new token by logging in again or refreshing your session |
AUTH_TOKEN_LINEAGE_REVOKED | Parent auth token no longer valid | The auth token was created by another auth token, and that token (or one above it) has been revoked, disabled or has expired, so this one no longer authenticates | Create a new auth token from a valid one, or sign in again |
EMAIL_NOT_VERIFIED | Email not verified | Returned by the login endpoint when the password is correct but the account’s email address has not been verified yet. It is only returned after the password has been checked. The response carries data.email so the client can offer a ‘resend verification email’ action without asking again. | Complete email verification by clicking the link sent to your inbox, or call /auth/resend-verification to receive a new link, or complete a password reset which also implicitly verifies the email. |
INVALID_OTP_CODE | Invalid OTP code | The provided 2FA code is incorrect or has expired | Generate a new code from your authenticator app and try again |
{ "statusCode": 403, "error": "Forbidden", "message": "Insufficient permissions"}| Error Code | Title | Description | Resolution |
|---|---|---|---|
INSUFFICIENT_PERMISSIONS | Insufficient permissions | You do not have the required permissions to perform this action | Contact the resource owner or administrator to request access |
ACCOUNT_BANNED | Account banned | Your account has been banned and cannot access this resource | Contact support for information about your account status |
{ "statusCode": 404, "error": "Not Found", "message": "Permission not found"}| Error Code | Title | Description | Resolution |
|---|---|---|---|
PROJECT_NOT_FOUND | Project not found | The requested project does not exist or has been deleted | Verify the project ID is correct and that you have access to this project |
PERMISSION_NOT_FOUND | Permission not found | The requested permission does not exist or has been removed | Verify the permission ID is correct |
Validation Error: the request does not match the operation schema, or its JSON body cannot be parsed. message names each failing check, and data, when present, lists them one entry per failing field.
{ "statusCode": 422, "error": "Validation Error", "message": "Validation failed: /name must NOT have fewer than 3 characters"}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',});curl -X PUT "https://api.hoody.com/api/v1/projects/507f1f77bcf86cd799439011/permissions/507f1f77bcf86cd799439033" \ -H "Authorization: Bearer <token>" \ -H "Content-Type: application/json" \ -d '{ "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.
Parameters
Section titled “Parameters”| Name | In | Type | Required | Description |
|---|---|---|---|---|
id | path | string | Yes | Project ID. |
permissionId | path | string | Yes | Permission ID to update. |
Request body
Section titled “Request body”| Name | Type | Required | Description |
|---|---|---|---|
permission_level | string | Yes | New permission level. One of read, edit, delete. |
{ "permission_level": "read"}Response
Section titled “Response”{ "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" } }}{ "statusCode": 400, "error": "Bad Request", "message": "Validation failed"}| Error Code | Title | Description | Resolution |
|---|---|---|---|
VALIDATION_ERROR | Invalid input parameters | One or more request parameters failed validation | Check the error message for specific field requirements and correct your input |
INVALID_ID_FORMAT | Invalid ID format | The provided ID must be a 24-character hexadecimal string | Ensure the ID is exactly 24 characters long and contains only hexadecimal characters (0-9, a-f) |
MISSING_REQUIRED_FIELD | Required field missing | One or more required fields are missing from the request | Include all required fields as specified in the API documentation |
{ "statusCode": 401, "error": "Unauthorized", "message": "Authentication token required"}| Error Code | Title | Description | Resolution |
|---|---|---|---|
MISSING_TOKEN | Authentication token missing | No authentication token was provided in the request | Include a valid JWT token in the Authorization header as Bearer <token> |
INVALID_TOKEN | Invalid authentication token | The provided authentication token is malformed or invalid | Obtain a new token by logging in again or using a valid auth token |
TOKEN_EXPIRED | Authentication token expired | The provided authentication token has expired | Obtain a new token by logging in again or refreshing your session |
AUTH_TOKEN_LINEAGE_REVOKED | Parent auth token no longer valid | The auth token was created by another auth token, and that token (or one above it) has been revoked, disabled or has expired, so this one no longer authenticates | Create a new auth token from a valid one, or sign in again |
EMAIL_NOT_VERIFIED | Email not verified | Returned by the login endpoint when the password is correct but the account’s email address has not been verified yet. It is only returned after the password has been checked. The response carries data.email so the client can offer a ‘resend verification email’ action without asking again. | Complete email verification by clicking the link sent to your inbox, or call /auth/resend-verification to receive a new link, or complete a password reset which also implicitly verifies the email. |
INVALID_OTP_CODE | Invalid OTP code | The provided 2FA code is incorrect or has expired | Generate a new code from your authenticator app and try again |
{ "statusCode": 403, "error": "Forbidden", "message": "Insufficient permissions"}| Error Code | Title | Description | Resolution |
|---|---|---|---|
INSUFFICIENT_PERMISSIONS | Insufficient permissions | You do not have the required permissions to perform this action | Contact the resource owner or administrator to request access |
ACCOUNT_BANNED | Account banned | Your account has been banned and cannot access this resource | Contact support for information about your account status |
{ "statusCode": 404, "error": "Not Found", "message": "Permission not found"}| Error Code | Title | Description | Resolution |
|---|---|---|---|
PROJECT_NOT_FOUND | Project not found | The requested project does not exist or has been deleted | Verify the project ID is correct and that you have access to this project |
PERMISSION_NOT_FOUND | Permission not found | The requested permission does not exist or has been removed | Verify the permission ID is correct |
Validation Error: the request does not match the operation schema, or its JSON body cannot be parsed. message names each failing check, and data, when present, lists them one entry per failing field.
{ "statusCode": 422, "error": "Validation Error", "message": "Validation failed: /name must NOT have fewer than 3 characters"}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',});curl -X PATCH "https://api.hoody.com/api/v1/projects/507f1f77bcf86cd799439011/permissions/507f1f77bcf86cd799439033" \ -H "Authorization: Bearer <token>" \ -H "Content-Type: application/json" \ -d '{ "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.
Parameters
Section titled “Parameters”| Name | In | Type | Required | Description |
|---|---|---|---|---|
id | path | string | Yes | Project ID. |
permissionId | path | string | Yes | Permission ID to remove. |
Response
Section titled “Response”{ "statusCode": 200, "message": "Project permission removed successfully"}{ "statusCode": 400, "error": "Bad Request", "message": "Bad Request"}{ "statusCode": 401, "error": "Unauthorized", "message": "Unauthorized"}| Error Code | Title | Description | Resolution |
|---|---|---|---|
MISSING_TOKEN | Authentication token missing | No authentication token was provided in the request | Include a valid JWT token in the Authorization header as Bearer <token> |
INVALID_TOKEN | Invalid authentication token | The provided authentication token is malformed or invalid | Obtain a new token by logging in again or using a valid auth token |
TOKEN_EXPIRED | Authentication token expired | The provided authentication token has expired | Obtain a new token by logging in again or refreshing your session |
AUTH_TOKEN_LINEAGE_REVOKED | Parent auth token no longer valid | The auth token was created by another auth token, and that token (or one above it) has been revoked, disabled or has expired, so this one no longer authenticates | Create a new auth token from a valid one, or sign in again |
INVALID_CREDENTIALS | Invalid credentials | The provided username/email or password is incorrect | Verify your credentials and try again, or use the password reset feature |
EMAIL_NOT_VERIFIED | Email not verified | Returned by the login endpoint when the password is correct but the account’s email address has not been verified yet. It is only returned after the password has been checked. The response carries data.email so the client can offer a ‘resend verification email’ action without asking again. | Complete email verification by clicking the link sent to your inbox, or call /auth/resend-verification to receive a new link, or complete a password reset which also implicitly verifies the email. |
INVALID_OTP_CODE | Invalid OTP code | The provided 2FA code is incorrect or has expired | Generate a new code from your authenticator app and try again |
{ "statusCode": 403, "error": "Forbidden", "message": "Forbidden"}| Error Code | Title | Description | Resolution |
|---|---|---|---|
INSUFFICIENT_PERMISSIONS | Insufficient permissions | You do not have the required permissions to perform this action | Ask the resource owner to grant you access |
ACCOUNT_BANNED | Account banned | Your account has been banned and cannot access this resource | Contact support for information about your account status |
{ "statusCode": 404, "error": "Not Found", "message": "Not Found"}Validation Error: the request does not match the operation schema, or its JSON body cannot be parsed. message names each failing check, and data, when present, lists them one entry per failing field.
{ "statusCode": 422, "error": "Validation Error", "message": "Validation failed: /name must NOT have fewer than 3 characters"}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');curl -X DELETE "https://api.hoody.com/api/v1/projects/507f1f77bcf86cd799439011/permissions/507f1f77bcf86cd799439033" \ -H "Authorization: Bearer <token>"Project statistics
Section titled “Project statistics”GET /api/v1/projects/{id}/stats
Section titled “GET /api/v1/projects/{id}/stats”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.
Parameters
Section titled “Parameters”| Name | In | Type | Required | Description |
|---|---|---|---|---|
id | path | string | Yes | Unique identifier of the project. |
Response
Section titled “Response”{ "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" } }}{ "statusCode": 400, "error": "Bad Request", "message": "Invalid ID format"}| Error Code | Title | Description | Resolution |
|---|---|---|---|
INVALID_ID_FORMAT | Invalid ID format | The provided ID must be a 24-character hexadecimal string | Ensure the ID is exactly 24 characters long and contains only hexadecimal characters (0-9, a-f) |
{ "statusCode": 401, "error": "Unauthorized", "message": "Authentication token required"}| Error Code | Title | Description | Resolution |
|---|---|---|---|
MISSING_TOKEN | Authentication token missing | No authentication token was provided in the request | Include a valid JWT token in the Authorization header as Bearer <token> |
INVALID_TOKEN | Invalid authentication token | The provided authentication token is malformed or invalid | Obtain a new token by logging in again or using a valid auth token |
TOKEN_EXPIRED | Authentication token expired | The provided authentication token has expired | Obtain a new token by logging in again or refreshing your session |
AUTH_TOKEN_LINEAGE_REVOKED | Parent auth token no longer valid | The auth token was created by another auth token, and that token (or one above it) has been revoked, disabled or has expired, so this one no longer authenticates | Create a new auth token from a valid one, or sign in again |
EMAIL_NOT_VERIFIED | Email not verified | Returned by the login endpoint when the password is correct but the account’s email address has not been verified yet. It is only returned after the password has been checked. The response carries data.email so the client can offer a ‘resend verification email’ action without asking again. | Complete email verification by clicking the link sent to your inbox, or call /auth/resend-verification to receive a new link, or complete a password reset which also implicitly verifies the email. |
INVALID_OTP_CODE | Invalid OTP code | The provided 2FA code is incorrect or has expired | Generate a new code from your authenticator app and try again |
{ "statusCode": 403, "error": "Forbidden", "message": "Insufficient permissions"}| Error Code | Title | Description | Resolution |
|---|---|---|---|
INSUFFICIENT_PERMISSIONS | Insufficient permissions | You do not have the required permissions to perform this action | Contact the resource owner or administrator to request access |
ACCOUNT_BANNED | Account banned | Your account has been banned and cannot access this resource | Contact support for information about your account status |
RESOURCE_ACCESS_DENIED | Resource access denied | You do not have permission to access this specific resource | Ensure you own this resource or have been granted access by the owner |
{ "statusCode": 404, "error": "Not Found", "message": "Resource not found"}| Error Code | Title | Description | Resolution |
|---|---|---|---|
RESOURCE_NOT_FOUND | Resource not found | The requested resource does not exist or has been deleted | Verify the resource ID and ensure it exists |
Validation Error: the request does not match the operation schema, or its JSON body cannot be parsed. message names each failing check, and data, when present, lists them one entry per failing field.
{ "statusCode": 422, "error": "Validation Error", "message": "Validation failed: /name must NOT have fewer than 3 characters"}{ "statusCode": 500, "error": "Internal Server Error", "message": "An unexpected error occurred"}| Error Code | Title | Description | Resolution |
|---|---|---|---|
INTERNAL_SERVER_ERROR | Internal server error | An unexpected error occurred on the server | Try again later, or contact support if the problem persists |
EXTERNAL_SERVICE_ERROR | External service error | A required external service is unavailable or returned an error | Try again later when the external service is available |
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');curl -X GET "https://api.hoody.com/api/v1/projects/507f1f77bcf86cd799439011/stats" \ -H "Authorization: Bearer <token>"Proxied usage
Section titled “Proxied usage”GET /api/v1/projects/{id}/proxy-usage
Section titled “GET /api/v1/projects/{id}/proxy-usage”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.
Parameters
Section titled “Parameters”| Name | In | Type | Required | Description |
|---|---|---|---|---|
from | query | string | Yes | First month, inclusive (YYYY-MM). |
to | query | string | Yes | Last month, inclusive (YYYY-MM). Max 12 months. |
id | path | string | Yes | Project ID. |
Response
Section titled “Response”{ "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": [] } } } } }}{ "statusCode": 400, "error": "Bad Request", "message": "Invalid ID format"}| Error Code | Title | Description | Resolution |
|---|---|---|---|
INVALID_ID_FORMAT | Invalid ID format | The provided ID must be a 24-character hexadecimal string | Ensure the ID is exactly 24 characters long and contains only hexadecimal characters (0-9, a-f) |
INVALID_PARAMETER_VALUE | Invalid parameter value | A parameter value is outside the allowed range or format | Ensure parameter values meet the documented constraints (min/max, format, regex) |
{ "statusCode": 401, "error": "Unauthorized", "message": "Authentication token required"}| Error Code | Title | Description | Resolution |
|---|---|---|---|
MISSING_TOKEN | Authentication token missing | No authentication token was provided in the request | Include a valid JWT token in the Authorization header as Bearer <token> |
INVALID_TOKEN | Invalid authentication token | The provided authentication token is malformed or invalid | Obtain a new token by logging in again or using a valid auth token |
TOKEN_EXPIRED | Authentication token expired | The provided authentication token has expired | Obtain a new token by logging in again or refreshing your session |
AUTH_TOKEN_LINEAGE_REVOKED | Parent auth token no longer valid | The auth token was created by another auth token, and that token (or one above it) has been revoked, disabled or has expired, so this one no longer authenticates | Create a new auth token from a valid one, or sign in again |
EMAIL_NOT_VERIFIED | Email not verified | Returned by the login endpoint when the password is correct but the account’s email address has not been verified yet. It is only returned after the password has been checked. The response carries data.email so the client can offer a ‘resend verification email’ action without asking again. | Complete email verification by clicking the link sent to your inbox, or call /auth/resend-verification to receive a new link, or complete a password reset which also implicitly verifies the email. |
INVALID_OTP_CODE | Invalid OTP code | The provided 2FA code is incorrect or has expired | Generate a new code from your authenticator app and try again |
{ "statusCode": 403, "error": "Forbidden", "message": "Insufficient permissions"}| Error Code | Title | Description | Resolution |
|---|---|---|---|
INSUFFICIENT_PERMISSIONS | Insufficient permissions | You do not have the required permissions to perform this action | Contact the resource owner or administrator to request access |
RESOURCE_ACCESS_DENIED | Resource access denied | You do not have permission to access this specific resource | Ensure you own this resource or have been granted access by the owner |
{ "statusCode": 404, "error": "Not Found", "message": "Resource not found"}| Error Code | Title | Description | Resolution |
|---|---|---|---|
RESOURCE_NOT_FOUND | Resource not found | The requested resource does not exist or has been deleted | Verify the resource ID and ensure it exists |
Validation Error: the request does not match the operation schema, or its JSON body cannot be parsed. message names each failing check, and data, when present, lists them one entry per failing field.
{ "statusCode": 422, "error": "Validation Error", "message": "Validation failed: /name must NOT have fewer than 3 characters"}{ "statusCode": 429, "error": "Too Many Requests", "message": "Rate limit exceeded"}| Error Code | Title | Description | Resolution |
|---|---|---|---|
RATE_LIMIT_EXCEEDED | Rate limit exceeded | You have exceeded the rate limit for this endpoint | Wait before making additional requests, or upgrade your plan for higher limits |
{ "statusCode": 500, "error": "Internal Server Error", "message": "An unexpected error occurred"}| Error Code | Title | Description | Resolution |
|---|---|---|---|
INTERNAL_SERVER_ERROR | Internal server error | An unexpected error occurred on the server | Try again later, or contact support if the problem persists |
{ "statusCode": 502, "message": "Partial proxy usage response", "data": { "from": "2025-01", "to": "2025-03", "excludes_deleted_containers": true, "retrieval_complete": false, "coverage_complete": false, "months_capped": false, "totals": { "requests": 843712, "response_bytes": 5210123456, "exact": true }, "retention": { "enforced": false, "retained_from": "2025-01" }, "sources": [ { "status": "partial", "reader_stale": true } ], "containers": {} }}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' });curl -X GET "https://api.hoody.com/api/v1/projects/507f1f77bcf86cd799439011/proxy-usage?from=2025-01&to=2025-03" \ -H "Authorization: Bearer <token>"GET /api/v1/containers/{id}/proxy-usage
Section titled “GET /api/v1/containers/{id}/proxy-usage”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.
Parameters
Section titled “Parameters”| Name | In | Type | Required | Description |
|---|---|---|---|---|
from | query | string | Yes | First month, inclusive (YYYY-MM). |
to | query | string | Yes | Last month, inclusive (YYYY-MM). Max 12 months. |
id | path | string | Yes | Container ID. |
Response
Section titled “Response”{ "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": [] } } } } }}{ "statusCode": 400, "error": "Bad Request", "message": "Invalid ID format"}| Error Code | Title | Description | Resolution |
|---|---|---|---|
INVALID_ID_FORMAT | Invalid ID format | The provided ID must be a 24-character hexadecimal string | Ensure the ID is exactly 24 characters long and contains only hexadecimal characters (0-9, a-f) |
INVALID_PARAMETER_VALUE | Invalid parameter value | A parameter value is outside the allowed range or format | Ensure parameter values meet the documented constraints (min/max, format, regex) |
{ "statusCode": 401, "error": "Unauthorized", "message": "Authentication token required"}| Error Code | Title | Description | Resolution |
|---|---|---|---|
MISSING_TOKEN | Authentication token missing | No authentication token was provided in the request | Include a valid JWT token in the Authorization header as Bearer <token> |
INVALID_TOKEN | Invalid authentication token | The provided authentication token is malformed or invalid | Obtain a new token by logging in again or using a valid auth token |
TOKEN_EXPIRED | Authentication token expired | The provided authentication token has expired | Obtain a new token by logging in again or refreshing your session |
AUTH_TOKEN_LINEAGE_REVOKED | Parent auth token no longer valid | The auth token was created by another auth token, and that token (or one above it) has been revoked, disabled or has expired, so this one no longer authenticates | Create a new auth token from a valid one, or sign in again |
EMAIL_NOT_VERIFIED | Email not verified | Returned by the login endpoint when the password is correct but the account’s email address has not been verified yet. It is only returned after the password has been checked. The response carries data.email so the client can offer a ‘resend verification email’ action without asking again. | Complete email verification by clicking the link sent to your inbox, or call /auth/resend-verification to receive a new link, or complete a password reset which also implicitly verifies the email. |
INVALID_OTP_CODE | Invalid OTP code | The provided 2FA code is incorrect or has expired | Generate a new code from your authenticator app and try again |
{ "statusCode": 403, "error": "Forbidden", "message": "Insufficient permissions"}| Error Code | Title | Description | Resolution |
|---|---|---|---|
INSUFFICIENT_PERMISSIONS | Insufficient permissions | You do not have the required permissions to perform this action | Contact the resource owner or administrator to request access |
RESOURCE_ACCESS_DENIED | Resource access denied | You do not have permission to access this specific resource | Ensure you own this resource or have been granted access by the owner |
{ "statusCode": 404, "error": "Not Found", "message": "Resource not found"}| Error Code | Title | Description | Resolution |
|---|---|---|---|
RESOURCE_NOT_FOUND | Resource not found | The requested resource does not exist or has been deleted | Verify the resource ID and ensure it exists |
Validation Error: the request does not match the operation schema, or its JSON body cannot be parsed. message names each failing check, and data, when present, lists them one entry per failing field.
{ "statusCode": 422, "error": "Validation Error", "message": "Validation failed: /name must NOT have fewer than 3 characters"}{ "statusCode": 429, "error": "Too Many Requests", "message": "Rate limit exceeded"}| Error Code | Title | Description | Resolution |
|---|---|---|---|
RATE_LIMIT_EXCEEDED | Rate limit exceeded | You have exceeded the rate limit for this endpoint | Wait before making additional requests, or upgrade your plan for higher limits |
{ "statusCode": 500, "error": "Internal Server Error", "message": "An unexpected error occurred"}| Error Code | Title | Description | Resolution |
|---|---|---|---|
INTERNAL_SERVER_ERROR | Internal server error | An unexpected error occurred on the server | Try again later, or contact support if the problem persists |
{ "statusCode": 502, "message": "Partial proxy usage response", "data": { "from": "2025-01", "to": "2025-01", "excludes_deleted_containers": true, "retrieval_complete": false, "coverage_complete": false, "months_capped": false, "totals": { "requests": 12345, "response_bytes": 7890123, "exact": true }, "retention": { "enforced": false, "retained_from": "2025-01" }, "sources": [ { "status": "partial", "reader_stale": true } ], "containers": {} }}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' });curl -X GET "https://api.hoody.com/api/v1/containers/507f1f77bcf86cd799439077/proxy-usage?from=2025-01&to=2025-01" \ -H "Authorization: Bearer <token>"Server rental runtime
Section titled “Server rental runtime”GET /api/v1/rentals/{id}/runtime
Section titled “GET /api/v1/rentals/{id}/runtime”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.
Parameters
Section titled “Parameters”| Name | In | Type | Required | Description |
|---|---|---|---|---|
id | path | string | Yes | Rental ID (server or subserver). |
Response
Section titled “Response”{ "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 } }}{ "statusCode": 400, "error": "Bad Request", "message": "Invalid ID format"}| Error Code | Title | Description | Resolution |
|---|---|---|---|
INVALID_ID_FORMAT | Invalid ID format | The provided ID must be a 24-character hexadecimal string | Ensure the ID is exactly 24 characters long and contains only hexadecimal characters (0-9, a-f) |
{ "statusCode": 401, "error": "Unauthorized", "message": "Authentication token required"}| Error Code | Title | Description | Resolution |
|---|---|---|---|
MISSING_TOKEN | Authentication token missing | No authentication token was provided in the request | Include a valid JWT token in the Authorization header as Bearer <token> |
INVALID_TOKEN | Invalid authentication token | The provided authentication token is malformed or invalid | Obtain a new token by logging in again or using a valid auth token |
AUTH_TOKEN_LINEAGE_REVOKED | Parent auth token no longer valid | The auth token was created by another auth token, and that token (or one above it) has been revoked, disabled or has expired, so this one no longer authenticates | Create a new auth token from a valid one, or sign in again |
EMAIL_NOT_VERIFIED | Email not verified | Returned by the login endpoint when the password is correct but the account’s email address has not been verified yet. It is only returned after the password has been checked. The response carries data.email so the client can offer a ‘resend verification email’ action without asking again. | Complete email verification by clicking the link sent to your inbox, or call /auth/resend-verification to receive a new link, or complete a password reset which also implicitly verifies the email. |
INVALID_OTP_CODE | Invalid OTP code | The provided 2FA code is incorrect or has expired | Generate a new code from your authenticator app and try again |
{ "statusCode": 403, "error": "Forbidden", "message": "Insufficient permissions"}| Error Code | Title | Description | Resolution |
|---|---|---|---|
INSUFFICIENT_PERMISSIONS | Insufficient permissions | You do not have the required permissions to perform this action | Contact the resource owner or administrator to request access |
{ "statusCode": 404, "error": "Not Found", "message": "Resource not found"}| Error Code | Title | Description | Resolution |
|---|---|---|---|
RESOURCE_NOT_FOUND | Resource not found | The requested resource does not exist or has been deleted | Verify the resource ID and ensure it exists |
{ "statusCode": 409, "error": "Conflict", "message": "Host runtime not available for a shared server"}| Error Code | Title | Description | Resolution |
|---|---|---|---|
RUNTIME_HOST_SHARED | Host runtime not available for a shared server | Host-level runtime info is not exposed for a physical server that hosts subservers or is a system server, because it would reveal co-tenant activity | Query runtime for the specific subserver you rent instead of the whole physical host |
Validation Error: the request does not match the operation schema, or its JSON body cannot be parsed. message names each failing check, and data, when present, lists them one entry per failing field.
{ "statusCode": 422, "error": "Validation Error", "message": "Validation failed: /name must NOT have fewer than 3 characters"}{ "statusCode": 429, "error": "Too Many Requests", "message": "Rate limit exceeded"}| Error Code | Title | Description | Resolution |
|---|---|---|---|
RATE_LIMIT_EXCEEDED | Rate limit exceeded | You have exceeded the rate limit for this endpoint | Wait before making additional requests, or upgrade your plan for higher limits |
{ "statusCode": 503, "error": "Service Unavailable", "message": "Runtime info temporarily unavailable"}| Error Code | Title | Description | Resolution |
|---|---|---|---|
RUNTIME_UNAVAILABLE | Runtime info temporarily unavailable | Live runtime info could not be collected for this server and no recent snapshot is available | Retry shortly. If it persists, the host may be unreachable or under maintenance |
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');curl -X GET "https://api.hoody.com/api/v1/rentals/507f1f77bcf86cd799439099/runtime" \ -H "Authorization: Bearer <token>"GET /api/v1/servers/{id}/runtime
Section titled “GET /api/v1/servers/{id}/runtime”Returns the same payload as GET /rentals/{id}/runtime. Accepts the same parameters and emits the same error codes.
Parameters
Section titled “Parameters”| Name | In | Type | Required | Description |
|---|---|---|---|---|
id | path | string | Yes | Server or subserver ID. |
Response
Section titled “Response”{ "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 } }}{ "statusCode": 400, "error": "Bad Request", "message": "Invalid ID format"}| Error Code | Title | Description | Resolution |
|---|---|---|---|
INVALID_ID_FORMAT | Invalid ID format | The provided ID must be a 24-character hexadecimal string | Ensure the ID is exactly 24 characters long and contains only hexadecimal characters (0-9, a-f) |
{ "statusCode": 401, "error": "Unauthorized", "message": "Authentication token required"}| Error Code | Title | Description | Resolution |
|---|---|---|---|
MISSING_TOKEN | Authentication token missing | No authentication token was provided in the request | Include a valid JWT token in the Authorization header as Bearer <token> |
INVALID_TOKEN | Invalid authentication token | The provided authentication token is malformed or invalid | Obtain a new token by logging in again or using a valid auth token |
TOKEN_EXPIRED | Authentication token expired | The provided authentication token has expired | Obtain a new token by logging in again or refreshing your session |
AUTH_TOKEN_LINEAGE_REVOKED | Parent auth token no longer valid | The auth token was created by another auth token, and that token (or one above it) has been revoked, disabled or has expired, so this one no longer authenticates | Create a new auth token from a valid one, or sign in again |
EMAIL_NOT_VERIFIED | Email not verified | Returned by the login endpoint when the password is correct but the account’s email address has not been verified yet. It is only returned after the password has been checked. The response carries data.email so the client can offer a ‘resend verification email’ action without asking again. | Complete email verification by clicking the link sent to your inbox, or call /auth/resend-verification to receive a new link, or complete a password reset which also implicitly verifies the email. |
INVALID_OTP_CODE | Invalid OTP code | The provided 2FA code is incorrect or has expired | Generate a new code from your authenticator app and try again |
{ "statusCode": 403, "error": "Forbidden", "message": "Insufficient permissions"}| Error Code | Title | Description | Resolution |
|---|---|---|---|
INSUFFICIENT_PERMISSIONS | Insufficient permissions | You do not have the required permissions to perform this action | Contact the resource owner or administrator to request access |
{ "statusCode": 404, "error": "Not Found", "message": "Resource not found"}| Error Code | Title | Description | Resolution |
|---|---|---|---|
RESOURCE_NOT_FOUND | Resource not found | The requested resource does not exist or has been deleted | Verify the resource ID and ensure it exists |
{ "statusCode": 409, "error": "Conflict", "message": "Host runtime not available for a shared server"}| Error Code | Title | Description | Resolution |
|---|---|---|---|
RUNTIME_HOST_SHARED | Host runtime not available for a shared server | Host-level runtime info is not exposed for a physical server that hosts subservers or is a system server, because it would reveal co-tenant activity | Query runtime for the specific subserver you rent instead of the whole physical host |
Validation Error: the request does not match the operation schema, or its JSON body cannot be parsed. message names each failing check, and data, when present, lists them one entry per failing field.
{ "statusCode": 422, "error": "Validation Error", "message": "Validation failed: /name must NOT have fewer than 3 characters"}{ "statusCode": 429, "error": "Too Many Requests", "message": "Rate limit exceeded"}| Error Code | Title | Description | Resolution |
|---|---|---|---|
RATE_LIMIT_EXCEEDED | Rate limit exceeded | You have exceeded the rate limit for this endpoint | Wait before making additional requests, or upgrade your plan for higher limits |
{ "statusCode": 503, "error": "Service Unavailable", "message": "Runtime info temporarily unavailable"}| Error Code | Title | Description | Resolution |
|---|---|---|---|
RUNTIME_UNAVAILABLE | Runtime info temporarily unavailable | Live runtime info could not be collected for this server and no recent snapshot is available | Retry shortly. If it persists, the host may be unreachable or under maintenance |
curl -X GET "https://api.hoody.com/api/v1/servers/507f1f77bcf86cd799439099/runtime" \ -H "Authorization: Bearer <token>"