{
  "openapi": "3.0.3",
  "info": {
    "title": "CloudBlast API",
    "description": "The CloudBlast V2 API provides a modern RESTful interface for managing your cloud infrastructure programmatically. All responses follow a consistent `{ \"data\": ... }` or `{ \"error\": ... }` format.",
    "version": "2.0.0"
  },
  "servers": [
    {
      "url": "https://console.cloudblast.io/api/v2",
      "description": "Production"
    }
  ],
  "security": [
    {
      "bearerAuth": []
    }
  ],
  "paths": {
    "/account": {
      "get": {
        "operationId": "getAccount",
        "tags": [
          "Account"
        ],
        "summary": "Get account info",
        "description": "Returns your account details including name, email, credit balance, and resource limits.",
        "responses": {
          "200": {
            "description": "Account information",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Account"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          }
        }
      }
    },
    "/account/usage": {
      "get": {
        "operationId": "getAccountUsage",
        "tags": [
          "Account"
        ],
        "summary": "Get resource usage",
        "description": "Returns your current resource usage across all servers, including CPU, RAM, disk, and IP counts against your limits.",
        "responses": {
          "200": {
            "description": "Resource usage",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/AccountUsage"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          }
        }
      }
    },
    "/account/invoices": {
      "get": {
        "operationId": "listInvoices",
        "tags": [
          "Account"
        ],
        "summary": "List invoices",
        "description": "Returns a paginated list of your invoices, sorted by most recent first.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Page"
          }
        ],
        "responses": {
          "200": {
            "description": "Paginated invoice list",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Invoice"
                      }
                    },
                    "meta": {
                      "$ref": "#/components/schemas/PaginationMeta"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          }
        }
      }
    },
    "/plans": {
      "get": {
        "operationId": "listPlans",
        "tags": [
          "Plans"
        ],
        "summary": "List available plans",
        "description": "Returns all non-hidden plans sorted by monthly price.\n\nOptionally filter by `location_id` to only return plans available at a specific location (global plans + location-specific plans). When `location_id` is provided, each plan includes an `available` field indicating whether it is currently in stock. If a location that is not open for ordering is specified, an empty list is returned.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Page"
          },
          {
            "name": "location_id",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer"
            },
            "description": "Filter plans by location. Returns global plans and plans specific to this location."
          }
        ],
        "responses": {
          "200": {
            "description": "Paginated plan list",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Plan"
                      },
                      "description": "When `location_id` is provided, each plan also includes an `available` boolean field indicating stock availability."
                    },
                    "meta": {
                      "$ref": "#/components/schemas/PaginationMeta"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "404": {
            "description": "Location not found (when location_id is provided)",
            "$ref": "#/components/responses/NotFound"
          }
        }
      }
    },
    "/locations": {
      "get": {
        "operationId": "listLocations",
        "tags": [
          "Locations"
        ],
        "summary": "List locations",
        "description": "Returns data center locations that are available for ordering. Coming soon locations are hidden. Each location includes `out_of_stock`, which is true when no visible plan can currently be provisioned there because of plan stock, node capacity, or IP availability.",
        "responses": {
          "200": {
            "description": "Location list",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Location"
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          }
        }
      }
    },
    "/locations/{location_id}/templates": {
      "get": {
        "operationId": "listLocationTemplates",
        "tags": [
          "Locations"
        ],
        "summary": "List templates for a location",
        "description": "Returns all available OS templates at a given location, identified by slug. Use the template `slug` when creating or reinstalling a server. Templates are deduplicated across nodes — you don't need to know which node will be selected.",
        "parameters": [
          {
            "name": "location_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer"
            },
            "description": "Location ID"
          }
        ],
        "responses": {
          "200": {
            "description": "Template list",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Template"
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      }
    },
    "/servers": {
      "get": {
        "operationId": "listServers",
        "tags": [
          "Servers"
        ],
        "summary": "List servers",
        "description": "Returns a paginated list of your servers. Optionally filter by status.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Page"
          },
          {
            "name": "status",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "installing",
                "install_failed",
                "suspended",
                "restoring_backup",
                "restoring_snapshot",
                "deleting",
                "deletion_failed"
              ]
            },
            "description": "Filter by server status. Omit to list all servers."
          }
        ],
        "responses": {
          "200": {
            "description": "Paginated server list",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Server"
                      }
                    },
                    "meta": {
                      "$ref": "#/components/schemas/PaginationMeta"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          }
        }
      },
      "post": {
        "operationId": "createServer",
        "tags": [
          "Servers"
        ],
        "summary": "Create a server",
        "description": "Creates a new server. The system automatically selects the best node in the given location based on available resources, template availability, and IP availability. Use template slugs (from `GET /locations/{id}/templates`) instead of UUIDs.\n\nTo install saved SSH keys during provisioning, pass their IDs in `ssh_key_ids`. Obtain key IDs from `GET /ssh-keys`. A root password is still generated and can be fetched after installation with `GET /servers/{server}/credentials`.\n\nThe server will be in `installing` status while being provisioned.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateServerRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Server created",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/CreatedServerDetail"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "402": {
            "description": "Overdue invoice",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "OVERDUE_INVOICE",
                    "message": "You have an overdue invoice. Please pay it before creating new servers."
                  }
                }
              }
            }
          },
          "422": {
            "$ref": "#/components/responses/ValidationError"
          }
        }
      }
    },
    "/servers/{server}": {
      "get": {
        "operationId": "getServer",
        "tags": [
          "Servers"
        ],
        "summary": "Get server details",
        "description": "Returns full details for a server including root password, plan info, and operating system. The server can be identified by either its full UUID or the 8-character short UUID.",
        "parameters": [
          {
            "$ref": "#/components/parameters/ServerIdentifier"
          }
        ],
        "responses": {
          "200": {
            "description": "Server details",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/ServerDetail"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      },
      "delete": {
        "operationId": "deleteServer",
        "tags": [
          "Servers"
        ],
        "summary": "Delete a server",
        "description": "Permanently deletes a server and releases its IP addresses back to the pool. This action is irreversible.",
        "parameters": [
          {
            "$ref": "#/components/parameters/ServerIdentifier"
          }
        ],
        "responses": {
          "204": {
            "description": "Server deletion initiated"
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          }
        }
      }
    },
    "/servers/{server}/credentials": {
      "get": {
        "operationId": "getServerCredentials",
        "tags": [
          "Servers"
        ],
        "summary": "Get server credentials",
        "description": "Returns the server password status and the decoded root password once installation is complete. While the server is still installing, `root_password` will be null and `password_status` will be `generating`.",
        "parameters": [
          {
            "$ref": "#/components/parameters/ServerIdentifier"
          }
        ],
        "responses": {
          "200": {
            "description": "Server credentials",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/ServerCredentials"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      }
    },
    "/servers/{server}/actions": {
      "post": {
        "operationId": "serverAction",
        "tags": [
          "Servers"
        ],
        "summary": "Send power action",
        "description": "Sends a power action to the server (start, shutdown, restart, kill, etc.).",
        "parameters": [
          {
            "$ref": "#/components/parameters/ServerIdentifier"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "action"
                ],
                "properties": {
                  "action": {
                    "type": "string",
                    "enum": [
                      "start",
                      "shutdown",
                      "restart",
                      "reset",
                      "kill",
                      "suspend",
                      "resume"
                    ],
                    "description": "The power action to perform"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Action initiated",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "object",
                      "properties": {
                        "action": {
                          "type": "string"
                        },
                        "status": {
                          "type": "string",
                          "example": "initiated"
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          }
        }
      }
    },
    "/servers/{server}/status": {
      "get": {
        "operationId": "getServerStatus",
        "tags": [
          "Servers"
        ],
        "summary": "Get real-time status",
        "description": "Returns the real-time status of the server from the hypervisor (e.g., `running`, `stopped`). Also includes the application-level status (e.g., `installing`, `suspended`).",
        "parameters": [
          {
            "$ref": "#/components/parameters/ServerIdentifier"
          }
        ],
        "responses": {
          "200": {
            "description": "Server status",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "object",
                      "properties": {
                        "state": {
                          "type": "string",
                          "description": "Real-time hypervisor state",
                          "example": "running"
                        },
                        "server_status": {
                          "type": "string",
                          "nullable": true,
                          "description": "Application-level status (null when server is healthy)",
                          "example": null
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      }
    },
    "/servers/{server}/reinstall": {
      "post": {
        "operationId": "reinstallServer",
        "tags": [
          "Servers"
        ],
        "summary": "Reinstall OS",
        "description": "Reinstalls the server with a new operating system template. All data on the server will be lost. You may optionally provide a new root password and install saved SSH keys by passing their IDs in `ssh_key_ids`.",
        "parameters": [
          {
            "$ref": "#/components/parameters/ServerIdentifier"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "template_slug"
                ],
                "properties": {
                  "template_slug": {
                    "type": "string",
                    "description": "Template slug (e.g., `ubuntu-24.04`)",
                    "example": "ubuntu-24.04"
                  },
                  "password": {
                    "type": "string",
                    "description": "New root password. If omitted, one will be generated.",
                    "minLength": 8,
                    "example": "myNewPassword123"
                  },
                  "ssh_key_ids": {
                    "type": "array",
                    "description": "IDs of saved SSH keys to install. Obtain IDs from `GET /ssh-keys`.",
                    "minItems": 1,
                    "maxItems": 20,
                    "uniqueItems": true,
                    "items": {
                      "type": "integer"
                    },
                    "example": [
                      12,
                      18
                    ]
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Reinstall initiated",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "object",
                      "properties": {
                        "status": {
                          "type": "string",
                          "example": "reinstalling"
                        },
                        "password": {
                          "type": "string",
                          "description": "The root password for the reinstalled server"
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "422": {
            "$ref": "#/components/responses/ValidationError"
          }
        }
      }
    },
    "/servers/{server}/rename": {
      "patch": {
        "operationId": "renameServer",
        "tags": [
          "Servers"
        ],
        "summary": "Rename server",
        "description": "Updates the display name of a server.",
        "parameters": [
          {
            "$ref": "#/components/parameters/ServerIdentifier"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "name"
                ],
                "properties": {
                  "name": {
                    "type": "string",
                    "maxLength": 40,
                    "description": "New server name",
                    "example": "my-web-server"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Updated server",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Server"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "422": {
            "$ref": "#/components/responses/ValidationError"
          }
        }
      }
    },
    "/servers/{server}/ips": {
      "get": {
        "operationId": "listServerIps",
        "tags": [
          "Server IPs"
        ],
        "summary": "List server IPs",
        "description": "Returns all IPv4 and IPv6 addresses assigned to the server.",
        "parameters": [
          {
            "$ref": "#/components/parameters/ServerIdentifier"
          }
        ],
        "responses": {
          "200": {
            "description": "IP address list",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/IpAddress"
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      },
      "post": {
        "operationId": "addServerIps",
        "tags": [
          "Server IPs"
        ],
        "summary": "Add extra IPs",
        "description": "Allocates additional IP addresses to the server from the available pool on the same node.",
        "parameters": [
          {
            "$ref": "#/components/parameters/ServerIdentifier"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "count"
                ],
                "properties": {
                  "count": {
                    "type": "integer",
                    "minimum": 1,
                    "maximum": 16,
                    "description": "Number of IPs to add",
                    "example": 1
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Newly added IP addresses",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/IpAddress"
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "description": "Rate limited — too many IP operations this week",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/servers/{server}/ips/{address}": {
      "delete": {
        "operationId": "removeServerIp",
        "tags": [
          "Server IPs"
        ],
        "summary": "Remove an IP",
        "description": "Removes a secondary IP address from the server. You cannot remove the primary IPv4 or IPv6 address.",
        "parameters": [
          {
            "$ref": "#/components/parameters/ServerIdentifier"
          },
          {
            "name": "address",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The IP address to remove (e.g., `203.0.113.50`)",
            "example": "203.0.113.50"
          }
        ],
        "responses": {
          "204": {
            "description": "IP removed"
          },
          "400": {
            "description": "Cannot remove primary IP",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "CANNOT_REMOVE_PRIMARY",
                    "message": "Cannot remove the primary IP address."
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "description": "Rate limited",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/servers/{server}/ips/{address}/rdns": {
      "put": {
        "operationId": "updateRdns",
        "tags": [
          "Server IPs"
        ],
        "summary": "Set reverse DNS",
        "description": "Sets the reverse DNS (PTR) record for an IP address.",
        "parameters": [
          {
            "$ref": "#/components/parameters/ServerIdentifier"
          },
          {
            "name": "address",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The IP address",
            "example": "203.0.113.50"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "rdns"
                ],
                "properties": {
                  "rdns": {
                    "type": "string",
                    "maxLength": 255,
                    "description": "The reverse DNS hostname",
                    "example": "server1.example.com"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Updated IP address",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/IpAddress"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "422": {
            "$ref": "#/components/responses/ValidationError"
          }
        }
      }
    },
    "/servers/{server}/backups": {
      "get": {
        "operationId": "listBackups",
        "tags": [
          "Backups"
        ],
        "summary": "List backups",
        "description": "Returns a paginated list of backups for a server.",
        "parameters": [
          {
            "$ref": "#/components/parameters/ServerIdentifier"
          },
          {
            "$ref": "#/components/parameters/Page"
          }
        ],
        "responses": {
          "200": {
            "description": "Paginated backup list",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Backup"
                      }
                    },
                    "meta": {
                      "$ref": "#/components/schemas/PaginationMeta"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      },
      "post": {
        "operationId": "createBackup",
        "tags": [
          "Backups"
        ],
        "summary": "Create a backup",
        "description": "Creates a new backup of the server. The server must not be in a conflicting state (installing, restoring, etc.).",
        "parameters": [
          {
            "$ref": "#/components/parameters/ServerIdentifier"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateBackupRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Backup created",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Backup"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "429": {
            "description": "Backup rate limit exceeded",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/servers/{server}/backups/{backup_uuid}/restore": {
      "post": {
        "operationId": "restoreBackup",
        "tags": [
          "Backups"
        ],
        "summary": "Restore a backup",
        "description": "Restores the server from a backup. The server will be unavailable during the restoration process.",
        "parameters": [
          {
            "$ref": "#/components/parameters/ServerIdentifier"
          },
          {
            "name": "backup_uuid",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Backup UUID"
          }
        ],
        "responses": {
          "200": {
            "description": "Restore initiated",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "object",
                      "properties": {
                        "status": {
                          "type": "string",
                          "example": "restoring"
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      }
    },
    "/servers/{server}/backups/{backup_uuid}": {
      "delete": {
        "operationId": "deleteBackup",
        "tags": [
          "Backups"
        ],
        "summary": "Delete a backup",
        "description": "Permanently deletes a backup. Locked backups cannot be deleted.",
        "parameters": [
          {
            "$ref": "#/components/parameters/ServerIdentifier"
          },
          {
            "name": "backup_uuid",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Backup UUID"
          }
        ],
        "responses": {
          "204": {
            "description": "Backup deleted"
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      }
    },
    "/ssh-keys": {
      "get": {
        "operationId": "listSSHKeys",
        "tags": [
          "SSH Keys"
        ],
        "summary": "List SSH keys",
        "description": "Returns all SSH keys associated with your account.",
        "responses": {
          "200": {
            "description": "SSH key list",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/SSHKey"
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          }
        }
      },
      "post": {
        "operationId": "createSSHKey",
        "tags": [
          "SSH Keys"
        ],
        "summary": "Add an SSH key",
        "description": "Adds a new SSH public key to your account.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "name",
                  "public_key"
                ],
                "properties": {
                  "name": {
                    "type": "string",
                    "maxLength": 40,
                    "description": "Display name for the key",
                    "example": "My Laptop"
                  },
                  "public_key": {
                    "type": "string",
                    "description": "The SSH public key",
                    "example": "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAA..."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "SSH key created",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/SSHKey"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "422": {
            "$ref": "#/components/responses/ValidationError"
          }
        }
      }
    },
    "/ssh-keys/{id}": {
      "delete": {
        "operationId": "deleteSSHKey",
        "tags": [
          "SSH Keys"
        ],
        "summary": "Delete an SSH key",
        "description": "Removes an SSH key from your account.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer"
            },
            "description": "SSH key ID"
          }
        ],
        "responses": {
          "204": {
            "description": "SSH key deleted"
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      }
    },
    "/security-groups": {
      "get": {
        "operationId": "listSecurityGroups",
        "tags": [
          "Security Groups"
        ],
        "summary": "List security groups",
        "description": "Returns all security groups owned by your account.",
        "responses": {
          "200": {
            "description": "Security group list",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/SecurityGroup"
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          }
        }
      },
      "post": {
        "operationId": "createSecurityGroup",
        "tags": [
          "Security Groups"
        ],
        "summary": "Create a security group",
        "description": "Creates a new security group. Add firewall rules and attach servers after creation.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "name"
                ],
                "properties": {
                  "name": {
                    "type": "string",
                    "maxLength": 30,
                    "example": "web-servers"
                  },
                  "description": {
                    "type": "string",
                    "nullable": true,
                    "example": "Allow HTTP/HTTPS traffic"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Security group created",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/SecurityGroup"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "422": {
            "$ref": "#/components/responses/ValidationError"
          }
        }
      }
    },
    "/security-groups/{id}": {
      "get": {
        "operationId": "getSecurityGroup",
        "tags": [
          "Security Groups"
        ],
        "summary": "Get security group details",
        "description": "Returns a security group with its firewall rules and attached servers.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer"
            },
            "description": "Security group ID"
          }
        ],
        "responses": {
          "200": {
            "description": "Security group details",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/SecurityGroupDetail"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      },
      "delete": {
        "operationId": "deleteSecurityGroup",
        "tags": [
          "Security Groups"
        ],
        "summary": "Delete a security group",
        "description": "Deletes a security group. All servers must be detached first.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer"
            },
            "description": "Security group ID"
          }
        ],
        "responses": {
          "204": {
            "description": "Security group deleted"
          },
          "400": {
            "description": "Servers are still attached",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "HAS_SERVERS",
                    "message": "Detach all servers before deleting the security group."
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      }
    },
    "/security-groups/{id}/rules": {
      "post": {
        "operationId": "createFirewallRule",
        "tags": [
          "Security Groups"
        ],
        "summary": "Add a firewall rule",
        "description": "Adds a firewall rule to a security group. If the group is already deployed to Proxmox, the rule will be synced automatically.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer"
            },
            "description": "Security group ID"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateFirewallRuleRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Firewall rule created",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/FirewallRule"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "422": {
            "$ref": "#/components/responses/ValidationError"
          }
        }
      }
    },
    "/security-groups/{id}/rules/{rule_id}": {
      "delete": {
        "operationId": "deleteFirewallRule",
        "tags": [
          "Security Groups"
        ],
        "summary": "Delete a firewall rule",
        "description": "Removes a firewall rule from a security group.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer"
            },
            "description": "Security group ID"
          },
          {
            "name": "rule_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer"
            },
            "description": "Firewall rule ID"
          }
        ],
        "responses": {
          "204": {
            "description": "Rule deleted"
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      }
    },
    "/security-groups/{id}/servers/attach": {
      "post": {
        "operationId": "attachServerToGroup",
        "tags": [
          "Security Groups"
        ],
        "summary": "Attach a server",
        "description": "Attaches a server to a security group. The firewall rules will be deployed to the server's node automatically.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer"
            },
            "description": "Security group ID"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "server_uuid"
                ],
                "properties": {
                  "server_uuid": {
                    "type": "string",
                    "description": "Server UUID or short UUID",
                    "example": "a1b2c3d4"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Server attached",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "object",
                      "properties": {
                        "status": {
                          "type": "string",
                          "example": "attached"
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      }
    },
    "/security-groups/{id}/servers/detach": {
      "delete": {
        "operationId": "detachServerFromGroup",
        "tags": [
          "Security Groups"
        ],
        "summary": "Detach a server",
        "description": "Detaches a server from a security group.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer"
            },
            "description": "Security group ID"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "server_uuid"
                ],
                "properties": {
                  "server_uuid": {
                    "type": "string",
                    "description": "Server UUID or short UUID",
                    "example": "a1b2c3d4"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Server detached",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "object",
                      "properties": {
                        "status": {
                          "type": "string",
                          "example": "detached"
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "bearerAuth": {
        "type": "http",
        "scheme": "bearer",
        "description": "API token from your CloudBlast account settings. Pass as `Authorization: Bearer <token>`."
      }
    },
    "parameters": {
      "Page": {
        "name": "page",
        "in": "query",
        "required": false,
        "schema": {
          "type": "integer",
          "default": 1
        },
        "description": "Page number for pagination"
      },
      "ServerIdentifier": {
        "name": "server",
        "in": "path",
        "required": true,
        "schema": {
          "type": "string"
        },
        "description": "Server identifier — any of: numeric `id`, `uuid_short` (8 chars), or full `uuid` (36 chars).",
        "example": "a1b2c3d4"
      }
    },
    "responses": {
      "Unauthenticated": {
        "description": "Authentication failed",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            },
            "example": {
              "error": {
                "code": "UNAUTHENTICATED",
                "message": "Missing or invalid Authorization header. Use: Authorization: Bearer <token>"
              }
            }
          }
        }
      },
      "NotFound": {
        "description": "Resource not found",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            },
            "example": {
              "error": {
                "code": "NOT_FOUND",
                "message": "Server not found."
              }
            }
          }
        }
      },
      "BadRequest": {
        "description": "Bad request",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "ValidationError": {
        "description": "Validation failed",
        "content": {
          "application/json": {
            "schema": {
              "type": "object",
              "properties": {
                "error": {
                  "type": "object",
                  "properties": {
                    "code": {
                      "type": "string",
                      "example": "VALIDATION_ERROR"
                    },
                    "message": {
                      "type": "string",
                      "example": "The given data was invalid."
                    },
                    "details": {
                      "type": "object",
                      "additionalProperties": {
                        "type": "array",
                        "items": {
                          "type": "string"
                        }
                      },
                      "example": {
                        "name": [
                          "The name field is required."
                        ]
                      }
                    }
                  }
                }
              }
            }
          }
        }
      },
      "Conflict": {
        "description": "Server is in a conflicting state",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            },
            "example": {
              "error": {
                "code": "SERVER_STATUS_CONFLICT",
                "message": "This server is currently installing and cannot perform this action."
              }
            }
          }
        }
      }
    },
    "schemas": {
      "Error": {
        "type": "object",
        "properties": {
          "error": {
            "type": "object",
            "properties": {
              "code": {
                "type": "string",
                "description": "Machine-readable error code"
              },
              "message": {
                "type": "string",
                "description": "Human-readable error message"
              }
            },
            "required": [
              "code",
              "message"
            ]
          }
        }
      },
      "PaginationMeta": {
        "type": "object",
        "properties": {
          "current_page": {
            "type": "integer",
            "example": 1
          },
          "last_page": {
            "type": "integer",
            "example": 3
          },
          "per_page": {
            "type": "integer",
            "example": 25
          },
          "total": {
            "type": "integer",
            "example": 72
          }
        }
      },
      "Account": {
        "type": "object",
        "properties": {
          "id": {
            "type": "integer",
            "example": 1
          },
          "name": {
            "type": "string",
            "example": "John"
          },
          "surname": {
            "type": "string",
            "example": "Doe"
          },
          "email": {
            "type": "string",
            "format": "email",
            "example": "john@example.com"
          },
          "credit": {
            "type": "number",
            "format": "float",
            "description": "Account credit balance in EUR",
            "example": 42.5
          },
          "ram_limit": {
            "type": "number",
            "description": "RAM limit in GB",
            "example": 64
          },
          "core_limit": {
            "type": "integer",
            "description": "CPU core limit",
            "example": 32
          },
          "ip_limit": {
            "type": "integer",
            "description": "Extra IP address limit",
            "example": 10
          },
          "backup_limit": {
            "type": "integer",
            "description": "Total backup limit across all servers",
            "example": 20
          }
        }
      },
      "AccountUsage": {
        "type": "object",
        "properties": {
          "servers": {
            "type": "integer",
            "description": "Number of active servers",
            "example": 3
          },
          "cpu_used": {
            "type": "integer",
            "description": "Total CPU cores allocated",
            "example": 8
          },
          "cpu_limit": {
            "type": "integer",
            "description": "CPU core limit",
            "example": 32
          },
          "ram_used": {
            "type": "integer",
            "description": "Total RAM allocated in bytes",
            "example": 8589934592
          },
          "ram_limit_gb": {
            "type": "number",
            "description": "RAM limit in GB",
            "example": 64
          },
          "disk_used": {
            "type": "integer",
            "description": "Total disk allocated in bytes",
            "example": 107374182400
          },
          "ip_used": {
            "type": "integer",
            "description": "Total IP addresses in use",
            "example": 6
          },
          "ip_limit": {
            "type": "integer",
            "description": "Extra IP address limit",
            "example": 10
          }
        }
      },
      "Invoice": {
        "type": "object",
        "properties": {
          "id": {
            "type": "integer",
            "example": 42
          },
          "status": {
            "type": "string",
            "enum": [
              "draft",
              "open",
              "paid",
              "void",
              "uncollectible"
            ],
            "example": "paid"
          },
          "total": {
            "type": "number",
            "format": "float",
            "description": "Total amount in EUR",
            "example": 29.99
          },
          "amount_due": {
            "type": "number",
            "format": "float",
            "example": 0
          },
          "amount_paid": {
            "type": "number",
            "format": "float",
            "example": 29.99
          },
          "type": {
            "type": "string",
            "nullable": true,
            "example": null
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "example": "2026-01-15T10:30:00+00:00"
          }
        }
      },
      "Plan": {
        "type": "object",
        "properties": {
          "id": {
            "type": "integer",
            "example": 1
          },
          "name": {
            "type": "string",
            "example": "Starter VPS"
          },
          "cpu": {
            "type": "integer",
            "description": "Number of CPU cores",
            "example": 2
          },
          "memory": {
            "type": "integer",
            "description": "RAM in bytes",
            "example": 2147483648
          },
          "disk": {
            "type": "integer",
            "description": "Disk size in bytes",
            "example": 42949672960
          },
          "bandwidth_limit": {
            "type": "integer",
            "nullable": true,
            "description": "Monthly bandwidth limit in bytes (null = unlimited)",
            "example": 1073741824000
          },
          "monthly_price": {
            "type": "number",
            "format": "float",
            "description": "Monthly price in EUR",
            "example": 9.99
          },
          "hourly_price": {
            "type": "number",
            "format": "float",
            "description": "Hourly price in EUR",
            "example": 0.015
          },
          "backup_price": {
            "type": "number",
            "format": "float",
            "description": "Backup price per GB/month in EUR",
            "example": 0.05
          },
          "backup_limit": {
            "type": "integer",
            "description": "Maximum number of backups",
            "example": 3
          },
          "location_id": {
            "type": "integer",
            "nullable": true,
            "description": "If set, plan is only available in this location",
            "example": null
          }
        }
      },
      "Location": {
        "type": "object",
        "properties": {
          "id": {
            "type": "integer",
            "example": 1
          },
          "short_code": {
            "type": "string",
            "example": "AMS1"
          },
          "description": {
            "type": "string",
            "nullable": true,
            "example": "Amsterdam, Netherlands"
          },
          "out_of_stock": {
            "type": "boolean",
            "description": "Whether this location currently has no provisionable plans. Resource capacity checks honor node bypass settings, but IP availability is still required.",
            "example": false
          }
        }
      },
      "Template": {
        "type": "object",
        "properties": {
          "slug": {
            "type": "string",
            "description": "Unique template identifier used in API requests",
            "example": "ubuntu-24.04"
          },
          "name": {
            "type": "string",
            "description": "Display name",
            "example": "Ubuntu 24.04 LTS"
          },
          "group_name": {
            "type": "string",
            "description": "Template category",
            "example": "Ubuntu"
          }
        }
      },
      "Server": {
        "type": "object",
        "properties": {
          "id": {
            "type": "integer",
            "description": "Numeric server ID. Can be used as the `{server}` path parameter (as can `uuid` and `uuid_short`).",
            "example": 42
          },
          "uuid": {
            "type": "string",
            "format": "uuid",
            "description": "Server UUID. Use this (or `uuid_short`) as the `{server}` path parameter.",
            "example": "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
          },
          "uuid_short": {
            "type": "string",
            "description": "First 8 characters of the UUID. Can also be used as the `{server}` path parameter.",
            "example": "a1b2c3d4"
          },
          "name": {
            "type": "string",
            "example": "Starter VPS"
          },
          "hostname": {
            "type": "string",
            "description": "Server hostname",
            "example": "web-01.example.com"
          },
          "status": {
            "type": "string",
            "nullable": true,
            "description": "Application status. `null` means the server is healthy.",
            "enum": [
              null,
              "installing",
              "install_failed",
              "suspended",
              "restoring_backup",
              "restoring_snapshot",
              "deleting",
              "deletion_failed"
            ],
            "example": null
          },
          "cpu": {
            "type": "integer",
            "description": "CPU cores",
            "example": 2
          },
          "memory": {
            "type": "integer",
            "description": "RAM in bytes",
            "example": 2147483648
          },
          "disk": {
            "type": "integer",
            "description": "Disk in bytes",
            "example": 42949672960
          },
          "bandwidth_usage": {
            "type": "integer",
            "description": "Current month bandwidth usage in bytes",
            "example": 536870912
          },
          "bandwidth_limit": {
            "type": "integer",
            "nullable": true,
            "description": "Monthly bandwidth limit in bytes",
            "example": 1073741824000
          },
          "node_id": {
            "type": "integer",
            "example": 1
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "example": "2026-01-10T14:00:00+00:00"
          },
          "ip_addresses": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/IpAddress"
            }
          }
        }
      },
      "ServerDetail": {
        "allOf": [
          {
            "$ref": "#/components/schemas/Server"
          },
          {
            "type": "object",
            "properties": {
              "root_password": {
                "type": "string",
                "nullable": true,
                "description": "Decoded root password. Null while server is installing.",
                "example": "k3Fm9xPq"
              },
              "password_status": {
                "type": "string",
                "enum": [
                  "ready",
                  "generating",
                  "failed"
                ],
                "description": "`ready` = password is available, `generating` = server is still installing",
                "example": "ready"
              },
              "plan": {
                "type": "object",
                "nullable": true,
                "properties": {
                  "id": {
                    "type": "integer"
                  },
                  "name": {
                    "type": "string"
                  },
                  "monthly_price": {
                    "type": "number",
                    "format": "float"
                  },
                  "hourly_price": {
                    "type": "number",
                    "format": "float"
                  }
                }
              },
              "operating_system": {
                "type": "string",
                "nullable": true,
                "description": "Installed OS name",
                "example": "Ubuntu 24.04 LTS"
              }
            }
          }
        ]
      },
      "CreatedServerDetail": {
        "allOf": [
          {
            "$ref": "#/components/schemas/Server"
          },
          {
            "type": "object",
            "properties": {
              "password_status": {
                "type": "string",
                "enum": [
                  "ready",
                  "generating",
                  "failed"
                ],
                "description": "`ready` = password is available, `generating` = server is still installing",
                "example": "generating"
              },
              "plan": {
                "type": "object",
                "nullable": true,
                "properties": {
                  "id": {
                    "type": "integer"
                  },
                  "name": {
                    "type": "string"
                  },
                  "monthly_price": {
                    "type": "number",
                    "format": "float"
                  },
                  "hourly_price": {
                    "type": "number",
                    "format": "float"
                  }
                }
              },
              "operating_system": {
                "type": "string",
                "nullable": true,
                "description": "Installed OS name",
                "example": "Ubuntu 24.04 LTS"
              }
            }
          }
        ]
      },
      "ServerCredentials": {
        "type": "object",
        "properties": {
          "username": {
            "type": "string",
            "description": "SSH login user the password belongs to.",
            "example": "root"
          },
          "root_password": {
            "type": "string",
            "nullable": true,
            "description": "Decoded root password. Null while server is installing.",
            "example": "k3Fm9xPq"
          },
          "password_status": {
            "type": "string",
            "enum": [
              "ready",
              "generating",
              "failed"
            ],
            "description": "`ready` = password is available, `generating` = server is still installing",
            "example": "ready"
          },
          "ipv4": {
            "type": "string",
            "nullable": true,
            "description": "Primary IPv4 address for SSH, or null if none assigned.",
            "example": "203.0.113.50"
          },
          "ipv6": {
            "type": "string",
            "nullable": true,
            "description": "Primary IPv6 address, or null if none assigned.",
            "example": "2a0e:97c0:180:2::"
          }
        }
      },
      "IpAddress": {
        "type": "object",
        "properties": {
          "address": {
            "type": "string",
            "example": "203.0.113.50"
          },
          "type": {
            "type": "string",
            "enum": [
              "ipv4",
              "ipv6"
            ],
            "example": "ipv4"
          },
          "gateway": {
            "type": "string",
            "example": "203.0.113.1"
          },
          "cidr": {
            "type": "integer",
            "example": 24
          },
          "rdns": {
            "type": "string",
            "nullable": true,
            "description": "Reverse DNS hostname",
            "example": "server1.example.com"
          }
        }
      },
      "Backup": {
        "type": "object",
        "properties": {
          "uuid": {
            "type": "string",
            "format": "uuid",
            "example": "f47ac10b-58cc-4372-a567-0e02b2c3d479"
          },
          "name": {
            "type": "string",
            "example": "Daily backup"
          },
          "is_successful": {
            "type": "boolean",
            "example": true
          },
          "is_locked": {
            "type": "boolean",
            "description": "Locked backups cannot be deleted",
            "example": false
          },
          "size": {
            "type": "integer",
            "description": "Backup size in bytes",
            "example": 2147483648
          },
          "completed_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true,
            "example": "2026-01-15T10:35:00+00:00"
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "example": "2026-01-15T10:30:00+00:00"
          }
        }
      },
      "SSHKey": {
        "type": "object",
        "properties": {
          "id": {
            "type": "integer",
            "example": 1
          },
          "name": {
            "type": "string",
            "example": "My Laptop"
          },
          "fingerprint": {
            "type": "string",
            "nullable": true,
            "example": "a1:b2:c3:d4:e5:f6:a1:b2:c3:d4:e5:f6:a1:b2:c3:d4"
          },
          "public_key": {
            "type": "string",
            "example": "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAA..."
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "example": "2026-01-10T14:00:00+00:00"
          }
        }
      },
      "SecurityGroup": {
        "type": "object",
        "properties": {
          "id": {
            "type": "integer",
            "example": 1
          },
          "name": {
            "type": "string",
            "example": "web-servers"
          },
          "description": {
            "type": "string",
            "nullable": true,
            "example": "Allow HTTP/HTTPS traffic"
          },
          "vm_count": {
            "type": "integer",
            "description": "Number of servers attached",
            "example": 3
          },
          "rules_count": {
            "type": "integer",
            "description": "Number of firewall rules",
            "example": 5
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "example": "2026-01-10T14:00:00+00:00"
          }
        }
      },
      "SecurityGroupDetail": {
        "allOf": [
          {
            "$ref": "#/components/schemas/SecurityGroup"
          },
          {
            "type": "object",
            "properties": {
              "rules": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/FirewallRule"
                }
              },
              "servers": {
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {
                    "uuid": {
                      "type": "string"
                    },
                    "uuid_short": {
                      "type": "string"
                    },
                    "name": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          }
        ]
      },
      "FirewallRule": {
        "type": "object",
        "properties": {
          "id": {
            "type": "integer",
            "example": 1
          },
          "type": {
            "type": "string",
            "enum": [
              "inbound",
              "outbound"
            ],
            "example": "inbound"
          },
          "action": {
            "type": "string",
            "enum": [
              "ACCEPT",
              "REJECT",
              "DROP"
            ],
            "example": "ACCEPT"
          },
          "protocol": {
            "type": "string",
            "example": "tcp"
          },
          "source": {
            "type": "string",
            "nullable": true,
            "example": null
          },
          "destination": {
            "type": "string",
            "nullable": true,
            "example": null
          },
          "source_port": {
            "type": "string",
            "nullable": true,
            "example": null
          },
          "destination_port": {
            "type": "string",
            "nullable": true,
            "example": "80,443"
          },
          "comment": {
            "type": "string",
            "nullable": true,
            "example": "Allow HTTP/HTTPS"
          },
          "priority": {
            "type": "integer",
            "example": 0
          }
        }
      },
      "CreateServerRequest": {
        "type": "object",
        "required": [
          "plan_id",
          "location_id",
          "template_slug"
        ],
        "properties": {
          "plan_id": {
            "type": "integer",
            "description": "Plan ID from `GET /plans`",
            "example": 1
          },
          "location_id": {
            "type": "integer",
            "description": "Location ID from `GET /locations`",
            "example": 1
          },
          "template_slug": {
            "type": "string",
            "description": "Template slug from `GET /locations/{id}/templates`",
            "example": "ubuntu-24.04"
          },
          "hostname": {
            "type": "string",
            "nullable": true,
            "description": "Server hostname. Defaults to the plan name if omitted.",
            "maxLength": 191,
            "example": "web-01.example.com"
          },
          "ssh_key_ids": {
            "type": "array",
            "description": "IDs of saved SSH keys to install during provisioning. Obtain IDs from `GET /ssh-keys`. The generated root password remains available.",
            "minItems": 1,
            "maxItems": 20,
            "uniqueItems": true,
            "items": {
              "type": "integer"
            },
            "example": [
              12,
              18
            ]
          }
        }
      },
      "CreateBackupRequest": {
        "type": "object",
        "required": [
          "name"
        ],
        "properties": {
          "name": {
            "type": "string",
            "maxLength": 40,
            "description": "Backup name",
            "example": "Before upgrade"
          },
          "mode": {
            "type": "string",
            "enum": [
              "snapshot",
              "suspend",
              "kill"
            ],
            "nullable": true,
            "description": "Backup mode. Defaults to `snapshot`.",
            "example": "snapshot"
          },
          "compression_type": {
            "type": "string",
            "enum": [
              "none",
              "lzo",
              "gzip",
              "zstd"
            ],
            "nullable": true,
            "description": "Compression type. Defaults to `zstd`.",
            "example": "zstd"
          }
        }
      },
      "CreateFirewallRuleRequest": {
        "type": "object",
        "required": [
          "type",
          "action",
          "protocol"
        ],
        "properties": {
          "type": {
            "type": "string",
            "enum": [
              "inbound",
              "outbound"
            ],
            "example": "inbound"
          },
          "action": {
            "type": "string",
            "enum": [
              "ACCEPT",
              "REJECT",
              "DROP"
            ],
            "example": "ACCEPT"
          },
          "protocol": {
            "type": "string",
            "description": "Protocol (e.g., `tcp`, `udp`, `icmp`)",
            "maxLength": 20,
            "example": "tcp"
          },
          "source": {
            "type": "string",
            "nullable": true,
            "description": "Source IP/CIDR",
            "example": "0.0.0.0/0"
          },
          "destination": {
            "type": "string",
            "nullable": true,
            "description": "Destination IP/CIDR"
          },
          "source_port": {
            "type": "string",
            "nullable": true,
            "description": "Source port or range",
            "maxLength": 50
          },
          "destination_port": {
            "type": "string",
            "nullable": true,
            "description": "Destination port or range (e.g., `80`, `8000:9000`, `80,443`)",
            "maxLength": 50,
            "example": "443"
          },
          "comment": {
            "type": "string",
            "nullable": true,
            "description": "Optional description",
            "example": "Allow HTTPS"
          },
          "priority": {
            "type": "integer",
            "nullable": true,
            "description": "Rule priority (lower = higher priority). Defaults to 0.",
            "minimum": 0,
            "example": 0
          }
        }
      }
    }
  }
}