# Rescue mode and one-time credentials

Boot a server into rescue mode, read a one-time password after a reinstall or a rescue, and leave rescue again. Rescue needs the `rescue` permission.

> **Beta.** Rescue through the API is built and switched off. RedSwitches decides when to switch it on; until then `POST /servers/{id}/rescue` answers `503 unavailable` and the `rescue` permission is not offered when you make a key. The endpoints and fields below are the beta contract and may still change.

## How it works

- Rescue works like a reinstall: it is an [action](actions.md) of kind `rescue` that boots the server into the same rescue system as the Rescue tab in the client area. Follow it with `GET /actions/{id}`.
- The `rescue` permission is chosen when a key is made, only while rescue is on, and is limited by the key's server list, like `power`.
- At most 4 rescue boots per server per day (`429 action_limit`, `details.per: "server_day"`).
- Not while another action, install or rescue runs on the server (`409 server_busy`).
- While RedSwitches has reinstalls paused, rescue is paused too (`503 unavailable`).
- `GET /servers/{id}` shows `rescue: true` while the server is in rescue mode.
- To leave rescue mode, reboot the server: `POST /servers/{id}/power` with `{"action": "reboot"}`, as in the client area.

## Start rescue

`POST /servers/{id}/rescue`. Needs an `Idempotency-Key`.

| Body field | Required | Rule |
|---|---|---|
| `return_password` | no | `true` or `false` (default). With `true`, the rescue login can be read once through the API (below). With `false`, it reaches you the same way as a rescue started in the client area. |

The body may be `{}`.

```bash
curl -sS -X POST https://api.redswitches.com/v1/servers/srv_123/rescue \
  -H "Authorization: Bearer $REDSWITCHES_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{"return_password": true}'
```

```ts
const action = await rs.servers.rescue("srv_123", { return_password: true });
const done = await rs.actions.wait(action.id);
```

```python
action = client.servers.rescue("srv_123", return_password=True)
done = client.actions.wait(action.id)
```

```go
action, err := client.Servers.Rescue(ctx, "srv_123", &redswitches.RescueRequest{ReturnPassword: true})
if err != nil {
	log.Fatal(err)
}
done, err := client.Actions.Wait(ctx, action.ID)
```

```json
{
  "id": "act_44",
  "kind": "rescue",
  "server_id": "srv_123",
  "state": "queued",
  "return_password": true,
  "poll_after": 30
}
```

The answer is `202 Accepted`.

## Read the credentials once

A reinstall or a rescue started with `"return_password": true` keeps its password for you to read **once**.

`GET /actions/{id}/credentials`

- Only the key that started the action can read it (the `read` permission is enough).
- It can be read after the action is `done`. Before that, the answer is `404 not_found`.
- The first read returns the credentials and deletes them. Every later read is `404 not_found`.
- Credentials nobody reads are deleted after 24 hours.
- Every read is logged, and the account owner is emailed that a password was retrieved through the API. The email never contains the password.
- Credentials never appear in action answers, logs or emails.
- `HEAD` is refused on this endpoint (`405`), so nothing can use up the password without reading it. The SDKs never retry this request after a network error or a 5xx answer: a lost answer may already have used it up.
- If the reinstall or rescue started but the password could not be kept, the action is `done` with reason `password_unavailable`, staff are told and set one for you, and the credentials read is `404`.
- While RedSwitches has the API, this part of it, or reinstalls and rescues switched off or paused, the read answers `503 unavailable` and the password is kept: try again later.
- If the key loses its permission or the server changes hands or hardware before the read, the password is deleted unread.

**Store the password the moment you read it**, for example in your secret store. If you lose it, there is no second read: start a new reinstall or rescue, or reset the password in the client area.

```bash
curl -sS https://api.redswitches.com/v1/actions/act_44/credentials \
  -H "Authorization: Bearer $REDSWITCHES_API_KEY"
```

```ts
const creds = await rs.actions.credentials("act_44");
await saveToVault("srv_123", creds); // do this before anything else
```

```python
creds = client.actions.credentials("act_44")
save_to_vault("srv_123", creds)  # do this before anything else
```

```go
creds, err := client.Actions.Credentials(ctx, "act_44")
if err != nil {
	log.Fatal(err)
}
saveToVault("srv_123", creds) // do this before anything else
```

```json
{
  "action_id": "act_44",
  "server_id": "srv_123",
  "username": "root",
  "password": "XXXXXXXXXXXXXXXX"
}
```

## Leave rescue

Reboot the server. It starts from its own disks again.

```bash
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"}'
```

This needs the `power` permission. See [Power and actions](guide-power.md).

## Errors

| Status | Code | Meaning |
|---|---|---|
| 403 | `permission_denied` | The key does not have `rescue`, or this server is not on its server list. |
| 404 | `not_found` | No such server or action on this account; or credentials not ready, already read, expired, or never asked for. |
| 409 | `server_busy` | Another action, install or rescue is running on the server. |
| 409 | `server_not_active` | The server is not active. |
| 422 | `not_supported` | This server cannot be rescued through the API. |
| 429 | `action_limit` | More than 4 rescue boots for this server today. |
| 503 | `unavailable` | Rescue is switched off, or RedSwitches has reinstalls and rescues paused. On a credentials read: the password is kept; try again later. |
