# API reference

Every endpoint of the RedSwitches API, built from the OpenAPI 3.1 spec (openapi.json). Base URL `https://api.redswitches.com/v1`.

Every request needs `Authorization: Bearer <key>`; every write needs an `Idempotency-Key` header. Items marked Beta are rolling out and may not answer yet.

| Method | Path | Permission | What it does |
|---|---|---|---|
| GET | `/auth/verify` | `read` | Check the key |
| GET | `/account` | `read` | Get the account |
| GET | `/offers` | `read` | List instant servers on offer |
| GET | `/offers/{id}` | `read` | Get one offer |
| GET | `/servers` | `read` | List servers |
| GET | `/servers/{id}` | `read` | Get a server |
| GET | `/servers/{id}/traffic` | `read` | Get traffic |
| POST | `/servers/{id}/label` | `manage` | Rename a server |
| GET | `/servers/{id}/rdns` | `read` | List reverse DNS requests |
| POST | `/servers/{id}/rdns` | `manage` | Request a reverse DNS change |
| POST | `/servers/{id}/power` | `power` | Power on, off or reboot |
| GET | `/actions/{id}` | `read` | Get an action |
| GET | `/actions/{id}/credentials` | `read` | Read an action's credentials once (Beta) |
| GET | `/orders` | `read` | List orders |
| POST | `/orders` | `order` | Order an instant server |
| GET | `/orders/{id}` | `read` | Get an order |
| GET | `/invoices` | `read_billing` | List invoices |
| GET | `/invoices/{id}` | `read_billing` | Get an invoice |
| GET | `/ssh-keys` | `read` | List saved SSH keys |
| POST | `/ssh-keys` | `ssh_keys` | Save an SSH key |
| DELETE | `/ssh-keys/{id}` | `ssh_keys` | Remove a saved SSH key |
| GET | `/servers/{id}/cancel-request` | `read` | Get the cancellation request (Beta) |
| POST | `/servers/{id}/cancel-request` | `cancel` | Request cancellation (Beta) |
| DELETE | `/servers/{id}/cancel-request` | `cancel` | Ask to withdraw the cancellation (Beta) |
| POST | `/servers/{id}/rescue` | `rescue` | Boot into rescue mode (Beta) |
| GET | `/servers/{id}/os` | `read` | List OS images for reinstall (Beta) |
| POST | `/servers/{id}/reinstall` | `reinstall` | Reinstall a server (Beta) |

## Account

### GET /auth/verify

Check the key. Permission `read`.

The key this request was made with: label, hint, granted and effective permissions, expiry.

Responses:

