Skip to content

Actions

Operations that run on a server, such as a reboot or a reinstall, take a while. Starting one answers 202 Accepted at once with an action, and you poll the action until it has finished.

curl -X POST "https://console.hosthatch.com/api/v1/projects/acme/servers/774736/actions/reboot/" \
  -H "Authorization: Bearer $HOSTHATCH_API_KEY" \
  -H "Idempotency-Key: 5f0c2e8a-6b1d-4c9e-9a57-3e2d1f0b7c44"

Endpoints

Endpoint What it does
GET /projects/{slug}/actions/ List actions
GET /projects/{slug}/actions/{id}/ Get an action
GET /projects/{slug}/servers/{id}/actions/ List a server's actions
POST /projects/{slug}/servers/{id}/actions/power-on/ Power on
POST /projects/{slug}/servers/{id}/actions/shutdown/ Shut down
POST /projects/{slug}/servers/{id}/actions/power-off/ Power off
POST /projects/{slug}/servers/{id}/actions/reboot/ Reboot
POST /projects/{slug}/servers/{id}/actions/reinstall/ Reinstall
POST /projects/{slug}/servers/{id}/actions/reset-password/ Reset the root password
POST /projects/{slug}/servers/{id}/actions/enable-ipv6/ Enable IPv6
POST /projects/{slug}/servers/{id}/actions/enable-private-network/ Enable the private network
POST /projects/{slug}/servers/{id}/actions/create-snapshot/ Take a snapshot
POST /projects/{slug}/servers/{id}/actions/restore-snapshot/ Restore a snapshot
POST /projects/{slug}/servers/{id}/actions/mount-iso/ Mount an ISO
POST /projects/{slug}/servers/{id}/actions/unmount-iso/ Unmount an ISO

How an action runs

  1. You start it with a POST to one of the endpoints above. The answer is 202 with the action, whose status is running.
  2. You poll it with Get an action until its status is success or error. Poll the action itself: lists show each action as it was last recorded, which can be a few minutes behind.
  3. On success, result holds what the action produced, if anything. On error, error says why.
Status Meaning
running Started, and not finished yet.
unknown The operation was sent to the server's host, but its answer was lost, so the outcome isn't confirmed yet. Keep polling: see One exclusive action at a time for how it settles.
success Done.
error It failed, or never happened. error.code and error.message say which.

Poll every few seconds at first, then less often: a reinstall can take several minutes. Every poll counts against the key's read budget. An action still running after 24 hours ends as error with the code timeout.

The action object

{
  "id": 9101,
  "type": "server.reboot",
  "status": "success",
  "resource": {"type": "server", "id": "774736"},
  "started_at": "2026-10-19T10:00:00Z",
  "finished_at": "2026-10-19T10:00:41Z",
  "error": null,
  "result": {}
}
Field Type Description
id integer The action's id.
type string What it does, such as server.reboot. See Types.
status string running, unknown, success or error.
resource object What it runs on: {"type": "server", "id": "774736"}.
started_at string When it was started.
finished_at string or null When it finished, or null while it runs.
error object or null On error: code and message, see Error codes. Otherwise null.
result object What the action produced, see Results. Empty for most types.

Types

Type Started by Exclusive
server.power_on Power on
server.shutdown Shut down
server.power_off Power off
server.reboot Reboot
server.reinstall Reinstall
server.reset_password Reset the root password
server.enable_ipv6 Enable IPv6
server.enable_private_network Enable the private network
server.create_snapshot Take a snapshot
server.restore_snapshot Restore a snapshot
server.mount_iso Mount an ISO
server.unmount_iso Unmount an ISO

Results

Type result
server.enable_ipv6 {"subnet": "2001:db8:2:f342::/64"}, the subnet routed to the server, as soon as it is assigned.
server.reset_password {"password": "..."}, the new root password, for 15 minutes. See Reset the root password.
server.create_snapshot {"snapshot_id": 2960}, the new snapshot, when it can be told.
Every other type {}

Error codes

error.code Meaning
failed The operation failed. Try again, and contact support if it keeps failing.
outcome_unknown Its outcome could never be confirmed. Check the server, and contact support if it is not as you expect.
task_result_unavailable Its result is no longer available. Check the server.
timeout It didn't finish within 24 hours.
resource_moved The server left the project before the result could be collected.

One exclusive action at a time

Power, reboot, reinstall, snapshot and ISO actions are exclusive: a server runs one of them at a time. Starting a second while one runs answers 409 action_in_progress, with the running action's id in action_id. Poll that action, and start yours once it has finished.

{
  "type": "https://docs.hosthatch.com/api/errors#action_in_progress",
  "title": "Action in progress",
  "status": 409,
  "detail": "Another action is still running on this server.",
  "code": "action_in_progress",
  "instance": "/api/v1/projects/acme/servers/774736/actions/reinstall/",
  "action_id": 9101
}

Resetting the password and enabling IPv6 or the private network can run next to anything.

Actions started in the console count too: an action from the console and one from the API never overlap on a server.

An exclusive action that is unknown keeps blocking its server until its outcome is settled, so that a second operation can never overlap one that may still be running. Power on, shut down and power off settle from the server's state. The others settle from the host's own record of the operation, or, if that can't tell, by support: support is told after 30 minutes, or 4 hours for a snapshot, and settles the action after checking the server. Contact support with the action's id if it holds up your work. A non-exclusive action that stays unknown for 30 minutes ends as error, with the code outcome_unknown.

Idempotency

Send an Idempotency-Key header with every request that starts an action. If you lose the answer and send the same request again with the same key, you get the original action back instead of starting a second one.

  • The key is 1 to 64 characters. Use a new random value, such as a UUID, for each operation.
  • Repeating the request with the same key and body answers 200 with the original action, whatever state it has reached, and an Idempotent-Replayed: true header. That works even while the systems behind the API are down.
  • The same key with another method, path or body answers 409 idempotency_key_reused, so a key spent on a power-on can never start a reinstall.
  • Keys are per project, and stay bound to their action for as long as it exists.

