# Order a VPS

Source: https://docs.imprezahost.com/order-vps.html

The VPS is one configurable product. You choose the location it runs in, the operating system, the number of vCPUs, the memory and the SSD disk, and what it is born with — the same choices as the store's configurator. Its price for a billing cycle is each resource's quantity times its unit price for that cycle. Tor Hosting plans and dedicated servers remain fixed plans with their own product ids.

The store's software choice is explicit: **No app** leaves the server without the Impreza Agent; you can [add it later with one click](#add-agent). Choosing the agent, Agent + MCP or a supported catalog app includes the agent; VPS installation runs during provisioning, while dedicated-server installation is performed by our team. Agent + MCP adds a setup guide for compatible AI tools, which still require your authorization. Control panels use a separate environment without the agent. Tor Hosting keeps its own aaPanel-based profiles.

The agent supports catalog, Docker-image and Git deployments, onion publishing, supported application backups and restores, and MCP-assisted application operations. Impreza Shield is opt-in per app and starts in audit mode, which counts but never blocks. VM backups and snapshots are infrastructure features and do not require choosing the Impreza Agent.

In **My Apps**, every **New server** or **Buy a server** link opens the [VPS configurator](https://portal.imprezahost.com/offshore-vps-servers). Choose the location, operating system, size and optional first-boot app there, then review the cart. The panel does not place an order in one click. The same portal path works on the portal's onion hostname without putting the configuration in the URL.

Everything is paid from the account credit balance. Top up first with `POST /v1/account/topup` or `impreza_topup` (Bitcoin, Monero, USDT, TRX) if the balance is short.

**Starting with an anonymous account?** Its initial MCP token is valid for
**15 minutes**. Renew through `POST /v1/credentials` using the account's REST key
and secret; a purchase requires the appropriate scopes, including `manage`,
and explicit spending ceilings. Older anonymous-account tokens without an
expiry expire on **16 October 2026 at 21:48 UTC**. Follow
[anonymous-account renewal](/tutorials/ai-mcp-integration.html#anonymous-account)
before continuing an unattended order. The creation IP is cleared after 24 hours
on the next cron pass; this does not delete backups or the operational account row.

> **MCP purchase default (hosted MCP since 21 October 2026; local `impreza-mcp` 0.54.0 or later):** for both configurable VPS products and fixed VPS plans, hosted and local MCP request Impreza Agent (`@agent`) when `app` is omitted, `null`, empty or whitespace-only. Explicit `none`, `@agent`, `@agent-mcp` or another supported app remains the requested choice. Non-VPS products do not gain an agent from this default. Direct REST, the portal and a cart opened directly keep **No app** (`none`). An existing local installation keeps its previous default until it is updated to 0.54.0.

The hosted MCP keeps its existing quote and confirmation: it shows the initial app before ordering, including for a fixed VPS plan. A checkout link originating from that MCP preserves the app presented to the customer. The local MCP states the default in the tool description and schema before invocation and places a direct REST order; it does not add a new fixed-plan quote or confirmation-token step. Its returned `app_requested` is the requested app, not evidence of installation. Local MCP refuses non-text app values before purchase I/O. Supported explicit choices are preserved and invalid-app errors must remain visible without silently choosing a different app.

An accepted order or 202 is separate from first-boot installation. Verify service binding, heartbeat and capabilities before treating the agent as ready. The purchase default by itself does not demonstrate an installation. Use explicit `app: "none"` when a bare OS is intended; existing servers, credentials and MCP client connections are not changed automatically.

## Find the right product

`GET /v1/products` (MCP: `impreza_list_products`) lists the configurable VPS first, with `kind: "vps"`, `recommended: true`, `quote_tool: "impreza_vps_offer"` and `order_tool: "impreza_order_vps"`. Its listed price is the smallest configuration, not a quote for the size you will buy. Other entries carry `kind: "tor_hosting"`, `"dedicated"` or `"other"` as appropriate. Existing product and pricing fields remain available.

For an ordinary VPS, use `impreza_vps_offer` to choose and quote a size, then `impreza_order_vps` without `product_id`. A hidden or old fixed VPS id, including 757, is refused even when supplied directly; it does not create an order or charge the account. Tor Hosting and Dedicated Server + plans remain available by their listed ids.

## Choose a configuration

`GET /v1/products/vps` (MCP: `impreza_vps_offer` with no arguments) returns, in your account currency:

- `locations` — each with an `id`, a `slug`, a `name` and, when known, its `country` and a short note on what that jurisdiction is best for;
- `operating_systems` — `id`, `slug`, `name` and `family`;
- `resources` — `cpu_cores`, `memory_gb` and `disk_gb`, each with its `min`, `max` and `price_per_unit` for every billing cycle it is sold on;
- `apps` — what the VPS can be born with, and the default;
- `starting_at` — the price of the smallest configuration per cycle.

`location` and `os` accept the `id`, the `slug` or the `name`. Names are compared on letters and digits only, so `"Ubuntu 24.04"`, `"ubuntu-24.04"` and `"ubuntu2404"` are the same choice. A location or OS that is hidden in the store is not offered here either.

## Get the exact price

Price one configuration before ordering it:

```
GET /v1/products/vps/quote?billing_cycle=monthly&location=romania&os=ubuntu-24.04&cpu_cores=2&memory_gb=4&disk_gb=40
```

The quote lists every line, `due_today` (also in cents), what it `renews` at, whether your `balance_covers` it and the `top_up_needed` otherwise, and `location_available`: whether that location has a server that can take a new VPS right now (`null` when that cannot be told). It also returns the exact `order` body to send. With MCP, pass the same six values to `impreza_vps_offer`.

The quote and the order use the same calculation, so the amount quoted is the amount charged. Nothing is ordered or reserved by a quote.

## Order it

```
POST /v1/orders
{
  "billing_cycle": "monthly",
  "location": "romania",
  "os": "ubuntu-24.04",
  "cpu_cores": 2,
  "memory_gb": 4,
  "disk_gb": 40,
  "hostname": "web-1"
}
```

Leave `product_id` out for the VPS. The call answers `202` with `status: provisioning` and the configuration once every check has passed; the VPS is usually ready in a few minutes. Poll `GET /v1/platform/servers` or `GET /v1/account/services`.

- `app` — what the VPS is born with. Direct REST orders default to `none` (a bare OS, no agent), matching a cart opened directly in the portal. The MCP purchase default is described above; it does not change the REST field default. Choose `@agent` explicitly to install the Impreza agent at first boot, or request it later through the AI with `impreza_install_agent` and your confirmation. `@agent-mcp` adds the agent's MCP setup; `none` is a bare OS; a `@panel-*` choice makes it a control-panel server (an OS the panel cannot run is refused with `INCOMPATIBLE_OS`); any app name from `GET /v1/platform/apps` installs that app on first boot.
- `hostname` — optional, a DNS name such as `web-1`. Without one, the VPS gets a generated hostname.
- `max_amount` — optional; the order is refused with `PRICE_ABOVE_LIMIT` if it would cost more.

With hosted MCP, call `impreza_order_vps` with the same values. The first call orders nothing: it returns the price, what is being bought and a `confirm_token`. Show that to the customer, then repeat the same arguments with `confirm_token` to place the order. The token is signed for the quoted amount — if the price changed in between, the order is refused, not charged — and the purchase counts against the credential's daily spend ceiling.

Clients using hosted MCP through an external checkout (such as ChatGPT) get a store link instead, already filled in with the configuration. The customer reviews it and completes the purchase there. The link never carries the hostname. Under the candidate MCP contract, it must retain the initial app reviewed in the MCP offer, including an explicit `none`; opening the portal cart directly still starts with No app. An invalid app or incompatible OS must be refused with a reason, without silently selecting a different app.

An accepted order (`202` or an order ID) is not an installed, usable agent. While installation is pending or has failed, preserve that status. Treat the agent as ready only after it is bound to the ordered service and its heartbeat and capabilities are verified. Installing the agent does not create a customer app, connect an MCP client or issue a new credential automatically. Existing servers are not reinstalled or updated by this default change.

## Add the agent later

A VPS ordered with **No app** has no Impreza Agent. You can add it later from the VPS page in the client area: open the service and use **Install the Impreza Agent with one click**.

1. The card shows the installer URL and the **SHA-256 of the exact script** that will run. The one-time registration token is added when the script runs; it is never shown or stored in the log.
2. Tick **I allow Impreza to run this script as root on this server** and choose **Install the agent**.
3. The install runs inside the server through the QEMU guest agent: it installs Docker if missing and the `impreza-agent` service, and registers the server with your account. Nothing else on the server is changed. Within about a minute the agent shows as `status: online` in **My Apps**.

The server re-checks every rule when you press the button, and the consent is bound to the script you were shown: if the script changed after the page loaded, the request is refused and you are asked to review it again. Only one install runs per server at a time.

The button is not offered when:

| Situation | What to do instead |
| --- | --- |
| Windows server | The agent supports Linux only. |
| Control-panel server (`@panel-*`) | The panel manages the server; the agent is not installed on it. |
| AlmaLinux, Rocky Linux, RHEL, CentOS or Oracle Linux (read from the server itself) | Use the manual installer from **My Apps**, below. |
| The QEMU guest agent does not answer | Use the manual installer from **My Apps**, below. |
| An agent is already registered for this server | Manage it in **My Apps**. |
| The service is not active, or has no server yet | Wait until the VPS is active. |

**Manual installer:** in **My Apps**, choose **+ Add another server** to get a 10-minute bootstrap one-liner and run it as `root` on the server (see [the AI and MCP tutorial](/tutorials/ai-mcp-integration.html#agent)).

The agent stays optional. Installing it with the button does not change the software choice of your order, so **reinstalling the operating system does not bring the agent back**. To remove it, use **Uninstall agent** in **My Apps**.

### Through your AI assistant

An AI assistant connected over MCP can find these servers and offer the same install, with your agreement. It should offer it only when what you asked for needs the agent: deploying an app, metrics, app backups or app logs.

- `impreza_get_account_overview` lists `agentless_servers`: each VPS of your account without the agent, with `agent_installable` and, when it is `false`, the `reason`. The section is present only for an unrestricted credential. Up to 10 servers are checked live per call; the rest answer `not_checked`, and `impreza_get_agent_install` checks one alone.
- `impreza_install_agent` takes two calls. The first installs nothing: it says what the agent is and returns a `confirm_token`, valid for 5 minutes, for that server, that credential and that exact script. The assistant tells you and asks; only with your agreement does it repeat the call with the token. The install is the same as the button's.
- `impreza_get_agent_install` follows it: `state` goes from `installing` to `online`, usually within a few minutes.

The install needs the `manage` scope. It is refused for a credential confined to specific resources, and a credential whose [human approval](/security/human-approvals.html) policy covers the `security` class waits for your approval in the client area instead. A server outside Impreza cannot be installed from the API: use the manual installer above.

| `reason` | Meaning |
| --- | --- |
| `server_stopped` | The VPS is stopped. Start it first. |
| `guest_agent_unavailable` | The QEMU guest agent does not answer. Use the manual installer. |
| `os_rhel_family` | AlmaLinux, Rocky Linux, RHEL, CentOS or Oracle Linux. Use the manual installer. |
| `os_unsupported` | Windows. The agent supports Linux only. |
| `os_unknown` | The operating system could not be read. Use the manual installer. |
| `service_not_active`, `not_provisioned` | Wait until the VPS is active. |
| `control_panel_server` | The panel manages the server. |
| `install_in_progress` | An install or setup is already running. Follow it with `impreza_get_agent_install`. |
| `agent_present` | The agent is already registered. |
| `platform_unavailable` | The server could not be checked right now. Try again later. |

**Over REST**, the same flow:

1. `GET /v1/platform/services/{id}/agent-install` (scope `read`) returns the state above and, when the install applies, a `confirm_token` bound to the API key that asked.
2. `POST /v1/platform/services/{id}/agent-install` with `{"confirm_token": "..."}` (scope `manage`) queues the install and answers `202`.
3. Read the `GET` again until `state` is `online`.

| Answer | Why |
| --- | --- |
| `400 CONFIRMATION_REQUIRED` | No `confirm_token`. |
| `400 CONFIRMATION_INVALID` | The token is expired, from another API key or service, or the script changed. Read the `GET` again. |
| `404 NOT_FOUND` | Not a Proxmox VPS of your account. |
| `409 CONFIRM_TOKEN_USED` | That token was already spent. |
| `409 NOT_INSTALLABLE` | The install does not apply now; the message names the `reason`. |
| `409 AGENT_PRESENT` | The agent is already registered. |
| `503 PLATFORM_UNAVAILABLE` | The server could not be checked. Nothing was installed. |

## What is refused

Nothing is ordered or charged in any of these cases.

| Answer | Why |
| --- | --- |
| `400 INVALID_REQUEST` | A location or OS this VPS does not offer, a size outside its range or not a whole number, a billing cycle it is not sold on, a bad hostname, or `config_options`, `custom_fields` or `domain` sent for the VPS. Every wrong field is named with the values it accepts. |
| `400 INCOMPATIBLE_OS` | A control panel on an operating system it cannot run. |
| `409 INSUFFICIENT_BALANCE` | The balance does not cover the whole price. The answer includes the `top_up_needed`. |
| `409 LOCATION_UNAVAILABLE` | No server in that location can take a new VPS right now. Pick another location or try later. |
| `409 PRICE_ABOVE_LIMIT` | The price is above your `max_amount`. |
| `409 ORDER_IN_PROGRESS` | Another order for the VPS is being placed on your account at this moment. Retry in a few seconds. |
| `409 DUPLICATE_ORDER` | The same configuration was ordered in the last 24 hours, and that order is already accepted or still awaiting payment. |
| `409 FIXED_VPS_UNAVAILABLE` | An old fixed VPS id was supplied. Choose the configurable VPS with `GET /v1/products/vps` and order without `product_id`. Tor Hosting and Dedicated Server + keep their fixed ids. |

A repeat of an order that was already placed and paid returns that same order, with `repeat: true`, instead of creating a second one. An order is a repeat when the location, OS, sizes, app and billing cycle are the same and, if the new order names a hostname, the hostname too. To order another identical VPS, give it a different `hostname`.

## Resize a VPS

Give a VPS more vCPUs, memory or disk. A resize changes sizes only: the location, the operating system and the billing cycle stay as they are. Moving a VPS to another location is a migration, and changing its operating system is a reinstall.

Price it first, passing only the sizes that change:

```
GET /v1/services/{id}/resize/quote?cpu_cores=2&memory_gb=4&disk_gb=40
```

The quote returns `from` and `to` (the three sizes before and after), one line per size that grows with its amount, `due_today` (also in cents), `pro_rata` (the days left in the current billing period), what the VPS `renews` at from its next due date, whether your `balance_covers` it and the `top_up_needed` otherwise, `takes_effect`, and the exact `order` body to send. The amount is the billing system's own pro-rated figure, the one the invoice carries. Nothing is ordered by a quote.

Then resize it:

```
POST /v1/services/{id}/resize
{
  "cpu_cores": 2,
  "memory_gb": 4,
  "disk_gb": 40
}
```

The call answers `201` with the `order_id`, the `invoice_id`, the `amount` charged (also `amount_cents`), `from`, `to` and `applied`. The invoice is paid from the account balance, and the new sizes are written to the VPS once it is paid. `max_amount` is optional: the resize is refused with `PRICE_ABOVE_LIMIT` if it would cost more. Repeating a resize that already went through changes nothing and charges nothing: the VPS already has those sizes, so the answer is `409 NO_CHANGE`.

When each part takes effect: the new vCPU count and memory are set on the VPS at once, and the running system sees them after a restart through the API — `POST /v1/vps/proxmox/{id}/reboot`, or `impreza_vps_power` with `action=reboot`. A reboot from inside the server keeps the old vCPU count and memory. The disk is enlarged at once; the root filesystem grows into the new space at that restart.

Sizes only go up: a VPS cannot be made smaller. Each size stays within the range `GET /v1/products/vps` lists, and memory may be limited per vCPU — the answer names the vCPU count a size needs.

With MCP, call `impreza_vps_resize` with the `service_id` and the new sizes. The first call resizes nothing: it returns the price, what changes, what the VPS renews at and a `confirm_token`. Show that to the customer, then repeat the same arguments with `confirm_token` to resize. The token is signed for the quoted amount — if the price changed in between, the resize is refused, not charged — and the resize counts against the credential's daily spend ceiling. Clients connected through an external checkout (such as ChatGPT) get the VPS's resize page in the client area instead, where the customer sets the sizes and confirms.

Nothing is ordered or charged in any of these cases:

| Answer | Why |
| --- | --- |
| `400 INVALID_REQUEST` | A size below the current one, outside its range, not a whole number or above what the vCPU count allows; `location`, `os`, `app`, `billing_cycle` or `product_id` sent to a resize; or a service that is not a configurable VPS. A fixed plan changes plan with `POST /v1/orders/{id}/upgrade`. |
| `404 NOT_FOUND` | No such VPS on this account. |
| `409 NO_CHANGE` | Nothing grows: the VPS already has these sizes. |
| `409 SERVICE_NOT_ACTIVE` | The VPS is suspended, pending or cancelled. |
| `409 UPGRADE_IN_PROGRESS` | An earlier upgrade of this VPS is still waiting for its invoice to be paid. Pay or cancel that invoice first. |
| `409 INSUFFICIENT_BALANCE` | The balance does not cover the amount due today. The answer includes the `top_up_needed`. |
| `409 PRICE_ABOVE_LIMIT` | The price is above your `max_amount`. |
| `409 ORDER_IN_PROGRESS` | Another change to this VPS is being placed at this moment. Retry in a few seconds. |
| `402 PAYMENT_NOT_SETTLED` | The balance changed while the resize was being placed and could not pay it. The resize was withdrawn and the VPS keeps its size. |

### Is it time to resize?

When the optional [Impreza agent](#add-agent) runs on the VPS, it reports the server's own CPU, memory and root-disk use with every heartbeat. The API keeps that as hourly totals for 14 days, and can tell sustained pressure from a peak:

```http
GET /v1/services/{id}/resize/recommendation
```

The answer never orders anything, and needs only the `read` scope. Its `status` is one of:

| `status` | Meaning |
| --- | --- |
| `recommended` | At least one resource has been under sustained pressure. `resources` says which and why, with what was observed; `proposal` has the sizes that would relieve it, the same quote as `GET /v1/services/{id}/resize/quote`, and `apply`, the body of the resize that would order it. |
| `no_recommendation` | Enough data, and no resource under sustained pressure. A short peak is shown in `observed` but is not a reason to resize. |
| `insufficient_data` | Fewer than 48 complete hours (an hour with at least 45 minutes of reports) in the last 72 hours, no complete hour in the last 6, or no agent on the VPS. Hours from before the VPS last changed size do not count. |
| `stale` | The agent has not reported in the last 15 minutes, so the current load is unknown. |
| `not_applicable` | The VPS is not active. |

The rules, the same for every VPS:

- CPU and memory are recommended when they averaged at least 80 % (CPU) or 85 % (memory) in 75 % of the complete hours **and** over the last 6. A recommendation stays until the last 6 hours fall below 65 % (CPU) or 70 % (memory), and once closed it cannot reopen for 24 hours.
- Disk is recommended when it was at least 85 % full in every one of the last 24 complete hours, and closes below 75 %.
- The proposed size puts the same use at about 60 % of the CPU, 70 % of the memory or 75 % of the disk, at least one vCPU, 1 GB or 10 GB more. A size that cannot be ordered, above the range or the per-vCPU memory limit, is named in `proposal_error` and not priced.
- These are the server's numbers as the agent sees them inside the VPS. An app at its own container memory limit is listed in `app_limits`: that is the app's setting, and a larger VPS does not raise it.

To act on it, resize as above: `POST /v1/services/{id}/resize` with the `apply.body`, which prices it again and needs the `manage` scope and a balance that covers it. When there is a proposal, `next_steps` names that call: `impreza_vps_resize` with the `service_id` and the proposed sizes.

With MCP, `impreza_vps_resize_recommendation` takes the `service_id` and returns the same answer; it is read-only and needs the `read` scope. A credential confined to other services is refused. It never resizes: an agent shows the proposal to the customer and, once they agree, calls `impreza_vps_resize`, which asks for its own confirmation.

In the client area, each server card on the apps page shows a **Size check** with the same status, the reason, how many complete hours it is based on and, when a larger size is recommended, the proposed sizes and today's price. Its only action is **Review the resize**, which opens the resize page; nothing is ordered until you confirm there.

A plan change is not a resize: `POST /v1/orders/{id}/upgrade` (MCP: `impreza_upgrade_service`) refuses to move the configurable VPS into or out of a plan with `409 UNSUPPORTED_UPGRADE`, and points to the resize.

## Fixed plans

Tor Hosting plans and dedicated servers are ordered with their `product_id` from `GET /v1/products`, which lists the VPS first, priced at its smallest size. For a plan with configurable options, pass them as `config_options` from `GET /v1/products/{id}`: each option must belong to that product, the ones you leave out take the default the store shows, and the price you are charged includes them.
