{
  "openapi": "3.1.0",
  "info": {
    "title": "VDSok Client API",
    "version": "1.0.0",
    "summary": "Public REST API for VDSok clients and resellers.",
    "description": "Machine access to a VDSok account: balance and invoices, the VDS catalog,\nservers (order, renew, power, reinstall, IPs, PTR, SSH keys, delete with\nrefund), domains, API keys and webhooks. Everything a client can do in the\ncabinet, minus tickets, dedicated servers, sub-accounts and profile editing.\n\nThis document is the source of truth for `openapi.json` served at\n`GET /api/v1/openapi.json` and for the generated SDKs (`@vdsok/sdk`,\n`vdsok`, `vdsok/sdk`). Human-readable guide: https://vdsok.guru/developers\n\n## Conventions\n\n* Base URL `https://vdsok.guru/api/v1`; the version lives in the path.\n  Breaking changes go to `/v2`, this document only grows additively.\n* JSON only. A `POST`/`PUT`/`PATCH` body that is not `application/json`\n  is rejected with `415`; a body over 64 KB with `413`.\n* Timestamps are RFC 3339 in UTC with a trailing `Z`.\n* Money is a decimal **string** with 2–4 fraction digits, never a float,\n  always next to a `currency` field (ISO 4217).\n* `server_id` is the panel id of the VM (`vds_tables.solusvm_id`), the\n  same number the cabinet shows in the URL.\n* Lists return `{\"data\": [...], \"next_cursor\": \"...\"|null}`. Pass\n  `next_cursor` back as `?cursor=` to get the next page; `limit` is\n  1..100. Cursors are opaque and signed — never build them by hand.\n* Every response carries `X-Request-ID`; quote it in support requests.\n  You may send your own `X-Request-ID` on any call: it is sanitized to\n  the first 64 characters of `A-Za-z0-9._:-` and, if anything is left,\n  adopted and echoed back; otherwise VDSok generates one. Rate-limit state is\n  in `X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`;\n  `429` and `503` add `Retry-After`.\n\n## Authentication and scopes\n\n`Authorization: Bearer vk_live_...` or `Bearer vk_test_...`. Keys are\ncreated in the cabinet (`/my/api`) by the account owner, each with a\nname, a set of scopes, an optional IP allow-list and validity window.\nEvery operation lists its required scopes in `x-scopes`; an empty list\nmeans \"any valid key\" (catalog, `/me`). Missing scope → `403\ninsufficient_scope` with `details.required`.\n\n## Rate limits\n\n120 requests/minute per key by default, plus a separate bucket of 20/min\nfor expensive calls (`x-expensive: true`: live status, availability\nchecks, quotes, ordering, top-ups, PDF, webhook test/redeliver). Limits\nare per key and adjustable by VDSok staff. Reads in the cabinet are not\ncounted against the API.\n\n## Idempotency\n\nOperations marked `x-idempotent: true` move money or touch external\nsystems and **require** an `Idempotency-Key` header (16..128 chars,\ne.g. a UUID). The key is remembered for 7 days together with a digest of\nthe endpoint and the body:\n\n* same key + same request → the stored response is replayed (secrets\n  such as `root_password` are blanked in the replay);\n* same key + different body or endpoint → `409 idempotency_conflict`;\n* same key while the first request is still running → `409\n  idempotency_in_progress` with `Retry-After`;\n* missing key → `400 idempotency_key_required`.\n\nStored results include 5xx outcomes after a refund, so a retry never\ndouble-charges.\n\n## Sandbox\n\nTest keys (`vk_test_…`) read the **real** account data and simulate\nevery mutation: no money moves, no VM or domain is created, no gateway\nis called. Ordering a server in sandbox returns a fake server\n(`id >= 9000000000`) that lives 24 hours and shows up in `GET /servers`\nfor that key only. Every response to a test key carries\n`X-Sandbox: true`. `x-sandbox` on each operation says what a test key\ngets: `real` (same as live, reads), `fake` (simulated write), or\n`forbidden` (`403 sandbox_not_supported`; webhooks).\n\n## Extensions used in this document\n\n* `x-scopes` — scopes required (all of them) for the operation.\n* `x-idempotent` — `Idempotency-Key` is mandatory and honoured.\n* `x-expensive` — counted against the expensive bucket (20/min).\n* `x-expensive-when` — the call lands in the expensive bucket only when\n  the listed query parameters have the listed values (e.g. `GET\n  /servers/{server_id}` with `?include=live`); absent means `x-expensive`\n  alone decides.\n* `x-sandbox` — behaviour under a test key: `real` | `fake` | `forbidden`.\n",
    "contact": {
      "name": "VDSok support",
      "url": "https://vdsok.guru/developers",
      "email": "support@vdsok.guru"
    },
    "termsOfService": "https://vdsok.guru/terms"
  },
  "servers": [
    {
      "url": "https://vdsok.guru/api/v1",
      "description": "Production (live and test keys)"
    }
  ],
  "security": [
    {
      "apiKey": []
    }
  ],
  "tags": [
    {
      "name": "Meta",
      "description": "Health, this document, the calling key."
    },
    {
      "name": "Account",
      "description": "Profile, balance, transactions, top-ups."
    },
    {
      "name": "Invoices",
      "description": "Invoices, paying from balance, payment links, PDF."
    },
    {
      "name": "Catalog",
      "description": "Tariffs, OS images, locations, domain zones, price quotes. Needs a valid key, no scope."
    },
    {
      "name": "Servers",
      "description": "VDS list, details, order, renew, delete with refund, notes and auto-renew."
    },
    {
      "name": "Server actions",
      "description": "Power, reinstall, root password reset."
    },
    {
      "name": "Orders",
      "description": "Server orders in progress (after a `202 provisioning`)."
    },
    {
      "name": "IPs",
      "description": "Additional IPv4 addresses and PTR records."
    },
    {
      "name": "SSH keys",
      "description": "Account-level public keys injected on order and reinstall."
    },
    {
      "name": "Domains",
      "description": "Availability, registration, renewal, nameservers, privacy, transfers."
    },
    {
      "name": "Keys",
      "description": "API keys visible to the caller; a key can revoke itself."
    },
    {
      "name": "Webhooks",
      "description": "Subscriptions, deliveries, redelivery, test events. Live keys only."
    }
  ],
  "paths": {
    "/health": {
      "parameters": [
        {
          "$ref": "#/components/parameters/RequestId"
        }
      ],
      "get": {
        "operationId": "get_health",
        "tags": [
          "Meta"
        ],
        "summary": "Liveness and API switch state",
        "description": "Always `200`. `status` is `disabled` while staff have the API switched off; every other endpoint then answers `503 api_disabled`.",
        "security": [],
        "x-scopes": [],
        "x-idempotent": false,
        "x-expensive": false,
        "x-sandbox": "real",
        "responses": {
          "200": {
            "description": "Service state",
            "headers": {
              "X-Request-ID": {
                "$ref": "#/components/headers/X-Request-ID"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "X-Sandbox": {
                "$ref": "#/components/headers/X-Sandbox"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Health"
                },
                "example": {
                  "status": "ok",
                  "time": "2026-09-15T10:00:00Z",
                  "version": "1"
                }
              }
            }
          }
        }
      }
    },
    "/openapi.json": {
      "parameters": [
        {
          "$ref": "#/components/parameters/RequestId"
        }
      ],
      "get": {
        "operationId": "get_openapi",
        "tags": [
          "Meta"
        ],
        "summary": "This document as JSON",
        "security": [],
        "x-scopes": [],
        "x-idempotent": false,
        "x-expensive": false,
        "x-sandbox": "real",
        "responses": {
          "200": {
            "description": "OpenAPI 3.1 document",
            "headers": {
              "X-Request-ID": {
                "$ref": "#/components/headers/X-Request-ID"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "X-Sandbox": {
                "$ref": "#/components/headers/X-Sandbox"
              },
              "Cache-Control": {
                "$ref": "#/components/headers/Cache-Control"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                }
              }
            }
          }
        }
      }
    },
    "/me": {
      "parameters": [
        {
          "$ref": "#/components/parameters/RequestId"
        }
      ],
      "get": {
        "operationId": "get_me",
        "tags": [
          "Meta"
        ],
        "summary": "Who am I",
        "description": "Identity of the calling key, its scopes and whether it is live or sandbox. Cheapest way to validate a key.",
        "x-scopes": [],
        "x-idempotent": false,
        "x-expensive": false,
        "x-sandbox": "real",
        "responses": {
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          },
          "200": {
            "description": "Calling key and account",
            "headers": {
              "X-Request-ID": {
                "$ref": "#/components/headers/X-Request-ID"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "X-Sandbox": {
                "$ref": "#/components/headers/X-Sandbox"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Me"
                }
              }
            }
          }
        }
      }
    },
    "/account": {
      "parameters": [
        {
          "$ref": "#/components/parameters/RequestId"
        }
      ],
      "get": {
        "operationId": "get_account",
        "tags": [
          "Account"
        ],
        "summary": "Account profile, client group and discount",
        "x-scopes": [
          "account:read"
        ],
        "x-idempotent": false,
        "x-expensive": false,
        "x-sandbox": "real",
        "responses": {
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          },
          "200": {
            "description": "Account",
            "headers": {
              "X-Request-ID": {
                "$ref": "#/components/headers/X-Request-ID"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "X-Sandbox": {
                "$ref": "#/components/headers/X-Sandbox"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Account"
                }
              }
            }
          }
        }
      }
    },
    "/balance": {
      "parameters": [
        {
          "$ref": "#/components/parameters/RequestId"
        }
      ],
      "get": {
        "operationId": "get_balance",
        "tags": [
          "Account"
        ],
        "summary": "Balance and upcoming charges",
        "x-scopes": [
          "balance:read"
        ],
        "x-idempotent": false,
        "x-expensive": false,
        "x-sandbox": "real",
        "responses": {
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          },
          "200": {
            "description": "Balance",
            "headers": {
              "X-Request-ID": {
                "$ref": "#/components/headers/X-Request-ID"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "X-Sandbox": {
                "$ref": "#/components/headers/X-Sandbox"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Balance"
                }
              }
            }
          }
        }
      }
    },
    "/transactions": {
      "parameters": [
        {
          "$ref": "#/components/parameters/RequestId"
        }
      ],
      "get": {
        "operationId": "list_transactions",
        "tags": [
          "Account"
        ],
        "summary": "Balance transactions, newest first",
        "x-scopes": [
          "balance:read"
        ],
        "x-idempotent": false,
        "x-expensive": false,
        "x-sandbox": "real",
        "parameters": [
          {
            "$ref": "#/components/parameters/Cursor"
          },
          {
            "$ref": "#/components/parameters/Limit"
          },
          {
            "name": "direction",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "credit",
                "debit"
              ]
            }
          },
          {
            "name": "since",
            "in": "query",
            "description": "Only transactions created at or after this moment.",
            "schema": {
              "$ref": "#/components/schemas/Timestamp"
            }
          },
          {
            "name": "until",
            "in": "query",
            "schema": {
              "$ref": "#/components/schemas/Timestamp"
            }
          }
        ],
        "responses": {
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "200": {
            "description": "Page of transactions",
            "headers": {
              "X-Request-ID": {
                "$ref": "#/components/headers/X-Request-ID"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "X-Sandbox": {
                "$ref": "#/components/headers/X-Sandbox"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TransactionPage"
                }
              }
            }
          }
        }
      }
    },
    "/balance/topup-info": {
      "parameters": [
        {
          "$ref": "#/components/parameters/RequestId"
        }
      ],
      "get": {
        "operationId": "get_topup_info",
        "tags": [
          "Account"
        ],
        "summary": "Top-up limits and available gateways",
        "x-scopes": [
          "balance:read"
        ],
        "x-idempotent": false,
        "x-expensive": false,
        "x-sandbox": "real",
        "responses": {
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          },
          "200": {
            "description": "Limits and gateways",
            "headers": {
              "X-Request-ID": {
                "$ref": "#/components/headers/X-Request-ID"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "X-Sandbox": {
                "$ref": "#/components/headers/X-Sandbox"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TopupInfo"
                }
              }
            }
          }
        }
      }
    },
    "/balance/topup": {
      "parameters": [
        {
          "$ref": "#/components/parameters/RequestId"
        }
      ],
      "post": {
        "operationId": "create_topup",
        "tags": [
          "Account"
        ],
        "summary": "Create a top-up invoice and get a payment link",
        "description": "Creates an unpaid `topup` invoice and returns the gateway URL to pay\nit. The balance changes only after the gateway confirms the payment\n(event `invoice.paid`). Sandbox returns a fake `payment_url`.\n",
        "x-scopes": [
          "balance:topup"
        ],
        "x-idempotent": true,
        "x-expensive": true,
        "x-sandbox": "fake",
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/TopupRequest"
              },
              "example": {
                "amount": "25.00",
                "gateway": "cryptobot"
              }
            }
          }
        },
        "responses": {
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "413": {
            "$ref": "#/components/responses/PayloadTooLarge"
          },
          "415": {
            "$ref": "#/components/responses/UnsupportedMediaType"
          },
          "502": {
            "$ref": "#/components/responses/BadGateway"
          },
          "504": {
            "$ref": "#/components/responses/GatewayTimeout"
          },
          "201": {
            "description": "Invoice created",
            "headers": {
              "X-Request-ID": {
                "$ref": "#/components/headers/X-Request-ID"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "X-Sandbox": {
                "$ref": "#/components/headers/X-Sandbox"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TopupResult"
                }
              }
            }
          }
        }
      }
    },
    "/invoices": {
      "parameters": [
        {
          "$ref": "#/components/parameters/RequestId"
        }
      ],
      "get": {
        "operationId": "list_invoices",
        "tags": [
          "Invoices"
        ],
        "summary": "Invoices, newest first",
        "x-scopes": [
          "invoices:read"
        ],
        "x-idempotent": false,
        "x-expensive": false,
        "x-sandbox": "real",
        "parameters": [
          {
            "$ref": "#/components/parameters/Cursor"
          },
          {
            "$ref": "#/components/parameters/Limit"
          },
          {
            "name": "status",
            "in": "query",
            "schema": {
              "$ref": "#/components/schemas/InvoiceStatus"
            }
          },
          {
            "name": "type",
            "in": "query",
            "schema": {
              "$ref": "#/components/schemas/InvoiceType"
            }
          }
        ],
        "responses": {
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "200": {
            "description": "Page of invoices",
            "headers": {
              "X-Request-ID": {
                "$ref": "#/components/headers/X-Request-ID"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "X-Sandbox": {
                "$ref": "#/components/headers/X-Sandbox"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/InvoicePage"
                }
              }
            }
          }
        }
      }
    },
    "/invoices/{invoice_id}": {
      "parameters": [
        {
          "$ref": "#/components/parameters/RequestId"
        },
        {
          "$ref": "#/components/parameters/InvoiceId"
        }
      ],
      "get": {
        "operationId": "get_invoice",
        "tags": [
          "Invoices"
        ],
        "summary": "One invoice with line items",
        "x-scopes": [
          "invoices:read"
        ],
        "x-idempotent": false,
        "x-expensive": false,
        "x-sandbox": "real",
        "responses": {
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "200": {
            "description": "Invoice",
            "headers": {
              "X-Request-ID": {
                "$ref": "#/components/headers/X-Request-ID"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "X-Sandbox": {
                "$ref": "#/components/headers/X-Sandbox"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Invoice"
                }
              }
            }
          }
        }
      }
    },
    "/invoices/{invoice_id}/pdf": {
      "parameters": [
        {
          "$ref": "#/components/parameters/RequestId"
        },
        {
          "$ref": "#/components/parameters/InvoiceId"
        }
      ],
      "get": {
        "operationId": "get_invoice_pdf",
        "tags": [
          "Invoices"
        ],
        "summary": "Invoice as PDF",
        "x-scopes": [
          "invoices:read"
        ],
        "x-idempotent": false,
        "x-expensive": true,
        "x-sandbox": "real",
        "responses": {
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "200": {
            "description": "PDF document",
            "headers": {
              "X-Request-ID": {
                "$ref": "#/components/headers/X-Request-ID"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "X-Sandbox": {
                "$ref": "#/components/headers/X-Sandbox"
              },
              "Content-Disposition": {
                "schema": {
                  "type": "string"
                },
                "example": "attachment; filename=\"invoice-10231.pdf\""
              }
            },
            "content": {
              "application/pdf": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              }
            }
          }
        }
      }
    },
    "/invoices/{invoice_id}/pay": {
      "parameters": [
        {
          "$ref": "#/components/parameters/RequestId"
        },
        {
          "$ref": "#/components/parameters/InvoiceId"
        }
      ],
      "post": {
        "operationId": "pay_invoice",
        "tags": [
          "Invoices"
        ],
        "summary": "Pay an unpaid invoice from balance",
        "description": "Charges the balance synchronously and answers `200` with\n`status: paid`. If the invoice orders a server, provisioning runs in\nthe background afterwards — watch it through `GET /orders` or the\n`server.created` webhook, the answer here does not wait for it.\nInsufficient balance → `402` and nothing changes.\n",
        "x-scopes": [
          "invoices:pay"
        ],
        "x-idempotent": true,
        "x-expensive": false,
        "x-sandbox": "fake",
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "responses": {
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "413": {
            "$ref": "#/components/responses/PayloadTooLarge"
          },
          "415": {
            "$ref": "#/components/responses/UnsupportedMediaType"
          },
          "502": {
            "$ref": "#/components/responses/BadGateway"
          },
          "504": {
            "$ref": "#/components/responses/GatewayTimeout"
          },
          "402": {
            "$ref": "#/components/responses/PaymentRequired"
          },
          "200": {
            "description": "Paid",
            "headers": {
              "X-Request-ID": {
                "$ref": "#/components/headers/X-Request-ID"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "X-Sandbox": {
                "$ref": "#/components/headers/X-Sandbox"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PayInvoiceResult"
                },
                "example": {
                  "invoice_id": 10231,
                  "status": "paid",
                  "amount": "5.90",
                  "currency": "USD",
                  "balance_after": "4.10"
                }
              }
            }
          }
        }
      }
    },
    "/invoices/{invoice_id}/payment-link": {
      "parameters": [
        {
          "$ref": "#/components/parameters/RequestId"
        },
        {
          "$ref": "#/components/parameters/InvoiceId"
        }
      ],
      "post": {
        "operationId": "create_invoice_payment_link",
        "tags": [
          "Invoices"
        ],
        "summary": "Gateway payment link for an unpaid invoice",
        "x-scopes": [
          "invoices:pay"
        ],
        "x-idempotent": false,
        "x-expensive": false,
        "x-sandbox": "fake",
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PaymentLinkRequest"
              }
            }
          }
        },
        "responses": {
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "413": {
            "$ref": "#/components/responses/PayloadTooLarge"
          },
          "415": {
            "$ref": "#/components/responses/UnsupportedMediaType"
          },
          "502": {
            "$ref": "#/components/responses/BadGateway"
          },
          "504": {
            "$ref": "#/components/responses/GatewayTimeout"
          },
          "200": {
            "description": "Link",
            "headers": {
              "X-Request-ID": {
                "$ref": "#/components/headers/X-Request-ID"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "X-Sandbox": {
                "$ref": "#/components/headers/X-Sandbox"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PaymentLink"
                }
              }
            }
          }
        }
      }
    },
    "/catalog/tariffs": {
      "parameters": [
        {
          "$ref": "#/components/parameters/RequestId"
        }
      ],
      "get": {
        "operationId": "list_tariffs",
        "tags": [
          "Catalog"
        ],
        "summary": "VDS tariffs available for order",
        "description": "Only `category = vds` and not disabled. Prices already include the caller's group discount; `list_price_monthly` is the public price.",
        "x-scopes": [],
        "x-idempotent": false,
        "x-expensive": false,
        "x-sandbox": "real",
        "parameters": [
          {
            "name": "location_id",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1
            }
          }
        ],
        "responses": {
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "200": {
            "description": "Tariffs",
            "headers": {
              "X-Request-ID": {
                "$ref": "#/components/headers/X-Request-ID"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "X-Sandbox": {
                "$ref": "#/components/headers/X-Sandbox"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data"
                  ],
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Tariff"
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/catalog/tariffs/{tariff_id}": {
      "parameters": [
        {
          "$ref": "#/components/parameters/RequestId"
        },
        {
          "$ref": "#/components/parameters/TariffId"
        }
      ],
      "get": {
        "operationId": "get_tariff",
        "tags": [
          "Catalog"
        ],
        "summary": "One tariff",
        "x-scopes": [],
        "x-idempotent": false,
        "x-expensive": false,
        "x-sandbox": "real",
        "responses": {
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "200": {
            "description": "Tariff",
            "headers": {
              "X-Request-ID": {
                "$ref": "#/components/headers/X-Request-ID"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "X-Sandbox": {
                "$ref": "#/components/headers/X-Sandbox"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Tariff"
                }
              }
            }
          }
        }
      }
    },
    "/catalog/os": {
      "parameters": [
        {
          "$ref": "#/components/parameters/RequestId"
        }
      ],
      "get": {
        "operationId": "list_os_images",
        "tags": [
          "Catalog"
        ],
        "summary": "OS images",
        "description": "With `tariff_id` the list excludes images that tariff forbids (`excluded_os`).",
        "x-scopes": [],
        "x-idempotent": false,
        "x-expensive": false,
        "x-sandbox": "real",
        "parameters": [
          {
            "name": "tariff_id",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1
            }
          }
        ],
        "responses": {
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "200": {
            "description": "Images",
            "headers": {
              "X-Request-ID": {
                "$ref": "#/components/headers/X-Request-ID"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "X-Sandbox": {
                "$ref": "#/components/headers/X-Sandbox"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data"
                  ],
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/OsImage"
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/catalog/locations": {
      "parameters": [
        {
          "$ref": "#/components/parameters/RequestId"
        }
      ],
      "get": {
        "operationId": "list_locations",
        "tags": [
          "Catalog"
        ],
        "summary": "Datacenter locations",
        "x-scopes": [],
        "x-idempotent": false,
        "x-expensive": false,
        "x-sandbox": "real",
        "responses": {
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          },
          "200": {
            "description": "Locations",
            "headers": {
              "X-Request-ID": {
                "$ref": "#/components/headers/X-Request-ID"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "X-Sandbox": {
                "$ref": "#/components/headers/X-Sandbox"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data"
                  ],
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Location"
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/catalog/zones": {
      "parameters": [
        {
          "$ref": "#/components/parameters/RequestId"
        }
      ],
      "get": {
        "operationId": "list_zones",
        "tags": [
          "Catalog"
        ],
        "summary": "Domain zones (TLDs) and prices",
        "x-scopes": [],
        "x-idempotent": false,
        "x-expensive": false,
        "x-sandbox": "real",
        "responses": {
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          },
          "200": {
            "description": "Zones",
            "headers": {
              "X-Request-ID": {
                "$ref": "#/components/headers/X-Request-ID"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "X-Sandbox": {
                "$ref": "#/components/headers/X-Sandbox"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data"
                  ],
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Zone"
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/catalog/quote": {
      "parameters": [
        {
          "$ref": "#/components/parameters/RequestId"
        }
      ],
      "get": {
        "operationId": "get_quote",
        "tags": [
          "Catalog"
        ],
        "summary": "Price of an order before placing it",
        "description": "Runs the exact functions the order path uses (period total, group /\nloyalty / volume / period discounts, promo code) and reports whether\nthe balance covers the total. Read-only: a promo code is validated but\nnot consumed. Give either `months` or `hours`.\n",
        "x-scopes": [],
        "x-idempotent": false,
        "x-expensive": true,
        "x-sandbox": "real",
        "parameters": [
          {
            "name": "tariff_id",
            "in": "query",
            "required": true,
            "schema": {
              "type": "integer",
              "minimum": 1
            }
          },
          {
            "name": "months",
            "in": "query",
            "schema": {
              "type": "integer",
              "enum": [
                1,
                3,
                6,
                12
              ]
            }
          },
          {
            "name": "hours",
            "in": "query",
            "description": "1..2160 (90 days) — the same ceiling the cabinet applies to a single hourly prepayment.",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 2160
            }
          },
          {
            "name": "billing_cycle",
            "in": "query",
            "schema": {
              "$ref": "#/components/schemas/BillingCycle"
            }
          },
          {
            "name": "promo_code",
            "in": "query",
            "schema": {
              "type": "string",
              "maxLength": 64
            }
          }
        ],
        "responses": {
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "200": {
            "description": "Quote",
            "headers": {
              "X-Request-ID": {
                "$ref": "#/components/headers/X-Request-ID"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "X-Sandbox": {
                "$ref": "#/components/headers/X-Sandbox"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Quote"
                }
              }
            }
          }
        }
      }
    },
    "/servers": {
      "parameters": [
        {
          "$ref": "#/components/parameters/RequestId"
        }
      ],
      "get": {
        "operationId": "list_servers",
        "tags": [
          "Servers"
        ],
        "summary": "Servers of the account",
        "description": "A test key also sees its sandbox servers (`id >= 9000000000`). `ip` finds a server by any of its assigned addresses.",
        "x-scopes": [
          "servers:read"
        ],
        "x-idempotent": false,
        "x-expensive": false,
        "x-sandbox": "real",
        "parameters": [
          {
            "$ref": "#/components/parameters/Cursor"
          },
          {
            "$ref": "#/components/parameters/Limit"
          },
          {
            "name": "status",
            "in": "query",
            "schema": {
              "$ref": "#/components/schemas/ServerStatus"
            }
          },
          {
            "name": "ip",
            "in": "query",
            "schema": {
              "type": "string",
              "maxLength": 45
            }
          }
        ],
        "responses": {
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "200": {
            "description": "Page of servers",
            "headers": {
              "X-Request-ID": {
                "$ref": "#/components/headers/X-Request-ID"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "X-Sandbox": {
                "$ref": "#/components/headers/X-Sandbox"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ServerPage"
                }
              }
            }
          }
        }
      },
      "post": {
        "operationId": "create_server",
        "tags": [
          "Servers"
        ],
        "summary": "Order a server",
        "description": "Synchronous like the cabinet: validates tariff, OS, name and capacity,\ncomputes the price, checks the balance **before writing anything**\n(`402` has no side effects), then charges and creates the VM. `201`\ncarries the server and the one-time `root_password`. If the panel\ntimes out the charge is kept and `202 provisioning` is returned;\npoll `GET /orders/{invoice_id}` — the order either becomes `active`\nor is refunded automatically. Sandbox: `dry_run` validation and a\nfake server, with no invoice (`invoice_id` and `order_url` are\n`null`).\n",
        "x-scopes": [
          "servers:order"
        ],
        "x-idempotent": true,
        "x-expensive": true,
        "x-sandbox": "fake",
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ServerCreate"
              },
              "example": {
                "tariff_id": 12,
                "os": "ubuntu-24.04",
                "name": "web-01",
                "months": 1,
                "ssh_key_ids": [
                  3
                ]
              }
            }
          }
        },
        "responses": {
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "413": {
            "$ref": "#/components/responses/PayloadTooLarge"
          },
          "415": {
            "$ref": "#/components/responses/UnsupportedMediaType"
          },
          "502": {
            "$ref": "#/components/responses/BadGateway"
          },
          "504": {
            "$ref": "#/components/responses/GatewayTimeout"
          },
          "402": {
            "$ref": "#/components/responses/PaymentRequired"
          },
          "201": {
            "description": "Server created and running",
            "headers": {
              "X-Request-ID": {
                "$ref": "#/components/headers/X-Request-ID"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "X-Sandbox": {
                "$ref": "#/components/headers/X-Sandbox"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ServerCreated"
                }
              }
            }
          },
          "202": {
            "description": "Charged, VM creation still in progress",
            "headers": {
              "X-Request-ID": {
                "$ref": "#/components/headers/X-Request-ID"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "X-Sandbox": {
                "$ref": "#/components/headers/X-Sandbox"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Order"
                },
                "example": {
                  "invoice_id": 10231,
                  "status": "provisioning",
                  "server_id": null,
                  "tariff_id": 12,
                  "amount": "5.90",
                  "currency": "USD",
                  "created_at": "2026-09-15T10:00:00Z",
                  "updated_at": "2026-09-15T10:00:00Z",
                  "order_url": "/api/v1/orders/10231",
                  "failure_reason": null
                }
              }
            }
          }
        }
      }
    },
    "/servers/{server_id}": {
      "parameters": [
        {
          "$ref": "#/components/parameters/RequestId"
        },
        {
          "$ref": "#/components/parameters/ServerId"
        }
      ],
      "get": {
        "operationId": "get_server",
        "tags": [
          "Servers"
        ],
        "summary": "Server details",
        "description": "Adds `refund_quote` (what `DELETE` would refund right now). `include=live` also queries\nthe panel for power state and usage, and then the call is billed against the expensive\nbucket (see `x-expensive-when`). The same `409 service_state` rule as\n`get_server_status` applies to `include=live`: synthetic ids (`2000000000 …\n8999999999`) have no panel, while sandbox ids (`>= 9000000000`) return the fake\nsnapshot.\n",
        "x-scopes": [
          "servers:read"
        ],
        "x-idempotent": false,
        "x-expensive": false,
        "x-expensive-when": {
          "include": "live"
        },
        "x-sandbox": "real",
        "parameters": [
          {
            "name": "include",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "live"
              ]
            }
          }
        ],
        "responses": {
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "200": {
            "description": "Server",
            "headers": {
              "X-Request-ID": {
                "$ref": "#/components/headers/X-Request-ID"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "X-Sandbox": {
                "$ref": "#/components/headers/X-Sandbox"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ServerDetail"
                }
              }
            }
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          }
        }
      },
      "patch": {
        "operationId": "update_server",
        "tags": [
          "Servers"
        ],
        "summary": "Change auto-renew, name or notes",
        "x-scopes": [
          "servers:manage"
        ],
        "x-idempotent": false,
        "x-expensive": false,
        "x-sandbox": "fake",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ServerUpdate"
              },
              "example": {
                "auto_renew": true,
                "notes": "prod, do not stop"
              }
            }
          }
        },
        "responses": {
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "413": {
            "$ref": "#/components/responses/PayloadTooLarge"
          },
          "415": {
            "$ref": "#/components/responses/UnsupportedMediaType"
          },
          "502": {
            "$ref": "#/components/responses/BadGateway"
          },
          "504": {
            "$ref": "#/components/responses/GatewayTimeout"
          },
          "200": {
            "description": "Updated server",
            "headers": {
              "X-Request-ID": {
                "$ref": "#/components/headers/X-Request-ID"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "X-Sandbox": {
                "$ref": "#/components/headers/X-Sandbox"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Server"
                }
              }
            }
          }
        }
      },
      "delete": {
        "operationId": "delete_server",
        "tags": [
          "Servers"
        ],
        "summary": "Delete the server and refund unused days",
        "description": "Removes the VM from the panel and credits the balance for the unused\npart of the paid period, computed from the invoices that were actually\npaid (see `GET /servers/{server_id}/refund-quote`). No refund for\nnon-refundable (promo) tariffs, servers blocked by staff, expired\nones and servers with no paid invoice behind them — the reason comes\nback in `refund_quote.excluded_reason`. A pending cancel request is\nwithdrawn silently (the answer does not mention it). Panel failure\nother than \"already gone\" → `502` with nothing changed.\n",
        "x-scopes": [
          "servers:delete"
        ],
        "x-idempotent": true,
        "x-expensive": false,
        "x-sandbox": "fake",
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "responses": {
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "413": {
            "$ref": "#/components/responses/PayloadTooLarge"
          },
          "415": {
            "$ref": "#/components/responses/UnsupportedMediaType"
          },
          "502": {
            "$ref": "#/components/responses/BadGateway"
          },
          "504": {
            "$ref": "#/components/responses/GatewayTimeout"
          },
          "200": {
            "description": "Deleted",
            "headers": {
              "X-Request-ID": {
                "$ref": "#/components/headers/X-Request-ID"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "X-Sandbox": {
                "$ref": "#/components/headers/X-Sandbox"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DeleteResult"
                }
              }
            }
          }
        }
      }
    },
    "/servers/{server_id}/status": {
      "parameters": [
        {
          "$ref": "#/components/parameters/RequestId"
        },
        {
          "$ref": "#/components/parameters/ServerId"
        }
      ],
      "get": {
        "operationId": "get_server_status",
        "tags": [
          "Servers"
        ],
        "summary": "Live power state and usage from the panel",
        "description": "Servers imported from history with synthetic ids (`2000000000 … 8999999999`, flagged\n`flags.synthetic: true`) have no panel record → `409 service_state`. Sandbox servers\nordered with a `vk_test_` key (ids `>= 9000000000`) are the exception: they are not\nflagged synthetic and answer `200` with a deterministic snapshot built without ever\ntouching the panel.\n",
        "x-scopes": [
          "servers:read"
        ],
        "x-idempotent": false,
        "x-expensive": true,
        "x-sandbox": "real",
        "responses": {
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "200": {
            "description": "Live status",
            "headers": {
              "X-Request-ID": {
                "$ref": "#/components/headers/X-Request-ID"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "X-Sandbox": {
                "$ref": "#/components/headers/X-Sandbox"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ServerLiveStatus"
                }
              }
            }
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "502": {
            "$ref": "#/components/responses/BadGateway"
          },
          "504": {
            "$ref": "#/components/responses/GatewayTimeout"
          }
        }
      }
    },
    "/servers/{server_id}/refund-quote": {
      "parameters": [
        {
          "$ref": "#/components/parameters/RequestId"
        },
        {
          "$ref": "#/components/parameters/ServerId"
        }
      ],
      "get": {
        "operationId": "get_server_refund_quote",
        "tags": [
          "Servers"
        ],
        "summary": "What DELETE would refund right now",
        "x-scopes": [
          "servers:read"
        ],
        "x-idempotent": false,
        "x-expensive": false,
        "x-sandbox": "real",
        "responses": {
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "200": {
            "description": "Refund quote",
            "headers": {
              "X-Request-ID": {
                "$ref": "#/components/headers/X-Request-ID"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "X-Sandbox": {
                "$ref": "#/components/headers/X-Sandbox"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RefundQuote"
                }
              }
            }
          }
        }
      }
    },
    "/servers/{server_id}/renew": {
      "parameters": [
        {
          "$ref": "#/components/parameters/RequestId"
        },
        {
          "$ref": "#/components/parameters/ServerId"
        }
      ],
      "post": {
        "operationId": "renew_server",
        "tags": [
          "Servers"
        ],
        "summary": "Renew for months or hours from balance",
        "description": "Extends `billing.next_due_at`; early renewal stacks on top of the current period. Monthly servers take `months`, hourly ones take `hours`.",
        "x-scopes": [
          "servers:order"
        ],
        "x-idempotent": true,
        "x-expensive": true,
        "x-sandbox": "fake",
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/RenewRequest"
              },
              "example": {
                "months": 3
              }
            }
          }
        },
        "responses": {
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "413": {
            "$ref": "#/components/responses/PayloadTooLarge"
          },
          "415": {
            "$ref": "#/components/responses/UnsupportedMediaType"
          },
          "502": {
            "$ref": "#/components/responses/BadGateway"
          },
          "504": {
            "$ref": "#/components/responses/GatewayTimeout"
          },
          "402": {
            "$ref": "#/components/responses/PaymentRequired"
          },
          "200": {
            "description": "Renewed",
            "headers": {
              "X-Request-ID": {
                "$ref": "#/components/headers/X-Request-ID"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "X-Sandbox": {
                "$ref": "#/components/headers/X-Sandbox"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RenewResult"
                }
              }
            }
          }
        }
      }
    },
    "/servers/{server_id}/actions/power": {
      "parameters": [
        {
          "$ref": "#/components/parameters/RequestId"
        },
        {
          "$ref": "#/components/parameters/ServerId"
        }
      ],
      "post": {
        "operationId": "power_server",
        "tags": [
          "Server actions"
        ],
        "summary": "Start, stop or restart",
        "x-scopes": [
          "servers:manage"
        ],
        "x-idempotent": false,
        "x-expensive": false,
        "x-sandbox": "fake",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PowerRequest"
              },
              "example": {
                "action": "restart"
              }
            }
          }
        },
        "responses": {
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "413": {
            "$ref": "#/components/responses/PayloadTooLarge"
          },
          "415": {
            "$ref": "#/components/responses/UnsupportedMediaType"
          },
          "502": {
            "$ref": "#/components/responses/BadGateway"
          },
          "504": {
            "$ref": "#/components/responses/GatewayTimeout"
          },
          "202": {
            "description": "Command accepted by the panel",
            "headers": {
              "X-Request-ID": {
                "$ref": "#/components/headers/X-Request-ID"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "X-Sandbox": {
                "$ref": "#/components/headers/X-Sandbox"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ActionResult"
                }
              }
            }
          }
        }
      }
    },
    "/servers/{server_id}/actions/reinstall": {
      "parameters": [
        {
          "$ref": "#/components/parameters/RequestId"
        },
        {
          "$ref": "#/components/parameters/ServerId"
        }
      ],
      "post": {
        "operationId": "reinstall_server",
        "tags": [
          "Server actions"
        ],
        "summary": "Reinstall the OS",
        "description": "Destroys all data on the disk. When `password` is omitted a new one is generated and returned once.",
        "x-scopes": [
          "servers:manage"
        ],
        "x-idempotent": false,
        "x-expensive": false,
        "x-sandbox": "fake",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ReinstallRequest"
              },
              "example": {
                "os": "debian-12",
                "ssh_key_ids": [
                  3
                ]
              }
            }
          }
        },
        "responses": {
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "413": {
            "$ref": "#/components/responses/PayloadTooLarge"
          },
          "415": {
            "$ref": "#/components/responses/UnsupportedMediaType"
          },
          "502": {
            "$ref": "#/components/responses/BadGateway"
          },
          "504": {
            "$ref": "#/components/responses/GatewayTimeout"
          },
          "202": {
            "description": "Reinstall started",
            "headers": {
              "X-Request-ID": {
                "$ref": "#/components/headers/X-Request-ID"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "X-Sandbox": {
                "$ref": "#/components/headers/X-Sandbox"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ReinstallResult"
                }
              }
            }
          }
        }
      }
    },
    "/servers/{server_id}/actions/reset-password": {
      "parameters": [
        {
          "$ref": "#/components/parameters/RequestId"
        },
        {
          "$ref": "#/components/parameters/ServerId"
        }
      ],
      "post": {
        "operationId": "reset_server_password",
        "tags": [
          "Server actions"
        ],
        "summary": "Generate a new root password",
        "description": "Also limited to 5 calls per 5 minutes per server.",
        "x-scopes": [
          "servers:manage"
        ],
        "x-idempotent": false,
        "x-expensive": false,
        "x-sandbox": "fake",
        "responses": {
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "413": {
            "$ref": "#/components/responses/PayloadTooLarge"
          },
          "415": {
            "$ref": "#/components/responses/UnsupportedMediaType"
          },
          "502": {
            "$ref": "#/components/responses/BadGateway"
          },
          "504": {
            "$ref": "#/components/responses/GatewayTimeout"
          },
          "200": {
            "description": "New password, shown once",
            "headers": {
              "X-Request-ID": {
                "$ref": "#/components/headers/X-Request-ID"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "X-Sandbox": {
                "$ref": "#/components/headers/X-Sandbox"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ResetPasswordResult"
                }
              }
            }
          }
        }
      }
    },
    "/orders": {
      "parameters": [
        {
          "$ref": "#/components/parameters/RequestId"
        }
      ],
      "get": {
        "operationId": "list_orders",
        "tags": [
          "Orders"
        ],
        "summary": "Orders still being provisioned, newest first",
        "description": "Only orders whose server is still being created are listed: billing\nhas no orders table, the state lives in the invoice. A finished order\nis a server (`GET /servers`) and a paid invoice (`GET /invoices`).\n",
        "x-scopes": [
          "servers:read"
        ],
        "x-idempotent": false,
        "x-expensive": false,
        "x-sandbox": "real",
        "parameters": [
          {
            "$ref": "#/components/parameters/Cursor"
          },
          {
            "$ref": "#/components/parameters/Limit"
          },
          {
            "name": "status",
            "in": "query",
            "description": "Only `provisioning` is accepted; any other value answers `400 validation_error`.",
            "schema": {
              "type": "string",
              "const": "provisioning"
            }
          }
        ],
        "responses": {
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "200": {
            "description": "Page of orders",
            "headers": {
              "X-Request-ID": {
                "$ref": "#/components/headers/X-Request-ID"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "X-Sandbox": {
                "$ref": "#/components/headers/X-Sandbox"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OrderPage"
                }
              }
            }
          }
        }
      }
    },
    "/orders/{invoice_id}": {
      "parameters": [
        {
          "$ref": "#/components/parameters/RequestId"
        },
        {
          "$ref": "#/components/parameters/InvoiceId"
        }
      ],
      "get": {
        "operationId": "get_order",
        "tags": [
          "Orders"
        ],
        "summary": "Order state by its invoice id",
        "description": "Poll after a `202 provisioning`. Terminal states are `active` (with `server_id`) and `cancelled` (charge refunded by the reconciler).",
        "x-scopes": [
          "servers:read"
        ],
        "x-idempotent": false,
        "x-expensive": false,
        "x-sandbox": "real",
        "responses": {
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "200": {
            "description": "Order",
            "headers": {
              "X-Request-ID": {
                "$ref": "#/components/headers/X-Request-ID"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "X-Sandbox": {
                "$ref": "#/components/headers/X-Sandbox"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Order"
                }
              }
            }
          }
        }
      }
    },
    "/servers/{server_id}/ips": {
      "parameters": [
        {
          "$ref": "#/components/parameters/RequestId"
        },
        {
          "$ref": "#/components/parameters/ServerId"
        }
      ],
      "get": {
        "operationId": "list_server_ips",
        "tags": [
          "IPs"
        ],
        "summary": "Addresses of the server",
        "description": "Read live from the panel, so the call is billed against the expensive bucket (api_v1/routes/ips.py:50).",
        "x-scopes": [
          "servers:read"
        ],
        "x-idempotent": false,
        "x-expensive": true,
        "x-sandbox": "real",
        "responses": {
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "200": {
            "description": "Addresses",
            "headers": {
              "X-Request-ID": {
                "$ref": "#/components/headers/X-Request-ID"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "X-Sandbox": {
                "$ref": "#/components/headers/X-Sandbox"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data"
                  ],
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Ip"
                      }
                    }
                  }
                }
              }
            }
          }
        }
      },
      "post": {
        "operationId": "add_server_ip",
        "tags": [
          "IPs"
        ],
        "summary": "Buy an additional IPv4",
        "description": "Charges the prorated price for the rest of the current period (see `GET .../ips/quote`) and raises `billing.recurring_amount`. Limit per server → `409 ip_limit_reached`.",
        "x-scopes": [
          "servers:order"
        ],
        "x-idempotent": true,
        "x-expensive": true,
        "x-sandbox": "fake",
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/IpAddRequest"
              },
              "example": {
                "count": 1
              }
            }
          }
        },
        "responses": {
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "413": {
            "$ref": "#/components/responses/PayloadTooLarge"
          },
          "415": {
            "$ref": "#/components/responses/UnsupportedMediaType"
          },
          "502": {
            "$ref": "#/components/responses/BadGateway"
          },
          "504": {
            "$ref": "#/components/responses/GatewayTimeout"
          },
          "402": {
            "$ref": "#/components/responses/PaymentRequired"
          },
          "201": {
            "description": "Address bought and charged",
            "headers": {
              "X-Request-ID": {
                "$ref": "#/components/headers/X-Request-ID"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "X-Sandbox": {
                "$ref": "#/components/headers/X-Sandbox"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/IpAdded"
                }
              }
            }
          }
        }
      }
    },
    "/servers/{server_id}/ips/quote": {
      "parameters": [
        {
          "$ref": "#/components/parameters/RequestId"
        },
        {
          "$ref": "#/components/parameters/ServerId"
        }
      ],
      "get": {
        "operationId": "get_server_ip_quote",
        "tags": [
          "IPs"
        ],
        "summary": "Price of one more IPv4 for this server",
        "description": "Asks the panel how many addresses the server already has, so the call is billed against the expensive bucket (api_v1/routes/ips.py:157).",
        "x-scopes": [
          "servers:read"
        ],
        "x-idempotent": false,
        "x-expensive": true,
        "x-sandbox": "real",
        "responses": {
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "200": {
            "description": "Quote",
            "headers": {
              "X-Request-ID": {
                "$ref": "#/components/headers/X-Request-ID"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "X-Sandbox": {
                "$ref": "#/components/headers/X-Sandbox"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/IpQuote"
                }
              }
            }
          }
        }
      }
    },
    "/servers/{server_id}/ips/{ip_id}": {
      "parameters": [
        {
          "$ref": "#/components/parameters/RequestId"
        },
        {
          "$ref": "#/components/parameters/ServerId"
        },
        {
          "$ref": "#/components/parameters/IpId"
        }
      ],
      "delete": {
        "operationId": "delete_server_ip",
        "tags": [
          "IPs"
        ],
        "summary": "Release an additional IPv4",
        "description": "The primary address cannot be released (`409 conflict`). No refund; the recurring amount drops from the next period.",
        "x-scopes": [
          "servers:order"
        ],
        "x-idempotent": false,
        "x-expensive": false,
        "x-sandbox": "fake",
        "responses": {
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "413": {
            "$ref": "#/components/responses/PayloadTooLarge"
          },
          "415": {
            "$ref": "#/components/responses/UnsupportedMediaType"
          },
          "502": {
            "$ref": "#/components/responses/BadGateway"
          },
          "504": {
            "$ref": "#/components/responses/GatewayTimeout"
          },
          "200": {
            "description": "Released",
            "headers": {
              "X-Request-ID": {
                "$ref": "#/components/headers/X-Request-ID"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "X-Sandbox": {
                "$ref": "#/components/headers/X-Sandbox"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/IpDeleted"
                }
              }
            }
          }
        }
      }
    },
    "/servers/{server_id}/ips/{ip_id}/ptr": {
      "parameters": [
        {
          "$ref": "#/components/parameters/RequestId"
        },
        {
          "$ref": "#/components/parameters/ServerId"
        },
        {
          "$ref": "#/components/parameters/IpId"
        }
      ],
      "put": {
        "operationId": "set_server_ip_ptr",
        "tags": [
          "IPs"
        ],
        "summary": "Set or remove the PTR (reverse DNS) record",
        "description": "The hostname goes in `domain`. Send `\"\"`, `null` or an empty object to\nremove the record. The address must have rDNS enabled in the panel,\notherwise the answer is `400`.\n",
        "x-scopes": [
          "servers:manage"
        ],
        "x-idempotent": false,
        "x-expensive": false,
        "x-sandbox": "fake",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PtrUpdate"
              },
              "example": {
                "domain": "mail.example.com"
              }
            }
          }
        },
        "responses": {
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "413": {
            "$ref": "#/components/responses/PayloadTooLarge"
          },
          "415": {
            "$ref": "#/components/responses/UnsupportedMediaType"
          },
          "502": {
            "$ref": "#/components/responses/BadGateway"
          },
          "504": {
            "$ref": "#/components/responses/GatewayTimeout"
          },
          "200": {
            "description": "The stored record",
            "headers": {
              "X-Request-ID": {
                "$ref": "#/components/headers/X-Request-ID"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "X-Sandbox": {
                "$ref": "#/components/headers/X-Sandbox"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PtrRecord"
                }
              }
            }
          }
        }
      }
    },
    "/ssh-keys": {
      "parameters": [
        {
          "$ref": "#/components/parameters/RequestId"
        }
      ],
      "get": {
        "operationId": "list_ssh_keys",
        "tags": [
          "SSH keys"
        ],
        "summary": "Public keys stored on the account",
        "description": "Listing needs `servers:read` (api_v1/routes/ssh_keys.py); adding and deleting need `servers:manage`.",
        "x-scopes": [
          "servers:read"
        ],
        "x-idempotent": false,
        "x-expensive": false,
        "x-sandbox": "real",
        "responses": {
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          },
          "200": {
            "description": "Keys",
            "headers": {
              "X-Request-ID": {
                "$ref": "#/components/headers/X-Request-ID"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "X-Sandbox": {
                "$ref": "#/components/headers/X-Sandbox"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data"
                  ],
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/SshKey"
                      }
                    }
                  }
                }
              }
            }
          }
        }
      },
      "post": {
        "operationId": "create_ssh_key",
        "tags": [
          "SSH keys"
        ],
        "summary": "Add a public key",
        "x-scopes": [
          "servers:manage"
        ],
        "x-idempotent": false,
        "x-expensive": false,
        "x-sandbox": "fake",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SshKeyCreate"
              },
              "example": {
                "name": "laptop",
                "public_key": "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIHPpImosNSJfm14MrVrZDm5Th08MJO3UUdzJWqQ9M7T2 user@laptop"
              }
            }
          }
        },
        "responses": {
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "413": {
            "$ref": "#/components/responses/PayloadTooLarge"
          },
          "415": {
            "$ref": "#/components/responses/UnsupportedMediaType"
          },
          "502": {
            "$ref": "#/components/responses/BadGateway"
          },
          "504": {
            "$ref": "#/components/responses/GatewayTimeout"
          },
          "201": {
            "description": "Stored key",
            "headers": {
              "X-Request-ID": {
                "$ref": "#/components/headers/X-Request-ID"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "X-Sandbox": {
                "$ref": "#/components/headers/X-Sandbox"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SshKey"
                }
              }
            }
          }
        }
      }
    },
    "/ssh-keys/{key_id}": {
      "parameters": [
        {
          "$ref": "#/components/parameters/RequestId"
        },
        {
          "$ref": "#/components/parameters/SshKeyId"
        }
      ],
      "delete": {
        "operationId": "delete_ssh_key",
        "tags": [
          "SSH keys"
        ],
        "summary": "Remove a public key",
        "description": "Does not touch servers where the key is already installed.",
        "x-scopes": [
          "servers:manage"
        ],
        "x-idempotent": false,
        "x-expensive": false,
        "x-sandbox": "fake",
        "responses": {
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "413": {
            "$ref": "#/components/responses/PayloadTooLarge"
          },
          "415": {
            "$ref": "#/components/responses/UnsupportedMediaType"
          },
          "502": {
            "$ref": "#/components/responses/BadGateway"
          },
          "504": {
            "$ref": "#/components/responses/GatewayTimeout"
          },
          "200": {
            "description": "Removed",
            "headers": {
              "X-Request-ID": {
                "$ref": "#/components/headers/X-Request-ID"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "X-Sandbox": {
                "$ref": "#/components/headers/X-Sandbox"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SshKeyDeleted"
                }
              }
            }
          }
        }
      }
    },
    "/domains/availability": {
      "parameters": [
        {
          "$ref": "#/components/parameters/RequestId"
        }
      ],
      "get": {
        "operationId": "check_domain_availability",
        "tags": [
          "Domains"
        ],
        "summary": "Is the name free to register",
        "x-scopes": [
          "domains:read"
        ],
        "x-idempotent": false,
        "x-expensive": true,
        "x-sandbox": "real",
        "parameters": [
          {
            "name": "name",
            "in": "query",
            "required": true,
            "description": "Full domain name, IDN allowed (sent as punycode or Unicode).",
            "schema": {
              "type": "string",
              "minLength": 3,
              "maxLength": 253
            }
          }
        ],
        "responses": {
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "200": {
            "description": "Availability and price",
            "headers": {
              "X-Request-ID": {
                "$ref": "#/components/headers/X-Request-ID"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "X-Sandbox": {
                "$ref": "#/components/headers/X-Sandbox"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AvailabilityResult"
                }
              }
            }
          },
          "502": {
            "$ref": "#/components/responses/BadGateway"
          },
          "504": {
            "$ref": "#/components/responses/GatewayTimeout"
          }
        }
      }
    },
    "/domains": {
      "parameters": [
        {
          "$ref": "#/components/parameters/RequestId"
        }
      ],
      "get": {
        "operationId": "list_domains",
        "tags": [
          "Domains"
        ],
        "summary": "Domains of the account",
        "x-scopes": [
          "domains:read"
        ],
        "x-idempotent": false,
        "x-expensive": false,
        "x-sandbox": "real",
        "parameters": [
          {
            "$ref": "#/components/parameters/Cursor"
          },
          {
            "$ref": "#/components/parameters/Limit"
          },
          {
            "name": "status",
            "in": "query",
            "schema": {
              "$ref": "#/components/schemas/DomainStatus"
            }
          }
        ],
        "responses": {
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "200": {
            "description": "Page of domains",
            "headers": {
              "X-Request-ID": {
                "$ref": "#/components/headers/X-Request-ID"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "X-Sandbox": {
                "$ref": "#/components/headers/X-Sandbox"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DomainPage"
                }
              }
            }
          }
        }
      },
      "post": {
        "operationId": "register_domain",
        "tags": [
          "Domains"
        ],
        "summary": "Register a domain",
        "description": "Charges the balance and registers at the registrar using the\naccount's contact profile. `201` when the registrar confirmed at\nonce, `202 pending` when it accepted the request and the domain will\nbecome `active` on the next sync (event `domain.registered`). Taken\nname → `409 domain_taken`.\n",
        "x-scopes": [
          "domains:order"
        ],
        "x-idempotent": true,
        "x-expensive": false,
        "x-sandbox": "fake",
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/DomainRegister"
              },
              "example": {
                "name": "example.com",
                "years": 1,
                "privacy": true,
                "auto_renew": true
              }
            }
          }
        },
        "responses": {
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "413": {
            "$ref": "#/components/responses/PayloadTooLarge"
          },
          "415": {
            "$ref": "#/components/responses/UnsupportedMediaType"
          },
          "502": {
            "$ref": "#/components/responses/BadGateway"
          },
          "504": {
            "$ref": "#/components/responses/GatewayTimeout"
          },
          "402": {
            "$ref": "#/components/responses/PaymentRequired"
          },
          "201": {
            "description": "Registered",
            "headers": {
              "X-Request-ID": {
                "$ref": "#/components/headers/X-Request-ID"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "X-Sandbox": {
                "$ref": "#/components/headers/X-Sandbox"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DomainOrderResult"
                }
              }
            }
          },
          "202": {
            "description": "Accepted by the registrar, pending",
            "headers": {
              "X-Request-ID": {
                "$ref": "#/components/headers/X-Request-ID"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "X-Sandbox": {
                "$ref": "#/components/headers/X-Sandbox"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DomainOrderResult"
                }
              }
            }
          }
        }
      }
    },
    "/domains/{domain_id}": {
      "parameters": [
        {
          "$ref": "#/components/parameters/RequestId"
        },
        {
          "$ref": "#/components/parameters/DomainId"
        }
      ],
      "get": {
        "operationId": "get_domain",
        "tags": [
          "Domains"
        ],
        "summary": "One domain",
        "x-scopes": [
          "domains:read"
        ],
        "x-idempotent": false,
        "x-expensive": false,
        "x-sandbox": "real",
        "responses": {
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "200": {
            "description": "Domain",
            "headers": {
              "X-Request-ID": {
                "$ref": "#/components/headers/X-Request-ID"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "X-Sandbox": {
                "$ref": "#/components/headers/X-Sandbox"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Domain"
                }
              }
            }
          }
        }
      },
      "patch": {
        "operationId": "update_domain",
        "tags": [
          "Domains"
        ],
        "summary": "Toggle auto-renew or WHOIS privacy",
        "description": "Privacy is applied at the registrar synchronously; a refusal there → `400 upstream_rejected` and nothing is saved.",
        "x-scopes": [
          "domains:manage"
        ],
        "x-idempotent": false,
        "x-expensive": false,
        "x-sandbox": "fake",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/DomainUpdate"
              },
              "example": {
                "privacy": false
              }
            }
          }
        },
        "responses": {
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "413": {
            "$ref": "#/components/responses/PayloadTooLarge"
          },
          "415": {
            "$ref": "#/components/responses/UnsupportedMediaType"
          },
          "502": {
            "$ref": "#/components/responses/BadGateway"
          },
          "504": {
            "$ref": "#/components/responses/GatewayTimeout"
          },
          "200": {
            "description": "Updated domain",
            "headers": {
              "X-Request-ID": {
                "$ref": "#/components/headers/X-Request-ID"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "X-Sandbox": {
                "$ref": "#/components/headers/X-Sandbox"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Domain"
                }
              }
            }
          }
        }
      }
    },
    "/domains/{domain_id}/renew": {
      "parameters": [
        {
          "$ref": "#/components/parameters/RequestId"
        },
        {
          "$ref": "#/components/parameters/DomainId"
        }
      ],
      "post": {
        "operationId": "renew_domain",
        "tags": [
          "Domains"
        ],
        "summary": "Renew for N years from balance",
        "description": "May answer `status = pending_sync` when the registrar accepted the renewal but the new expiry date is not yet visible; it is picked up by the daily sync.",
        "x-scopes": [
          "domains:order"
        ],
        "x-idempotent": true,
        "x-expensive": false,
        "x-sandbox": "fake",
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/DomainRenew"
              },
              "example": {
                "years": 1
              }
            }
          }
        },
        "responses": {
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "413": {
            "$ref": "#/components/responses/PayloadTooLarge"
          },
          "415": {
            "$ref": "#/components/responses/UnsupportedMediaType"
          },
          "502": {
            "$ref": "#/components/responses/BadGateway"
          },
          "504": {
            "$ref": "#/components/responses/GatewayTimeout"
          },
          "402": {
            "$ref": "#/components/responses/PaymentRequired"
          },
          "200": {
            "description": "Renewed (`renewed`, or `pending_sync` when only our record lags behind)",
            "headers": {
              "X-Request-ID": {
                "$ref": "#/components/headers/X-Request-ID"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "X-Sandbox": {
                "$ref": "#/components/headers/X-Sandbox"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DomainRenewResult"
                }
              }
            }
          },
          "202": {
            "description": "Charged, the registrar has not answered yet (`pending`)",
            "headers": {
              "X-Request-ID": {
                "$ref": "#/components/headers/X-Request-ID"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "X-Sandbox": {
                "$ref": "#/components/headers/X-Sandbox"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DomainRenewResult"
                }
              }
            }
          }
        }
      }
    },
    "/domains/{domain_id}/nameservers": {
      "parameters": [
        {
          "$ref": "#/components/parameters/RequestId"
        },
        {
          "$ref": "#/components/parameters/DomainId"
        }
      ],
      "put": {
        "operationId": "set_domain_nameservers",
        "tags": [
          "Domains"
        ],
        "summary": "Replace the nameserver set",
        "x-scopes": [
          "domains:manage"
        ],
        "x-idempotent": false,
        "x-expensive": false,
        "x-sandbox": "fake",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/NameserversUpdate"
              },
              "example": {
                "nameservers": [
                  "ns1.example.net",
                  "ns2.example.net"
                ]
              }
            }
          }
        },
        "responses": {
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "413": {
            "$ref": "#/components/responses/PayloadTooLarge"
          },
          "415": {
            "$ref": "#/components/responses/UnsupportedMediaType"
          },
          "502": {
            "$ref": "#/components/responses/BadGateway"
          },
          "504": {
            "$ref": "#/components/responses/GatewayTimeout"
          },
          "200": {
            "description": "Updated domain",
            "headers": {
              "X-Request-ID": {
                "$ref": "#/components/headers/X-Request-ID"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "X-Sandbox": {
                "$ref": "#/components/headers/X-Sandbox"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Domain"
                }
              }
            }
          }
        }
      }
    },
    "/domains/transfers": {
      "parameters": [
        {
          "$ref": "#/components/parameters/RequestId"
        }
      ],
      "post": {
        "operationId": "transfer_domain",
        "tags": [
          "Domains"
        ],
        "summary": "Transfer a domain in from another registrar",
        "description": "Charges the transfer price (usually includes a one-year renewal) and starts the transfer; the domain appears with status `transfer_pending`.",
        "x-scopes": [
          "domains:order"
        ],
        "x-idempotent": true,
        "x-expensive": false,
        "x-sandbox": "fake",
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/DomainTransfer"
              },
              "example": {
                "name": "example.org",
                "auth_code": "AbC-123-xyz"
              }
            }
          }
        },
        "responses": {
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "413": {
            "$ref": "#/components/responses/PayloadTooLarge"
          },
          "415": {
            "$ref": "#/components/responses/UnsupportedMediaType"
          },
          "502": {
            "$ref": "#/components/responses/BadGateway"
          },
          "504": {
            "$ref": "#/components/responses/GatewayTimeout"
          },
          "402": {
            "$ref": "#/components/responses/PaymentRequired"
          },
          "202": {
            "description": "Transfer started",
            "headers": {
              "X-Request-ID": {
                "$ref": "#/components/headers/X-Request-ID"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "X-Sandbox": {
                "$ref": "#/components/headers/X-Sandbox"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DomainTransferResult"
                }
              }
            }
          }
        }
      }
    },
    "/keys": {
      "parameters": [
        {
          "$ref": "#/components/parameters/RequestId"
        }
      ],
      "get": {
        "operationId": "list_api_keys",
        "tags": [
          "Keys"
        ],
        "summary": "API keys of the account",
        "x-scopes": [
          "keys:read"
        ],
        "x-idempotent": false,
        "x-expensive": false,
        "x-sandbox": "real",
        "responses": {
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          },
          "200": {
            "description": "Keys (never the secret itself)",
            "headers": {
              "X-Request-ID": {
                "$ref": "#/components/headers/X-Request-ID"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "X-Sandbox": {
                "$ref": "#/components/headers/X-Sandbox"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiKeyPage"
                }
              }
            }
          }
        }
      }
    },
    "/keys/{key_id}": {
      "parameters": [
        {
          "$ref": "#/components/parameters/RequestId"
        },
        {
          "$ref": "#/components/parameters/ApiKeyId"
        }
      ],
      "get": {
        "operationId": "get_api_key",
        "tags": [
          "Keys"
        ],
        "summary": "One API key",
        "x-scopes": [
          "keys:read"
        ],
        "x-idempotent": false,
        "x-expensive": false,
        "x-sandbox": "real",
        "responses": {
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "200": {
            "description": "Key",
            "headers": {
              "X-Request-ID": {
                "$ref": "#/components/headers/X-Request-ID"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "X-Sandbox": {
                "$ref": "#/components/headers/X-Sandbox"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiKey"
                }
              }
            }
          }
        }
      },
      "delete": {
        "operationId": "revoke_api_key",
        "tags": [
          "Keys"
        ],
        "summary": "Revoke the calling key (kill switch)",
        "description": "Only the key that makes the request can be revoked here, whatever its\nscopes, so a leaked key can be killed from anywhere without giving\nevery key the power to destroy the whole integration. Other keys are\nrevoked in the cabinet. Any other `key_id` answers\n`403 insufficient_scope` with `details.required = [\"self\"]`, and a key\nthat is already revoked answers `409 conflict`.\n\n**The one mutation that is real under a test key.** Every other write\nis simulated for `vk_test_…` (`x-sandbox: fake`); this one is not,\nbecause a leaked test key must be killable with the leaked key itself.\nNo money moves and nothing outside the key row is touched. The build\nscript keeps this exception on a short allow-list, so no other\nmutation can quietly become real.\n",
        "x-scopes": [],
        "x-idempotent": false,
        "x-expensive": false,
        "x-sandbox": "real",
        "responses": {
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "413": {
            "$ref": "#/components/responses/PayloadTooLarge"
          },
          "415": {
            "$ref": "#/components/responses/UnsupportedMediaType"
          },
          "502": {
            "$ref": "#/components/responses/BadGateway"
          },
          "504": {
            "$ref": "#/components/responses/GatewayTimeout"
          },
          "200": {
            "description": "Revoked",
            "headers": {
              "X-Request-ID": {
                "$ref": "#/components/headers/X-Request-ID"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "X-Sandbox": {
                "$ref": "#/components/headers/X-Sandbox"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiKeyRevoked"
                }
              }
            }
          }
        }
      }
    },
    "/webhooks": {
      "parameters": [
        {
          "$ref": "#/components/parameters/RequestId"
        }
      ],
      "get": {
        "operationId": "list_webhooks",
        "tags": [
          "Webhooks"
        ],
        "summary": "Webhook subscriptions",
        "x-scopes": [
          "webhooks:manage"
        ],
        "x-idempotent": false,
        "x-expensive": false,
        "x-sandbox": "forbidden",
        "responses": {
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          },
          "200": {
            "description": "Subscriptions",
            "headers": {
              "X-Request-ID": {
                "$ref": "#/components/headers/X-Request-ID"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "X-Sandbox": {
                "$ref": "#/components/headers/X-Sandbox"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebhookSubscriptionPage"
                }
              }
            }
          }
        }
      },
      "post": {
        "operationId": "create_webhook",
        "tags": [
          "Webhooks"
        ],
        "summary": "Subscribe a URL to events",
        "description": "URL must be `https://` on a public IP. The `secret` is returned once; rotate it with `POST /webhooks/{webhook_id}/rotate-secret`.",
        "x-scopes": [
          "webhooks:manage"
        ],
        "x-idempotent": false,
        "x-expensive": false,
        "x-sandbox": "forbidden",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WebhookSubscriptionCreate"
              },
              "example": {
                "url": "https://hooks.example.com/vdsok",
                "events": [
                  "server.created",
                  "server.terminated",
                  "invoice.paid",
                  "balance.low"
                ],
                "description": "billing sync"
              }
            }
          }
        },
        "responses": {
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "413": {
            "$ref": "#/components/responses/PayloadTooLarge"
          },
          "415": {
            "$ref": "#/components/responses/UnsupportedMediaType"
          },
          "502": {
            "$ref": "#/components/responses/BadGateway"
          },
          "504": {
            "$ref": "#/components/responses/GatewayTimeout"
          },
          "201": {
            "description": "Subscription with its secret",
            "headers": {
              "X-Request-ID": {
                "$ref": "#/components/headers/X-Request-ID"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "X-Sandbox": {
                "$ref": "#/components/headers/X-Sandbox"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebhookSubscriptionWithSecret"
                }
              }
            }
          }
        }
      }
    },
    "/webhooks/events": {
      "parameters": [
        {
          "$ref": "#/components/parameters/RequestId"
        }
      ],
      "get": {
        "operationId": "list_webhook_events",
        "tags": [
          "Webhooks"
        ],
        "summary": "Event types you can subscribe to",
        "x-scopes": [
          "webhooks:manage"
        ],
        "x-idempotent": false,
        "x-expensive": false,
        "x-sandbox": "forbidden",
        "responses": {
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          },
          "200": {
            "description": "Event catalog",
            "headers": {
              "X-Request-ID": {
                "$ref": "#/components/headers/X-Request-ID"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "X-Sandbox": {
                "$ref": "#/components/headers/X-Sandbox"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data"
                  ],
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/WebhookEventDescriptor"
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/webhooks/{webhook_id}": {
      "parameters": [
        {
          "$ref": "#/components/parameters/RequestId"
        },
        {
          "$ref": "#/components/parameters/WebhookId"
        }
      ],
      "get": {
        "operationId": "get_webhook",
        "tags": [
          "Webhooks"
        ],
        "summary": "One subscription",
        "x-scopes": [
          "webhooks:manage"
        ],
        "x-idempotent": false,
        "x-expensive": false,
        "x-sandbox": "forbidden",
        "responses": {
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "200": {
            "description": "Subscription",
            "headers": {
              "X-Request-ID": {
                "$ref": "#/components/headers/X-Request-ID"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "X-Sandbox": {
                "$ref": "#/components/headers/X-Sandbox"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebhookSubscription"
                }
              }
            }
          }
        }
      },
      "patch": {
        "operationId": "update_webhook",
        "tags": [
          "Webhooks"
        ],
        "summary": "Change URL, events, description; re-enable after auto-disable",
        "x-scopes": [
          "webhooks:manage"
        ],
        "x-idempotent": false,
        "x-expensive": false,
        "x-sandbox": "forbidden",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WebhookSubscriptionUpdate"
              },
              "example": {
                "active": true
              }
            }
          }
        },
        "responses": {
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "413": {
            "$ref": "#/components/responses/PayloadTooLarge"
          },
          "415": {
            "$ref": "#/components/responses/UnsupportedMediaType"
          },
          "502": {
            "$ref": "#/components/responses/BadGateway"
          },
          "504": {
            "$ref": "#/components/responses/GatewayTimeout"
          },
          "200": {
            "description": "Updated subscription",
            "headers": {
              "X-Request-ID": {
                "$ref": "#/components/headers/X-Request-ID"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "X-Sandbox": {
                "$ref": "#/components/headers/X-Sandbox"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebhookSubscription"
                }
              }
            }
          }
        }
      },
      "delete": {
        "operationId": "delete_webhook",
        "tags": [
          "Webhooks"
        ],
        "summary": "Delete a subscription and its delivery log",
        "x-scopes": [
          "webhooks:manage"
        ],
        "x-idempotent": false,
        "x-expensive": false,
        "x-sandbox": "forbidden",
        "responses": {
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "413": {
            "$ref": "#/components/responses/PayloadTooLarge"
          },
          "415": {
            "$ref": "#/components/responses/UnsupportedMediaType"
          },
          "502": {
            "$ref": "#/components/responses/BadGateway"
          },
          "504": {
            "$ref": "#/components/responses/GatewayTimeout"
          },
          "200": {
            "description": "Deleted",
            "headers": {
              "X-Request-ID": {
                "$ref": "#/components/headers/X-Request-ID"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "X-Sandbox": {
                "$ref": "#/components/headers/X-Sandbox"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebhookDeleted"
                }
              }
            }
          }
        }
      }
    },
    "/webhooks/{webhook_id}/rotate-secret": {
      "parameters": [
        {
          "$ref": "#/components/parameters/RequestId"
        },
        {
          "$ref": "#/components/parameters/WebhookId"
        }
      ],
      "post": {
        "operationId": "rotate_webhook_secret",
        "tags": [
          "Webhooks"
        ],
        "summary": "Issue a new signing secret",
        "description": "The old secret stops working immediately; deliveries already queued are re-signed with the new one at send time.",
        "x-scopes": [
          "webhooks:manage"
        ],
        "x-idempotent": false,
        "x-expensive": false,
        "x-sandbox": "forbidden",
        "responses": {
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "413": {
            "$ref": "#/components/responses/PayloadTooLarge"
          },
          "415": {
            "$ref": "#/components/responses/UnsupportedMediaType"
          },
          "502": {
            "$ref": "#/components/responses/BadGateway"
          },
          "504": {
            "$ref": "#/components/responses/GatewayTimeout"
          },
          "200": {
            "description": "The new secret (the subscription itself is unchanged)",
            "headers": {
              "X-Request-ID": {
                "$ref": "#/components/headers/X-Request-ID"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "X-Sandbox": {
                "$ref": "#/components/headers/X-Sandbox"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebhookSecret"
                }
              }
            }
          }
        }
      }
    },
    "/webhooks/{webhook_id}/test": {
      "parameters": [
        {
          "$ref": "#/components/parameters/RequestId"
        },
        {
          "$ref": "#/components/parameters/WebhookId"
        }
      ],
      "post": {
        "operationId": "test_webhook",
        "tags": [
          "Webhooks"
        ],
        "summary": "Send a `ping` event now and report the result",
        "description": "Delivered inline (not through the queue) so the answer shows the\nreceiver's status code and latency. A disabled subscription answers\n`409 conflict`; if the delivery cannot be queued at all the call\nanswers `503 temporarily_unavailable`.\n",
        "x-scopes": [
          "webhooks:manage"
        ],
        "x-idempotent": false,
        "x-expensive": true,
        "x-sandbox": "forbidden",
        "responses": {
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "413": {
            "$ref": "#/components/responses/PayloadTooLarge"
          },
          "415": {
            "$ref": "#/components/responses/UnsupportedMediaType"
          },
          "502": {
            "$ref": "#/components/responses/BadGateway"
          },
          "504": {
            "$ref": "#/components/responses/GatewayTimeout"
          },
          "200": {
            "description": "Delivery attempt result",
            "headers": {
              "X-Request-ID": {
                "$ref": "#/components/headers/X-Request-ID"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "X-Sandbox": {
                "$ref": "#/components/headers/X-Sandbox"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebhookTestResult"
                }
              }
            }
          }
        }
      }
    },
    "/webhooks/{webhook_id}/deliveries": {
      "parameters": [
        {
          "$ref": "#/components/parameters/RequestId"
        },
        {
          "$ref": "#/components/parameters/WebhookId"
        }
      ],
      "get": {
        "operationId": "list_webhook_deliveries",
        "tags": [
          "Webhooks"
        ],
        "summary": "Delivery log, newest first",
        "description": "Delivered rows are kept 14 days, dead ones 30 days.",
        "x-scopes": [
          "webhooks:manage"
        ],
        "x-idempotent": false,
        "x-expensive": false,
        "x-sandbox": "forbidden",
        "parameters": [
          {
            "$ref": "#/components/parameters/Cursor"
          },
          {
            "$ref": "#/components/parameters/Limit"
          },
          {
            "name": "status",
            "in": "query",
            "description": "`delivered` — `delivered_at` set; `dead` — no further attempts; `pending` — still waiting for `next_attempt_at`.",
            "schema": {
              "type": "string",
              "enum": [
                "pending",
                "delivered",
                "dead"
              ]
            }
          },
          {
            "name": "event_type",
            "in": "query",
            "schema": {
              "$ref": "#/components/schemas/WebhookEventType"
            }
          }
        ],
        "responses": {
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "200": {
            "description": "Page of deliveries",
            "headers": {
              "X-Request-ID": {
                "$ref": "#/components/headers/X-Request-ID"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "X-Sandbox": {
                "$ref": "#/components/headers/X-Sandbox"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebhookDeliveryPage"
                }
              }
            }
          }
        }
      }
    },
    "/webhooks/deliveries/{delivery_id}": {
      "parameters": [
        {
          "$ref": "#/components/parameters/RequestId"
        },
        {
          "$ref": "#/components/parameters/DeliveryId"
        }
      ],
      "get": {
        "operationId": "get_webhook_delivery",
        "tags": [
          "Webhooks"
        ],
        "summary": "One delivery with the exact payload that was sent",
        "description": "The only place `payload` is returned — the bytes signed and delivered, identical across retries.",
        "x-scopes": [
          "webhooks:manage"
        ],
        "x-idempotent": false,
        "x-expensive": false,
        "x-sandbox": "forbidden",
        "responses": {
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "200": {
            "description": "Delivery",
            "headers": {
              "X-Request-ID": {
                "$ref": "#/components/headers/X-Request-ID"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "X-Sandbox": {
                "$ref": "#/components/headers/X-Sandbox"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebhookDeliveryWithPayload"
                }
              }
            }
          }
        }
      }
    },
    "/webhooks/deliveries/{delivery_id}/redeliver": {
      "parameters": [
        {
          "$ref": "#/components/parameters/RequestId"
        },
        {
          "$ref": "#/components/parameters/DeliveryId"
        }
      ],
      "post": {
        "operationId": "redeliver_webhook",
        "tags": [
          "Webhooks"
        ],
        "summary": "Re-queue a delivery",
        "description": "Sends the **same bytes** as the original event (same `id`, same `created_at`), so receivers can deduplicate by `X-Webhook-Id`.",
        "x-scopes": [
          "webhooks:manage"
        ],
        "x-idempotent": false,
        "x-expensive": true,
        "x-sandbox": "forbidden",
        "responses": {
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "413": {
            "$ref": "#/components/responses/PayloadTooLarge"
          },
          "415": {
            "$ref": "#/components/responses/UnsupportedMediaType"
          },
          "502": {
            "$ref": "#/components/responses/BadGateway"
          },
          "504": {
            "$ref": "#/components/responses/GatewayTimeout"
          },
          "202": {
            "description": "Queued",
            "headers": {
              "X-Request-ID": {
                "$ref": "#/components/headers/X-Request-ID"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "X-Sandbox": {
                "$ref": "#/components/headers/X-Sandbox"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebhookRedelivery"
                }
              }
            }
          }
        }
      }
    }
  },
  "webhooks": {
    "server.created": {
      "post": {
        "operationId": "webhook_server_created",
        "tags": [
          "Webhooks"
        ],
        "security": [
          {
            "webhookSignature": []
          }
        ],
        "summary": "A server was created (order or paid invoice provisioned)",
        "requestBody": {
          "$ref": "#/components/requestBodies/ServerEvent"
        },
        "responses": {
          "2XX": {
            "$ref": "#/components/responses/WebhookAck"
          }
        }
      }
    },
    "server.suspended": {
      "post": {
        "operationId": "webhook_server_suspended",
        "tags": [
          "Webhooks"
        ],
        "security": [
          {
            "webhookSignature": []
          }
        ],
        "summary": "Server suspended (non-payment or staff action); `data.previous.status` holds the prior state",
        "requestBody": {
          "$ref": "#/components/requestBodies/ServerEvent"
        },
        "responses": {
          "2XX": {
            "$ref": "#/components/responses/WebhookAck"
          }
        }
      }
    },
    "server.unsuspended": {
      "post": {
        "operationId": "webhook_server_unsuspended",
        "tags": [
          "Webhooks"
        ],
        "security": [
          {
            "webhookSignature": []
          }
        ],
        "summary": "Server resumed after payment or by staff",
        "requestBody": {
          "$ref": "#/components/requestBodies/ServerEvent"
        },
        "responses": {
          "2XX": {
            "$ref": "#/components/responses/WebhookAck"
          }
        }
      }
    },
    "server.terminated": {
      "post": {
        "operationId": "webhook_server_terminated",
        "tags": [
          "Webhooks"
        ],
        "security": [
          {
            "webhookSignature": []
          }
        ],
        "summary": "Server deleted (by the client with refund, by cancel request, or after long non-payment)",
        "requestBody": {
          "$ref": "#/components/requestBodies/ServerEvent"
        },
        "responses": {
          "2XX": {
            "$ref": "#/components/responses/WebhookAck"
          }
        }
      }
    },
    "server.reinstalled": {
      "post": {
        "operationId": "webhook_server_reinstalled",
        "tags": [
          "Webhooks"
        ],
        "security": [
          {
            "webhookSignature": []
          }
        ],
        "summary": "OS reinstall finished",
        "requestBody": {
          "$ref": "#/components/requestBodies/ServerEvent"
        },
        "responses": {
          "2XX": {
            "$ref": "#/components/responses/WebhookAck"
          }
        }
      }
    },
    "invoice.created": {
      "post": {
        "operationId": "webhook_invoice_created",
        "tags": [
          "Webhooks"
        ],
        "security": [
          {
            "webhookSignature": []
          }
        ],
        "summary": "New invoice (renewal, order, top-up)",
        "requestBody": {
          "$ref": "#/components/requestBodies/InvoiceEvent"
        },
        "responses": {
          "2XX": {
            "$ref": "#/components/responses/WebhookAck"
          }
        }
      }
    },
    "invoice.paid": {
      "post": {
        "operationId": "webhook_invoice_paid",
        "tags": [
          "Webhooks"
        ],
        "security": [
          {
            "webhookSignature": []
          }
        ],
        "summary": "Invoice paid (gateway or balance)",
        "requestBody": {
          "$ref": "#/components/requestBodies/InvoiceEvent"
        },
        "responses": {
          "2XX": {
            "$ref": "#/components/responses/WebhookAck"
          }
        }
      }
    },
    "invoice.overdue": {
      "post": {
        "operationId": "webhook_invoice_overdue",
        "tags": [
          "Webhooks"
        ],
        "security": [
          {
            "webhookSignature": []
          }
        ],
        "summary": "Invoice past due date and still unpaid",
        "requestBody": {
          "$ref": "#/components/requestBodies/InvoiceEvent"
        },
        "responses": {
          "2XX": {
            "$ref": "#/components/responses/WebhookAck"
          }
        }
      }
    },
    "balance.low": {
      "post": {
        "operationId": "webhook_balance_low",
        "tags": [
          "Webhooks"
        ],
        "security": [
          {
            "webhookSignature": []
          }
        ],
        "summary": "Balance dropped below the upcoming-charges threshold",
        "requestBody": {
          "$ref": "#/components/requestBodies/BalanceEvent"
        },
        "responses": {
          "2XX": {
            "$ref": "#/components/responses/WebhookAck"
          }
        }
      }
    },
    "domain.registered": {
      "post": {
        "operationId": "webhook_domain_registered",
        "tags": [
          "Webhooks"
        ],
        "security": [
          {
            "webhookSignature": []
          }
        ],
        "summary": "Domain became active at the registrar",
        "requestBody": {
          "$ref": "#/components/requestBodies/DomainEvent"
        },
        "responses": {
          "2XX": {
            "$ref": "#/components/responses/WebhookAck"
          }
        }
      }
    },
    "domain.expiring": {
      "post": {
        "operationId": "webhook_domain_expiring",
        "tags": [
          "Webhooks"
        ],
        "security": [
          {
            "webhookSignature": []
          }
        ],
        "summary": "Domain expires soon (30, 7 and 1 day before)",
        "requestBody": {
          "$ref": "#/components/requestBodies/DomainEvent"
        },
        "responses": {
          "2XX": {
            "$ref": "#/components/responses/WebhookAck"
          }
        }
      }
    },
    "domain.renewed": {
      "post": {
        "operationId": "webhook_domain_renewed",
        "tags": [
          "Webhooks"
        ],
        "security": [
          {
            "webhookSignature": []
          }
        ],
        "summary": "Domain renewed (manually or by auto-renew)",
        "requestBody": {
          "$ref": "#/components/requestBodies/DomainEvent"
        },
        "responses": {
          "2XX": {
            "$ref": "#/components/responses/WebhookAck"
          }
        }
      }
    },
    "key.created": {
      "post": {
        "operationId": "webhook_key_created",
        "tags": [
          "Webhooks"
        ],
        "security": [
          {
            "webhookSignature": []
          }
        ],
        "summary": "A new API key was created in the cabinet",
        "requestBody": {
          "$ref": "#/components/requestBodies/KeyEvent"
        },
        "responses": {
          "2XX": {
            "$ref": "#/components/responses/WebhookAck"
          }
        }
      }
    },
    "key.revoked": {
      "post": {
        "operationId": "webhook_key_revoked",
        "tags": [
          "Webhooks"
        ],
        "security": [
          {
            "webhookSignature": []
          }
        ],
        "summary": "An API key was revoked (client, self-revoke, staff or ban)",
        "requestBody": {
          "$ref": "#/components/requestBodies/KeyEvent"
        },
        "responses": {
          "2XX": {
            "$ref": "#/components/responses/WebhookAck"
          }
        }
      }
    },
    "ping": {
      "post": {
        "operationId": "webhook_ping",
        "tags": [
          "Webhooks"
        ],
        "security": [
          {
            "webhookSignature": []
          }
        ],
        "summary": "Test event sent by `POST /webhooks/{webhook_id}/test`",
        "requestBody": {
          "$ref": "#/components/requestBodies/PingEvent"
        },
        "responses": {
          "2XX": {
            "$ref": "#/components/responses/WebhookAck"
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "apiKey": {
        "type": "http",
        "scheme": "bearer",
        "bearerFormat": "vk_live_… | vk_test_…",
        "description": "API key created in the cabinet. `vk_live_` keys act on the account;\n`vk_test_` keys read real data and simulate writes (see Sandbox).\nKeys are independent of cabinet sessions: password changes, \"log out\neverywhere\" and 2FA changes do not touch them; a ban revokes all.\n"
      },
      "webhookSignature": {
        "type": "apiKey",
        "in": "header",
        "name": "X-Webhook-Signature",
        "description": "Not used to call this API — documents how **outgoing** webhooks are\nsigned so receivers can verify them.\n\nHeaders on every delivery:\n\n* `X-Webhook-Signature: v1=<hex HMAC-SHA256(secret, \"{ts}.{body}\")>`\n* `X-Webhook-Timestamp: <ts>` — unix seconds when the delivery was sent\n* `X-Webhook-Id: evt_…` — the event id, stable across retries\n* `X-Webhook-Event: server.created` — the event type\n* `User-Agent: VDSok-Webhooks/1.0`\n\nVerification: take the raw request body bytes (not re-serialized),\ncompute `HMAC-SHA256(secret, timestamp + \".\" + body)`, compare with\nconstant time to the value after `v1=`, and reject when\n`|now - timestamp| > 300` seconds. The SDKs ship `Webhooks.verify()`\nand `construct_event()` that do exactly this.\n"
      }
    },
    "parameters": {
      "RequestId": {
        "name": "X-Request-ID",
        "in": "header",
        "required": false,
        "description": "Optional trace id of your own. VDSok keeps only the characters\n`A-Za-z0-9._:-` and the first 64 of them; if anything is left, that\nsanitized value becomes the id of the request — it comes back in the\n`X-Request-ID` response header, appears in the error envelope as\n`error.request_id` and is stored in the request log. If nothing is\nleft (empty or entirely stripped) VDSok generates a UUIDv4 instead. A\nmalformed header is never an error. Reuse across different requests\nis allowed but makes support harder; the SDKs send a fresh id per\nattempt.\n",
        "schema": {
          "type": "string",
          "maxLength": 64,
          "examples": [
            "ci-build-4821"
          ]
        }
      },
      "Cursor": {
        "name": "cursor",
        "in": "query",
        "description": "Opaque `next_cursor` from the previous page.",
        "schema": {
          "type": "string",
          "maxLength": 2048
        }
      },
      "Limit": {
        "name": "limit",
        "in": "query",
        "schema": {
          "type": "integer",
          "minimum": 1,
          "maximum": 100,
          "default": 50
        }
      },
      "IdempotencyKey": {
        "name": "Idempotency-Key",
        "in": "header",
        "required": true,
        "description": "Unique per logical request, 16..128 chars (a UUID is fine). Remembered for 7 days.",
        "schema": {
          "type": "string",
          "minLength": 16,
          "maxLength": 128
        }
      },
      "ServerId": {
        "name": "server_id",
        "in": "path",
        "required": true,
        "description": "Panel id of the VM (`solusvm_id`).",
        "schema": {
          "type": "integer",
          "format": "int64",
          "minimum": 1
        }
      },
      "InvoiceId": {
        "name": "invoice_id",
        "in": "path",
        "required": true,
        "schema": {
          "type": "integer",
          "format": "int64",
          "minimum": 1
        }
      },
      "TariffId": {
        "name": "tariff_id",
        "in": "path",
        "required": true,
        "schema": {
          "type": "integer",
          "minimum": 1
        }
      },
      "IpId": {
        "name": "ip_id",
        "in": "path",
        "required": true,
        "schema": {
          "type": "integer",
          "format": "int64",
          "minimum": 1
        }
      },
      "SshKeyId": {
        "name": "key_id",
        "in": "path",
        "required": true,
        "schema": {
          "type": "integer",
          "format": "int64",
          "minimum": 1
        }
      },
      "DomainId": {
        "name": "domain_id",
        "in": "path",
        "required": true,
        "schema": {
          "type": "integer",
          "format": "int64",
          "minimum": 1
        }
      },
      "ApiKeyId": {
        "name": "key_id",
        "in": "path",
        "required": true,
        "schema": {
          "type": "integer",
          "format": "int64",
          "minimum": 1
        }
      },
      "WebhookId": {
        "name": "webhook_id",
        "in": "path",
        "required": true,
        "schema": {
          "type": "integer",
          "format": "int64",
          "minimum": 1
        }
      },
      "DeliveryId": {
        "name": "delivery_id",
        "in": "path",
        "required": true,
        "schema": {
          "type": "integer",
          "format": "int64",
          "minimum": 1
        }
      }
    },
    "headers": {
      "X-Request-ID": {
        "description": "Id of this request; quote it when contacting support. Echoes the\nsanitized `X-Request-ID` you sent when anything survived sanitizing,\notherwise a server-generated UUIDv4.\n",
        "schema": {
          "type": "string",
          "maxLength": 64
        },
        "example": "9f1c2a9d-4b7e-4a21-8d3f-0c6e5b2a1d44"
      },
      "Cache-Control": {
        "description": "`no-store` on every endpoint except `GET /openapi.json`, which is `public, max-age=300`.",
        "schema": {
          "type": "string"
        },
        "example": "public, max-age=300"
      },
      "X-RateLimit-Limit": {
        "description": "Requests allowed per minute for this key in the bucket the call hit (normal or expensive).",
        "schema": {
          "type": "integer",
          "minimum": 1
        }
      },
      "X-RateLimit-Remaining": {
        "description": "Requests left in the current 60-second window.",
        "schema": {
          "type": "integer",
          "minimum": 0
        }
      },
      "X-RateLimit-Reset": {
        "description": "Unix time (seconds) when the window resets.",
        "schema": {
          "type": "integer",
          "minimum": 0
        }
      },
      "X-Sandbox": {
        "description": "Present with value `true` on every response to a test key; absent for live keys.",
        "schema": {
          "type": "string",
          "const": "true"
        }
      },
      "Retry-After": {
        "description": "Seconds to wait before retrying.",
        "schema": {
          "type": "integer",
          "minimum": 1
        }
      }
    },
    "requestBodies": {
      "ServerEvent": {
        "required": true,
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/WebhookEventServer"
            }
          }
        }
      },
      "InvoiceEvent": {
        "required": true,
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/WebhookEventInvoice"
            }
          }
        }
      },
      "BalanceEvent": {
        "required": true,
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/WebhookEventBalance"
            }
          }
        }
      },
      "DomainEvent": {
        "required": true,
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/WebhookEventDomain"
            }
          }
        }
      },
      "KeyEvent": {
        "required": true,
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/WebhookEventKey"
            }
          }
        }
      },
      "PingEvent": {
        "required": true,
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/WebhookEventPing"
            }
          }
        }
      }
    },
    "responses": {
      "WebhookAck": {
        "description": "Any 2xx marks the delivery as done; the body is ignored."
      },
      "BadRequest": {
        "description": "Malformed request. Codes: `invalid_request`, `validation_error`\n(`details.fields`), `invalid_cursor`, `idempotency_key_required`,\n`os_not_allowed`, `invalid_period`, `invalid_action`,\n`upstream_rejected` (registrar or panel refused the parameters).\n",
        "headers": {
          "X-Request-ID": {
            "$ref": "#/components/headers/X-Request-ID"
          },
          "X-RateLimit-Limit": {
            "$ref": "#/components/headers/X-RateLimit-Limit"
          },
          "X-RateLimit-Remaining": {
            "$ref": "#/components/headers/X-RateLimit-Remaining"
          },
          "X-RateLimit-Reset": {
            "$ref": "#/components/headers/X-RateLimit-Reset"
          },
          "X-Sandbox": {
            "$ref": "#/components/headers/X-Sandbox"
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            },
            "example": {
              "error": {
                "code": "validation_error",
                "message": "months must be one of 1, 3, 6, 12",
                "request_id": "9f1c2a9d-4b7e-4a21-8d3f-0c6e5b2a1d44",
                "details": {
                  "fields": {
                    "months": "invalid_period"
                  }
                }
              }
            }
          }
        }
      },
      "Unauthorized": {
        "description": "Codes: `invalid_token`, `key_expired`, `key_not_yet_valid`.",
        "headers": {
          "X-Request-ID": {
            "$ref": "#/components/headers/X-Request-ID"
          },
          "X-RateLimit-Limit": {
            "$ref": "#/components/headers/X-RateLimit-Limit"
          },
          "X-RateLimit-Remaining": {
            "$ref": "#/components/headers/X-RateLimit-Remaining"
          },
          "X-RateLimit-Reset": {
            "$ref": "#/components/headers/X-RateLimit-Reset"
          },
          "X-Sandbox": {
            "$ref": "#/components/headers/X-Sandbox"
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            },
            "example": {
              "error": {
                "code": "invalid_token",
                "message": "Unknown or revoked API key",
                "request_id": "9f1c2a9d-4b7e-4a21-8d3f-0c6e5b2a1d44"
              }
            }
          }
        }
      },
      "PaymentRequired": {
        "description": "`insufficient_funds`. Nothing was charged or created; `details` has `required`, `balance`, `shortfall`, `currency`.",
        "headers": {
          "X-Request-ID": {
            "$ref": "#/components/headers/X-Request-ID"
          },
          "X-RateLimit-Limit": {
            "$ref": "#/components/headers/X-RateLimit-Limit"
          },
          "X-RateLimit-Remaining": {
            "$ref": "#/components/headers/X-RateLimit-Remaining"
          },
          "X-RateLimit-Reset": {
            "$ref": "#/components/headers/X-RateLimit-Reset"
          },
          "X-Sandbox": {
            "$ref": "#/components/headers/X-Sandbox"
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            },
            "example": {
              "error": {
                "code": "insufficient_funds",
                "message": "Balance 4.10 USD is below the required 5.90 USD",
                "request_id": "9f1c2a9d-4b7e-4a21-8d3f-0c6e5b2a1d44",
                "details": {
                  "required": "5.90",
                  "balance": "4.10",
                  "shortfall": "1.80",
                  "currency": "USD"
                }
              }
            }
          }
        }
      },
      "Forbidden": {
        "description": "Codes: `insufficient_scope` (`details.required`), `ip_not_allowed`,\n`account_suspended`, `api_disabled_for_account`,\n`sandbox_not_supported` (test key on a `forbidden` operation),\n`sandbox_disabled` (test keys switched off globally), `server_blocked`,\n`domain_blocked`.\n",
        "headers": {
          "X-Request-ID": {
            "$ref": "#/components/headers/X-Request-ID"
          },
          "X-RateLimit-Limit": {
            "$ref": "#/components/headers/X-RateLimit-Limit"
          },
          "X-RateLimit-Remaining": {
            "$ref": "#/components/headers/X-RateLimit-Remaining"
          },
          "X-RateLimit-Reset": {
            "$ref": "#/components/headers/X-RateLimit-Reset"
          },
          "X-Sandbox": {
            "$ref": "#/components/headers/X-Sandbox"
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            },
            "example": {
              "error": {
                "code": "insufficient_scope",
                "message": "This key lacks servers:delete",
                "request_id": "9f1c2a9d-4b7e-4a21-8d3f-0c6e5b2a1d44",
                "details": {
                  "required": [
                    "servers:delete"
                  ]
                }
              }
            }
          }
        }
      },
      "NotFound": {
        "description": "`not_found` — no such object on this account (also for objects owned by someone else).",
        "headers": {
          "X-Request-ID": {
            "$ref": "#/components/headers/X-Request-ID"
          },
          "X-RateLimit-Limit": {
            "$ref": "#/components/headers/X-RateLimit-Limit"
          },
          "X-RateLimit-Remaining": {
            "$ref": "#/components/headers/X-RateLimit-Remaining"
          },
          "X-RateLimit-Reset": {
            "$ref": "#/components/headers/X-RateLimit-Reset"
          },
          "X-Sandbox": {
            "$ref": "#/components/headers/X-Sandbox"
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            },
            "example": {
              "error": {
                "code": "not_found",
                "message": "Server 2001 not found",
                "request_id": "9f1c2a9d-4b7e-4a21-8d3f-0c6e5b2a1d44"
              }
            }
          }
        }
      },
      "Conflict": {
        "description": "State conflict. Codes: `conflict`, `idempotency_conflict` (same key,\ndifferent request), `idempotency_in_progress` (retry after\n`Retry-After`), `operation_in_progress` (another order/delete/IP\nchange on the same object is running), `service_state`, `no_capacity`,\n`tariff_unavailable`, `ip_limit_reached`, `domain_taken`,\n`domain_exists`, `cancel_pending`.\n",
        "headers": {
          "X-Request-ID": {
            "$ref": "#/components/headers/X-Request-ID"
          },
          "X-RateLimit-Limit": {
            "$ref": "#/components/headers/X-RateLimit-Limit"
          },
          "X-RateLimit-Remaining": {
            "$ref": "#/components/headers/X-RateLimit-Remaining"
          },
          "X-RateLimit-Reset": {
            "$ref": "#/components/headers/X-RateLimit-Reset"
          },
          "X-Sandbox": {
            "$ref": "#/components/headers/X-Sandbox"
          },
          "Retry-After": {
            "$ref": "#/components/headers/Retry-After"
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            },
            "example": {
              "error": {
                "code": "service_state",
                "message": "Server is already cancelled",
                "request_id": "9f1c2a9d-4b7e-4a21-8d3f-0c6e5b2a1d44",
                "details": {
                  "status": "cancelled"
                }
              }
            }
          }
        }
      },
      "PayloadTooLarge": {
        "description": "`payload_too_large` — request body over 64 KB.",
        "headers": {
          "X-Request-ID": {
            "$ref": "#/components/headers/X-Request-ID"
          },
          "X-RateLimit-Limit": {
            "$ref": "#/components/headers/X-RateLimit-Limit"
          },
          "X-RateLimit-Remaining": {
            "$ref": "#/components/headers/X-RateLimit-Remaining"
          },
          "X-RateLimit-Reset": {
            "$ref": "#/components/headers/X-RateLimit-Reset"
          },
          "X-Sandbox": {
            "$ref": "#/components/headers/X-Sandbox"
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "UnsupportedMediaType": {
        "description": "`unsupported_media_type` — body is not `application/json`.",
        "headers": {
          "X-Request-ID": {
            "$ref": "#/components/headers/X-Request-ID"
          },
          "X-RateLimit-Limit": {
            "$ref": "#/components/headers/X-RateLimit-Limit"
          },
          "X-RateLimit-Remaining": {
            "$ref": "#/components/headers/X-RateLimit-Remaining"
          },
          "X-RateLimit-Reset": {
            "$ref": "#/components/headers/X-RateLimit-Reset"
          },
          "X-Sandbox": {
            "$ref": "#/components/headers/X-Sandbox"
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "RateLimited": {
        "description": "`rate_limited` — the per-key bucket (normal or expensive) or the anonymous per-IP bucket is exhausted.",
        "headers": {
          "X-Request-ID": {
            "$ref": "#/components/headers/X-Request-ID"
          },
          "X-RateLimit-Limit": {
            "$ref": "#/components/headers/X-RateLimit-Limit"
          },
          "X-RateLimit-Remaining": {
            "$ref": "#/components/headers/X-RateLimit-Remaining"
          },
          "X-RateLimit-Reset": {
            "$ref": "#/components/headers/X-RateLimit-Reset"
          },
          "X-Sandbox": {
            "$ref": "#/components/headers/X-Sandbox"
          },
          "Retry-After": {
            "$ref": "#/components/headers/Retry-After"
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            },
            "example": {
              "error": {
                "code": "rate_limited",
                "message": "Too many requests",
                "request_id": "9f1c2a9d-4b7e-4a21-8d3f-0c6e5b2a1d44",
                "details": {
                  "bucket": "expensive",
                  "limit": 20
                }
              }
            }
          }
        }
      },
      "ServerError": {
        "description": "`server_error` — unexpected failure; the request id is logged.",
        "headers": {
          "X-Request-ID": {
            "$ref": "#/components/headers/X-Request-ID"
          },
          "X-RateLimit-Limit": {
            "$ref": "#/components/headers/X-RateLimit-Limit"
          },
          "X-RateLimit-Remaining": {
            "$ref": "#/components/headers/X-RateLimit-Remaining"
          },
          "X-RateLimit-Reset": {
            "$ref": "#/components/headers/X-RateLimit-Reset"
          },
          "X-Sandbox": {
            "$ref": "#/components/headers/X-Sandbox"
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "BadGateway": {
        "description": "`upstream_error` — the panel, registrar or gateway answered with an error. For money operations nothing was charged unless the response says otherwise.",
        "headers": {
          "X-Request-ID": {
            "$ref": "#/components/headers/X-Request-ID"
          },
          "X-RateLimit-Limit": {
            "$ref": "#/components/headers/X-RateLimit-Limit"
          },
          "X-RateLimit-Remaining": {
            "$ref": "#/components/headers/X-RateLimit-Remaining"
          },
          "X-RateLimit-Reset": {
            "$ref": "#/components/headers/X-RateLimit-Reset"
          },
          "X-Sandbox": {
            "$ref": "#/components/headers/X-Sandbox"
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "ServiceUnavailable": {
        "description": "Codes: `api_disabled` (switched off by staff), `upstream_unavailable`,\n`temporarily_unavailable` (e.g. the discount could not be computed —\nwe refuse rather than silently charge full price). Retry after\n`Retry-After`.\n",
        "headers": {
          "X-Request-ID": {
            "$ref": "#/components/headers/X-Request-ID"
          },
          "X-RateLimit-Limit": {
            "$ref": "#/components/headers/X-RateLimit-Limit"
          },
          "X-RateLimit-Remaining": {
            "$ref": "#/components/headers/X-RateLimit-Remaining"
          },
          "X-RateLimit-Reset": {
            "$ref": "#/components/headers/X-RateLimit-Reset"
          },
          "X-Sandbox": {
            "$ref": "#/components/headers/X-Sandbox"
          },
          "Retry-After": {
            "$ref": "#/components/headers/Retry-After"
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            },
            "example": {
              "error": {
                "code": "api_disabled",
                "message": "The API is temporarily disabled",
                "request_id": "9f1c2a9d-4b7e-4a21-8d3f-0c6e5b2a1d44"
              }
            }
          }
        }
      },
      "GatewayTimeout": {
        "description": "`upstream_timeout` — the panel or registrar did not answer in time. For `POST /servers` the charge is kept and the order continues (see `202`).",
        "headers": {
          "X-Request-ID": {
            "$ref": "#/components/headers/X-Request-ID"
          },
          "X-RateLimit-Limit": {
            "$ref": "#/components/headers/X-RateLimit-Limit"
          },
          "X-RateLimit-Remaining": {
            "$ref": "#/components/headers/X-RateLimit-Remaining"
          },
          "X-RateLimit-Reset": {
            "$ref": "#/components/headers/X-RateLimit-Reset"
          },
          "X-Sandbox": {
            "$ref": "#/components/headers/X-Sandbox"
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      }
    },
    "schemas": {
      "Money": {
        "type": "string",
        "description": "Decimal amount as a string with 2–4 fraction digits. Never a float.",
        "pattern": "^-?[0-9]+\\.[0-9]{2,4}$",
        "examples": [
          "5.90",
          "0.0083",
          "-12.00"
        ]
      },
      "Currency": {
        "type": "string",
        "description": "ISO 4217 code of the account currency.",
        "pattern": "^[A-Z]{3}$",
        "examples": [
          "USD"
        ]
      },
      "Timestamp": {
        "type": "string",
        "format": "date-time",
        "description": "RFC 3339 in UTC with a trailing `Z`.",
        "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}(\\.[0-9]+)?Z$",
        "examples": [
          "2026-09-15T10:00:00Z"
        ]
      },
      "NullableTimestamp": {
        "anyOf": [
          {
            "$ref": "#/components/schemas/Timestamp"
          },
          {
            "type": "null"
          }
        ]
      },
      "Scope": {
        "type": "string",
        "description": "Permission granted to a key. Presets in the cabinet — `read_only`, `operate`, `full` — are just bundles of these.",
        "enum": [
          "account:read",
          "balance:read",
          "balance:topup",
          "invoices:read",
          "invoices:pay",
          "servers:read",
          "servers:manage",
          "servers:order",
          "servers:delete",
          "domains:read",
          "domains:manage",
          "domains:order",
          "keys:read",
          "webhooks:manage"
        ]
      },
      "BillingCycle": {
        "type": "string",
        "enum": [
          "monthly",
          "hourly"
        ]
      },
      "ErrorCode": {
        "type": "string",
        "description": "Closed list per status. Clients should still tolerate unknown codes\n(treat them by HTTP status).\n\n400 `invalid_request` `validation_error` `invalid_cursor`\n`idempotency_key_required` `os_not_allowed` `invalid_period`\n`invalid_action` `upstream_rejected`;\n401 `invalid_token` `key_expired` `key_not_yet_valid`;\n402 `insufficient_funds`;\n403 `insufficient_scope` `ip_not_allowed` `account_suspended`\n`api_disabled_for_account` `sandbox_not_supported` `sandbox_disabled`\n`server_blocked` `domain_blocked`;\n404 `not_found`;\n409 `conflict` `idempotency_conflict` `idempotency_in_progress`\n`operation_in_progress` `service_state` `no_capacity`\n`tariff_unavailable` `ip_limit_reached` `domain_taken`\n`domain_exists` `cancel_pending`;\n405 `method_not_allowed` (the response also carries `Allow`);\n413 `payload_too_large`; 415 `unsupported_media_type`;\n429 `rate_limited`; 500 `server_error`; 502 `upstream_error`;\n503 `api_disabled` `upstream_unavailable` `temporarily_unavailable`;\n504 `upstream_timeout`.\n",
        "enum": [
          "invalid_request",
          "validation_error",
          "invalid_cursor",
          "idempotency_key_required",
          "os_not_allowed",
          "invalid_period",
          "invalid_action",
          "upstream_rejected",
          "invalid_token",
          "key_expired",
          "key_not_yet_valid",
          "insufficient_funds",
          "insufficient_scope",
          "ip_not_allowed",
          "account_suspended",
          "api_disabled_for_account",
          "sandbox_not_supported",
          "sandbox_disabled",
          "server_blocked",
          "domain_blocked",
          "not_found",
          "conflict",
          "idempotency_conflict",
          "idempotency_in_progress",
          "operation_in_progress",
          "service_state",
          "no_capacity",
          "tariff_unavailable",
          "ip_limit_reached",
          "domain_taken",
          "domain_exists",
          "cancel_pending",
          "method_not_allowed",
          "payload_too_large",
          "unsupported_media_type",
          "rate_limited",
          "server_error",
          "upstream_error",
          "api_disabled",
          "upstream_unavailable",
          "temporarily_unavailable",
          "upstream_timeout"
        ]
      },
      "Error": {
        "type": "object",
        "description": "The only error shape the API produces, including app-level 404/405/413/500.",
        "required": [
          "error"
        ],
        "properties": {
          "error": {
            "type": "object",
            "required": [
              "code",
              "message",
              "request_id"
            ],
            "properties": {
              "code": {
                "$ref": "#/components/schemas/ErrorCode"
              },
              "message": {
                "type": "string",
                "description": "Human-readable, English, not for parsing."
              },
              "request_id": {
                "type": "string"
              },
              "details": {
                "type": "object",
                "description": "Code-specific extras (`required` scopes, `fields`, money figures for `insufficient_funds`).",
                "additionalProperties": true
              }
            }
          }
        },
        "examples": [
          {
            "error": {
              "code": "not_found",
              "message": "Server 2001 not found",
              "request_id": "9f1c2a9d-4b7e-4a21-8d3f-0c6e5b2a1d44"
            }
          }
        ]
      },
      "Health": {
        "type": "object",
        "required": [
          "status",
          "time",
          "version"
        ],
        "properties": {
          "status": {
            "type": "string",
            "enum": [
              "ok",
              "disabled"
            ]
          },
          "time": {
            "$ref": "#/components/schemas/Timestamp"
          },
          "version": {
            "type": "string",
            "const": "1",
            "description": "API version this deployment serves (`api_v1.API_VERSION`)."
          }
        }
      },
      "Me": {
        "type": "object",
        "required": [
          "key",
          "account_id",
          "livemode",
          "scopes",
          "available_scopes",
          "sandbox_enabled",
          "api_version"
        ],
        "properties": {
          "key": {
            "$ref": "#/components/schemas/ApiKey"
          },
          "account_id": {
            "type": "integer",
            "format": "int64"
          },
          "livemode": {
            "type": "boolean",
            "description": "False for `vk_test_…` keys — writes are simulated."
          },
          "scopes": {
            "type": "array",
            "uniqueItems": true,
            "items": {
              "$ref": "#/components/schemas/Scope"
            },
            "description": "Same list as `key.scopes`."
          },
          "available_scopes": {
            "type": "array",
            "uniqueItems": true,
            "items": {
              "$ref": "#/components/schemas/Scope"
            },
            "description": "Every scope this API version knows (`api_v1.auth.SCOPES`)."
          },
          "sandbox_enabled": {
            "type": "boolean",
            "description": "Whether test keys are accepted at all right now."
          },
          "api_version": {
            "type": "string",
            "const": "1"
          }
        },
        "examples": [
          {
            "key": {
              "id": 3,
              "name": "ci-deploy",
              "hint": "vk_live_…7Qx2",
              "mode": "live",
              "scopes": [
                "servers:read",
                "servers:manage"
              ],
              "ip_allowlist": [],
              "rate_per_minute": null,
              "rate_expensive_per_minute": null,
              "not_before": null,
              "expires_at": null,
              "active": true,
              "revoked_at": null,
              "revoked_reason": null,
              "last_used_at": "2026-09-15T09:59:00Z",
              "last_used_ip": "192.0.2.77",
              "created_at": "2026-09-01T12:00:00Z"
            },
            "account_id": 1042,
            "livemode": true,
            "scopes": [
              "servers:read",
              "servers:manage"
            ],
            "available_scopes": [
              "account:read",
              "balance:read",
              "servers:read",
              "servers:manage"
            ],
            "sandbox_enabled": true,
            "api_version": "1"
          }
        ]
      },
      "ClientGroup": {
        "type": "object",
        "required": [
          "id",
          "name",
          "discount_percent"
        ],
        "properties": {
          "id": {
            "type": "integer"
          },
          "name": {
            "type": "string"
          },
          "discount_percent": {
            "type": "number",
            "minimum": 0,
            "maximum": 100
          }
        }
      },
      "Account": {
        "type": "object",
        "required": [
          "id",
          "login",
          "email",
          "currency",
          "group",
          "email_verified",
          "two_factor_enabled",
          "created_at"
        ],
        "properties": {
          "id": {
            "type": "integer",
            "format": "int64"
          },
          "login": {
            "type": "string"
          },
          "email": {
            "type": "string",
            "format": "email"
          },
          "name": {
            "type": [
              "string",
              "null"
            ]
          },
          "company": {
            "type": [
              "string",
              "null"
            ]
          },
          "currency": {
            "$ref": "#/components/schemas/Currency"
          },
          "group": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/ClientGroup"
              },
              {
                "type": "null"
              }
            ]
          },
          "loyalty_discount_percent": {
            "type": "number",
            "minimum": 0,
            "maximum": 100
          },
          "email_verified": {
            "type": "boolean"
          },
          "two_factor_enabled": {
            "type": "boolean"
          },
          "created_at": {
            "$ref": "#/components/schemas/Timestamp"
          }
        },
        "examples": [
          {
            "id": 1042,
            "login": "acme-hosting",
            "email": "owner@example.com",
            "name": null,
            "company": null,
            "currency": "USD",
            "group": {
              "id": 2,
              "name": "Reseller",
              "discount_percent": 15
            },
            "loyalty_discount_percent": 0,
            "email_verified": true,
            "two_factor_enabled": true,
            "created_at": "2025-01-10T08:30:00Z"
          }
        ]
      },
      "Balance": {
        "type": "object",
        "required": [
          "balance",
          "currency",
          "upcoming_7d",
          "upcoming_30d",
          "low_balance"
        ],
        "properties": {
          "balance": {
            "$ref": "#/components/schemas/Money"
          },
          "currency": {
            "$ref": "#/components/schemas/Currency"
          },
          "upcoming_7d": {
            "$ref": "#/components/schemas/Money"
          },
          "upcoming_30d": {
            "$ref": "#/components/schemas/Money"
          },
          "low_balance": {
            "type": "boolean",
            "description": "Balance does not cover the next 7 days of renewals."
          },
          "auto_renew_total_monthly": {
            "$ref": "#/components/schemas/Money"
          }
        },
        "examples": [
          {
            "balance": "42.15",
            "currency": "USD",
            "upcoming_7d": "5.90",
            "upcoming_30d": "23.60",
            "low_balance": false,
            "auto_renew_total_monthly": "23.60"
          }
        ]
      },
      "Transaction": {
        "type": "object",
        "required": [
          "id",
          "direction",
          "amount",
          "currency",
          "type",
          "description",
          "invoice_id",
          "created_at"
        ],
        "properties": {
          "id": {
            "type": "integer",
            "format": "int64"
          },
          "direction": {
            "type": "string",
            "enum": [
              "credit",
              "debit"
            ]
          },
          "amount": {
            "$ref": "#/components/schemas/Money",
            "description": "Absolute value; see `direction`."
          },
          "currency": {
            "$ref": "#/components/schemas/Currency"
          },
          "type": {
            "type": "string",
            "description": "Derived from `transactions.gateway` plus the sign of the amount —\nthere is no `type` column. The mapping, exhaustively:\n\n* `refund` → `refund`;\n* `admin` → `adjustment` (staff credit or debit);\n* `referral` → `referral` (credit), `referral_reversal` →\n  `referral` with `direction: debit`;\n* `hourly` → `payment` (an hourly charge taken by the cron);\n* `balance` → `payment` when the amount is negative (paid from\n  balance) and `refund` when it is positive;\n* any payment-gateway name (`cryptobot`, …) → `topup`;\n* anything unrecognized → `other`.\n\n`bonus` is reserved for promotional credits; `gateway` always\ncarries the raw column value, so a new gateway never hides\nbehind `other`.\n",
            "enum": [
              "topup",
              "payment",
              "refund",
              "bonus",
              "referral",
              "adjustment",
              "other"
            ]
          },
          "gateway": {
            "type": [
              "string",
              "null"
            ],
            "description": "Raw `transactions.gateway` value."
          },
          "description": {
            "type": "string"
          },
          "invoice_id": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int64"
          },
          "created_at": {
            "$ref": "#/components/schemas/Timestamp"
          }
        },
        "examples": [
          {
            "id": 88012,
            "direction": "debit",
            "amount": "5.90",
            "currency": "USD",
            "type": "payment",
            "gateway": "balance",
            "description": "VDS #2001 renewal, 1 month",
            "invoice_id": 10231,
            "created_at": "2026-09-15T10:00:00Z"
          }
        ]
      },
      "TransactionPage": {
        "type": "object",
        "required": [
          "data",
          "next_cursor"
        ],
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Transaction"
            }
          },
          "next_cursor": {
            "type": [
              "string",
              "null"
            ]
          }
        }
      },
      "TopupInfo": {
        "type": "object",
        "description": "The first step of a top-up: the limits and the gateway codes the\naccount may use right now. `gateways` is a flat list of codes — pass\none of them verbatim as `TopupRequest.gateway`.\n",
        "required": [
          "currency",
          "min",
          "max",
          "first_topup_bonus_percent",
          "first_topup_eligible",
          "gateways"
        ],
        "properties": {
          "currency": {
            "$ref": "#/components/schemas/Currency"
          },
          "min": {
            "$ref": "#/components/schemas/Money",
            "description": "Smallest accepted top-up."
          },
          "max": {
            "$ref": "#/components/schemas/Money",
            "description": "Largest accepted top-up."
          },
          "first_topup_bonus_percent": {
            "type": "number",
            "minimum": 0,
            "description": "Bonus added to a first top-up, in percent; `0` when the promotion is off."
          },
          "first_topup_eligible": {
            "type": "boolean",
            "description": "Whether this account still qualifies for that bonus."
          },
          "gateways": {
            "type": "array",
            "description": "Codes of the enabled payment gateways, in the order the cabinet shows them.",
            "items": {
              "type": "string",
              "examples": [
                "cryptobot"
              ]
            }
          }
        },
        "examples": [
          {
            "currency": "USD",
            "min": "0.01",
            "max": "10000.00",
            "first_topup_bonus_percent": 0,
            "first_topup_eligible": false,
            "gateways": [
              "cryptobot",
              "heleket",
              "lolzmarket"
            ]
          }
        ]
      },
      "TopupRequest": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "amount",
          "gateway"
        ],
        "properties": {
          "amount": {
            "$ref": "#/components/schemas/Money",
            "description": "Also accepted as a number; the range is `min`..`max` from `GET /balance/topup-info`."
          },
          "gateway": {
            "type": "string",
            "description": "One of the `gateways` strings from `GET /balance/topup-info`.",
            "maxLength": 32
          }
        }
      },
      "TopupResult": {
        "type": "object",
        "required": [
          "invoice_id",
          "payment_url",
          "amount",
          "currency",
          "gateway"
        ],
        "properties": {
          "invoice_id": {
            "type": "integer",
            "format": "int64"
          },
          "payment_url": {
            "type": "string",
            "format": "uri"
          },
          "amount": {
            "$ref": "#/components/schemas/Money"
          },
          "currency": {
            "$ref": "#/components/schemas/Currency"
          },
          "gateway": {
            "type": "string"
          }
        },
        "examples": [
          {
            "invoice_id": 10240,
            "payment_url": "https://pay.example/inv/abc",
            "amount": "25.00",
            "currency": "USD",
            "gateway": "cryptobot"
          }
        ]
      },
      "InvoiceStatus": {
        "type": "string",
        "description": "Exactly the values the `invoices.status` column holds, so anything the\nbilling system has ever written can be serialized:\n\n* `not_paid` — issued, awaiting payment;\n* `pending` — payment started at the gateway, not confirmed yet;\n* `paid` — settled;\n* `cancelled` — withdrawn (superseded renewal, cancelled order);\n* `refunded` — paid and later refunded to the balance;\n* `failed` — paid at the gateway but the service could not be\n  provisioned; staff refund or re-provision it manually.\n",
        "enum": [
          "not_paid",
          "pending",
          "paid",
          "cancelled",
          "refunded",
          "failed"
        ]
      },
      "InvoiceType": {
        "type": "string",
        "description": "The `invoices.type` vocabulary verbatim — the same strings `?type=`\nfilters on. Notes:\n\n* `vds_addon` — an additional IPv4 (and other add-ons) for a VDS;\n* `domain_purchase` covers registrations and transfers;\n* `late_fee` — a late-payment fee inherited from the WHMCS era;\n* `dedicated_purchase` / `dedicated_renewal` — dedicated servers.\n  Dedicated servers are out of v1 scope (no endpoints for them), but\n  their invoices sit on the same account and do come back from\n  `GET /invoices`;\n* `other` — invoices imported from WHMCS whose line item had no\n  recognizable type.\n",
        "enum": [
          "topup",
          "vds_purchase",
          "vds_renewal",
          "vds_addon",
          "domain_purchase",
          "domain_renewal",
          "late_fee",
          "dedicated_purchase",
          "dedicated_renewal",
          "other"
        ]
      },
      "InvoiceItem": {
        "type": "object",
        "required": [
          "description",
          "amount"
        ],
        "properties": {
          "description": {
            "type": "string"
          },
          "amount": {
            "$ref": "#/components/schemas/Money"
          },
          "server_id": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int64"
          },
          "domain_id": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int64"
          }
        }
      },
      "Invoice": {
        "type": "object",
        "required": [
          "id",
          "status",
          "type",
          "amount",
          "currency",
          "description",
          "created_at",
          "due_at",
          "paid_at",
          "gateway",
          "items"
        ],
        "properties": {
          "id": {
            "type": "integer",
            "format": "int64"
          },
          "status": {
            "$ref": "#/components/schemas/InvoiceStatus"
          },
          "type": {
            "$ref": "#/components/schemas/InvoiceType"
          },
          "amount": {
            "$ref": "#/components/schemas/Money"
          },
          "currency": {
            "$ref": "#/components/schemas/Currency"
          },
          "description": {
            "type": "string"
          },
          "gateway": {
            "type": [
              "string",
              "null"
            ]
          },
          "created_at": {
            "$ref": "#/components/schemas/Timestamp"
          },
          "due_at": {
            "$ref": "#/components/schemas/NullableTimestamp"
          },
          "paid_at": {
            "$ref": "#/components/schemas/NullableTimestamp"
          },
          "cancelled_at": {
            "$ref": "#/components/schemas/NullableTimestamp"
          },
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/InvoiceItem"
            }
          },
          "pdf_url": {
            "type": "string",
            "description": "Relative API path of the PDF."
          }
        },
        "examples": [
          {
            "id": 10231,
            "status": "paid",
            "type": "vds_renewal",
            "amount": "5.90",
            "currency": "USD",
            "description": "VDS #2001 renewal, 1 month",
            "gateway": "balance",
            "created_at": "2026-09-15T10:00:00Z",
            "due_at": "2026-09-20T00:00:00Z",
            "paid_at": "2026-09-15T10:00:01Z",
            "cancelled_at": null,
            "items": [
              {
                "description": "VDS #2001, 1 month",
                "amount": "5.90",
                "server_id": 2001,
                "domain_id": null
              }
            ],
            "pdf_url": "/api/v1/invoices/10231/pdf"
          }
        ]
      },
      "InvoicePage": {
        "type": "object",
        "required": [
          "data",
          "next_cursor"
        ],
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Invoice"
            }
          },
          "next_cursor": {
            "type": [
              "string",
              "null"
            ]
          }
        }
      },
      "PayInvoiceResult": {
        "type": "object",
        "required": [
          "invoice_id",
          "status",
          "amount",
          "currency",
          "balance_after"
        ],
        "properties": {
          "invoice_id": {
            "type": "integer",
            "format": "int64"
          },
          "status": {
            "type": "string",
            "const": "paid"
          },
          "amount": {
            "$ref": "#/components/schemas/Money",
            "description": "What was taken from the balance."
          },
          "currency": {
            "$ref": "#/components/schemas/Currency"
          },
          "balance_after": {
            "$ref": "#/components/schemas/Money",
            "description": "The balance read just before the charge",
            "minus `amount`.": null
          }
        }
      },
      "PaymentLinkRequest": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "gateway": {
            "type": "string",
            "maxLength": 32,
            "description": "Defaults to the gateway already recorded on the invoice (continuing a started payment)."
          }
        }
      },
      "PaymentLink": {
        "type": "object",
        "required": [
          "invoice_id",
          "payment_url",
          "gateway"
        ],
        "properties": {
          "invoice_id": {
            "type": "integer",
            "format": "int64"
          },
          "payment_url": {
            "type": "string",
            "format": "uri"
          },
          "gateway": {
            "type": "string"
          }
        }
      },
      "Resources": {
        "type": "object",
        "required": [
          "cpu_cores",
          "ram_mb",
          "disk_gb"
        ],
        "properties": {
          "cpu_cores": {
            "type": "integer",
            "minimum": 1
          },
          "ram_mb": {
            "type": "integer",
            "minimum": 1
          },
          "disk_gb": {
            "type": "integer",
            "minimum": 1
          },
          "bandwidth_tb": {
            "type": [
              "number",
              "null"
            ],
            "description": "`null` = unmetered."
          },
          "port_mbps": {
            "type": [
              "integer",
              "null"
            ]
          }
        }
      },
      "PeriodPrice": {
        "type": "object",
        "required": [
          "months",
          "discount_percent",
          "total"
        ],
        "properties": {
          "months": {
            "type": "integer",
            "enum": [
              1,
              3,
              6,
              12
            ]
          },
          "discount_percent": {
            "type": "number",
            "minimum": 0,
            "maximum": 100
          },
          "total": {
            "$ref": "#/components/schemas/Money"
          }
        }
      },
      "Tariff": {
        "type": "object",
        "required": [
          "id",
          "name",
          "location",
          "resources",
          "price_monthly",
          "list_price_monthly",
          "price_hourly",
          "currency",
          "periods",
          "hourly_available",
          "in_stock",
          "non_refundable",
          "extra_ip_price_monthly"
        ],
        "properties": {
          "id": {
            "type": "integer"
          },
          "name": {
            "type": "string"
          },
          "description": {
            "type": [
              "string",
              "null"
            ]
          },
          "location": {
            "$ref": "#/components/schemas/Location"
          },
          "resources": {
            "$ref": "#/components/schemas/Resources"
          },
          "price_monthly": {
            "$ref": "#/components/schemas/Money",
            "description": "After the caller's group discount."
          },
          "list_price_monthly": {
            "$ref": "#/components/schemas/Money"
          },
          "price_hourly": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/Money"
              },
              {
                "type": "null"
              }
            ]
          },
          "currency": {
            "$ref": "#/components/schemas/Currency"
          },
          "periods": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/PeriodPrice"
            }
          },
          "hourly_available": {
            "type": "boolean"
          },
          "in_stock": {
            "type": "boolean",
            "description": "False when the location has no capacity; ordering answers `409 no_capacity`."
          },
          "non_refundable": {
            "type": "boolean",
            "description": "Promo tariff — deletion gives no refund."
          },
          "excluded_os": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "OS slugs this tariff cannot run."
          },
          "extra_ip_price_monthly": {
            "$ref": "#/components/schemas/Money"
          },
          "max_extra_ips": {
            "type": "integer",
            "minimum": 0
          }
        },
        "examples": [
          {
            "id": 12,
            "name": "VDS-1",
            "description": null,
            "location": {
              "id": 1,
              "code": "nl-ams",
              "name": "Amsterdam",
              "country": "NL",
              "city": "Amsterdam"
            },
            "resources": {
              "cpu_cores": 1,
              "ram_mb": 1024,
              "disk_gb": 20,
              "bandwidth_tb": null,
              "port_mbps": 200
            },
            "price_monthly": "5.02",
            "list_price_monthly": "5.90",
            "price_hourly": "0.0083",
            "currency": "USD",
            "periods": [
              {
                "months": 1,
                "discount_percent": 0,
                "total": "5.02"
              },
              {
                "months": 12,
                "discount_percent": 10,
                "total": "54.22"
              }
            ],
            "hourly_available": true,
            "in_stock": true,
            "non_refundable": false,
            "excluded_os": [
              "windows-2022"
            ],
            "extra_ip_price_monthly": "1.00",
            "max_extra_ips": 5
          }
        ]
      },
      "OsImage": {
        "type": "object",
        "required": [
          "slug",
          "name",
          "family"
        ],
        "properties": {
          "slug": {
            "type": "string",
            "description": "Pass this as `os` when ordering or reinstalling.",
            "examples": [
              "ubuntu-24.04"
            ]
          },
          "name": {
            "type": "string"
          },
          "family": {
            "type": "string",
            "enum": [
              "linux",
              "windows",
              "other"
            ]
          },
          "version": {
            "type": [
              "string",
              "null"
            ]
          },
          "supports_ssh_keys": {
            "type": "boolean"
          },
          "min_disk_gb": {
            "type": [
              "integer",
              "null"
            ]
          }
        }
      },
      "Location": {
        "type": "object",
        "required": [
          "id",
          "code",
          "name",
          "country"
        ],
        "properties": {
          "id": {
            "type": "integer"
          },
          "code": {
            "type": "string",
            "examples": [
              "nl-ams"
            ]
          },
          "name": {
            "type": "string"
          },
          "country": {
            "type": "string",
            "pattern": "^[A-Z]{2}$"
          },
          "city": {
            "type": [
              "string",
              "null"
            ]
          },
          "in_stock": {
            "type": "boolean"
          }
        }
      },
      "Zone": {
        "type": "object",
        "required": [
          "tld",
          "price_register",
          "price_renew",
          "price_transfer",
          "currency",
          "min_years",
          "max_years",
          "privacy_supported"
        ],
        "properties": {
          "tld": {
            "type": "string",
            "examples": [
              ".com"
            ]
          },
          "price_register": {
            "$ref": "#/components/schemas/Money"
          },
          "price_renew": {
            "$ref": "#/components/schemas/Money"
          },
          "price_transfer": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/Money"
              },
              {
                "type": "null"
              }
            ]
          },
          "currency": {
            "$ref": "#/components/schemas/Currency"
          },
          "min_years": {
            "type": "integer",
            "minimum": 1
          },
          "max_years": {
            "type": "integer",
            "minimum": 1,
            "maximum": 10
          },
          "privacy_supported": {
            "type": "boolean"
          },
          "transfer_supported": {
            "type": "boolean"
          }
        }
      },
      "Discount": {
        "type": "object",
        "required": [
          "type",
          "percent",
          "amount"
        ],
        "properties": {
          "type": {
            "type": "string",
            "enum": [
              "group",
              "loyalty",
              "volume",
              "period",
              "promo"
            ]
          },
          "percent": {
            "type": "number",
            "minimum": 0,
            "maximum": 100
          },
          "amount": {
            "$ref": "#/components/schemas/Money"
          }
        }
      },
      "Quote": {
        "type": "object",
        "required": [
          "tariff_id",
          "billing_cycle",
          "base_amount",
          "discounts",
          "total",
          "currency",
          "balance",
          "balance_sufficient",
          "shortfall"
        ],
        "properties": {
          "tariff_id": {
            "type": "integer"
          },
          "billing_cycle": {
            "$ref": "#/components/schemas/BillingCycle"
          },
          "months": {
            "type": [
              "integer",
              "null"
            ]
          },
          "hours": {
            "type": [
              "integer",
              "null"
            ]
          },
          "base_amount": {
            "$ref": "#/components/schemas/Money"
          },
          "discounts": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Discount"
            }
          },
          "total": {
            "$ref": "#/components/schemas/Money"
          },
          "currency": {
            "$ref": "#/components/schemas/Currency"
          },
          "promo": {
            "type": [
              "object",
              "null"
            ],
            "required": [
              "code",
              "valid"
            ],
            "properties": {
              "code": {
                "type": "string"
              },
              "valid": {
                "type": "boolean"
              },
              "message": {
                "type": [
                  "string",
                  "null"
                ]
              }
            }
          },
          "balance": {
            "$ref": "#/components/schemas/Money"
          },
          "balance_sufficient": {
            "type": "boolean"
          },
          "shortfall": {
            "$ref": "#/components/schemas/Money"
          }
        },
        "examples": [
          {
            "tariff_id": 12,
            "billing_cycle": "monthly",
            "months": 3,
            "hours": null,
            "base_amount": "17.70",
            "discounts": [
              {
                "type": "group",
                "percent": 15,
                "amount": "2.66"
              },
              {
                "type": "period",
                "percent": 5,
                "amount": "0.75"
              }
            ],
            "total": "14.29",
            "currency": "USD",
            "promo": null,
            "balance": "42.15",
            "balance_sufficient": true,
            "shortfall": "0.00"
          }
        ]
      },
      "ServerStatus": {
        "type": "string",
        "description": "`active` — running or at least not stopped by billing; `stopped` —\npowered off by the client; `suspended` — switched off for\nnon-payment or by staff; `pending_cancel` — a cancel request at end\nof period is approved; `cancelled` — deleted by the client or by a\ncancel request; `terminated` — removed after prolonged non-payment.\n",
        "enum": [
          "active",
          "stopped",
          "suspended",
          "pending_cancel",
          "cancelled",
          "terminated"
        ]
      },
      "ServerFlags": {
        "type": "object",
        "required": [
          "blocked",
          "suspended",
          "expired",
          "pending_cancel",
          "protected_until",
          "is_test",
          "synthetic"
        ],
        "properties": {
          "blocked": {
            "type": "boolean",
            "description": "Locked by staff; every mutation answers `403 server_blocked`."
          },
          "suspended": {
            "type": "boolean"
          },
          "expired": {
            "type": "boolean",
            "description": "`next_due_at` is in the past."
          },
          "pending_cancel": {
            "type": "boolean"
          },
          "protected_until": {
            "$ref": "#/components/schemas/NullableTimestamp",
            "description": "Grace protection after migration — no suspension before this date."
          },
          "is_test": {
            "type": "boolean",
            "description": "Free test server; deletion refunds nothing."
          },
          "synthetic": {
            "type": "boolean",
            "description": "Imported service with a synthetic id (`>= 2000000000`) and no panel record."
          }
        }
      },
      "ServerBilling": {
        "type": "object",
        "required": [
          "cycle",
          "months",
          "price_monthly",
          "recurring_amount",
          "currency",
          "next_due_at",
          "auto_renew",
          "promo_code",
          "extra_ips"
        ],
        "properties": {
          "cycle": {
            "$ref": "#/components/schemas/BillingCycle"
          },
          "months": {
            "type": "integer",
            "minimum": 1,
            "description": "Length of one billing period for monthly servers (1",
            "3": null,
            "6 or 12 for anything ordered through the API).": null
          },
          "price_monthly": {
            "$ref": "#/components/schemas/Money"
          },
          "recurring_amount": {
            "$ref": "#/components/schemas/Money",
            "description": "What one renewal costs now (tariff + extra IPs − discounts)."
          },
          "currency": {
            "$ref": "#/components/schemas/Currency"
          },
          "next_due_at": {
            "$ref": "#/components/schemas/NullableTimestamp"
          },
          "auto_renew": {
            "type": "boolean"
          },
          "promo_code": {
            "type": [
              "string",
              "null"
            ]
          },
          "extra_ips": {
            "type": "integer",
            "minimum": 0
          }
        }
      },
      "ServerRef": {
        "type": "object",
        "required": [
          "id",
          "name"
        ],
        "properties": {
          "id": {
            "type": [
              "integer",
              "null"
            ],
            "description": "`null` for a service whose tariff row is gone."
          },
          "name": {
            "type": "string"
          }
        }
      },
      "ServerResources": {
        "type": "object",
        "description": "Resources of the tariff behind this server. Any field is `null` when the tariff row no longer carries it.",
        "required": [
          "vcpu",
          "ram_mb",
          "disk_mb"
        ],
        "properties": {
          "vcpu": {
            "type": [
              "integer",
              "null"
            ],
            "minimum": 1
          },
          "ram_mb": {
            "type": [
              "integer",
              "null"
            ],
            "minimum": 1
          },
          "disk_mb": {
            "type": [
              "integer",
              "null"
            ],
            "minimum": 1,
            "description": "Disk in MiB (not GiB",
            "unlike `Tariff.resources`).": null
          }
        }
      },
      "Server": {
        "type": "object",
        "description": "Never contains passwords; `root_password` appears only in `ServerCreated`.",
        "required": [
          "id",
          "name",
          "hostname",
          "status",
          "tariff",
          "location",
          "os",
          "primary_ip",
          "ips",
          "resources",
          "flags",
          "billing",
          "notes",
          "created_at"
        ],
        "properties": {
          "id": {
            "type": "integer",
            "format": "int64",
            "description": "Panel id (`solusvm_id`); sandbox servers are `>= 9000000000`."
          },
          "name": {
            "type": "string",
            "maxLength": 64
          },
          "hostname": {
            "type": "string",
            "description": "Falls back to `name` when the panel has no separate host name."
          },
          "status": {
            "$ref": "#/components/schemas/ServerStatus"
          },
          "tariff": {
            "$ref": "#/components/schemas/ServerRef"
          },
          "location": {
            "type": [
              "string",
              "null"
            ],
            "description": "Location name",
            "e.g. `Amsterdam`.": null
          },
          "os": {
            "type": [
              "string",
              "null"
            ],
            "description": "OS `slug` as ordered, e.g. `ubuntu-24.04`."
          },
          "primary_ip": {
            "type": [
              "string",
              "null"
            ],
            "description": "First assigned address."
          },
          "ips": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "All assigned addresses, v4 and v6."
          },
          "resources": {
            "$ref": "#/components/schemas/ServerResources"
          },
          "flags": {
            "$ref": "#/components/schemas/ServerFlags"
          },
          "billing": {
            "$ref": "#/components/schemas/ServerBilling"
          },
          "notes": {
            "type": "string",
            "maxLength": 2000,
            "description": "Client note (`vds_tables.client_notes`); empty string when unset."
          },
          "created_at": {
            "$ref": "#/components/schemas/NullableTimestamp",
            "description": "`null` for services imported from WHMCS without a creation date."
          }
        },
        "examples": [
          {
            "id": 2001,
            "name": "web-01",
            "hostname": "web-01",
            "status": "active",
            "tariff": {
              "id": 12,
              "name": "VDS-1"
            },
            "location": "Amsterdam",
            "os": "ubuntu-24.04",
            "primary_ip": "203.0.113.29",
            "ips": [
              "203.0.113.29",
              "2001:db8::29"
            ],
            "resources": {
              "vcpu": 1,
              "ram_mb": 1024,
              "disk_mb": 20480
            },
            "flags": {
              "blocked": false,
              "suspended": false,
              "expired": false,
              "pending_cancel": false,
              "protected_until": null,
              "is_test": false,
              "synthetic": false
            },
            "billing": {
              "cycle": "monthly",
              "months": 1,
              "price_monthly": "5.90",
              "recurring_amount": "6.90",
              "currency": "USD",
              "next_due_at": "2026-10-01T00:00:00Z",
              "auto_renew": true,
              "promo_code": null,
              "extra_ips": 1
            },
            "notes": "",
            "created_at": "2026-03-01T12:00:00Z"
          }
        ]
      },
      "ServerLiveStatus": {
        "type": "object",
        "required": [
          "server_id",
          "power",
          "checked_at"
        ],
        "properties": {
          "server_id": {
            "type": "integer",
            "format": "int64"
          },
          "power": {
            "type": "string",
            "enum": [
              "running",
              "stopped",
              "unknown"
            ]
          },
          "cpu_percent": {
            "type": [
              "number",
              "null"
            ],
            "minimum": 0
          },
          "memory": {
            "type": [
              "object",
              "null"
            ],
            "required": [
              "used_mb",
              "total_mb"
            ],
            "properties": {
              "used_mb": {
                "type": "integer",
                "minimum": 0
              },
              "total_mb": {
                "type": "integer",
                "minimum": 0
              }
            }
          },
          "disk": {
            "type": [
              "object",
              "null"
            ],
            "required": [
              "used_gb",
              "total_gb"
            ],
            "properties": {
              "used_gb": {
                "type": "number",
                "minimum": 0
              },
              "total_gb": {
                "type": "number",
                "minimum": 0
              }
            }
          },
          "uptime_seconds": {
            "type": [
              "integer",
              "null"
            ],
            "minimum": 0
          },
          "checked_at": {
            "$ref": "#/components/schemas/Timestamp"
          }
        },
        "examples": [
          {
            "server_id": 2001,
            "power": "running",
            "cpu_percent": 3.5,
            "memory": {
              "used_mb": 412,
              "total_mb": 1024
            },
            "disk": {
              "used_gb": 6.2,
              "total_gb": 20
            },
            "uptime_seconds": 864000,
            "checked_at": "2026-09-15T10:00:00Z"
          }
        ]
      },
      "RefundBreakdownItem": {
        "type": "object",
        "required": [
          "invoice_id",
          "amount",
          "period_start",
          "period_end",
          "days_left",
          "refund",
          "paid_at"
        ],
        "properties": {
          "invoice_id": {
            "type": "integer",
            "format": "int64"
          },
          "amount": {
            "$ref": "#/components/schemas/Money",
            "description": "What the invoice paid for this window."
          },
          "period_start": {
            "$ref": "#/components/schemas/NullableTimestamp"
          },
          "period_end": {
            "$ref": "#/components/schemas/NullableTimestamp"
          },
          "days_left": {
            "type": "integer",
            "minimum": 0,
            "description": "Whole days left in this window; a display value",
            "the refund of the window is `refund`.": null
          },
          "refund": {
            "$ref": "#/components/schemas/Money"
          },
          "paid_at": {
            "$ref": "#/components/schemas/NullableTimestamp"
          }
        }
      },
      "RefundQuote": {
        "type": "object",
        "description": "Prorated over the unused part of the paid period, based on the\ninvoices that were really paid (not on the tariff price). Zero with\n`excluded_reason` when a rule excludes the server. Referral bonuses\npaid out for those invoices are deducted, so always\n`amount == gross_amount − referral_adjustment`.\n\n`breakdown` is the per-invoice derivation and it is filled **only for\nmonthly services**, where `Σ breakdown[].refund == gross_amount`. An\nhourly server is refunded from the remaining prepaid hours rather than\nfrom invoice windows, so its `breakdown` is empty (`[]`) while\n`gross_amount` is positive — reconcile it against `note`, which spells\nout hours × rate. Do not treat an empty `breakdown` next to a positive\n`gross_amount` as a discrepancy.\n",
        "required": [
          "server_id",
          "amount",
          "currency",
          "refundable",
          "excluded_reason",
          "days_left",
          "gross_amount",
          "referral_adjustment",
          "note",
          "breakdown",
          "computed_at"
        ],
        "properties": {
          "server_id": {
            "type": "integer",
            "format": "int64"
          },
          "amount": {
            "$ref": "#/components/schemas/Money",
            "description": "What would actually be credited."
          },
          "currency": {
            "$ref": "#/components/schemas/Currency"
          },
          "refundable": {
            "type": "boolean",
            "description": "`excluded_reason` is null and `amount` > 0."
          },
          "excluded_reason": {
            "type": [
              "string",
              "null"
            ],
            "enum": [
              null,
              "promo_tariff",
              "blocked",
              "service_state",
              "unpaid",
              "no_payment_record",
              "hourly",
              "consumed",
              "currency_mismatch",
              "unavailable"
            ],
            "description": "Why the refund is zero (or cut):\n\n* `promo_tariff` — non-refundable (promo) tariff;\n* `blocked` — the server was blocked by staff;\n* `service_state` — already cancelled or terminated;\n* `unpaid` — suspended and the paid period is over;\n* `no_payment_record` — no paid invoices behind the service\n  (test servers, staff gifts, sandbox servers);\n* `hourly` — hourly server with no prepaid hours left;\n* `consumed` — invoices exist but the paid period is used up (or\n  eaten by `referral_adjustment`);\n* `currency_mismatch` — the invoices are not in USD, support\n  computes the refund by hand;\n* `unavailable` — only inside `ServerDetail.refund_quote`: the\n  computation failed and the card must not claim a zero refund.\n"
          },
          "days_left": {
            "type": "number",
            "minimum": 0,
            "description": "Days of the paid period left",
            "fractional.": null
          },
          "gross_amount": {
            "$ref": "#/components/schemas/Money",
            "description": "Refund over the invoices before the referral adjustment."
          },
          "referral_adjustment": {
            "$ref": "#/components/schemas/Money"
          },
          "note": {
            "type": "string",
            "description": "Human-readable explanation of the computation."
          },
          "breakdown": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/RefundBreakdownItem"
            }
          },
          "computed_at": {
            "$ref": "#/components/schemas/Timestamp"
          }
        },
        "examples": [
          {
            "server_id": 2001,
            "amount": "3.15",
            "currency": "USD",
            "refundable": true,
            "excluded_reason": null,
            "days_left": 16.0417,
            "gross_amount": "3.15",
            "referral_adjustment": "0.00",
            "note": "Возврат за 16.0 дн. по 1 счёт(ам)",
            "breakdown": [
              {
                "invoice_id": 10231,
                "amount": "5.90",
                "period_start": "2026-09-01T00:00:00Z",
                "period_end": "2026-10-01T00:00:00Z",
                "days_left": 16,
                "refund": "3.15",
                "paid_at": "2026-09-01T00:00:00Z"
              }
            ],
            "computed_at": "2026-09-15T10:00:00Z"
          }
        ]
      },
      "ServerDetail": {
        "allOf": [
          {
            "$ref": "#/components/schemas/Server"
          },
          {
            "type": "object",
            "required": [
              "refund_quote"
            ],
            "properties": {
              "refund_quote": {
                "$ref": "#/components/schemas/RefundQuote"
              },
              "live": {
                "anyOf": [
                  {
                    "$ref": "#/components/schemas/ServerLiveStatus"
                  },
                  {
                    "type": "null"
                  }
                ],
                "description": "Only with `?include=live`."
              }
            }
          }
        ]
      },
      "ServerPage": {
        "type": "object",
        "required": [
          "data",
          "next_cursor"
        ],
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Server"
            }
          },
          "next_cursor": {
            "type": [
              "string",
              "null"
            ]
          }
        }
      },
      "ServerCreate": {
        "type": "object",
        "description": "Give `months` (monthly cycle) or `hours` (hourly cycle, when the\ntariff allows it), not both; sending both is `400`.\n",
        "additionalProperties": false,
        "not": {
          "required": [
            "months",
            "hours"
          ]
        },
        "required": [
          "tariff_id",
          "os"
        ],
        "properties": {
          "tariff_id": {
            "type": "integer",
            "minimum": 1
          },
          "os": {
            "type": "string",
            "description": "`slug` from `GET /catalog/os`.",
            "maxLength": 64
          },
          "name": {
            "type": "string",
            "minLength": 1,
            "maxLength": 64,
            "description": "Host name (`A-Za-z0-9._-`). Generated when omitted."
          },
          "server_name": {
            "type": "string",
            "minLength": 1,
            "maxLength": 64,
            "deprecated": true,
            "description": "Alias of `name`, accepted for compatibility with the cabinet. Use `name`."
          },
          "password": {
            "type": "string",
            "minLength": 8,
            "maxLength": 64,
            "description": "Root password: 8–64 characters, at least one letter and one digit,\nonly latin letters, digits and `!@#$%^&*-` (the panel accepts\nnothing else). Generated by VDSok and returned once when omitted.\n"
          },
          "months": {
            "type": "integer",
            "enum": [
              1,
              3,
              6,
              12
            ],
            "default": 1
          },
          "hours": {
            "type": "integer",
            "const": 1,
            "description": "Ordering an hourly server prepays exactly one hour; buy more with `POST /servers/{server_id}/renew`."
          },
          "billing_cycle": {
            "$ref": "#/components/schemas/BillingCycle"
          },
          "promo_code": {
            "type": "string",
            "maxLength": 64
          },
          "ssh_key_ids": {
            "type": "array",
            "maxItems": 10,
            "items": {
              "type": "integer",
              "format": "int64"
            }
          },
          "custom_fields": {
            "type": "object",
            "maxProperties": 30,
            "additionalProperties": {
              "type": "string"
            },
            "description": "Answers to the order form fields configured by VDSok, if any. At most 30 keys; the values are stored as text."
          }
        }
      },
      "ServerCreated": {
        "type": "object",
        "required": [
          "server",
          "root_password",
          "invoice_id",
          "charged",
          "currency",
          "balance_after",
          "order_url"
        ],
        "properties": {
          "server": {
            "$ref": "#/components/schemas/Server"
          },
          "root_password": {
            "type": "string",
            "description": "Shown once; blanked in idempotent replays."
          },
          "invoice_id": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int64",
            "description": "`null` for a sandbox order: nothing was written."
          },
          "charged": {
            "$ref": "#/components/schemas/Money"
          },
          "currency": {
            "$ref": "#/components/schemas/Currency"
          },
          "balance_after": {
            "$ref": "#/components/schemas/Money"
          },
          "order_url": {
            "type": [
              "string",
              "null"
            ],
            "description": "Relative API path of the order; `null` in the sandbox."
          }
        }
      },
      "ServerUpdate": {
        "type": "object",
        "additionalProperties": false,
        "minProperties": 1,
        "properties": {
          "auto_renew": {
            "type": "boolean"
          },
          "name": {
            "type": "string",
            "minLength": 1,
            "maxLength": 64
          },
          "notes": {
            "type": [
              "string",
              "null"
            ],
            "maxLength": 2000
          }
        }
      },
      "DeleteResult": {
        "type": "object",
        "required": [
          "server_id",
          "status",
          "refund",
          "currency",
          "balance_after",
          "refund_quote"
        ],
        "properties": {
          "server_id": {
            "type": "integer",
            "format": "int64"
          },
          "status": {
            "type": "string",
            "const": "cancelled"
          },
          "refund": {
            "$ref": "#/components/schemas/Money",
            "description": "What was credited to the balance; `refund_quote.amount` is the same number."
          },
          "currency": {
            "$ref": "#/components/schemas/Currency"
          },
          "balance_after": {
            "$ref": "#/components/schemas/Money"
          },
          "refund_quote": {
            "$ref": "#/components/schemas/RefundQuote",
            "description": "How the refund was computed. A pending cancel request is withdrawn silently",
            "the result does not report it.": null
          }
        }
      },
      "RenewRequest": {
        "type": "object",
        "additionalProperties": false,
        "oneOf": [
          {
            "required": [
              "months"
            ]
          },
          {
            "required": [
              "hours"
            ]
          }
        ],
        "properties": {
          "months": {
            "type": "integer",
            "enum": [
              1,
              3,
              6,
              12
            ]
          },
          "hours": {
            "type": "integer",
            "minimum": 1,
            "maximum": 2160,
            "description": "1..2160 (90 days)",
            "as in the cabinet.": null
          }
        }
      },
      "RenewResult": {
        "type": "object",
        "required": [
          "server",
          "invoice_id",
          "charged",
          "currency",
          "balance_after",
          "next_due_at"
        ],
        "properties": {
          "server": {
            "$ref": "#/components/schemas/Server"
          },
          "invoice_id": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int64",
            "description": "`null` in the sandbox and when the invoice could not be looked up; the renewal itself still happened."
          },
          "charged": {
            "$ref": "#/components/schemas/Money"
          },
          "currency": {
            "$ref": "#/components/schemas/Currency"
          },
          "balance_after": {
            "$ref": "#/components/schemas/Money"
          },
          "next_due_at": {
            "$ref": "#/components/schemas/Timestamp"
          },
          "months": {
            "type": "integer",
            "description": "Present when renewed with `months`."
          },
          "hours": {
            "type": "integer",
            "description": "Present when renewed with `hours`."
          }
        }
      },
      "PowerRequest": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "action"
        ],
        "properties": {
          "action": {
            "type": "string",
            "enum": [
              "start",
              "stop",
              "restart"
            ]
          }
        }
      },
      "ActionResult": {
        "type": "object",
        "required": [
          "server_id",
          "action",
          "status"
        ],
        "properties": {
          "server_id": {
            "type": "integer",
            "format": "int64"
          },
          "action": {
            "type": "string"
          },
          "status": {
            "type": "string",
            "enum": [
              "accepted",
              "done"
            ]
          },
          "message": {
            "type": [
              "string",
              "null"
            ]
          }
        }
      },
      "ReinstallRequest": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "os"
        ],
        "properties": {
          "os": {
            "type": "string",
            "maxLength": 64
          },
          "password": {
            "type": "string",
            "minLength": 8,
            "maxLength": 64,
            "description": "Same rules as `ServerCreate.password`; generated and returned once when omitted."
          },
          "ssh_key_ids": {
            "type": "array",
            "maxItems": 10,
            "items": {
              "type": "integer",
              "format": "int64"
            }
          }
        }
      },
      "ReinstallResult": {
        "type": "object",
        "required": [
          "server_id",
          "status",
          "os",
          "root_password"
        ],
        "properties": {
          "server_id": {
            "type": "integer",
            "format": "int64"
          },
          "status": {
            "type": "string",
            "const": "reinstalling"
          },
          "os": {
            "type": "string"
          },
          "root_password": {
            "type": [
              "string",
              "null"
            ],
            "description": "Only when generated by VDSok."
          }
        }
      },
      "ResetPasswordResult": {
        "type": "object",
        "required": [
          "server_id",
          "password"
        ],
        "properties": {
          "server_id": {
            "type": "integer",
            "format": "int64"
          },
          "password": {
            "type": "string"
          }
        }
      },
      "OrderStatus": {
        "type": "string",
        "description": "Exactly what `services/vds_orders.get_order_status` can report:\n\n* `provisioning` — charged, the VM is being created (poll);\n* `invoice_created` — the invoice is not paid yet (gateway payment);\n* `processing` — paid, the server has not appeared yet;\n* `active` — done, `server_id` is filled in;\n* `cancelled` — the invoice was cancelled and the charge refunded.\n\nTerminal states are `active` and `cancelled`.\n",
        "enum": [
          "provisioning",
          "invoice_created",
          "processing",
          "active",
          "cancelled"
        ]
      },
      "Order": {
        "type": "object",
        "required": [
          "invoice_id",
          "status",
          "server_id",
          "tariff_id",
          "amount",
          "currency",
          "created_at",
          "updated_at",
          "order_url",
          "failure_reason"
        ],
        "properties": {
          "invoice_id": {
            "type": "integer",
            "format": "int64"
          },
          "status": {
            "$ref": "#/components/schemas/OrderStatus"
          },
          "server_id": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int64"
          },
          "server_name": {
            "type": [
              "string",
              "null"
            ],
            "description": "Only in orders returned by `GET /orders` and `GET /orders/{invoice_id}`."
          },
          "tariff_name": {
            "type": [
              "string",
              "null"
            ],
            "description": "Only in orders returned by `GET /orders` and `GET /orders/{invoice_id}`."
          },
          "tariff_id": {
            "type": [
              "integer",
              "null"
            ],
            "description": "From the invoice metadata; `null` when it was not recorded."
          },
          "amount": {
            "$ref": "#/components/schemas/Money"
          },
          "currency": {
            "$ref": "#/components/schemas/Currency"
          },
          "created_at": {
            "$ref": "#/components/schemas/NullableTimestamp"
          },
          "updated_at": {
            "$ref": "#/components/schemas/NullableTimestamp",
            "description": "Time of payment",
            "or of creation when not paid yet.": null
          },
          "order_url": {
            "type": "string",
            "description": "Relative API path to poll."
          },
          "failure_reason": {
            "type": [
              "string",
              "null"
            ],
            "description": "Reserved; always `null` today — a failed order is refunded and reported as `cancelled`."
          }
        }
      },
      "OrderPage": {
        "type": "object",
        "required": [
          "data",
          "next_cursor"
        ],
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Order"
            }
          },
          "next_cursor": {
            "type": [
              "string",
              "null"
            ]
          }
        }
      },
      "Ip": {
        "type": "object",
        "required": [
          "id",
          "address",
          "version",
          "primary",
          "ptr",
          "price_monthly",
          "added_at"
        ],
        "properties": {
          "id": {
            "type": "integer",
            "format": "int64"
          },
          "address": {
            "type": "string"
          },
          "version": {
            "type": "integer",
            "enum": [
              4,
              6
            ]
          },
          "primary": {
            "type": "boolean"
          },
          "ptr": {
            "type": [
              "string",
              "null"
            ]
          },
          "gateway": {
            "type": [
              "string",
              "null"
            ]
          },
          "netmask": {
            "type": [
              "string",
              "null"
            ]
          },
          "price_monthly": {
            "$ref": "#/components/schemas/Money",
            "description": "`0.00` for the primary address."
          },
          "added_at": {
            "$ref": "#/components/schemas/Timestamp"
          }
        },
        "examples": [
          {
            "id": 501,
            "address": "203.0.113.30",
            "version": 4,
            "primary": false,
            "ptr": "mail.example.com",
            "gateway": "203.0.113.1",
            "netmask": "255.255.255.0",
            "price_monthly": "1.00",
            "added_at": "2026-09-10T00:00:00Z"
          }
        ]
      },
      "IpQuote": {
        "type": "object",
        "required": [
          "server_id",
          "price_monthly",
          "prorated_now",
          "currency",
          "next_due_at",
          "extra_ips",
          "max_extra_ips",
          "balance_sufficient"
        ],
        "properties": {
          "server_id": {
            "type": "integer",
            "format": "int64"
          },
          "price_monthly": {
            "$ref": "#/components/schemas/Money"
          },
          "prorated_now": {
            "$ref": "#/components/schemas/Money",
            "description": "Charged immediately for the rest of the current period."
          },
          "currency": {
            "$ref": "#/components/schemas/Currency"
          },
          "next_due_at": {
            "$ref": "#/components/schemas/NullableTimestamp"
          },
          "extra_ips": {
            "type": "integer",
            "minimum": 0
          },
          "max_extra_ips": {
            "type": "integer",
            "minimum": 0
          },
          "balance_sufficient": {
            "type": "boolean"
          }
        }
      },
      "IpAddRequest": {
        "type": "object",
        "description": "The body may be omitted entirely; `count` exists only so that `count != 1` is refused explicitly — the panel hands out addresses one at a time.",
        "additionalProperties": false,
        "properties": {
          "count": {
            "type": "integer",
            "const": 1,
            "default": 1
          }
        }
      },
      "IpAdded": {
        "type": "object",
        "description": "The address itself is not here — the panel assigns it asynchronously; read it from `GET /servers/{server_id}/ips`.",
        "required": [
          "success",
          "server_id",
          "charged",
          "currency",
          "days"
        ],
        "properties": {
          "success": {
            "type": "boolean",
            "const": true
          },
          "server_id": {
            "type": "integer",
            "format": "int64"
          },
          "charged": {
            "$ref": "#/components/schemas/Money",
            "description": "Prorated price for the rest of the paid period."
          },
          "currency": {
            "$ref": "#/components/schemas/Currency"
          },
          "days": {
            "type": "integer",
            "minimum": 0,
            "description": "Days of the paid period the charge covers."
          }
        }
      },
      "IpDeleted": {
        "type": "object",
        "required": [
          "status",
          "server_id",
          "ip_id"
        ],
        "properties": {
          "status": {
            "type": "string",
            "const": "deleted"
          },
          "server_id": {
            "type": "integer",
            "format": "int64"
          },
          "ip_id": {
            "type": "integer",
            "format": "int64"
          }
        }
      },
      "PtrUpdate": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "domain": {
            "type": [
              "string",
              "null"
            ],
            "description": "Hostname for the reverse record (letters, digits, dots, hyphens;\nat least two labels). `\"\"`, `null` or an empty body removes the\nrecord.\n",
            "maxLength": 253
          }
        },
        "examples": [
          {
            "domain": "mail.example.com"
          }
        ]
      },
      "PtrRecord": {
        "type": "object",
        "description": "The stored reverse record. Read the rest of the address from `GET /servers/{server_id}/ips`.",
        "required": [
          "id",
          "ptr"
        ],
        "properties": {
          "id": {
            "type": "integer",
            "format": "int64",
            "description": "Id of the address."
          },
          "ptr": {
            "type": [
              "string",
              "null"
            ],
            "description": "`null` when the record was removed."
          }
        },
        "examples": [
          {
            "id": 501,
            "ptr": "mail.example.com"
          }
        ]
      },
      "SshKey": {
        "type": "object",
        "required": [
          "id",
          "name",
          "fingerprint",
          "type",
          "public_key",
          "created_at"
        ],
        "properties": {
          "id": {
            "type": "integer",
            "format": "int64"
          },
          "name": {
            "type": "string",
            "maxLength": 120
          },
          "fingerprint": {
            "type": "string",
            "description": "SHA256:… of the public key."
          },
          "type": {
            "type": "string",
            "description": "Key algorithm as it appears in the first field of the OpenSSH line; the same set the cabinet accepts.",
            "enum": [
              "ssh-ed25519",
              "ssh-rsa",
              "ssh-dss",
              "ecdsa-sha2-nistp256",
              "ecdsa-sha2-nistp384",
              "ecdsa-sha2-nistp521"
            ]
          },
          "public_key": {
            "type": "string",
            "maxLength": 8192
          },
          "created_at": {
            "$ref": "#/components/schemas/Timestamp"
          }
        },
        "examples": [
          {
            "id": 3,
            "name": "laptop",
            "fingerprint": "SHA256:QzFtXimF4Gcrxgvgz7xkTZHtkico5cu4knzbDqcr4Es",
            "type": "ssh-ed25519",
            "public_key": "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIHPpImosNSJfm14MrVrZDm5Th08MJO3UUdzJWqQ9M7T2 user@laptop",
            "created_at": "2026-02-01T09:00:00Z"
          }
        ]
      },
      "SshKeyCreate": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "name",
          "public_key"
        ],
        "properties": {
          "name": {
            "type": "string",
            "minLength": 1,
            "maxLength": 120
          },
          "public_key": {
            "type": "string",
            "minLength": 60,
            "maxLength": 8192,
            "description": "One line in OpenSSH format."
          }
        }
      },
      "DomainStatus": {
        "type": "string",
        "description": "Derived server-side from the `domains` row — there is no single status\ncolumn, so the exact rule is spelled out here and must stay in sync\nwith the serializer:\n\n* `cancelled` — `domains.blocked = 1` (staff removed the service);\n* `transfer_pending` — `registrar_status` reported by the registrar is\n  a pending-transfer state and the domain is not active yet;\n* `pending` — registered here but the registrar has not confirmed it\n  yet (`registrar_synced_at IS NULL` and no `expires_at`), or\n  `registrar_status` is a pending-registration state;\n* `expired` — the expiry moment is in the past (`expires_at` from the\n  registrar, otherwise `last_billed + period` years) or\n  `domains.suspended = 1`;\n* `active` — everything else.\n\n`blocked` is exposed separately as its own boolean, because a blocked\ndomain still needs its other fields to round-trip.\n",
        "enum": [
          "pending",
          "active",
          "expired",
          "transfer_pending",
          "cancelled"
        ]
      },
      "Domain": {
        "type": "object",
        "required": [
          "id",
          "name",
          "tld",
          "status",
          "registered_at",
          "expires_at",
          "auto_renew",
          "privacy",
          "nameservers",
          "locked",
          "blocked",
          "created_at"
        ],
        "properties": {
          "id": {
            "type": "integer",
            "format": "int64"
          },
          "name": {
            "type": "string"
          },
          "tld": {
            "type": "string"
          },
          "status": {
            "$ref": "#/components/schemas/DomainStatus"
          },
          "registered_at": {
            "allOf": [
              {
                "$ref": "#/components/schemas/NullableTimestamp"
              }
            ],
            "description": "When the domain was taken on here (`domains.created_at`); for domains imported from WHMCS this is the import-era value."
          },
          "expires_at": {
            "allOf": [
              {
                "$ref": "#/components/schemas/NullableTimestamp"
              }
            ],
            "description": "Registrar expiry (`domains.expires_at`); until the first registrar sync it is computed as `last_billed + period` years, the same way the cabinet does it."
          },
          "auto_renew": {
            "type": "boolean"
          },
          "privacy": {
            "type": "boolean",
            "description": "WHOIS privacy enabled at the registrar."
          },
          "nameservers": {
            "type": "array",
            "minItems": 2,
            "maxItems": 2,
            "items": {
              "type": "string"
            },
            "description": "Exactly two — `domains.ns1` and `domains.ns2`. VDSok stores no further slots."
          },
          "locked": {
            "type": "boolean",
            "description": "Transfer lock at the registrar (`domains.registrar_locked`; `false` until the first registrar sync)."
          },
          "blocked": {
            "type": "boolean",
            "description": "Locked by staff; mutations answer `403 domain_blocked`."
          },
          "price_renew": {
            "$ref": "#/components/schemas/Money"
          },
          "currency": {
            "$ref": "#/components/schemas/Currency"
          },
          "created_at": {
            "$ref": "#/components/schemas/Timestamp"
          }
        },
        "examples": [
          {
            "id": 77,
            "name": "example.com",
            "tld": ".com",
            "status": "active",
            "registered_at": "2026-01-15T00:00:00Z",
            "expires_at": "2027-01-15T00:00:00Z",
            "auto_renew": true,
            "privacy": true,
            "nameservers": [
              "ns1.vdsok.guru",
              "ns2.vdsok.guru"
            ],
            "locked": true,
            "blocked": false,
            "price_renew": "12.50",
            "currency": "USD",
            "created_at": "2026-01-15T10:00:00Z"
          }
        ]
      },
      "DomainPage": {
        "type": "object",
        "required": [
          "data",
          "next_cursor"
        ],
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Domain"
            }
          },
          "next_cursor": {
            "type": [
              "string",
              "null"
            ]
          }
        }
      },
      "AvailabilityResult": {
        "type": "object",
        "required": [
          "name",
          "available",
          "reason",
          "price_register",
          "price_renew",
          "currency"
        ],
        "properties": {
          "name": {
            "type": "string"
          },
          "available": {
            "type": "boolean"
          },
          "reason": {
            "type": [
              "string",
              "null"
            ],
            "enum": [
              null,
              "taken",
              "premium",
              "reserved",
              "invalid",
              "unsupported_tld"
            ],
            "description": "Why it cannot be registered here."
          },
          "premium": {
            "type": "boolean"
          },
          "price_register": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/Money"
              },
              {
                "type": "null"
              }
            ]
          },
          "price_renew": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/Money"
              },
              {
                "type": "null"
              }
            ]
          },
          "currency": {
            "$ref": "#/components/schemas/Currency"
          },
          "min_years": {
            "type": "integer",
            "minimum": 1
          }
        },
        "examples": [
          {
            "name": "example.com",
            "available": false,
            "reason": "taken",
            "premium": false,
            "price_register": "11.90",
            "price_renew": "12.50",
            "currency": "USD",
            "min_years": 1
          }
        ]
      },
      "DomainRegister": {
        "type": "object",
        "description": "Registrant contact data is taken from the account profile (the same as in the cabinet).",
        "additionalProperties": false,
        "required": [
          "name"
        ],
        "properties": {
          "name": {
            "type": "string",
            "minLength": 3,
            "maxLength": 253
          },
          "years": {
            "type": "integer",
            "minimum": 1,
            "maximum": 10,
            "default": 1
          },
          "nameservers": {
            "type": "array",
            "minItems": 2,
            "maxItems": 2,
            "items": {
              "type": "string",
              "maxLength": 253
            },
            "description": "Exactly two; defaults to the VDSok nameservers."
          },
          "privacy": {
            "type": "boolean",
            "default": false
          },
          "promo_code": {
            "type": "string",
            "maxLength": 64
          }
        }
      },
      "DomainOrderResult": {
        "type": "object",
        "description": "`201` when the registrar confirmed, `202 pending` when it did not\nanswer in time — the charge stays and staff reconcile it by hand.\n",
        "required": [
          "status",
          "domain",
          "domain_id",
          "zone",
          "years",
          "charged",
          "discount",
          "promo_code",
          "currency",
          "expires_at",
          "message"
        ],
        "properties": {
          "status": {
            "type": "string",
            "enum": [
              "registered",
              "pending"
            ]
          },
          "domain": {
            "type": "string",
            "description": "The domain name",
            "not an object.": null
          },
          "domain_id": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int64",
            "description": "`null` while the domain row does not exist yet (pending, sandbox)."
          },
          "zone": {
            "type": [
              "string",
              "null"
            ]
          },
          "years": {
            "type": "integer",
            "minimum": 1,
            "maximum": 10
          },
          "charged": {
            "$ref": "#/components/schemas/Money"
          },
          "discount": {
            "$ref": "#/components/schemas/Money",
            "description": "Promo-code discount already included in `charged`."
          },
          "promo_code": {
            "type": [
              "string",
              "null"
            ],
            "description": "The code that was actually applied."
          },
          "currency": {
            "$ref": "#/components/schemas/Currency"
          },
          "expires_at": {
            "$ref": "#/components/schemas/NullableTimestamp"
          },
          "message": {
            "type": [
              "string",
              "null"
            ]
          }
        }
      },
      "DomainRenew": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "years"
        ],
        "properties": {
          "years": {
            "type": "integer",
            "minimum": 1,
            "maximum": 10
          }
        }
      },
      "DomainRenewResult": {
        "type": "object",
        "required": [
          "status",
          "domain",
          "domain_id",
          "years",
          "total_years",
          "charged",
          "currency",
          "balance_after",
          "expires_at",
          "message"
        ],
        "properties": {
          "status": {
            "type": "string",
            "enum": [
              "renewed",
              "pending_sync",
              "pending"
            ],
            "description": "`pending` comes with `202`; `pending_sync` is a success (`200`) whose new expiry date is picked up by the daily sync."
          },
          "domain": {
            "type": [
              "string",
              "null"
            ],
            "description": "The domain name",
            "not an object.": null
          },
          "domain_id": {
            "type": "integer",
            "format": "int64"
          },
          "years": {
            "type": "integer",
            "description": "Years added by this call."
          },
          "total_years": {
            "type": [
              "integer",
              "null"
            ],
            "description": "Paid period after the renewal; early renewal stacks."
          },
          "charged": {
            "$ref": "#/components/schemas/Money"
          },
          "currency": {
            "$ref": "#/components/schemas/Currency"
          },
          "balance_after": {
            "$ref": "#/components/schemas/Money"
          },
          "expires_at": {
            "$ref": "#/components/schemas/NullableTimestamp"
          },
          "message": {
            "type": [
              "string",
              "null"
            ]
          }
        }
      },
      "DomainTransferResult": {
        "type": "object",
        "description": "Always `202`; the registrar takes 5–7 days. Poll `GET /domains/{domain_id}` until `status` turns `active`.",
        "required": [
          "status",
          "domain",
          "domain_id",
          "charged",
          "currency",
          "message"
        ],
        "properties": {
          "status": {
            "type": "string",
            "enum": [
              "pending_transfer",
              "pending"
            ],
            "description": "`pending` — the registrar did not answer in time and the charge was kept on purpose."
          },
          "domain": {
            "type": "string"
          },
          "domain_id": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int64"
          },
          "charged": {
            "$ref": "#/components/schemas/Money"
          },
          "currency": {
            "$ref": "#/components/schemas/Currency"
          },
          "message": {
            "type": [
              "string",
              "null"
            ]
          }
        }
      },
      "NameserversUpdate": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "nameservers"
        ],
        "properties": {
          "nameservers": {
            "type": "array",
            "minItems": 2,
            "maxItems": 2,
            "uniqueItems": true,
            "items": {
              "type": "string",
              "minLength": 3,
              "maxLength": 253
            },
            "description": "Exactly two; both are sent to the registrar and stored as `ns1`/`ns2`."
          }
        }
      },
      "DomainUpdate": {
        "type": "object",
        "additionalProperties": false,
        "minProperties": 1,
        "properties": {
          "auto_renew": {
            "type": "boolean"
          },
          "privacy": {
            "type": "boolean"
          }
        }
      },
      "DomainTransfer": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "name",
          "auth_code"
        ],
        "properties": {
          "name": {
            "type": "string",
            "minLength": 3,
            "maxLength": 253
          },
          "auth_code": {
            "type": "string",
            "minLength": 1,
            "maxLength": 128,
            "description": "EPP / transfer code from the current registrar."
          },
          "nameservers": {
            "type": "array",
            "minItems": 2,
            "maxItems": 2,
            "items": {
              "type": "string",
              "maxLength": 253
            },
            "description": "Exactly two; defaults to the VDSok nameservers."
          }
        }
      },
      "ApiKey": {
        "type": "object",
        "description": "The secret is never returned; `hint` is prefix + last 4 characters.",
        "required": [
          "id",
          "name",
          "hint",
          "mode",
          "scopes",
          "ip_allowlist",
          "rate_per_minute",
          "rate_expensive_per_minute",
          "not_before",
          "expires_at",
          "active",
          "revoked_at",
          "revoked_reason",
          "last_used_at",
          "last_used_ip",
          "created_at"
        ],
        "properties": {
          "id": {
            "type": "integer",
            "format": "int64"
          },
          "name": {
            "type": "string",
            "maxLength": 120
          },
          "hint": {
            "type": "string",
            "maxLength": 24,
            "examples": [
              "vk_live_…7Qx2"
            ]
          },
          "mode": {
            "type": "string",
            "enum": [
              "live",
              "test"
            ]
          },
          "scopes": {
            "type": "array",
            "uniqueItems": true,
            "items": {
              "$ref": "#/components/schemas/Scope"
            }
          },
          "ip_allowlist": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "IPs or CIDRs; empty = any."
          },
          "rate_per_minute": {
            "type": [
              "integer",
              "null"
            ],
            "minimum": 1
          },
          "rate_expensive_per_minute": {
            "type": [
              "integer",
              "null"
            ],
            "minimum": 1
          },
          "not_before": {
            "$ref": "#/components/schemas/NullableTimestamp"
          },
          "expires_at": {
            "$ref": "#/components/schemas/NullableTimestamp"
          },
          "active": {
            "type": "boolean",
            "description": "`api_keys.active` and not revoked."
          },
          "revoked_at": {
            "$ref": "#/components/schemas/NullableTimestamp"
          },
          "revoked_reason": {
            "type": [
              "string",
              "null"
            ],
            "maxLength": 255
          },
          "last_used_at": {
            "$ref": "#/components/schemas/NullableTimestamp"
          },
          "last_used_ip": {
            "type": [
              "string",
              "null"
            ],
            "maxLength": 45,
            "description": "Refreshed at most once a minute per key."
          },
          "created_at": {
            "$ref": "#/components/schemas/Timestamp"
          }
        }
      },
      "ApiKeyPage": {
        "type": "object",
        "required": [
          "data",
          "next_cursor"
        ],
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ApiKey"
            }
          },
          "next_cursor": {
            "type": [
              "string",
              "null"
            ],
            "description": "Always `null` today — the whole list fits in one response; the field exists so a future cursor does not break clients."
          }
        }
      },
      "ApiKeyRevoked": {
        "type": "object",
        "required": [
          "status",
          "key"
        ],
        "properties": {
          "status": {
            "type": "string",
            "const": "revoked"
          },
          "key": {
            "$ref": "#/components/schemas/ApiKey"
          }
        }
      },
      "WebhookEventType": {
        "type": "string",
        "enum": [
          "server.created",
          "server.suspended",
          "server.unsuspended",
          "server.terminated",
          "server.reinstalled",
          "invoice.created",
          "invoice.paid",
          "invoice.overdue",
          "balance.low",
          "domain.registered",
          "domain.expiring",
          "domain.renewed",
          "key.created",
          "key.revoked",
          "ping"
        ]
      },
      "WebhookEventSelector": {
        "anyOf": [
          {
            "$ref": "#/components/schemas/WebhookEventType"
          },
          {
            "type": "string",
            "const": "*",
            "description": "Every event type",
            "including ones added later.": null
          }
        ]
      },
      "WebhookEventDescriptor": {
        "type": "object",
        "required": [
          "type",
          "description"
        ],
        "properties": {
          "type": {
            "$ref": "#/components/schemas/WebhookEventType"
          },
          "description": {
            "type": "string",
            "description": "Short human label (Russian)",
            "for UI lists.": null
          }
        }
      },
      "WebhookSubscription": {
        "type": "object",
        "required": [
          "id",
          "url",
          "events",
          "description",
          "active",
          "failures_in_row",
          "disabled_at",
          "disabled_reason",
          "last_delivery_at",
          "last_status",
          "created_at"
        ],
        "properties": {
          "id": {
            "type": "integer",
            "format": "int64"
          },
          "url": {
            "type": "string",
            "format": "uri",
            "maxLength": 512
          },
          "events": {
            "type": "array",
            "uniqueItems": true,
            "items": {
              "$ref": "#/components/schemas/WebhookEventSelector"
            }
          },
          "description": {
            "type": "string",
            "maxLength": 255
          },
          "active": {
            "type": "boolean"
          },
          "failures_in_row": {
            "type": "integer",
            "minimum": 0
          },
          "disabled_at": {
            "$ref": "#/components/schemas/NullableTimestamp"
          },
          "disabled_reason": {
            "type": [
              "string",
              "null"
            ],
            "maxLength": 255,
            "description": "Free text, e.g. `20 failures in a row: …`."
          },
          "last_delivery_at": {
            "$ref": "#/components/schemas/NullableTimestamp"
          },
          "last_status": {
            "type": [
              "integer",
              "null"
            ],
            "description": "HTTP status of the last attempt."
          },
          "created_at": {
            "$ref": "#/components/schemas/Timestamp"
          }
        },
        "examples": [
          {
            "id": 5,
            "url": "https://hooks.example.com/vdsok",
            "events": [
              "server.created",
              "invoice.paid"
            ],
            "description": "billing sync",
            "active": true,
            "failures_in_row": 0,
            "disabled_at": null,
            "disabled_reason": null,
            "last_delivery_at": "2026-09-15T09:00:00Z",
            "last_status": 200,
            "created_at": "2026-09-01T12:00:00Z"
          }
        ]
      },
      "WebhookSubscriptionPage": {
        "type": "object",
        "required": [
          "data",
          "next_cursor"
        ],
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/WebhookSubscription"
            }
          },
          "next_cursor": {
            "type": [
              "string",
              "null"
            ],
            "description": "Always `null` today — the whole list fits in one response; the field exists so a future cursor does not break clients."
          }
        }
      },
      "WebhookSubscriptionWithSecret": {
        "allOf": [
          {
            "$ref": "#/components/schemas/WebhookSubscription"
          },
          {
            "type": "object",
            "required": [
              "secret"
            ],
            "properties": {
              "secret": {
                "type": "string",
                "description": "`whsec_…`, shown once.",
                "pattern": "^whsec_[A-Za-z0-9_-]{40,}$"
              }
            }
          }
        ]
      },
      "WebhookSecret": {
        "type": "object",
        "description": "Result of a secret rotation — only the id and the new secret.",
        "required": [
          "id",
          "secret"
        ],
        "properties": {
          "id": {
            "type": "integer",
            "format": "int64"
          },
          "secret": {
            "type": "string",
            "description": "`whsec_…`, shown once.",
            "pattern": "^whsec_[A-Za-z0-9_-]{40,}$"
          }
        }
      },
      "SshKeyDeleted": {
        "type": "object",
        "required": [
          "status",
          "id"
        ],
        "properties": {
          "status": {
            "type": "string",
            "const": "deleted"
          },
          "id": {
            "type": "integer",
            "format": "int64"
          }
        }
      },
      "WebhookDeleted": {
        "type": "object",
        "required": [
          "status",
          "id"
        ],
        "properties": {
          "status": {
            "type": "string",
            "const": "deleted"
          },
          "id": {
            "type": "integer",
            "format": "int64"
          }
        }
      },
      "WebhookSubscriptionCreate": {
        "type": "object",
        "required": [
          "url",
          "events"
        ],
        "properties": {
          "url": {
            "type": "string",
            "format": "uri",
            "maxLength": 512,
            "description": "`https://` on a public address; no redirects are followed."
          },
          "events": {
            "type": "array",
            "minItems": 1,
            "uniqueItems": true,
            "items": {
              "$ref": "#/components/schemas/WebhookEventSelector"
            }
          },
          "description": {
            "type": "string",
            "maxLength": 255,
            "default": ""
          }
        }
      },
      "WebhookSubscriptionUpdate": {
        "type": "object",
        "minProperties": 1,
        "properties": {
          "url": {
            "type": "string",
            "format": "uri",
            "maxLength": 512
          },
          "events": {
            "type": "array",
            "minItems": 1,
            "uniqueItems": true,
            "items": {
              "$ref": "#/components/schemas/WebhookEventSelector"
            }
          },
          "description": {
            "type": "string",
            "maxLength": 255
          },
          "active": {
            "type": "boolean",
            "description": "Set `true` to re-enable after auto-disable; resets `failures_in_row`, `disabled_at` and `disabled_reason`."
          }
        }
      },
      "WebhookDelivery": {
        "type": "object",
        "required": [
          "id",
          "subscription_id",
          "event_id",
          "event_type",
          "attempts",
          "next_attempt_at",
          "delivered_at",
          "dead",
          "last_status",
          "last_error",
          "last_response",
          "created_at"
        ],
        "properties": {
          "id": {
            "type": "integer",
            "format": "int64"
          },
          "subscription_id": {
            "type": "integer",
            "format": "int64"
          },
          "event_id": {
            "type": "string",
            "pattern": "^evt_[A-Za-z0-9]+$"
          },
          "event_type": {
            "$ref": "#/components/schemas/WebhookEventType"
          },
          "attempts": {
            "type": "integer",
            "minimum": 0
          },
          "next_attempt_at": {
            "$ref": "#/components/schemas/Timestamp"
          },
          "delivered_at": {
            "$ref": "#/components/schemas/NullableTimestamp"
          },
          "dead": {
            "type": "boolean",
            "description": "No further attempts will be made; re-queue it with `POST /webhooks/deliveries/{delivery_id}/redeliver`."
          },
          "last_status": {
            "type": [
              "integer",
              "null"
            ]
          },
          "last_error": {
            "type": [
              "string",
              "null"
            ],
            "maxLength": 500
          },
          "last_response": {
            "type": [
              "string",
              "null"
            ],
            "maxLength": 1000,
            "description": "First 1000 bytes of the receiver's body."
          },
          "created_at": {
            "$ref": "#/components/schemas/Timestamp"
          }
        }
      },
      "WebhookDeliveryWithPayload": {
        "allOf": [
          {
            "$ref": "#/components/schemas/WebhookDelivery"
          },
          {
            "type": "object",
            "required": [
              "payload"
            ],
            "properties": {
              "payload": {
                "$ref": "#/components/schemas/WebhookEvent",
                "description": "The exact envelope that was sent."
              }
            }
          }
        ]
      },
      "WebhookDeliveryPage": {
        "type": "object",
        "required": [
          "data",
          "next_cursor"
        ],
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/WebhookDelivery"
            }
          },
          "next_cursor": {
            "type": [
              "string",
              "null"
            ]
          }
        }
      },
      "WebhookTestResult": {
        "type": "object",
        "required": [
          "delivery",
          "ok",
          "status",
          "latency_ms",
          "detail"
        ],
        "properties": {
          "delivery": {
            "$ref": "#/components/schemas/WebhookDelivery"
          },
          "ok": {
            "type": "boolean",
            "description": "The receiver answered 2xx."
          },
          "status": {
            "type": [
              "integer",
              "null"
            ],
            "description": "HTTP status returned by the receiver; null when the request never completed."
          },
          "latency_ms": {
            "type": "integer",
            "minimum": 0,
            "description": "Measured around the inline delivery",
            "always present.": null
          },
          "detail": {
            "type": [
              "string",
              "null"
            ],
            "description": "Error text when `ok` is false",
            "otherwise null.": null
          }
        }
      },
      "WebhookRedelivery": {
        "type": "object",
        "required": [
          "status",
          "delivery"
        ],
        "properties": {
          "status": {
            "type": "string",
            "const": "queued"
          },
          "delivery": {
            "$ref": "#/components/schemas/WebhookDelivery"
          }
        }
      },
      "WebhookEvent": {
        "type": "object",
        "description": "Envelope of every delivery. Serialized once when the event is queued;\nretries and redeliveries send the identical bytes, so `id`,\n`created_at` and the signature input never change. `data.object` is\nthe full snapshot in the same shape the REST API returns;\n`data.previous` holds the fields that changed (e.g. `{\"status\":\n\"active\"}` on `server.suspended`) and is absent when the event has no\nprior state; `resource` is the API path of the object.\n",
        "required": [
          "id",
          "type",
          "created_at",
          "livemode",
          "account_id",
          "api_version",
          "data",
          "resource"
        ],
        "properties": {
          "id": {
            "type": "string",
            "pattern": "^evt_[A-Za-z0-9]+$"
          },
          "type": {
            "$ref": "#/components/schemas/WebhookEventType"
          },
          "created_at": {
            "$ref": "#/components/schemas/Timestamp"
          },
          "livemode": {
            "type": "boolean",
            "description": "Always true — webhooks are live-only."
          },
          "account_id": {
            "type": "integer",
            "format": "int64"
          },
          "api_version": {
            "type": "string",
            "const": "1"
          },
          "data": {
            "type": "object",
            "required": [
              "object"
            ],
            "properties": {
              "object": {
                "type": "object",
                "additionalProperties": true
              },
              "previous": {
                "type": "object",
                "additionalProperties": true
              }
            }
          },
          "resource": {
            "type": [
              "string",
              "null"
            ],
            "description": "Relative API path, e.g. `/api/v1/servers/2001`."
          }
        },
        "examples": [
          {
            "id": "evt_01J7ZK3Q9X4R",
            "type": "server.suspended",
            "created_at": "2026-09-15T10:00:00Z",
            "livemode": true,
            "account_id": 1042,
            "api_version": "1",
            "data": {
              "object": {
                "id": 2001,
                "name": "web-01",
                "status": "suspended"
              },
              "previous": {
                "status": "active"
              }
            },
            "resource": "/api/v1/servers/2001"
          }
        ]
      },
      "WebhookEventServer": {
        "allOf": [
          {
            "$ref": "#/components/schemas/WebhookEvent"
          },
          {
            "type": "object",
            "properties": {
              "type": {
                "type": "string",
                "enum": [
                  "server.created",
                  "server.suspended",
                  "server.unsuspended",
                  "server.terminated",
                  "server.reinstalled"
                ]
              },
              "data": {
                "type": "object",
                "properties": {
                  "object": {
                    "$ref": "#/components/schemas/Server"
                  }
                }
              }
            }
          }
        ]
      },
      "WebhookEventInvoice": {
        "allOf": [
          {
            "$ref": "#/components/schemas/WebhookEvent"
          },
          {
            "type": "object",
            "properties": {
              "type": {
                "type": "string",
                "enum": [
                  "invoice.created",
                  "invoice.paid",
                  "invoice.overdue"
                ]
              },
              "data": {
                "type": "object",
                "properties": {
                  "object": {
                    "$ref": "#/components/schemas/Invoice"
                  }
                }
              }
            }
          }
        ]
      },
      "WebhookEventBalance": {
        "allOf": [
          {
            "$ref": "#/components/schemas/WebhookEvent"
          },
          {
            "type": "object",
            "properties": {
              "type": {
                "type": "string",
                "const": "balance.low"
              },
              "data": {
                "type": "object",
                "properties": {
                  "object": {
                    "$ref": "#/components/schemas/Balance"
                  }
                }
              },
              "resource": {
                "type": "string",
                "const": "/api/v1/balance"
              }
            }
          }
        ]
      },
      "WebhookEventDomain": {
        "allOf": [
          {
            "$ref": "#/components/schemas/WebhookEvent"
          },
          {
            "type": "object",
            "properties": {
              "type": {
                "type": "string",
                "enum": [
                  "domain.registered",
                  "domain.expiring",
                  "domain.renewed"
                ]
              },
              "data": {
                "type": "object",
                "properties": {
                  "object": {
                    "$ref": "#/components/schemas/Domain"
                  }
                }
              }
            }
          }
        ]
      },
      "WebhookEventKey": {
        "allOf": [
          {
            "$ref": "#/components/schemas/WebhookEvent"
          },
          {
            "type": "object",
            "properties": {
              "type": {
                "type": "string",
                "enum": [
                  "key.created",
                  "key.revoked"
                ]
              },
              "data": {
                "type": "object",
                "properties": {
                  "object": {
                    "$ref": "#/components/schemas/ApiKey"
                  }
                }
              }
            }
          }
        ]
      },
      "WebhookEventPing": {
        "allOf": [
          {
            "$ref": "#/components/schemas/WebhookEvent"
          },
          {
            "type": "object",
            "properties": {
              "type": {
                "type": "string",
                "const": "ping"
              },
              "data": {
                "type": "object",
                "properties": {
                  "object": {
                    "type": "object",
                    "required": [
                      "subscription_id",
                      "message"
                    ],
                    "properties": {
                      "subscription_id": {
                        "type": "integer",
                        "format": "int64"
                      },
                      "message": {
                        "type": "string",
                        "examples": [
                          "Test delivery from VDSok"
                        ]
                      }
                    }
                  }
                }
              },
              "resource": {
                "type": "null"
              }
            }
          }
        ]
      }
    }
  }
}
