Servers¶
A server is a virtual machine in one of your projects. Its id is a lowercase hexadecimal string, such as "774736". This page covers reading servers and changing their hostname, reverse DNS and cancellation.
Operations that run on the server, such as power, reinstall and snapshots, are actions. Ordering, upgrading and extra bandwidth are orders. Firewall groups are attached on the Firewalls page.
Endpoints¶
| Endpoint | What it does |
|---|---|
GET / |
List servers |
POST / |
Order a server |
GET / |
Get a server |
PATCH / |
Rename a server |
GET / |
List reverse DNS names |
PUT / |
Set a reverse DNS name |
DELETE / |
Clear a reverse DNS name |
GET / |
List upgrade options |
POST / |
Upgrade a server |
POST / |
Buy extra bandwidth |
POST / |
Cancel a server |
The server object¶
{
"id": "774736",
"hostname": "web-01",
"status": "running",
"pending_changes": false,
"location": {"code": "AMS", "city": "Amsterdam", "country_code": "NL"},
"image": {"name": "almalinux10", "display_name": "AlmaLinux 10"},
"plan": {"name": "Cloud VPS 2x4", "category": "Compute", "cpu_cores": 2, "ram_mb": 4096, "disk_gb": 80, "boot_disk_gb": 0},
"network": {
"ipv4": [
{"address": "203.0.113.10", "primary": true, "netmask": "255.255.255.0", "gateway": "203.0.113.1"},
{"address": "203.0.113.24", "primary": false, "netmask": "255.255.255.0", "gateway": null}
],
"ipv6": [{"subnet": "2001:db8:2:f342::/64"}],
"private_network": {"eligible": true, "enabled": false}
},
"bandwidth": {
"pooled": true,
"allocated_gb": 1000, "extra_gb": 0, "used_gb": 12,
"pool": {"allocated_gb": 5000, "extra_gb": 0, "used_gb": 301}
},
"firewall_groups": [12],
"ssh_keys": [3731],
"iso": null,
"has_user_data": false,
"billing": {
"service_id": 188060, "status": "Active", "billing_cycle": "monthly",
"next_due_date": "2026-11-13", "recurring_amount": "12.00", "currency": "USD",
"upgradeable_to": [41, 42]
},
"created_at": "2026-10-13T12:58:59Z"
}
| Field | Type | Description |
|---|---|---|
id |
string | The server's id, lowercase hexadecimal. |
hostname |
string or null | The server's name. |
status |
string | running, stopped or suspended. |
pending_changes |
boolean | The server has changes, such as a new plan, that its next reboot through the API applies. A reboot from inside the server doesn't apply them. |
location |
object | code, the location code that orders use, such as AMS; city; and country_code, ISO 3166-1 alpha-2 in capitals. Each is null when unknown. |
image |
object | The operating system: name, which reinstall takes, and display_name. Either can be null when unknown. |
plan |
object | name, category, cpu_cores, ram_mb, disk_gb and boot_disk_gb. Each can be null when unknown. |
network.ipv4 |
array | The server's IPv4 addresses, the primary one first. Each has address, primary, netmask, which can be null, and gateway, which only the primary address has. |
network.ipv6 |
array | The IPv6 subnets routed to the server, as {"subnet": "2001:db8::/64"}. Empty until you enable IPv6. |
network.private_network |
object or null | eligible: the server can join the private network; enabled: it has. Either can be null when unknown. |
bandwidth |
object or null | This month's traffic: allocated_gb, extra_gb bought on top, and used_gb, each an integer or null when unknown. pooled servers share an allowance with your other servers in the location, and pool has its totals, which can be null too; pool itself is null when the server is not pooled. |
firewall_groups |
array or null | The ids of the firewall groups attached to the server. null when they couldn't be read just now: never read null as "no firewall". |
ssh_keys |
array | The ids of the project's SSH keys set on the server. |
iso |
object or null | The mounted ISO, as {"id", "name"}, where name can be null; or null when none is mounted. |
has_user_data |
boolean | The server was installed with cloud-init user data. |
billing |
object or null | service_id; status as billing reports it, such as Active; billing_cycle, such as monthly or semiannually; next_due_date; recurring_amount and currency; and upgradeable_to, the product ids an upgrade can move it to. status, billing_cycle, next_due_date and recurring_amount can be null. The whole object is null when the server has no billing service, or billing couldn't be read just now. |
created_at |
string or null | When the server was created. |
When billing or the firewall can't be read, the server is still returned, with that field null.
In lists¶
Lists return a summary of each server. Get the server for the rest. hostname, ipv4_primary and plan.name can be null, and so can each of location's fields.
{
"id": "774736",
"hostname": "web-01",
"status": "running",
"ipv4_primary": "203.0.113.10",
"location": {"code": "AMS", "city": "Amsterdam", "country_code": "NL"},
"plan": {"name": "Cloud VPS 2x4"}
}
Reading and renaming¶
List servers¶
GET /
The project's servers, as summaries.
curl "https://console.hosthatch.com/api/v1/projects/acme/servers/" \
-H "Authorization: Bearer $HOSTHATCH_API_KEY"
Get a server¶
GET /
One server, with everything in the server object.
Rename a server¶
PATCH /
Change the server's hostname, the only property of a server that can change this way. The answer is the updated server.
curl -X PATCH "https://console.hosthatch.com/api/v1/projects/acme/servers/774736/" \
-H "Authorization: Bearer $HOSTHATCH_API_KEY" \
-H "Content-Type: application/json" \
-d '{"hostname": "web-01.example.com"}'
A hostname is 2 to 64 characters. It is one or more labels separated by dots, and each label has 1 to 63 letters, digits and hyphens, and starts and ends with a letter or a digit. A body without hostname changes nothing.
Reverse DNS¶
Reverse DNS maps an address back to a name, which mail servers and some other services check. Set a matching forward record (A or AAAA) for the name at your DNS provider too.
List reverse DNS names¶
GET /
The reverse DNS name of each of the server's IPv4 addresses. ptr is null where none is set.
{
"count": 2,
"next": null,
"previous": null,
"results": [
{"address": "203.0.113.10", "ptr": "web-01.example.com"},
{"address": "203.0.113.24", "ptr": null}
]
}
Set a reverse DNS name¶
PUT /
Set the name of one of the server's addresses: one of its IPv4 addresses, or any address inside one of its IPv6 subnets. Another address answers 404 not_found.
curl -X PUT "https://console.hosthatch.com/api/v1/projects/acme/servers/774736/reverse-dns/203.0.113.10/" \
-H "Authorization: Bearer $HOSTHATCH_API_KEY" \
-H "Content-Type: application/json" \
-d '{"ptr": "web-01.example.com"}'
{"address": "203.0.113.10", "ptr": "web-01.example.com"}
ptr is a domain name of up to 255 characters, in ASCII, without a dot at the end. Each label has letters, digits and hyphens, and doesn't start or end with a hyphen.
Clear a reverse DNS name¶
DELETE /
Remove the name of one of the server's addresses.
When the reverse DNS service is unavailable, these endpoints answer 503 reverse_dns_unavailable with Retry-After: 300.
Cancellation¶
Cancel a server¶
POST /
Ask for the server to be cancelled.
| Field | Type | Description |
|---|---|---|
when |
string | end_of_term: the server runs until the end of the period you paid for, then it is deleted. immediate: it is deleted now, with everything on it. |
reason |
string | Why, in up to 1000 characters. Required for end_of_term. |
curl -X POST "https://console.hosthatch.com/api/v1/projects/acme/servers/774736/cancel/" \
-H "Authorization: Bearer $HOSTHATCH_API_KEY" \
-H "Content-Type: application/json" \
-d '{"when": "end_of_term", "reason": "Moving to a bigger plan"}'
{"status": "cancellation_requested", "when": "end_of_term"}
A server keeps one cancellation request, so the request is safe to repeat as it is. Sending the same one again answers 200 and changes nothing, and it needs no Idempotency-Key. A request of the other kind answers 409 conflict. Once an immediate cancellation has been carried out, the server is gone and a repeat answers 404.
A 502 upstream_error means the request may not have been recorded: send the same request again.
Errors¶
| Status | Code | When |
|---|---|---|
| 400 | validation_error |
A field is invalid. |
| 403 | insufficient_role |
Cancelling needs the admin or owner role. |
| 403 | read_only_key |
A change with a read-only key. |
| 403 | billing_account_required |
The project's owner has no billing account. |
| 403 | project_not_ready |
The project is still being set up. |
| 404 | not_found |
No such server or address in the project. |
| 409 | conflict |
A cancellation of the other kind is requested, or the server's billing service can't be matched: contact support. |
| 502 | upstream_error |
A system behind the API failed. |
| 503 | upstream_unavailable |
A system behind the API is unavailable for now. |
| 503 | reverse_dns_unavailable |
The reverse DNS service is unavailable for now. |