---
title: "Create VM"
method: POST
path: "/api/v1/vms"
tags: ["Virtual Machines"]
---

# Create VM

`POST /api/v1/vms`

Create a new virtual machine with a chosen OS template, compute plan, and region. The VM is automatically assigned to a VPC for private networking.

## Authentication

How your VM is accessed depends on the OS:

- **Linux** — provide `ssh_keys`, `password`, or both. At least one is required.
- **Windows** — `password` is required. SSH keys are not supported.

## Extra Storage

Set `extra_storage` (GB) to attach an additional block volume. On Linux, choose the filesystem with `extra_storage_type` (defaults to `ext4`). Windows volumes are automatically formatted as NTFS.

## Backups

- **Daily** — set `backup_type` to `daily`. Runs every day at `backup_time` (defaults to `8am`).
- **Weekly** — set `backup_type` to `weekly` with a `backup_date` (e.g. `Saturday`). Runs at `backup_time`.

Omit `backup_type` or set it to `none` to skip backups.

## VPC Network

Each VM is attached to a VPC for private networking:

1. **Use existing** — set `vpc_id` to join an existing VPC.
2. **Create new** — set `vpc_name` and `vpc_cidr` to create a custom VPC.
3. **Auto-create** (default) — leave all VPC fields empty. A VPC named `vpc-{vm-name}` is created automatically.

## Billing Checks

Before provisioning, the API validates:

- Account billing status (not banned, no failed payments)
- Active payment method exists

## Headers

- `X-Project-ID` string, uuid, required

## Request body

- CreateVMRequest
  - `name` string, required — VM display name
  - `template_id` string, uuid, required — OS template ID. Use `GET /api/v1/public/templates` to list available templates.
  - `pricing_id` integer, required — Pricing plan ID that determines vCPU, RAM, storage, and bandwidth. Use `GET /api/v1/public/pricing/vm` to list available plans.
  - `region` 'us-east', required — Data center region
  - `ssh_keys` string[] — SSH public keys for VM access. Required for Linux VMs if no password is provided. Ignored for Windows VMs.
  - `password` string — Root password for the VM. Required for Windows VMs. For Linux VMs, required if no SSH keys are provided. Both SSH keys and password can be set on Linux. Must be at least 12 characters with: 2+ uppercase letters, 2+ digits, 1+ special character (@+-_.,!). Only alphanumeric characters and @+-_.,! are allowed.
  - `extra_storage` integer — Additional block storage volume in GB (0–10,000). Attached as a separate disk to the VM.
  - `extra_storage_type` 'ext4' | 'xfs' | 'btrfs' — Filesystem type for extra storage. Required for Linux VMs with extra storage (defaults to ext4 if omitted). For Windows VMs, storage is automatically formatted as NTFS — this field is ignored.
  - `backup_type` 'none' | 'daily' | 'weekly' — Set `daily` for daily backups or `weekly` for weekly backups. Use `none` or omit for no backups.
  - `backup_time` string — Time of day to run backups (e.g. `8am`). Defaults to `8am` if not specified.
  - `backup_date` string — Day of the week for weekly backups (e.g. `Saturday`). Required when `backup_type` is `weekly`, ignored for daily backups. Valid values: Monday–Sunday.
  - `tags` string[] — Custom tags for the VM
  - `vpc_id` string, uuid — Attach VM to an existing VPC by its ID. If omitted along with `vpc_name`, a VPC is auto-created.
  - `vpc_name` string — Create a new VPC with this name. Must be used together with `vpc_cidr`.
  - `vpc_cidr` string — CIDR block for the new VPC (e.g. `10.0.1.0/24`). Must be used together with `vpc_name`.
  - `skip_public_ip` boolean — When `true`, the VM is created without a public IPv4 address. It will only be reachable on its VPC private IP, so a VPC is required — pass `vpc_id` (existing) or `vpc_name` + `vpc_cidr` (new), or leave VPC fields empty to auto-create one. Combining `skip_public_ip=true` with `skip_vpc=true` is rejected because the VM would have no network at all.
  - `skip_vpc` boolean — When `true`, no VPC is created or attached. The VM will only have its public IP — no private networking. Cannot be combined with `skip_public_ip=true`.

## Response `201`

VM created successfully

- object
  - `success` boolean
  - `data` VM
    - `id` string, uuid, required — Unique VM identifier
    - `name` string, required — VM display name
    - `status` 'active' | 'passive' | 'provisioning' | 'booting' | 'initiating' | 'finalizing' | 'failure', required — Current VM status. Lifecycle transitions: - Creation: `initiating` → `provisioning` → `booting` → `active` - Stop: `active` → `finalizing` → `passive` - Start: `passive` → `booting` → `active` - Reboot: `active` → `booting` → `active` | Status | Meaning | Billable | |--------|---------|----------| | `initiating` | Queued, initial setup before provisioning | Yes | | `provisioning` | VM being created in the hypervisor | Yes | | `booting` | VM starting up | Yes | | `active` | Running and accessible | Yes | | `passive` | Stopped, resources still reserved | Yes | | `finalizing` | Shutting down | Yes | | `failure` | Creation or operation failed | No |
    - `cpu` integer, required — Number of vCPU cores
    - `ram` integer, required — RAM in GB
    - `storage` integer, required — Base storage in GB
    - `added_storage` integer, required — Additional storage in GB
    - `total_storage` integer, required — Total storage (base + added) in GB
    - `template_id` string, uuid, required — OS template ID used to create this VM
    - `template_name` string, required — OS template name
    - `template_version` string, required — OS template version
    - `version` string — VM version
    - `price_per_hour` string, required — Hourly billing rate in USD
    - `pricing_id` integer, required — Pricing plan ID
    - `created_by` string — User ID who created this VM
    - `billing_type` 'payg' | 'subscription' — Billing type for this VM
    - `subscription_id` string, uuid — Subscription ID if billing_type is subscription
    - `backup_type` string, nullable — Backup schedule type
    - `region` 'us-east', required — Data center region
    - `project_id` string, uuid — Project this VM belongs to
    - `public_ipv4_address` string — Public IPv4 address
    - `public_ipv6_address` string, nullable — Public IPv6 address
    - `private_ipv4_address` string — Private IPv4 address (VPC)
    - `private_ipv6_address` string, nullable — Private IPv6 address
    - `tags` VMTag[] — Custom tags
      - `id` string, required — Unique tag identifier
      - `name` string, required — Tag name
      - `priority` integer, required — Tag priority (ordering)
      - `created_at` string, date-time, required — When the tag was created
    - `active` boolean, required — Whether the VM is active
    - `created_at` string, date-time, required
    - `updated_at` string, date-time, required

## Other responses

- `400` — Invalid request parameters
- `401` — Authentication required
- `402` — Account balance is insufficient for this operation. Top up the balance and retry.
- `403` — Billing validation failed. The account is not in good standing. Check the `reason` field: - `banned` — account suspended - `failed` — last payment failed; top up the account balance - `no_billing_customer` — billing not set up

---

[API](https://skmtc.net/rafftechnologies/apis/raff-api.md) · [All operations](https://skmtc.net/rafftechnologies/apis/raff-api/llms.txt) · [OpenAPI document](https://skmtc-service-staging.skmtc.workers.dev/v1/apis/rafftechnologies/raff-api/versions/a3f123570011/schema)