- 200: [KeyInfo](#schema-keyinfo). The key.
- 400, 401, 403, 404, 405, 429, 500, 503: [Error](#schema-error).

### GET /account

Get the account. Permission `read`.

Id, status and currency. `credit` only for a key with read_billing.

Responses:

- 200: [Account](#schema-account). The account.
- 400, 401, 403, 404, 405, 429, 500, 503: [Error](#schema-error).

## Offers

### GET /offers

List instant servers on offer. Permission `read`.

Instant servers in stock for this account, with prices in the account's currency. Not paginated.

Responses:

- 200: [OfferList](#schema-offerlist). Offers.
- 400, 401, 403, 404, 405, 429, 500, 503: [Error](#schema-error).

### GET /offers/{id}

Get one offer. Permission `read`.

One offer of the list, or 404 when it is not on offer now.

Parameters:

- `id` (path, required): string `^ofr_[1-9][0-9]{0,9}$`. A typed id (`ofr_<number>`). Another prefix, a leading zero or anything encoded is 404.

Responses:

- 200: [Offer](#schema-offer). The offer.
- 400, 401, 403, 404, 405, 429, 500, 503: [Error](#schema-error).

Specific error codes: `not_found`.

## Servers

### GET /servers

List servers. Permission `read`.

The account's servers, newest first. Cancelled and terminated services are not listed.

Parameters:

- `cursor` (query): string `^srv_[1-9][0-9]{0,9}$`. next_cursor of the previous page.
- `limit` (query): integer. Items per page, 1 to 100 (default 50).

Responses:

- 200: [ServerPage](#schema-serverpage). A page of servers.
- 400, 401, 403, 404, 405, 429, 500, 503: [Error](#schema-error).

### GET /servers/{id}

Get a server. Permission `read`.

The list fields plus IP addresses, OS, hardware and delivery state. Stored blocks carry their own as_of or are "unavailable". No request ever calls the server's network live.

Parameters:

- `id` (path, required): string `^srv_[1-9][0-9]{0,9}$`. A typed id (`srv_<number>`). Another prefix, a leading zero or anything encoded is 404.

Responses:

- 200: [ServerDetail](#schema-serverdetail). The server.
- 400, 401, 403, 404, 405, 429, 500, 503: [Error](#schema-error).

Specific error codes: `not_found`.

### GET /servers/{id}/traffic

Get traffic. Permission `read`.

Data used in the current period and the allowance. used_bytes is "unavailable" (never zero) when no current figure is stored or the window reaches back before this account held the server.

Parameters:

- `id` (path, required): string `^srv_[1-9][0-9]{0,9}$`. A typed id (`srv_<number>`). Another prefix, a leading zero or anything encoded is 404.

Responses:

- 200: [Traffic](#schema-traffic). Traffic.
- 400, 401, 403, 404, 405, 429, 500, 503: [Error](#schema-error).

Specific error codes: `not_found`.

### POST /servers/{id}/label

Rename a server. Permission `manage`.

Sets the server's label (cosmetic; never a host name). "" clears it.

Parameters:

- `id` (path, required): string `^srv_[1-9][0-9]{0,9}$`. A typed id (`srv_<number>`). Another prefix, a leading zero or anything encoded is 404.
- `Idempotency-Key` (header, required): string `^[A-Za-z0-9_-]{8,64}$`. 8 to 64 letters, digits, dashes or underscores. One per intended action; reuse it only to retry the same request.

Body: [LabelRequest](#schema-labelrequest) (JSON; unknown fields refused).

Responses:

- 200: [LabelResult](#schema-labelresult). Renamed.
- 400, 401, 403, 404, 405, 409, 413, 422, 429, 500, 503: [Error](#schema-error).

Specific error codes: `invalid_body`, `idempotency_key_required`, `idempotency_conflict`, `in_progress`, `not_found`.

## Reverse DNS

### GET /servers/{id}/rdns

List reverse DNS requests. Permission `read`.

This server's open reverse DNS requests made by this account (pending or applied).

Parameters:

- `id` (path, required): string `^srv_[1-9][0-9]{0,9}$`. A typed id (`srv_<number>`). Another prefix, a leading zero or anything encoded is 404.

Responses:

- 200: [RdnsList](#schema-rdnslist). Requests.
- 400, 401, 403, 404, 405, 429, 500, 503: [Error](#schema-error).

Specific error codes: `not_found`.

### POST /servers/{id}/rdns

Request a reverse DNS change. Permission `manage`.

Queues a PTR change for an IP of this server. The IP must be on the server's stored IP list. At most one open request per IP and 20 per server per day. Applied shortly afterwards, not in the request. On servers where it is carried out as an action, and always for hostname "" (clear the PTR), the answer is RdnsQueued with an action id to poll; another hostname for an IP with an open action is 409 server_busy.

Parameters:

- `id` (path, required): string `^srv_[1-9][0-9]{0,9}$`. A typed id (`srv_<number>`). Another prefix, a leading zero or anything encoded is 404.
- `Idempotency-Key` (header, required): string `^[A-Za-z0-9_-]{8,64}$`. 8 to 64 letters, digits, dashes or underscores. One per intended action; reuse it only to retry the same request.

Body: [RdnsRequest](#schema-rdnsrequest) (JSON; unknown fields refused).

Responses:

- 202: [RdnsAccepted](#schema-rdnsaccepted) | [RdnsQueued](#schema-rdnsqueued). Accepted: an rDNS request applied by the scheduled job (RdnsAccepted), or an action to poll (RdnsQueued, with an act_ id).
- 400, 401, 403, 404, 405, 409, 413, 422, 429, 500, 503: [Error](#schema-error).

Specific error codes: `invalid_body`, `idempotency_key_required`, `idempotency_conflict`, `in_progress`, `not_found`, `not_supported`, `server_not_active`, `server_busy`, `ip_not_on_server`, `action_limit`.

## Power and actions

### POST /servers/{id}/power

Power on, off or reboot. Permission `power`.

Records a power action and returns at once (202). Poll GET /actions/{id}. The key's server list must cover the server. One action per server at a time; ceilings per server and per account per rolling hour; a burst of power-offs pauses API power for the account.

Parameters:

- `id` (path, required): string `^srv_[1-9][0-9]{0,9}$`. A typed id (`srv_<number>`). Another prefix, a leading zero or anything encoded is 404.
- `Idempotency-Key` (header, required): string `^[A-Za-z0-9_-]{8,64}$`. 8 to 64 letters, digits, dashes or underscores. One per intended action; reuse it only to retry the same request.

Body: [PowerRequest](#schema-powerrequest) (JSON; unknown fields refused).

Responses:

- 202: [ActionAccepted](#schema-actionaccepted). Queued.
- 400, 401, 403, 404, 405, 409, 413, 422, 429, 500, 503: [Error](#schema-error).

Specific error codes: `invalid_body`, `idempotency_key_required`, `idempotency_conflict`, `in_progress`, `not_found`, `permission_denied`, `power_paused`, `server_busy`, `server_not_active`, `not_supported`, `action_limit`.

### GET /actions/{id}

Get an action. Permission `read`.

An action of this account (made with any of its keys).

Parameters:

- `id` (path, required): string `^act_[1-9][0-9]{0,9}$`. A typed id (`act_<number>`). Another prefix, a leading zero or anything encoded is 404.

Responses:

- 200: [Action](#schema-action). The action.
- 400, 401, 403, 404, 405, 429, 500, 503: [Error](#schema-error).

Specific error codes: `not_found`.

### GET /actions/{id}/credentials

Read an action's credentials once. Permission `read`. Beta — rolling out.

Beta. The password (or rescue login) of a reinstall or rescue action that was made with return_password true. Needs read; only the key that started the action, after the action is done. The first read returns it and wipes it; unread credentials are wiped after 24 hours. Every read is audited and the owner is emailed. Afterwards, before the action is done, for another key, for an action without return_password, or when the password could not be kept (action reason password_unavailable): 404 not_found. While a switch is off (platform, layer, pause) the answer is 503 unavailable and the password is kept for a later read. HEAD is refused (405) so that nothing can consume the password without reading it. Do not retry this request after a network error or a 5xx answer: the lost answer may already have used the one read (retrying after 429 rate_limited is safe).

Parameters:

- `id` (path, required): string `^act_[1-9][0-9]{0,9}$`. A typed id (`act_<number>`). Another prefix, a leading zero or anything encoded is 404.

Responses:

- 200: [Credentials](#schema-credentials). The credentials, this one time.
- 400, 401, 403, 404, 405, 429, 500, 503: [Error](#schema-error).

Specific error codes: `not_found`, `permission_denied`, `unavailable`.

## Orders

### GET /orders

List orders. Permission `read`.

The account's orders, newest first.

Parameters:

- `cursor` (query): string `^ord_[1-9][0-9]{0,9}$`. next_cursor of the previous page.
- `limit` (query): integer. Items per page, 1 to 100 (default 50).

Responses:

- 200: [OrderPage](#schema-orderpage). A page of orders.
- 400, 401, 403, 404, 405, 429, 500, 503: [Error](#schema-error).

### POST /orders

Order an instant server. Permission `order`.

Orders one instant server, paid from account credit. Run it first with `?dry_run=true` (no Idempotency-Key needed) and send the returned total as expected_total. Then poll GET /orders/{id} until every service is `ready`.

Parameters:

- `dry_run` (query): "true". `true` only: check and price the order; nothing is created or reserved. No Idempotency-Key needed.
- `Idempotency-Key` (header): string `^[A-Za-z0-9_-]{8,64}$`. Required for a real order (8 to 64 letters, digits, dashes or underscores); not needed with dry_run=true.

Body: [OrderCreateRequest](#schema-ordercreaterequest) (JSON; unknown fields refused).

Responses:

- 201: [OrderCreated](#schema-ordercreated). Ordered and paid from credit; delivery queued.
- 200: [OrderDryRun](#schema-orderdryrun). Dry run: what the order would cost. Nothing created.
- 400, 401, 402, 403, 404, 405, 409, 413, 422, 429, 500, 503: [Error](#schema-error).

Specific error codes: `invalid_body`, `idempotency_key_required`, `idempotency_conflict`, `in_progress`, `insufficient_credit`, `ordering_not_enabled`, `not_eligible`, `cooling_off`, `cap_reached`, `ordering_paused`, `price_changed`, `sold_out`, `order_not_placed`, `order_under_review`, `not_orderable`.

### GET /orders/{id}

Get an order. Permission `read`.

An order with each service's delivery state and poll_after.

Parameters:

- `id` (path, required): string `^ord_[1-9][0-9]{0,9}$`. A typed id (`ord_<number>`). Another prefix, a leading zero or anything encoded is 404.

Responses:

- 200: [Order](#schema-order). The order.
- 400, 401, 403, 404, 405, 429, 500, 503: [Error](#schema-error).

Specific error codes: `not_found`.

## Invoices

### GET /invoices

List invoices. Permission `read_billing`.

The account's invoices, newest first (drafts hidden). Needs read_billing.

Parameters:

- `cursor` (query): string `^inv_[1-9][0-9]{0,9}$`. next_cursor of the previous page.
- `limit` (query): integer. Items per page, 1 to 100 (default 50).

Responses:

- 200: [InvoicePage](#schema-invoicepage). A page of invoices.
- 400, 401, 403, 404, 405, 429, 500, 503: [Error](#schema-error).

Specific error codes: `permission_denied`.

### GET /invoices/{id}

Get an invoice. Permission `read_billing`.

One invoice with its line items. Needs read_billing.

Parameters:

- `id` (path, required): string `^inv_[1-9][0-9]{0,9}$`. A typed id (`inv_<number>`). Another prefix, a leading zero or anything encoded is 404.

Responses:

- 200: [InvoiceDetail](#schema-invoicedetail). The invoice.
- 400, 401, 403, 404, 405, 429, 500, 503: [Error](#schema-error).

Specific error codes: `permission_denied`, `not_found`.

## SSH keys

### GET /ssh-keys

List saved SSH keys. Permission `read`.

The account's saved SSH keys.

Responses:

- 200: [SshKeyList](#schema-sshkeylist). Keys.
- 400, 401, 403, 404, 405, 429, 500, 503: [Error](#schema-error).

### POST /ssh-keys

Save an SSH key. Permission `ssh_keys`.

Saves a public key on the account. The owner is emailed. At most 20 key changes per account per day.

Parameters:

- `Idempotency-Key` (header, required): string `^[A-Za-z0-9_-]{8,64}$`. 8 to 64 letters, digits, dashes or underscores. One per intended action; reuse it only to retry the same request.

Body: [SshKeyCreateRequest](#schema-sshkeycreaterequest) (JSON; unknown fields refused).

Responses:

- 201: [SshKey](#schema-sshkey). Saved.
- 400, 401, 403, 404, 405, 409, 413, 422, 429, 500, 503: [Error](#schema-error).

Specific error codes: `invalid_body`, `idempotency_key_required`, `idempotency_conflict`, `in_progress`, `invalid_ssh_key`, `ssh_key_conflict`, `action_limit`.

### DELETE /ssh-keys/{id}

Remove a saved SSH key. Permission `ssh_keys`.

Removes a saved key from the account. Servers where it is already installed are not touched. The owner is emailed.

Parameters:

- `id` (path, required): string `^sshkey_[1-9][0-9]{0,9}$`. A typed id (`sshkey_<number>`). Another prefix, a leading zero or anything encoded is 404.
- `Idempotency-Key` (header, required): string `^[A-Za-z0-9_-]{8,64}$`. 8 to 64 letters, digits, dashes or underscores. One per intended action; reuse it only to retry the same request.

Responses:

- 200: [SshKeyDeleted](#schema-sshkeydeleted). Removed.
- 400, 401, 403, 404, 405, 409, 413, 422, 429, 500, 503: [Error](#schema-error).

Specific error codes: `idempotency_key_required`, `idempotency_conflict`, `in_progress`, `not_found`, `action_limit`.

## Cancellation

### GET /servers/{id}/cancel-request

Get the cancellation request. Permission `read`. Beta — rolling out.

Beta. The server's cancellation state: none, requested (with dates) or withdrawal_requested.

Parameters:

- `id` (path, required): string `^srv_[1-9][0-9]{0,9}$`. A typed id (`srv_<number>`). Another prefix, a leading zero or anything encoded is 404.

Responses:

- 200: [CancellationState](#schema-cancellationstate). State.
- 400, 401, 403, 404, 405, 429, 500, 503: [Error](#schema-error).

Specific error codes: `not_found`.

### POST /servers/{id}/cancel-request

Request cancellation. Permission `cancel`. Beta — rolling out.

Beta. Files a cancellation at the end of the billing period (the server keeps running until then) for an active or suspended server. The owner is emailed. When a request already exists it is returned (200). Covered by the key's server list. At most 2 per account per day. 409 server_busy while a request to keep the server is less than a day old.

Parameters:

- `id` (path, required): string `^srv_[1-9][0-9]{0,9}$`. A typed id (`srv_<number>`). Another prefix, a leading zero or anything encoded is 404.
- `Idempotency-Key` (header, required): string `^[A-Za-z0-9_-]{8,64}$`. 8 to 64 letters, digits, dashes or underscores. One per intended action; reuse it only to retry the same request.

Body: [CancelRequestBody](#schema-cancelrequestbody) (JSON; unknown fields refused).

Responses:

- 201: [CancellationState](#schema-cancellationstate). Requested.
- 200: [CancellationState](#schema-cancellationstate). A request already existed.
- 400, 401, 403, 404, 405, 409, 413, 422, 429, 500, 503: [Error](#schema-error).

Specific error codes: `invalid_body`, `idempotency_key_required`, `idempotency_conflict`, `in_progress`, `not_found`, `permission_denied`, `server_not_active`, `server_busy`, `action_limit`.

### DELETE /servers/{id}/cancel-request

Ask to withdraw the cancellation. Permission `cancel`. Beta — rolling out.

Beta. Asks RedSwitches staff to withdraw the cancellation (filed once; repeating it changes nothing). Nothing is un-cancelled automatically. 404 when there is no cancellation request.

Parameters:

- `id` (path, required): string `^srv_[1-9][0-9]{0,9}$`. A typed id (`srv_<number>`). Another prefix, a leading zero or anything encoded is 404.
- `Idempotency-Key` (header, required): string `^[A-Za-z0-9_-]{8,64}$`. 8 to 64 letters, digits, dashes or underscores. One per intended action; reuse it only to retry the same request.

Responses:

- 200: [CancellationState](#schema-cancellationstate). Withdrawal requested.
- 400, 401, 403, 404, 405, 409, 413, 422, 429, 500, 503: [Error](#schema-error).

Specific error codes: `idempotency_key_required`, `idempotency_conflict`, `in_progress`, `not_found`, `permission_denied`.

## Reinstall and rescue

### POST /servers/{id}/rescue

Boot into rescue mode. Permission `rescue`. Beta — rolling out.

Beta. Off unless RedSwitches switches rescue on. Records a rescue action (202) that boots the server into rescue mode, as the portal's Rescue tab does. With return_password true the rescue login can be read once from GET /actions/{id}/credentials after the action is done. Leave rescue with POST /servers/{id}/power {"action":"reboot"}. Covered by the key's server list. At most 4 per server per day. 503 unavailable while RedSwitches has reinstalls and rescues paused.

Parameters:

- `id` (path, required): string `^srv_[1-9][0-9]{0,9}$`. A typed id (`srv_<number>`). Another prefix, a leading zero or anything encoded is 404.
- `Idempotency-Key` (header, required): string `^[A-Za-z0-9_-]{8,64}$`. 8 to 64 letters, digits, dashes or underscores. One per intended action; reuse it only to retry the same request.

Body: [RescueRequest](#schema-rescuerequest) (JSON; unknown fields refused).

Responses:

- 202: [RescueAccepted](#schema-rescueaccepted). Queued.
- 400, 401, 403, 404, 405, 409, 413, 422, 429, 500, 503: [Error](#schema-error).

Specific error codes: `invalid_body`, `idempotency_key_required`, `idempotency_conflict`, `in_progress`, `not_found`, `permission_denied`, `server_busy`, `server_not_active`, `not_supported`, `action_limit`, `unavailable`.

### GET /servers/{id}/os

List OS images for reinstall. Permission `read`. Beta — rolling out.

Beta. The OS images the portal offers for this server, from a stored list.

Parameters:

- `id` (path, required): string `^srv_[1-9][0-9]{0,9}$`. A typed id (`srv_<number>`). Another prefix, a leading zero or anything encoded is 404.

Responses:

- 200: [OsImageList](#schema-osimagelist). Images.
- 400, 401, 403, 404, 405, 429, 500, 503: [Error](#schema-error).

Specific error codes: `not_found`.

### POST /servers/{id}/reinstall

Reinstall a server. Permission `reinstall`. Beta — rolling out.

Beta. Off unless RedSwitches switches reinstall on. Records a reinstall action (202) with the chosen saved SSH keys. No password is returned unless return_password is true (then readable once from GET /actions/{id}/credentials); otherwise, if one is set, it is emailed to the owner as in the portal. Covered by the key's server list. At most 2 per server and 5 per account per day. 503 unavailable while RedSwitches has reinstalls paused.

Parameters:

- `id` (path, required): string `^srv_[1-9][0-9]{0,9}$`. A typed id (`srv_<number>`). Another prefix, a leading zero or anything encoded is 404.
- `Idempotency-Key` (header, required): string `^[A-Za-z0-9_-]{8,64}$`. 8 to 64 letters, digits, dashes or underscores. One per intended action; reuse it only to retry the same request.

Body: [ReinstallRequest](#schema-reinstallrequest) (JSON; unknown fields refused).

Responses:

- 202: [ReinstallAccepted](#schema-reinstallaccepted). Queued.
- 400, 401, 403, 404, 405, 409, 413, 422, 429, 500, 503: [Error](#schema-error).

Specific error codes: `invalid_body`, `idempotency_key_required`, `idempotency_conflict`, `in_progress`, `not_found`, `permission_denied`, `server_busy`, `server_not_active`, `not_supported`, `invalid_ssh_key`, `action_limit`, `unavailable`.

## Objects

### MinorAmount

An amount in MINOR units (cents) as a string of digits, and its currency. Used by ordering: `{"amount":"15609","currency":"EUR"}` is 156.09 EUR.

| Field | Type | Description |
|---|---|---|
| `amount` | string `^(0or[1-9][0-9]{0,11})$` |  |
| `currency` | string `^[A-Z]{3}$` | ISO 4217 code of the account's currency. |

### Location

| Field | Type | Description |
|---|---|---|
| `city` | string |  |
| `country` | string `^[A-Z]{2}$` or null | ISO 3166-1 alpha-2, or null when unknown. |

### KeyInfo

| Field | Type | Description |
|---|---|---|
| `id` | string `^key_[1-9][0-9]{0,9}$` |  |
| `label` | string |  |
| `hint` | string | The key's last four characters. |
| `env` | "live" or "test" |  |
| `permissions` | array of "read" or "read_billing" or "order" or "manage" or "ssh_keys" or "power" or "cancel" or "reinstall" or "rescue" | Permissions granted to the key. |
| `effective_permissions` | array of "read" or "read_billing" or "order" or "manage" or "ssh_keys" or "power" or "cancel" or "reinstall" or "rescue" | Granted permissions that work right now (a permission does not work while RedSwitches has its part of the API switched off). |
| `expires_at` | string (date-time) or null | UTC, ISO 8601, always with Z. |

### Account

| Field | Type | Description |
|---|---|---|
| `id` | string `^acc_[1-9][0-9]{0,9}$` |  |
| `status` | "active" or "inactive" or "closed" |  |
| `currency` | string `^[A-Z]{3}$` | ISO 4217 code of the account's currency. |
| `credit` | string `^-?[0-9]{1,13}\.[0-9]{2}$` | Credit balance. Present only for a key with read_billing. |

### OfferPrice

| Field | Type | Description |
|---|---|---|
| `cycle` | "monthly" or "quarterly" or "semiannually" or "annually" or "biennially" or "triennially" |  |
| `price` | string `^-?[0-9]{1,13}\.[0-9]{2}$` | Recurring price per cycle, excluding tax, for the default configuration. |
| `setup` | string `^-?[0-9]{1,13}\.[0-9]{2}$` | One-time setup fee of that cycle. |

### OsChoice

| Field | Type | Description |
|---|---|---|
| `id` | string `^os_[1-9][0-9]{0,9}$` |  |
| `name` | string |  |

### Offer

An instant server on offer. Prices are per billing cycle, excluding tax, in the account's currency, for the default configuration. Use a dry-run order for the exact total.

| Field | Type | Description |
|---|---|---|
| `id` | string `^ofr_[1-9][0-9]{0,9}$` |  |
| `name` | string |  |
| `location` | [Location](#schema-location) or  or null |  |
| `cpu` | string or null |  |
| `ram` | string or null |  |
| `disks` | string or null |  |
| `port_speed` | string or null |  |
| `traffic` | string or null |  |
| `currency` | string `^[A-Z]{3}$` | ISO 4217 code of the account's currency. |
| `prices` | array of [OfferPrice](#schema-offerprice) |  |
| `os` | array of [OsChoice](#schema-oschoice) | The OS choices for an order (os_id). |
| `stock` | integer or "5+" | Units in stock, 0 to 4, or "5+". |
| `as_of` | string (date-time) | When this list was read (lists are cached for about 30 seconds). |

### OfferList

| Field | Type | Description |
|---|---|---|
| `data` | array of [Offer](#schema-offer) |  |

### Server

A server of the account (cancelled and terminated services are not listed).

| Field | Type | Description |
|---|---|---|
| `id` | string `^srv_[1-9][0-9]{0,9}$` |  |
| `label` | string or null |  |
| `product` | string |  |
| `location` | [Location](#schema-location) or  or null |  |
| `status` | "pending" or "active" or "suspended" |  |
| `primary_ip` | string or null | IPv4 or IPv6 address, without a prefix length. |
| `billing_cycle` | "monthly" or "quarterly" or "semiannually" or "annually" or "biennially" or "triennially" or "one_time" or "free" or null |  |
| `next_due_date` | string (date) or null |  |
| `recurring_amount` | string `^-?[0-9]{1,13}\.[0-9]{2}$` | A decimal amount in major units, as a string (never a float). Example `"129.00"`. |
| `currency` | string `^[A-Z]{3}$` | ISO 4217 code of the account's currency. |
| `created` | string (date) or null |  |

### IpBlock

| Field | Type | Description |
|---|---|---|
| `as_of` | string (date-time) | UTC, ISO 8601, always with Z. |
| `addresses` | array of object |  |

### InstalledOs

| Field | Type | Description |
|---|---|---|
| `as_of` | string (date-time) | UTC, ISO 8601, always with Z. |
| `name` | string or null |  |
| `installing` | boolean |  |

### Hardware

| Field | Type | Description |
|---|---|---|
| `as_of` | string (date-time) | UTC, ISO 8601, always with Z. |
| `cpu` | string or null |  |
| `ram` | string or null |  |
| `disks` | string or null |  |

### ServerDetail

One server: the list fields plus stored facts. Each stored block has its own as_of, or is the string "unavailable".

| Field | Type | Description |
|---|---|---|
| `id` | string `^srv_[1-9][0-9]{0,9}$` |  |
| `label` | string or null |  |
| `product` | string |  |
| `location` | [Location](#schema-location) or  or null |  |
| `status` | "pending" or "active" or "suspended" |  |
| `primary_ip` | string or null | IPv4 or IPv6 address, without a prefix length. |
| `billing_cycle` | "monthly" or "quarterly" or "semiannually" or "annually" or "biennially" or "triennially" or "one_time" or "free" or null |  |
| `next_due_date` | string (date) or null |  |
| `recurring_amount` | string `^-?[0-9]{1,13}\.[0-9]{2}$` | A decimal amount in major units, as a string (never a float). Example `"129.00"`. |
| `currency` | string `^[A-Z]{3}$` | ISO 4217 code of the account's currency. |
| `created` | string (date) or null |  |
| `ips` | [IpBlock](#schema-ipblock) or "unavailable" |  |
| `os` | object |  |
| `hardware` | [Hardware](#schema-hardware) or "unavailable" |  |
| `delivery` | "awaiting_payment" or "assigning" or "installing" or "ready" or "attention" or "closed" or  or null | Null for a server that is not an instant deploy. |
| `rescue` | boolean | True while the server is booted into rescue mode (from stored state; false when not known). Leave rescue with a power reboot. |

### Traffic

| Field | Type | Description |
|---|---|---|
| `id` | string `^srv_[1-9][0-9]{0,9}$` |  |
| `used_bytes` | integer or "unavailable" |  |
| `unavailable_reason` | "not_collected" or "ownership_changed_in_window" or null | Why used_bytes is unavailable: nothing current is stored, or the measured window starts before this account held the server. Null when used_bytes is a number. |
| `period_start` | string (date-time) or null | UTC, ISO 8601, always with Z. |
| `period_end` | string (date-time) or null | UTC, ISO 8601, always with Z. |
| `basis` | "billing_period" or "last_30_days" or "since_ownership" or null | billing_period: the account's billing month. last_30_days: the network's rolling 30-day total. since_ownership: counted from when this account started holding the server. |
| `as_of` | string (date-time) or null | UTC, ISO 8601, always with Z. |
| `allowance_bytes` | integer or null | Null when unmetered or unknown. |
| `unmetered` | boolean |  |

### Order

| Field | Type | Description |
|---|---|---|
| `id` | string `^ord_[1-9][0-9]{0,9}$` |  |
| `date` | string (date-time) or null | UTC, ISO 8601, always with Z. |
| `status` | "pending" or "active" or "cancelled" or "on_hold" or "other" |  |
| `payment` | "paid" or "free" or "unpaid" or "partially_paid" or "pending" or "cancelled" or "refunded" or "collections" or "unknown" |  |
| `invoice` | string `^inv_[1-9][0-9]{0,9}$` or null |  |
| `services` | array of object |  |
| `poll_after` | integer or null | Seconds until it is worth asking again; null when nothing is still being delivered. |

### ServerPage

| Field | Type | Description |
|---|---|---|
| `data` | array of [Server](#schema-server) |  |
| `next_cursor` | string `^srv_[1-9][0-9]{0,9}$` or null | Pass as cursor for the next page; null on the last page. |

### OrderPage

| Field | Type | Description |
|---|---|---|
| `data` | array of [Order](#schema-order) |  |
| `next_cursor` | string `^ord_[1-9][0-9]{0,9}$` or null | Pass as cursor for the next page; null on the last page. |

### InvoicePage

| Field | Type | Description |
|---|---|---|
| `data` | array of [Invoice](#schema-invoice) |  |
| `next_cursor` | string `^inv_[1-9][0-9]{0,9}$` or null | Pass as cursor for the next page; null on the last page. |

### Invoice

Draft invoices are never shown.

| Field | Type | Description |
|---|---|---|
| `id` | string `^inv_[1-9][0-9]{0,9}$` |  |
| `number` | string |  |
| `status` | "paid" or "unpaid" or "cancelled" or "refunded" or "collections" or "payment_pending" or "other" |  |
| `date` | string (date) or null |  |
| `due_date` | string (date) or null |  |
| `paid_at` | string (date-time) or null | UTC, ISO 8601, always with Z. |
| `currency` | string `^[A-Z]{3}$` | ISO 4217 code of the account's currency. |
| `subtotal` | string `^-?[0-9]{1,13}\.[0-9]{2}$` | A decimal amount in major units, as a string (never a float). Example `"129.00"`. |
| `tax` | string `^-?[0-9]{1,13}\.[0-9]{2}$` | A decimal amount in major units, as a string (never a float). Example `"129.00"`. |
| `total` | string `^-?[0-9]{1,13}\.[0-9]{2}$` | A decimal amount in major units, as a string (never a float). Example `"129.00"`. |
| `credit` | string `^-?[0-9]{1,13}\.[0-9]{2}$` | Credit applied. |
| `balance` | string `^-?[0-9]{1,13}\.[0-9]{2}$` | Still due. |

### InvoiceItem

| Field | Type | Description |
|---|---|---|
| `description` | string |  |
| `amount` | string `^-?[0-9]{1,13}\.[0-9]{2}$` | A decimal amount in major units, as a string (never a float). Example `"129.00"`. |
| `taxed` | boolean |  |
| `service` | string `^srv_[1-9][0-9]{0,9}$` or null |  |

### InvoiceDetail

| Field | Type | Description |
|---|---|---|
| `id` | string `^inv_[1-9][0-9]{0,9}$` |  |
| `number` | string |  |
| `status` | "paid" or "unpaid" or "cancelled" or "refunded" or "collections" or "payment_pending" or "other" |  |
| `date` | string (date) or null |  |
| `due_date` | string (date) or null |  |
| `paid_at` | string (date-time) or null | UTC, ISO 8601, always with Z. |
| `currency` | string `^[A-Z]{3}$` | ISO 4217 code of the account's currency. |
| `subtotal` | string `^-?[0-9]{1,13}\.[0-9]{2}$` | A decimal amount in major units, as a string (never a float). Example `"129.00"`. |
| `tax` | string `^-?[0-9]{1,13}\.[0-9]{2}$` | A decimal amount in major units, as a string (never a float). Example `"129.00"`. |
| `total` | string `^-?[0-9]{1,13}\.[0-9]{2}$` | A decimal amount in major units, as a string (never a float). Example `"129.00"`. |
| `credit` | string `^-?[0-9]{1,13}\.[0-9]{2}$` | Credit applied. |
| `balance` | string `^-?[0-9]{1,13}\.[0-9]{2}$` | Still due. |
| `items` | array of [InvoiceItem](#schema-invoiceitem) |  |

### SshKey

| Field | Type | Description |
|---|---|---|
| `id` | string `^sshkey_[1-9][0-9]{0,9}$` |  |
| `name` | string |  |
| `type` | string |  |
| `fingerprint` | string or null |  |
| `added` | string (date-time) or null | UTC, ISO 8601, always with Z. |

### SshKeyList

| Field | Type | Description |
|---|---|---|
| `data` | array of [SshKey](#schema-sshkey) |  |

### SshKeyCreateRequest

| Field | Type | Description |
|---|---|---|
| `name` | string | Optional. Up to 64 characters; no control characters, < or >. |
| `public_key` | string | One line, as in id_ed25519.pub. |

### SshKeyDeleted

| Field | Type | Description |
|---|---|---|
| `id` | string `^sshkey_[1-9][0-9]{0,9}$` |  |
| `deleted` | true |  |
| `installed_servers_unchanged` | true | Removing a saved key does not touch servers where it is already installed. |

### LabelRequest

| Field | Type | Description |
|---|---|---|
| `label` | string `^[\p{L}\p{N} ._\-]{0,60}$` | Letters, digits, spaces, dots, dashes, underscores; at most 60. White space is collapsed. "" clears the label. Control characters are refused. |

### LabelResult

| Field | Type | Description |
|---|---|---|
| `id` | string `^srv_[1-9][0-9]{0,9}$` |  |
| `label` | string or null |  |

### RdnsRequest

| Field | Type | Description |
|---|---|---|
| `ip` | string | An IPv4 or IPv6 address assigned to this server. |
| `hostname` | string | A full host name (lower-cased, trailing dot removed), or "" to clear the PTR record. |

### RdnsAccepted

| Field | Type | Description |
|---|---|---|
| `server_id` | string `^srv_[1-9][0-9]{0,9}$` |  |
| `ip` | string |  |
| `hostname` | string |  |
| `state` | "pending" |  |
| `already_requested` | boolean | True when the same change was already waiting. |

### RdnsList

The requests applied by the scheduled job come first (oldest first), then up to 20 changes carried out as actions (newest first). To find the newest entry for an IP, sort by requested.

| Field | Type | Description |
|---|---|---|
| `server_id` | string `^srv_[1-9][0-9]{0,9}$` |  |
| `data` | array of object |  |

### PowerRequest

| Field | Type | Description |
|---|---|---|
| `action` | "on" or "off" or "reboot" |  |

### ActionAccepted

An action was recorded and will run shortly. Poll GET /actions/{id}.

| Field | Type | Description |
|---|---|---|
| `id` | string `^act_[1-9][0-9]{0,9}$` |  |
| `kind` | "power" |  |
| `server_id` | string `^srv_[1-9][0-9]{0,9}$` |  |
| `action` | "on" or "off" or "reboot" |  |
| `state` | "queued" |  |
| `poll_after` | integer |  |

### Action

| Field | Type | Description |
|---|---|---|
| `id` | string `^act_[1-9][0-9]{0,9}$` |  |
| `kind` | "label" or "rdns" or "ssh_key_add" or "ssh_key_remove" or "power" or "cancel_request" or "cancel_withdrawal" or "reinstall" or "rescue" or null |  |
| `server_id` | string `^srv_[1-9][0-9]{0,9}$` or null |  |
| `action` | "on" or "off" or "reboot" or null |  |
| `state` | "queued" or "running" or "done" or "failed" or "unknown" | unknown: the outcome could not be confirmed. No further API power action runs on that server until RedSwitches settles it. |
| `reason` | "expired" or "server_busy" or "server_not_active" or "server_changed" or "power_paused" or "not_supported" or "provider_refused" or "no_answer" or "provider_unavailable" or "settled_by_staff" or "key_no_longer_allowed" or "ip_not_on_server" or "paused" or "not_tracked" or "password_unavailable" or null | For failed and unknown actions. A done action has none, except password_unavailable (a reinstall or rescue started, but the password asked for could not be kept) and not_tracked. Null otherwise or when there is no public word for it. |
| `created` | string (date-time) or null | UTC, ISO 8601, always with Z. |
| `started` | string (date-time) or null | UTC, ISO 8601, always with Z. |
| `finished` | string (date-time) or null | UTC, ISO 8601, always with Z. |

### OrderCreateRequest

Exactly these fields; anything else is 400 invalid_body. Nothing from the body is echoed back.

| Field | Type | Description |
|---|---|---|
| `offer_id` | string `^ofr_[1-9][0-9]{0,9}$` |  |
| `billing_cycle` | "monthly" | Only monthly in this release. |
| `os_id` | string `^os_[1-9][0-9]{0,9}$` | One of the offer's os choices. |
| `ssh_key_id` | string `^sshkey_[1-9][0-9]{0,9}$` | Optional: a key saved on the account. |
| `label` | string `^[\p{L}\p{N} ._\-]{1,60}$` |  |
| `expected_total` | [MinorAmount](#schema-minoramount) | The total you expect to pay now, from a dry run. Required unless dry_run=true. |

### OrderCreated

| Field | Type | Description |
|---|---|---|
| `id` | string `^ord_[1-9][0-9]{0,9}$` |  |
| `invoice_id` | string `^inv_[1-9][0-9]{0,9}$` |  |
| `server_ids` | array of string `^srv_[1-9][0-9]{0,9}$` |  |
| `status` | "paid" |  |
| `delivery` | "queued" |  |
| `billing_cycle` | "monthly" |  |
| `total` | [MinorAmount](#schema-minoramount) | Paid now, tax included, minor units. |
| `recurring` | [MinorAmount](#schema-minoramount) | Each following cycle, before tax, minor units. |
| `paid_from_credit` | [MinorAmount](#schema-minoramount) | An amount in MINOR units (cents) as a string of digits, and its currency. Used by ordering: `{"amount":"15609","currency":"EUR"}` is 156.09 EUR. |
| `poll_after` | 30 |  |

### OrderDryRun

| Field | Type | Description |
|---|---|---|
| `dry_run` | true |  |
| `offer_id` | string `^ofr_[1-9][0-9]{0,9}$` |  |
| `billing_cycle` | "monthly" |  |
| `total` | [MinorAmount](#schema-minoramount) | The first payment (setup and tax included). Send this as expected_total. |
| `recurring` | [MinorAmount](#schema-minoramount) | Each following cycle, before tax. |
| `paid_from_credit` | [MinorAmount](#schema-minoramount) | What would be paid from credit (the same shape as the 201 answer). |

### ErrorDetails

Typed facts to act on, computed by RedSwitches (never an echo of the request).

| Field | Type | Description |
|---|---|---|
| `total` | [MinorAmount](#schema-minoramount) | price_changed: the current total. |
| `needed` | [MinorAmount](#schema-minoramount) | insufficient_credit: the amount missing. |
| `cap` | "servers_day" or "servers_month" or "open" or "money_month" or "renewal_month" or "key_month" | cap_reached: the limit the order would go over. |
| `order` | string `^ord_[1-9][0-9]{0,9}$` | order_under_review: the order that was created. |
| `retry_after` | integer | in_progress, cooling_off: seconds to wait. |
| `limit` | integer or [MinorAmount](#schema-minoramount) | action_limit: the ceiling (an integer). cap_reached: the limit in force: an integer for servers_day, servers_month and open; an amount in the account's currency (minor units) for money_month, renewal_month and key_month. |
| `window` | "day" or "30_days" or "open" | cap_reached: the window of the limit: day (servers_day), 30_days (servers_month, money_month, renewal_month, key_month), open (paid orders not delivered yet; no time window). |
| `per` | "server_hour" or "account_hour" or "server_day" or "account_day" | action_limit: the window of the ceiling. |
| `field` | string | invalid_body: the documented field that failed (absent when the failure is not about one field). |
| `reason` | string | invalid_body: what is accepted, in fixed words (never your value). |

### Error

| Field | Type | Description |
|---|---|---|
| `error` | object |  |

### RdnsQueued

The change is carried out as an action. Poll GET /actions/{id}.

| Field | Type | Description |
|---|---|---|
| `id` | string `^act_[1-9][0-9]{0,9}$` |  |
| `server_id` | string `^srv_[1-9][0-9]{0,9}$` |  |
| `ip` | string |  |
| `hostname` | string | "" when the PTR is being cleared. |
| `state` | "queued" |  |
| `already_requested` | boolean | True when the same change was already open; its action is returned. |
| `poll_after` | integer |  |

### CancelRequestBody

The body may be omitted or {}.

| Field | Type | Description |
|---|---|---|
| `reason` | string | Optional. Up to 255 characters; no control characters, < > { }. |

### CancellationState

The server's cancellation request. A request made through the API takes effect at the end of the billing period.

| Field | Type | Description |
|---|---|---|
| `server_id` | string `^srv_[1-9][0-9]{0,9}$` |  |
| `state` | "none" or "requested" or "withdrawal_requested" |  |
| `requested` | string (date-time) or null | UTC, ISO 8601, always with Z. |
| `effective` | string (date) or null | When the server ends (its next due date). |
| `type` | "end_of_billing_period" or "immediate" or null |  |

### OsImageList

data is null (reason not_collected) until the list has been read for this server's current hardware.

| Field | Type | Description |
|---|---|---|
| `server_id` | string `^srv_[1-9][0-9]{0,9}$` |  |
| `as_of` | string (date-time) or null | UTC, ISO 8601, always with Z. |
| `reason` | "not_collected" or null |  |
| `data` | array of object or null |  |

### ReinstallRequest

| Field | Type | Description |
|---|---|---|
| `os_id` | string `^img_[A-Za-z0-9_.-]{1,64}$` | An image id from GET /servers/{id}/os (img_…; the order's os_… ids are refused with 400). |
| `ssh_key_ids` | array of string `^sshkey_[1-9][0-9]{0,9}$` | 1 to 10 saved keys to install. |
| `hostname` | string | Optional. Lower-case letters, digits, dots and dashes. |
| `raid` | "none" or "raid0" or "raid1" or "raid10" | Optional; only on servers that offer a RAID choice (else 422 not_supported). |
| `return_password` | boolean | Optional, default false. True: the root password set by the reinstall can be read ONCE from GET /actions/{id}/credentials after the action is done (within 24 hours). False: it is never returned (emailed to the owner as in the portal). |

### RescueRequest

The body may be {}.

| Field | Type | Description |
|---|---|---|
| `return_password` | boolean | Optional, default false. True: the rescue login can be read ONCE from GET /actions/{id}/credentials after the action is done (within 24 hours). False: the rescue login is delivered as in the portal. |

### RescueAccepted

| Field | Type | Description |
|---|---|---|
| `id` | string `^act_[1-9][0-9]{0,9}$` |  |
| `kind` | "rescue" |  |
| `server_id` | string `^srv_[1-9][0-9]{0,9}$` |  |
| `state` | "queued" |  |
| `return_password` | boolean |  |
| `poll_after` | integer |  |

### Credentials

Returned once. Store it at once: the next read is 404. The owner is emailed that a password was retrieved (never the password).

| Field | Type | Description |
|---|---|---|
| `action_id` | string `^act_[1-9][0-9]{0,9}$` |  |
| `server_id` | string `^srv_[1-9][0-9]{0,9}$` |  |
| `username` | string |  |
| `password` | string |  |

### ReinstallAccepted

| Field | Type | Description |
|---|---|---|
| `id` | string `^act_[1-9][0-9]{0,9}$` |  |
| `kind` | "reinstall" |  |
| `server_id` | string `^srv_[1-9][0-9]{0,9}$` |  |
| `os_id` | string `^img_[A-Za-z0-9_.-]{1,64}$` | An OS image id for reinstall (another namespace than the order's os_<n> choices). |
| `state` | "queued" |  |
| `return_password` | boolean |  |
| `poll_after` | integer |  |

## Error codes

| Status | Code | Message |
|---|---|---|
| 400 | `body_not_allowed` | This request must not have a body. |
| 400 | `idempotency_key_required` | This request needs an Idempotency-Key header of 8 to 64 letters, digits, dashes or underscores. |
| 400 | `invalid_body` | The request body is not valid JSON of the documented shape for this endpoint. Unknown fields are refused. |
| 400 | `invalid_parameter` | A query parameter is not allowed here or its value is not valid. See the API documentation for this endpoint. |
| 400 | `key_in_url` | API keys are accepted only in the Authorization header. A working key sent in a URL is revoked. |
| 401 | `invalid_key` | Missing or invalid API key. Send it as "Authorization: Bearer <key>". |
| 401 | `key_expired` | This API key has expired. |
| 401 | `key_revoked` | This API key has been revoked. |
| 401 | `test_key` | Test keys cannot be used on the live API. |
| 402 | `insufficient_credit` | The account credit that may be spent through the API does not cover this order. Add funds in the client area. |
| 403 | `account_blocked` | API access for this account is blocked. Please contact support. |
| 403 | `account_inactive` | This account is not active. |
| 403 | `api_not_enabled` | API access is not enabled for this account. |
| 403 | `cap_reached` | This order would go over a limit of this key or of the account. Nothing was ordered. |
| 403 | `cooling_off` | Ordering opens 24 hours after it was turned on and after a new ordering key. |
| 403 | `email_not_verified` | The account owner must verify their email address before the API can be used. |
| 403 | `ip_not_allowed` | This key cannot be used from your IP address. |
| 403 | `not_eligible` | This account cannot order through the API right now. The account owner can see the reason on the API page. |
| 403 | `not_invited` | API access is by invitation only for now. |
| 403 | `ordering_not_enabled` | Ordering through the API is not turned on for this account. The owner turns it on on the API page. |
| 403 | `ordering_paused` | Ordering through the API is paused by RedSwitches. Nothing was ordered. Try again later. |
| 403 | `owner_changed` | This API key was created by a user who no longer owns the account. The owner must create a new key. |
| 403 | `permission_denied` | This API key does not have the permission this endpoint needs. |
| 403 | `power_paused` | Power actions through the API are paused for this account. RedSwitches staff have been told. |
| 404 | `not_found` | Nothing was found at this address: no such endpoint, or no such item on this account. |
| 405 | `method_not_allowed` | This endpoint does not take this method. The Allow header lists the methods it takes. |
| 409 | `in_progress` | A request with this Idempotency-Key is still being processed. Ask again with the same key in a few seconds. |
| 409 | `order_not_placed` | The order could not be completed and nothing was charged. RedSwitches staff have been told. |
| 409 | `order_under_review` | This order needs a check by RedSwitches staff before it continues. Do not repeat it; you will hear from us. |
| 409 | `price_changed` | The total is not the expected_total that was sent. Nothing was ordered. The current total is in the details. |
| 409 | `server_busy` | Another action on this server is queued, running or unsettled. Wait until it has finished, then try again. |
| 409 | `server_not_active` | This server is not active (pending, suspended or ended), so this action is not available. |
| 409 | `sold_out` | This server is not in stock any more. Nothing was ordered. |
| 409 | `ssh_key_conflict` | That key is already saved on this account, or the account holds the most keys it can. |
| 413 | `body_too_large` | The request body is larger than 16 KB. |
| 422 | `idempotency_conflict` | This Idempotency-Key was used for a different request. Use a new key for a new order. |
| 422 | `invalid_ssh_key` | That is not a valid SSH public key. |
| 422 | `ip_not_on_server` | That IP address is not assigned to this server. |
| 422 | `not_orderable` | This offer cannot be ordered with these choices through the API. |
| 422 | `not_supported` | This server does not support that through the API. |
| 429 | `action_limit` | This would go over a limit of the account for this action (see the details). Nothing was changed. Try again later. |
| 429 | `rate_limited` | Too many requests. Wait for the number of seconds in the Retry-After header. |
| 500 | `internal_error` | Something went wrong on our side. Quote the request id when you contact support. |
| 503 | `unavailable` | The API is temporarily unavailable. |
