Container Firewall
Section titled “Container Firewall”Manage ingress and egress firewall rules for containers. Use these endpoints to list the active rule set, add or remove rules, toggle rule state without deleting, or fully reset the firewall back to an open state. Each container is bounded by a maximum rule count and a maximum serialized rule size, both returned by the list endpoint.
List firewall rules
Section titled “List firewall rules”GET /api/v1/containers/{id}/firewall/rules
Section titled “GET /api/v1/containers/{id}/firewall/rules”Retrieve the full ingress and egress rule set for a container, plus advisory counters and limits.
Parameters
Section titled “Parameters”| Name | In | Type | Required | Description |
|---|---|---|---|---|
id | path | string | Yes | Container ID |
curl -X GET "https://api.hoody.com/api/v1/containers/67e89abc123def456789abcd-890abcdef12345678901cdef/firewall/rules" \ -H "Authorization: Bearer <token>"import { HoodyClient } from 'hoody-sdk';
const client = new HoodyClient({ baseURL: 'https://api.hoody.com', token: process.env.HOODY_TOKEN });
const { data } = await client.api.firewall.listRules("c_abc123def456");console.log(data.ingress);console.log(data.egress);{ "statusCode": 200, "message": "Firewall rules retrieved successfully", "data": { "ingress": [ { "action": "allow", "protocol": "tcp", "description": "Allow HTTPS traffic", "destination_port": "443", "source": "0.0.0.0/0", "state": "enabled", "direction": "ingress" }, { "action": "allow", "protocol": "icmp4", "description": "Allow ping from any source", "source": "0.0.0.0/0", "state": "enabled", "icmp_type": "8", "icmp_code": "0", "direction": "ingress" } ], "egress": [ { "action": "allow", "protocol": "tcp", "description": "Allow outbound HTTPS", "destination_port": "443", "destination": "0.0.0.0/0", "state": "enabled", "direction": "egress" }, { "action": "drop", "protocol": "tcp", "description": "Block outbound SMTP", "destination_port": "25", "destination": "0.0.0.0/0", "state": "enabled", "direction": "egress" } ], "rule_count": 4, "byte_count": 512, "max_rules": 500, "max_bytes": 262144 }}Response statuses
Section titled “Response statuses”{ "statusCode": 200, "message": "Firewall rules retrieved successfully", "data": { "ingress": [], "egress": [], "rule_count": 0, "byte_count": 0, "max_rules": 500, "max_bytes": 262144 }}{ "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 |
{ "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": "Container not found"}| Error Code | Title | Description | Resolution |
|---|---|---|---|
CONTAINER_NOT_FOUND | Container not found | The requested container does not exist or you do not have permission to access it. | Verify the container ID is correct and that you have access to the project it belongs to. |
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"}| Error Code | Title | Description | Resolution |
|---|---|---|---|
FIREWALL_HOST_UNAVAILABLE | Firewall temporarily unavailable | The container’s firewall could not be reached for a moment, for example because its server is busy. Nothing was changed. | Retry after the number of seconds in the Retry-After header. |
Add firewall rules
Section titled “Add firewall rules”POST /api/v1/containers/{id}/firewall/ingress
Section titled “POST /api/v1/containers/{id}/firewall/ingress”Add a new ingress (inbound) firewall rule. Controls which traffic can reach the container.
Parameters
Section titled “Parameters”| Name | In | Type | Required | Description |
|---|---|---|---|---|
id | path | string | Yes | Container ID |
Request Body
Section titled “Request Body”| Field | Type | Required | Description |
|---|---|---|---|
action | string | Yes | Action to take: allow (permit), reject (deny with response), drop (deny silently) |
protocol | string | Yes | Network protocol: tcp, udp, or icmp4 |
description | string | Yes | Human-readable rule description (max 255 characters) |
destination_port | string | No | Port number, range (80-90), or comma-separated list (80,443). Required for TCP/UDP. |
source | string | No | Source IPv4 address or CIDR range. Use 0.0.0.0/0 for any source. |
source_port | string | No | Source port filter (rarely used) |
state | string | No | Rule state: enabled or disabled (defaults to enabled) |
icmp_type | string | No | ICMP type number (e.g., 8 for echo request/ping) |
icmp_code | string | No | ICMP code number |
curl -X POST "https://api.hoody.com/api/v1/containers/67e89abc123def456789abcd-890abcdef12345678901cdef/firewall/ingress" \ -H "Authorization: Bearer <token>" \ -H "Content-Type: application/json" \ -d '{ "action": "allow", "protocol": "tcp", "description": "Allow SSH from office", "destination_port": "22", "source": "203.0.113.5/32" }'import { HoodyClient } from 'hoody-sdk';
const client = new HoodyClient({ baseURL: 'https://api.hoody.com', token: process.env.HOODY_TOKEN });
await client.api.firewall.createIngressRule("c_abc123def456", { action: "allow", protocol: "tcp", description: "Allow SSH from office", destination_port: "22", source: "203.0.113.5/32"});{ "statusCode": 201, "message": "Ingress rule added successfully", "data": {}}Response statuses
Section titled “Response statuses”Rule already exists. No changes made.
{ "statusCode": 200, "message": "Rule already exists", "data": {}}{ "statusCode": 201, "message": "Ingress rule added successfully", "data": {}}{ "statusCode": 400, "error": "CONTAINER_FIREWALL_RULE_LIMIT", "message": "This container has reached its firewall rule limit.", "data": { "field": "container_firewall_rule_limit", "container_id": "507f1f77bcf86cd799439011", "server_id": "507f1f77bcf86cd799439022", "current_count": 500, "limit": 500 }}| Error Code | Title | Description | Resolution |
|---|---|---|---|
CONTAINER_FIREWALL_RULE_LIMIT | Container firewall rule limit reached | The container already holds the maximum number of firewall rules allowed (ingress and egress counted together). The applicable limit is returned as max_rules when listing firewall rules. | Remove an existing firewall rule on this container before adding a new one. |
CONTAINER_FIREWALL_BYTES_LIMIT | Container firewall rule size limit reached | The container’s firewall rules have reached their total serialized size budget. This can be hit below the rule-count limit when individual rules are large (long descriptions or address lists). The applicable limit is returned as max_bytes when listing firewall rules. | Remove rules, or shorten descriptions and address lists, before adding a new rule. |
INVALID_RULE_DEFINITION | Invalid Firewall Rule | The firewall rule definition is invalid: a field required by the protocol is missing (destination_port for TCP/UDP), a field is not allowed with the protocol (ports with icmp4, icmp_type with tcp/udp), or a value is malformed (a port outside 1-65535, a range whose first port is not lower, an address that is not IPv4 or IPv4 CIDR). data.field names the field. The rule was not added or changed. | Correct the field named in data.field. Ports are 1-65535, ranges are written low-high, addresses are comma-separated IPv4 addresses or CIDR ranges. |
{ "statusCode": 404, "error": "Not Found", "message": "Container 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"}{ "statusCode": 503, "error": "FIREWALL_INVENTORY_UNAVAILABLE", "message": "Unable to verify this container's firewall rules. No changes were made.", "data": { "field": "firewall_inventory", "container_id": "507f1f77bcf86cd799439011" }}| Error Code | Title | Description | Resolution |
|---|---|---|---|
FIREWALL_INVENTORY_UNAVAILABLE | Firewall inventory unavailable | The container’s live firewall rule list could not be established (host unreachable, or a malformed response), so the rule limit could not be evaluated. The request fails closed: no rule was added. | Retry shortly. If it persists, the hosting server may be unreachable. |
FIREWALL_HOST_UNAVAILABLE | Firewall temporarily unavailable | The container’s firewall could not be reached for a moment, for example because its server is busy. Nothing was changed. | Retry after the number of seconds in the Retry-After header. |
POST /api/v1/containers/{id}/firewall/egress
Section titled “POST /api/v1/containers/{id}/firewall/egress”Add a new egress (outbound) firewall rule. Controls which traffic the container can send.
Parameters
Section titled “Parameters”| Name | In | Type | Required | Description |
|---|---|---|---|---|
id | path | string | Yes | Container ID |
Request Body
Section titled “Request Body”| Field | Type | Required | Description |
|---|---|---|---|
action | string | Yes | Action to take: allow (permit), reject (deny with response), drop (deny silently) |
protocol | string | Yes | Network protocol: tcp, udp, or icmp4 |
description | string | Yes | Human-readable rule description (max 255 characters) |
destination_port | string | No | Port number, range (80-90), or comma-separated list (80,443). Required for TCP/UDP. |
destination | string | No | Destination IPv4 address or CIDR range. Use 0.0.0.0/0 for any destination. |
source_port | string | No | Source port filter (rarely used) |
state | string | No | Rule state: enabled or disabled (defaults to enabled) |
icmp_type | string | No | ICMP type number |
icmp_code | string | No | ICMP code number |
curl -X POST "https://api.hoody.com/api/v1/containers/67e89abc123def456789abcd-890abcdef12345678901cdef/firewall/egress" \ -H "Authorization: Bearer <token>" \ -H "Content-Type: application/json" \ -d '{ "action": "allow", "protocol": "tcp", "description": "Allow outbound HTTPS", "destination_port": "443", "destination": "0.0.0.0/0" }'import { HoodyClient } from 'hoody-sdk';
const client = new HoodyClient({ baseURL: 'https://api.hoody.com', token: process.env.HOODY_TOKEN });
await client.api.firewall.createEgressRule("c_abc123def456", { action: "allow", protocol: "tcp", description: "Allow outbound HTTPS", destination_port: "443", destination: "0.0.0.0/0"});{ "statusCode": 201, "message": "Egress rule added successfully", "data": {}}Response statuses
Section titled “Response statuses”Rule already exists. No changes made.
{ "statusCode": 200, "message": "Rule already exists", "data": {}}{ "statusCode": 201, "message": "Egress rule added successfully", "data": {}}{ "statusCode": 400, "error": "CONTAINER_FIREWALL_RULE_LIMIT", "message": "This container has reached its firewall rule limit.", "data": { "field": "container_firewall_rule_limit", "container_id": "507f1f77bcf86cd799439011", "server_id": "507f1f77bcf86cd799439022", "current_count": 500, "limit": 500 }}| Error Code | Title | Description | Resolution |
|---|---|---|---|
CONTAINER_FIREWALL_RULE_LIMIT | Container firewall rule limit reached | The container already holds the maximum number of firewall rules allowed (ingress and egress counted together). The applicable limit is returned as max_rules when listing firewall rules. | Remove an existing firewall rule on this container before adding a new one. |
CONTAINER_FIREWALL_BYTES_LIMIT | Container firewall rule size limit reached | The container’s firewall rules have reached their total serialized size budget. This can be hit below the rule-count limit when individual rules are large (long descriptions or address lists). The applicable limit is returned as max_bytes when listing firewall rules. | Remove rules, or shorten descriptions and address lists, before adding a new rule. |
INVALID_RULE_DEFINITION | Invalid Firewall Rule | The firewall rule definition is invalid: a field required by the protocol is missing (destination_port for TCP/UDP), a field is not allowed with the protocol (ports with icmp4, icmp_type with tcp/udp), or a value is malformed (a port outside 1-65535, a range whose first port is not lower, an address that is not IPv4 or IPv4 CIDR). data.field names the field. The rule was not added or changed. | Correct the field named in data.field. Ports are 1-65535, ranges are written low-high, addresses are comma-separated IPv4 addresses or CIDR ranges. |
{ "statusCode": 404, "error": "Not Found", "message": "Container 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"}{ "statusCode": 503, "error": "FIREWALL_INVENTORY_UNAVAILABLE", "message": "Unable to verify this container's firewall rules. No changes were made.", "data": { "field": "firewall_inventory", "container_id": "507f1f77bcf86cd799439011" }}| Error Code | Title | Description | Resolution |
|---|---|---|---|
FIREWALL_INVENTORY_UNAVAILABLE | Firewall inventory unavailable | The container’s live firewall rule list could not be established (host unreachable, or a malformed response), so the rule limit could not be evaluated. The request fails closed: no rule was added. | Retry shortly. If it persists, the hosting server may be unreachable. |
FIREWALL_HOST_UNAVAILABLE | Firewall temporarily unavailable | The container’s firewall could not be reached for a moment, for example because its server is busy. Nothing was changed. | Retry after the number of seconds in the Retry-After header. |
Reset firewall
Section titled “Reset firewall”POST /api/v1/containers/{id}/firewall/reset
Section titled “POST /api/v1/containers/{id}/firewall/reset”Delete the ACL and detach the container from its firewall bridge, returning it to an open state. This is destructive: all ingress and egress rules are removed at once.
Parameters
Section titled “Parameters”| Name | In | Type | Required | Description |
|---|---|---|---|---|
id | path | string | Yes | Container ID |
curl -X POST "https://api.hoody.com/api/v1/containers/67e89abc123def456789abcd-890abcdef12345678901cdef/firewall/reset" \ -H "Authorization: Bearer <token>"import { HoodyClient } from 'hoody-sdk';
const client = new HoodyClient({ baseURL: 'https://api.hoody.com', token: process.env.HOODY_TOKEN });
await client.api.firewall.reset("c_abc123def456");{ "statusCode": 200, "message": "Firewall reset successfully", "data": { "rules": { "ingress": [], "egress": [] } }}Response statuses
Section titled “Response statuses”{ "statusCode": 200, "message": "Firewall reset successfully", "data": { "rules": { "ingress": [], "egress": [] } }}{ "statusCode": 404, "error": "Not Found", "message": "Container 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"}| Error Code | Title | Description | Resolution |
|---|---|---|---|
FIREWALL_HOST_UNAVAILABLE | Firewall temporarily unavailable | The container’s firewall could not be reached for a moment, for example because its server is busy. Nothing was changed. | Retry after the number of seconds in the Retry-After header. |
Toggle firewall rules
Section titled “Toggle firewall rules”PATCH /api/v1/containers/{id}/firewall/ingress
Section titled “PATCH /api/v1/containers/{id}/firewall/ingress”Enable or disable an ingress rule without deleting it. Provide the same fields used to create the rule so the matching one can be identified.
Parameters
Section titled “Parameters”| Name | In | Type | Required | Description |
|---|---|---|---|---|
id | path | string | Yes | Container ID |
Request Body
Section titled “Request Body”| Field | Type | Required | Description |
|---|---|---|---|
state | string | Yes | New state for the rule: enabled or disabled |
action | string | No | Action for matching traffic: allow, reject, or drop |
protocol | string | No | Protocol type: tcp, udp, or icmp4 |
destination_port | string | No | Destination port, range (80-90), or list (80,443) |
source_port | string | No | Source port, range, or list |
source | string | No | Source IPv4/CIDR address(es) |
description | string | No | Rule description |
icmp_type | string | No | ICMP type number for icmp4 protocol |
icmp_code | string | No | ICMP code number for icmp4 protocol |
The SDK has one method per state. Each sets state itself, so leave it out of the data object:
client.api.firewall.enableIngressRule(id, data)setsstatetoenabled.client.api.firewall.disableIngressRule(id, data)setsstatetodisabled.
curl -X PATCH "https://api.hoody.com/api/v1/containers/67e89abc123def456789abcd-890abcdef12345678901cdef/firewall/ingress" \ -H "Authorization: Bearer <token>" \ -H "Content-Type: application/json" \ -d '{ "state": "disabled", "protocol": "tcp", "destination_port": "443" }'import { HoodyClient } from 'hoody-sdk';
const client = new HoodyClient({ baseURL: 'https://api.hoody.com', token: process.env.HOODY_TOKEN });
await client.api.firewall.disableIngressRule("c_abc123def456", { protocol: "tcp", destination_port: "443"});{ "statusCode": 200, "message": "Ingress rule state toggled successfully", "data": { "direction": "ingress", "new_state": "disabled", "updated": { "action": "allow", "protocol": "tcp", "description": "Allow HTTPS traffic", "destination_port": "443", "source": "0.0.0.0/0", "state": "disabled" } }}Response statuses
Section titled “Response statuses”{ "statusCode": 200, "message": "Ingress rule state toggled successfully", "data": { "direction": "ingress", "new_state": "disabled", "updated": { "action": "allow", "protocol": "tcp", "description": "Allow HTTPS traffic", "destination_port": "443", "source": "0.0.0.0/0", "state": "disabled" } }}{ "statusCode": 404, "error": "Not Found", "message": "Container 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"}| Error Code | Title | Description | Resolution |
|---|---|---|---|
FIREWALL_HOST_UNAVAILABLE | Firewall temporarily unavailable | The container’s firewall could not be reached for a moment, for example because its server is busy. Nothing was changed. | Retry after the number of seconds in the Retry-After header. |
PATCH /api/v1/containers/{id}/firewall/egress
Section titled “PATCH /api/v1/containers/{id}/firewall/egress”Enable or disable an egress rule without deleting it. Provide the same fields used to create the rule so the matching one can be identified.
Parameters
Section titled “Parameters”| Name | In | Type | Required | Description |
|---|---|---|---|---|
id | path | string | Yes | Container ID |
Request Body
Section titled “Request Body”| Field | Type | Required | Description |
|---|---|---|---|
state | string | Yes | New state for the rule: enabled or disabled |
action | string | No | Action for matching traffic: allow, reject, or drop |
protocol | string | No | Protocol type: tcp, udp, or icmp4 |
destination_port | string | No | Destination port, range (80-90), or list (80,443) |
source_port | string | No | Source port, range, or list |
destination | string | No | Destination IPv4/CIDR address(es) |
description | string | No | Rule description |
icmp_type | string | No | ICMP type number for icmp4 protocol |
icmp_code | string | No | ICMP code number for icmp4 protocol |
The SDK has one method per state. Each sets state itself, so leave it out of the data object:
client.api.firewall.enableEgressRule(id, data)setsstatetoenabled.client.api.firewall.disableEgressRule(id, data)setsstatetodisabled.
curl -X PATCH "https://api.hoody.com/api/v1/containers/67e89abc123def456789abcd-890abcdef12345678901cdef/firewall/egress" \ -H "Authorization: Bearer <token>" \ -H "Content-Type: application/json" \ -d '{ "state": "enabled", "protocol": "tcp", "destination_port": "443" }'import { HoodyClient } from 'hoody-sdk';
const client = new HoodyClient({ baseURL: 'https://api.hoody.com', token: process.env.HOODY_TOKEN });
await client.api.firewall.enableEgressRule("c_abc123def456", { protocol: "tcp", destination_port: "443"});{ "statusCode": 200, "message": "Egress rule state toggled successfully", "data": { "direction": "egress", "new_state": "enabled", "updated": { "action": "allow", "protocol": "tcp", "description": "Allow outbound HTTPS", "destination_port": "443", "destination": "0.0.0.0/0", "state": "enabled" } }}Response statuses
Section titled “Response statuses”{ "statusCode": 200, "message": "Egress rule state toggled successfully", "data": { "direction": "egress", "new_state": "enabled", "updated": { "action": "allow", "protocol": "tcp", "description": "Allow outbound HTTPS", "destination_port": "443", "destination": "0.0.0.0/0", "state": "enabled" } }}{ "statusCode": 404, "error": "Not Found", "message": "Container 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"}| Error Code | Title | Description | Resolution |
|---|---|---|---|
FIREWALL_HOST_UNAVAILABLE | Firewall temporarily unavailable | The container’s firewall could not be reached for a moment, for example because its server is busy. Nothing was changed. | Retry after the number of seconds in the Retry-After header. |
Remove firewall rules
Section titled “Remove firewall rules”DELETE /api/v1/containers/{id}/firewall/ingress
Section titled “DELETE /api/v1/containers/{id}/firewall/ingress”Remove one or more ingress rules. Provide filters to match a specific rule, or set all: true to remove every ingress rule on the container. The firewall ACL remains attached. A body with no filter and no all: true is refused with 422 FIREWALL_FILTER_REQUIRED, and a body carrying a filter name this direction does not have (for example destination on ingress) is refused with 400 FIREWALL_UNKNOWN_FILTER. An omitted state matches rules in either state.
Parameters
Section titled “Parameters”| Name | In | Type | Required | Description |
|---|---|---|---|---|
id | path | string | Yes | Container ID |
Request Body
Section titled “Request Body”| Field | Type | Required | Description |
|---|---|---|---|
all | boolean | No | Remove all matching rules (default: first match only). Set to true with no other filters to remove all ingress rules. |
action | string | No | Action for matching traffic: allow, reject, or drop |
protocol | string | No | Protocol type: tcp, udp, or icmp4 |
destination_port | string | No | Destination port, range (80-90), or list (80,443) |
source | string | No | Source IPv4/CIDR address(es) |
source_port | string | No | Source port, range, or list |
description | string | No | Rule description |
state | string | No | Match only rules in this state: enabled or disabled. Omit to match rules in either state. |
icmp_type | string | No | ICMP type number for icmp4 protocol |
icmp_code | string | No | ICMP code number for icmp4 protocol |
curl -X DELETE "https://api.hoody.com/api/v1/containers/67e89abc123def456789abcd-890abcdef12345678901cdef/firewall/ingress" \ -H "Authorization: Bearer <token>" \ -H "Content-Type: application/json" \ -d '{ "protocol": "tcp", "destination_port": "22", "source": "192.168.1.0/24" }'import { HoodyClient } from 'hoody-sdk';
const client = new HoodyClient({ baseURL: 'https://api.hoody.com', token: process.env.HOODY_TOKEN });
await client.api.firewall.deleteIngressRule("c_abc123def456", { protocol: "tcp", destination_port: "22", source: "192.168.1.0/24"});{ "statusCode": 200, "message": "Ingress rule removed successfully", "data": { "direction": "ingress", "removed_count": 1, "removed": [ { "action": "allow", "protocol": "tcp", "description": "Allow SSH from office", "destination_port": "22", "source": "192.168.1.0/24", "state": "enabled" } ] }}Response statuses
Section titled “Response statuses”{ "statusCode": 200, "message": "Ingress rule removed successfully", "data": { "direction": "ingress", "removed_count": 1, "removed": [ { "action": "allow", "protocol": "tcp", "description": "Allow SSH from office", "destination_port": "22", "source": "192.168.1.0/24", "state": "enabled" } ] }}{ "statusCode": 400, "error": "FIREWALL_UNKNOWN_FILTER", "message": "Unrecognised firewall filter(s).", "data": { "unknown_filters": ["destination"] }}| Error Code | Title | Description | Resolution |
|---|---|---|---|
FIREWALL_UNKNOWN_FILTER | Unrecognised Firewall Filter | A remove request carried a filter this direction does not have: a misspelled name, or a field that belongs to the other direction (destination on ingress, source on egress). An unrecognised filter would be ignored, which combined with all: true would remove every rule in the direction. data.unknown_filters lists the names. Nothing was removed. | Correct or drop the names listed in data.unknown_filters and send the request again. |
INVALID_RULE_DEFINITION | Invalid Firewall Rule | The firewall rule definition is invalid: a field required by the protocol is missing (destination_port for TCP/UDP), a field is not allowed with the protocol (ports with icmp4, icmp_type with tcp/udp), or a value is malformed (a port outside 1-65535, a range whose first port is not lower, an address that is not IPv4 or IPv4 CIDR). data.field names the field. The rule was not added or changed. | Correct the field named in data.field. Ports are 1-65535, ranges are written low-high, addresses are comma-separated IPv4 addresses or CIDR ranges. |
{ "statusCode": 404, "error": "Not Found", "message": "Container not found"}| Error Code | Title | Description | Resolution |
|---|---|---|---|
FIREWALL_FILTER_REQUIRED | Firewall rule filter required | A remove request named no rule: it carried no filter with a value and did not set all: true. Nothing was removed. | Send at least one filter (for example protocol and destination_port), or all: true to remove every rule in the direction. |
| Error Code | Title | Description | Resolution |
|---|---|---|---|
FIREWALL_HOST_UNAVAILABLE | Firewall temporarily unavailable | The container’s firewall could not be reached for a moment, for example because its server is busy. Nothing was changed. | Retry after the number of seconds in the Retry-After header. |
DELETE /api/v1/containers/{id}/firewall/egress
Section titled “DELETE /api/v1/containers/{id}/firewall/egress”Remove one or more egress rules. Provide filters to match a specific rule, or set all: true to remove every egress rule on the container. The firewall ACL remains attached. A body with no filter and no all: true is refused with 422 FIREWALL_FILTER_REQUIRED, and a body carrying a filter name this direction does not have (for example source on egress) is refused with 400 FIREWALL_UNKNOWN_FILTER. An omitted state matches rules in either state.
Parameters
Section titled “Parameters”| Name | In | Type | Required | Description |
|---|---|---|---|---|
id | path | string | Yes | Container ID |
Request Body
Section titled “Request Body”| Field | Type | Required | Description |
|---|---|---|---|
all | boolean | No | Remove all matching rules (default: first match only). Set to true with no other filters to remove all egress rules. |
action | string | No | Action for matching traffic: allow, reject, or drop |
protocol | string | No | Protocol type: tcp, udp, or icmp4 |
destination_port | string | No | Destination port, range (80-90), or list (80,443) |
destination | string | No | Destination IPv4/CIDR address(es) |
source_port | string | No | Source port, range, or list |
description | string | No | Rule description |
state | string | No | Match only rules in this state: enabled or disabled. Omit to match rules in either state. |
icmp_type | string | No | ICMP type number for icmp4 protocol |
icmp_code | string | No | ICMP code number for icmp4 protocol |
curl -X DELETE "https://api.hoody.com/api/v1/containers/67e89abc123def456789abcd-890abcdef12345678901cdef/firewall/egress" \ -H "Authorization: Bearer <token>" \ -H "Content-Type: application/json" \ -d '{ "all": true }'import { HoodyClient } from 'hoody-sdk';
const client = new HoodyClient({ baseURL: 'https://api.hoody.com', token: process.env.HOODY_TOKEN });
await client.api.firewall.deleteEgressRule("c_abc123def456", { all: true});{ "statusCode": 200, "message": "Egress rules removed successfully", "data": { "direction": "egress", "removed_count": 2, "removed": [ { "action": "allow", "protocol": "tcp", "description": "Allow outbound HTTPS", "destination_port": "443", "destination": "0.0.0.0/0", "state": "enabled" }, { "action": "allow", "protocol": "tcp", "description": "Allow outbound DNS", "destination_port": "53", "destination": "8.8.8.8", "state": "enabled" } ] }}Response statuses
Section titled “Response statuses”{ "statusCode": 200, "message": "Egress rules removed successfully", "data": { "direction": "egress", "removed_count": 1, "removed": [ { "action": "drop", "protocol": "tcp", "description": "Block outbound SMTP", "destination_port": "25", "destination": "0.0.0.0/0", "state": "enabled" } ] }}{ "statusCode": 400, "error": "FIREWALL_UNKNOWN_FILTER", "message": "Unrecognised firewall filter(s).", "data": { "unknown_filters": ["source"] }}| Error Code | Title | Description | Resolution |
|---|---|---|---|
FIREWALL_UNKNOWN_FILTER | Unrecognised Firewall Filter | A remove request carried a filter this direction does not have: a misspelled name, or a field that belongs to the other direction (destination on ingress, source on egress). An unrecognised filter would be ignored, which combined with all: true would remove every rule in the direction. data.unknown_filters lists the names. Nothing was removed. | Correct or drop the names listed in data.unknown_filters and send the request again. |
INVALID_RULE_DEFINITION | Invalid Firewall Rule | The firewall rule definition is invalid: a field required by the protocol is missing (destination_port for TCP/UDP), a field is not allowed with the protocol (ports with icmp4, icmp_type with tcp/udp), or a value is malformed (a port outside 1-65535, a range whose first port is not lower, an address that is not IPv4 or IPv4 CIDR). data.field names the field. The rule was not added or changed. | Correct the field named in data.field. Ports are 1-65535, ranges are written low-high, addresses are comma-separated IPv4 addresses or CIDR ranges. |
{ "statusCode": 404, "error": "Not Found", "message": "Container not found"}| Error Code | Title | Description | Resolution |
|---|---|---|---|
FIREWALL_FILTER_REQUIRED | Firewall rule filter required | A remove request named no rule: it carried no filter with a value and did not set all: true. Nothing was removed. | Send at least one filter (for example protocol and destination_port), or all: true to remove every rule in the direction. |
| Error Code | Title | Description | Resolution |
|---|---|---|---|
FIREWALL_HOST_UNAVAILABLE | Firewall temporarily unavailable | The container’s firewall could not be reached for a moment, for example because its server is busy. Nothing was changed. | Retry after the number of seconds in the Retry-After header. |