RedSwitches API Private beta Reference
Menu

Power and actions guide

Reboot, power off and power on servers safely from scripts, and follow each action to the end. The endpoint details are on Actions and power.

Before you start

  • The key needs the power permission, and the server must be on the key's server list. "All servers" means the servers on the account when the list was saved; a newer server is not covered until the owner updates the list.
  • Every power request needs an Idempotency-Key.

The pattern: request, then follow

A power request only queues the action and answers at once with 202 and an action id. The action itself runs moments later. Follow it with GET /actions/{id}, waiting poll_after seconds before the first look.

act=$(curl -sS -X POST https://api.redswitches.com/v1/servers/srv_123/power \
  -H "Authorization: Bearer $REDSWITCHES_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{"action":"reboot"}' | jq -r .id)
sleep 10
until state=$(curl -sS "https://api.redswitches.com/v1/actions/$act" \
    -H "Authorization: Bearer $REDSWITCHES_API_KEY" | jq -r .state) \
  && [ "$state" != queued ] && [ "$state" != running ]; do
  sleep 5
done
echo "$act: $state"
const action = await rs.power.run("srv_123", { action: "reboot" });
const result = await rs.actions.wait(action.id);
if (result.state !== "done") console.error(result.state, result.reason);
action = client.power.run("srv_123", action="reboot")
result = client.actions.wait(action.id)
if result.state != "done":
    print(result.state, result.reason)
action, err := client.Power.Run(ctx, "srv_123", "reboot")
if err != nil {
	log.Fatal(err)
}
result, err := client.Actions.Wait(ctx, action.ID)
if err == nil && result.State != "done" {
	log.Println(result.State, *result.Reason)
}
{
  "id": "act_42",
  "kind": "power",
  "server_id": "srv_123",
  "action": "reboot",
  "state": "done",
  "reason": null,
  "created": "2026-11-15T09:30:00Z",
  "started": "2026-11-15T09:30:04Z",
  "finished": "2026-11-15T09:30:07Z"
}

done means the command was carried out. A reboot then takes the usual time for the machine to come back; check your own service (SSH, HTTP) for that.

One action per server

Only one action runs on a server at a time. While one is queued, running or not yet settled, another request for the same server answers 409 server_busy, whatever key or Idempotency-Key you use. Wait for the first to finish.

The same answer comes while a server is being delivered or installed, or while a change started in the client area is under way.

When the outcome is unknown

If the command was sent but no clear answer came back, the action ends unknown. We do not retry it silently, because a second power-off or reboot could do harm. RedSwitches staff check the machine and settle the action. Until then, further API power actions on that server answer 409 server_busy. The power buttons in the client area keep working.

Ceilings and the power-off brake

CeilingDefaultAnswer
Actions per server6 in a rolling hour429 action_limit, details.per: "server_hour"
Actions per account20 in a rolling hour429 action_limit, details.per: "account_hour"
Power-offs per account5 within 10 minutes pauses API power403 power_paused

The power-off brake protects you from a runaway script. Four power-offs within 10 minutes go through; the fifth is refused, and API power for the whole account is paused and our staff are told. Every further power request answers 403 power_paused until staff resume it. Contact support to resume.

Only accepted actions count towards the ceilings.

Other refusals

AnswerMeaning
403 permission_deniedThe key lacks power, or the server is not on its list.
409 server_not_activeThe server is pending, suspended or ended. A suspended server cannot be powered on through the API.
422 not_supportedThis server cannot be powered through the API. Use the client area.

Queued too long

An action that has not started within 15 minutes expires: it ends failed with reason expired, and nothing is done. Send a new request (with a new Idempotency-Key) if you still want it.

Retries

If the power request itself times out, send it again with the same Idempotency-Key and body: you get the same action back, and the server is powered only once. See Idempotency and retries. Use a new key only for a new intention, such as a second reboot later.

Recipes

Reboot every server that has a label starting with web-, one at a time:

for id in $(curl -sS "https://api.redswitches.com/v1/servers?limit=100" \
    -H "Authorization: Bearer $REDSWITCHES_API_KEY" | jq -r '.data[] | select(.label // "" | startswith("web-")) | .id'); do
  curl -sS -X POST "https://api.redswitches.com/v1/servers/$id/power" \
    -H "Authorization: Bearer $REDSWITCHES_API_KEY" \
    -H "Content-Type: application/json" \
    -H "Idempotency-Key: $(uuidgen)" \
    -d '{"action":"reboot"}'
  sleep 120   # let it come back before the next one
done
const { data } = await rs.servers.list({ limit: 100 });
for (const s of data.filter((x) => x.label?.startsWith("web-"))) {
  const a = await rs.power.run(s.id, { action: "reboot" });
  await rs.actions.wait(a.id);
}
for s in client.servers.list(limit=100).data:
    if (s.label or "").startswith("web-"):
        a = client.power.run(s.id, action="reboot")
        client.actions.wait(a.id)
page, _ := client.Servers.List(ctx, &redswitches.ListOptions{Limit: 100})
for _, s := range page.Data {
	if s.Label != nil && strings.HasPrefix(*s.Label, "web-") {
		a, err := client.Power.Run(ctx, s.ID, "reboot")
		if err == nil {
			client.Actions.Wait(ctx, a.ID)
		}
	}
}
{ "id": "act_44", "kind": "power", "server_id": "srv_123", "action": "reboot", "state": "queued", "poll_after": 10 }

Keep the 6-per-hour and 20-per-hour ceilings in mind for larger fleets.