Without a key, a repeated request starts a new action, or answers 409 action_in_progress while the first is still running.

A 502 upstream_error with an action_id means the action was recorded, but its outcome isn't confirmed yet. Poll that action rather than starting another.

Listing actions

List actions

GET /projects/{slug}/actions/

Any member · Read-only keys: yes · Returns 200 Action[]

The project's actions, newest first. Filter them with query parameters:

Parameter Description
resource_type server.
resource_id A server id.
status running, unknown, success or error.
type An action type, such as server.reinstall.
curl "https://console.hosthatch.com/api/v1/projects/acme/actions/?status=running" \
  -H "Authorization: Bearer $HOSTHATCH_API_KEY"

An unknown filter value answers 400 validation_error.

Get an action

GET /projects/{slug}/actions/{id}/

Any member · Read-only keys: yes · Returns 200 Action

One action, checked for its latest state before the answer. This is the endpoint to poll.

List a server's actions

GET /projects/{slug}/servers/{id}/actions/

Any member · Read-only keys: yes · Returns 200 Action[]

The actions run on one server, newest first.

Power

The power endpoints take no request body.

Power on

POST /projects/{slug}/servers/{id}/actions/power-on/

Any member · Read-only keys: no · Returns 202 Action

Start the server.

Shut down

POST /projects/{slug}/servers/{id}/actions/shutdown/

Any member · Read-only keys: no · Returns 202 Action

Ask the operating system to shut down, as pressing the power button would. The operating system may ignore it: power off if the server doesn't stop.

Power off

POST /projects/{slug}/servers/{id}/actions/power-off/

Any member · Read-only keys: no · Returns 202 Action

Cut the power at once, as pulling the plug would. Anything the server hasn't saved is lost.

Reboot

POST /projects/{slug}/servers/{id}/actions/reboot/

Any member · Read-only keys: no · Returns 202 Action

Restart the server. A server with pending_changes gets them applied by this reboot.

Operating system

Reinstall

POST /projects/{slug}/servers/{id}/actions/reinstall/

Any member · Read-only keys: no · Returns 202 Action

Erase the server's disk and install an image on it.

Warning

Everything on the server's disk is lost, and can't be recovered.

curl -X POST "https://console.hosthatch.com/api/v1/projects/acme/servers/774736/actions/reinstall/" \
  -H "Authorization: Bearer $HOSTHATCH_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: 0d7a1f7e-1f52-4cf7-b7a4-0f8e5d6c3b21" \
  -d '{"image": "ubuntu24", "ssh_keys": [3731]}'
Field Type Description
image string Required. The image to install, by name, such as almalinux10. A server's image.name is one, and List images lists them all.
ssh_keys array of integers Ids of the project's SSH keys to install, up to 100. Leave it out to keep the server's keys; [] removes them.
user_data string Not available yet: sending it answers 400 feature_unavailable. Cloud-init user data, up to 65536 characters, starting with #cloud-config or #!.

An image that doesn't exist or is disabled, and a key that isn't the project's, answer 400 validation_error on that field.

Reset the root password

POST /projects/{slug}/servers/{id}/actions/reset-password/

Any member · Read-only keys: no · Returns 202 Action

Set a new random root password on the running server, through its guest agent. The request takes no body.

Once the action has succeeded, reading the action shows the new password in result.password:

{
  "id": 9102,
  "type": "server.reset_password",
  "status": "success",
  "resource": {"type": "server", "id": "774736"},
  "started_at": "2026-10-19T10:05:00Z",
  "finished_at": "2026-10-19T10:05:09Z",
  "error": null,
  "result": {"password": "kN4v-..."}
}

The password is shown:

  • for 15 minutes after the action succeeded, and then erased;
  • only when you read this one action, never in lists or in the answer to a repeated request;
  • never to a read-only key;
  • only while it is still the server's root password, and the server is still in the project.

Network

Enable IPv6

POST /projects/{slug}/servers/{id}/actions/enable-ipv6/

Any member · Read-only keys: no · Returns 202 Action

Route an IPv6 /64 subnet to the server. The request takes no body. result.subnet holds the subnet as soon as it is assigned, as the server's network.ipv6 lists it, and the action succeeds once the network is set up for it. Then configure an address from the subnet inside the server: see IPv6 configuration.

A server that already has IPv6 answers 409 already_enabled, and 409 insufficient_capacity means no subnet is free for its location right now.

Enable the private network

POST /projects/{slug}/servers/{id}/actions/enable-private-network/

Any member · Read-only keys: no · Returns 202 Action

Attach the server to the private network shared by your servers in its location. The request takes no body. The action succeeds at once, but the server gets its private interface at its next start or reboot through this API. Then configure the interface's address inside the server: see Private networking.

A server that can't join answers 409 not_eligible, and one that already has it 409 already_enabled.

Errors

Every endpoint that starts an action can answer these:

Status Code When
400 validation_error A field, or the Idempotency-Key, is invalid.
400 feature_unavailable user_data on a reinstall.
403 read_only_key Starting an action 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 action in the project.
409 action_in_progress Another exclusive action is running on the server.
409 conflict The server's host refused the operation in the server's current state.
409 idempotency_key_reused The key was used for another request.
409 already_enabled, not_eligible, insufficient_capacity See Network.
502 upstream_error The host failed, or its answer was lost: with an action_id, poll that action.
503 node_maintenance The server's host is in maintenance. Retry-After is 300 seconds.

A start that the server's host refuses is still recorded: the action list shows it as error, with the code failed.